{"id":5401,"date":"2023-02-01T18:26:38","date_gmt":"2023-02-01T17:26:38","guid":{"rendered":"https:\/\/blog.besharp.it\/?p=5401"},"modified":"2023-03-24T17:48:12","modified_gmt":"2023-03-24T16:48:12","slug":"how-to-onboard-thousand-of-devices-on-aws-greengrass-and-live-happily","status":"publish","type":"post","link":"https:\/\/blog.besharp.it\/how-to-onboard-thousand-of-devices-on-aws-greengrass-and-live-happily\/","title":{"rendered":"How to onboard thousand of devices on AWS Greengrass and live happily"},"content":{"rendered":"\n

“If I had six hours to chop down a tree, I’d spend the first four hours sharpening the axe.” <\/em>Abraham Lincoln.<\/strong><\/p>\n\n\n\n

I must confess: I’m lazy, so lazy that I spend my time working on automating everything. My fellow colleagues know my attitude, and I hope to avoid ending in this situation:<\/p>\n\n\n\n

<\/p>\n\n\n

\n
\"\"
https:\/\/xkcd.com\/1319\/<\/figcaption><\/figure><\/div>\n\n\n

<\/p>\n\n\n\n

When it comes to massive deployments, automation is the only strategy that guarantees survival in the IT world.<\/p>\n\n\n\n

A customer asked us to help him use its extra edge computational capacity spread over the country. Every branch had a virtualization environment: running on-demand workloads with the least possible maintenance and configuration effort would be the icing on the cake.<\/p>\n\n\n\n

Since everything is on the edge and networking communication could be tricky, we thought about\u00a0 AWS IoT Greengrass. Mattia<\/a> already used AWS IoT Greengrass to deploy long-running and on-demand functions at the edge<\/a>; we were confident that the technology could fit our case. Our last problem to solve was avoiding to onboard every virtual machine manually.<\/p>\n\n\n\n

Lucky for us, AWS IoT Greengrass Fleet provisioning is the solution we were searching for. It allows massive deployments of edge devices, maintaining security over the enrollment process.<\/p>\n\n\n\n

To automatically provision a fleet of devices, we need first to authenticate our request during the onboarding phase; otherwise, everyone could add themselves and do evil things inside our deployment. Once the provisioning phase is completed, a unique certificate will be assigned to that device and will be used as the authentication method to interact with AWS Services.<\/p>\n\n\n\n

Two authentication methods (claims and trusted users) are available; their usage depends on the deployment scenario.<\/p>\n\n\n\n

Provisioning using a trusted user applies to scenarios when user onboarding needs user interaction (like wifi-connected appliances with companion mobile apps).<\/p>\n\n\n\n

It impersonates a user who requests a certificate on behalf of the IoT device, then uploads the final certificate to the device.<\/p>\n\n\n\n

Provisioning using claims uses a “base” certificate (stored on the device) to authenticate and request the final certificate directly from the IoT device. This scenario requires no user interaction, so massive deployments are a perfect fit. <\/p>\n\n\n\n

Bingo! We have our solution: we will use the AWS IoT Greengrass Core with the AWS IoT fleet provisioning plugin.<\/p>\n\n\n\n

First, let’s dig into the claims provisioning workflow to understand it better.<\/p>\n\n\n\n

    \n
  1. Create a provisioning certificate and allow it to obtain final certificates by attaching a policy<\/li>\n\n\n\n
  2. Create a provisioning template that automatically fills device details (like name, group, or serial number) in AWS IoT Core <\/li>\n\n\n\n
  3. Install Greengrass software on a template edge device,<\/li>\n\n\n\n
  4. Configure the fleet provisioning plugin and customize the deployment.<\/li>\n\n\n\n
  5. Start deploying devices! <\/li>\n<\/ol>\n\n\n\n

    Since we are lazy, we will use scripting and CloudFormation as much as possible. As a bonus point, we’ll create a golden virtual machine image with all the installed components we can use as a template to deploy at the edge.<\/p>\n\n\n\n

    First, a script will create and save provisioning certificates using AWS CLI. We will save them using  AWS SecretsManager, as you will see later, we use SecretsManager to automate their deployment on the golden virtual machine image.<\/p>\n\n\n\n

    #!\/bin\/bash\nENV=${1}\n\n\nSECRETSMANAGER_PREFIX=\"MyAwesomeProjectSecret\"\nTHINGGROUP_NAME=\"MyThingGroup\"\n\n# Create the certificate\nCERTIFICATE_ARN=$(aws iot create-keys-and-certificate \\\n            \t--certificate-pem-outfile \"claim-certs\/claim.pem.crt\" \\\n            \t--public-key-outfile \"claim-certs\/claim.public.pem.key\" \\\n            \t--private-key-outfile \"claim-certs\/claim.private.pem.key\" \\\n            \t--set-as-active | jq -r .certificateArn)\n\nSECRET_STRING=$(echo \"$(cat claim-certs\/claim.pem.crt)|$(cat claim-certs\/claim.private.pem.key)\"  | tr '\\n' ';' )\naws secretsmanager create-secret --name $SECRETSMANAGER_PREFIX\/$ENV\/claims-certificate --secret-string $SECRET_STRING\n\n# Attach the policy to the certificate\naws iot attach-policy --policy-name GreengrassProvisioningClaimPolicy --target $CERTIFICATE_ARN\naws iot create-thing-group --thing-group-name $THINGGROUP_NAME<\/code><\/pre>\n\n\n\n

    Run this script before deploying this CloudFormation template that will create the thing group, policies to associate it with claim certificates, and the required service roles.<\/p>\n\n\n\n

    ---\nAWSTemplateFormatVersion: '2010-09-09'\nDescription: GreenGrass with Fleet Manager provisioning template\n\nMetadata:\n\n  'AWS::CloudFormation::Interface':\n\tParameterGroups:\n  \t- Label: {default: 'Required parameters'}\n    \tParameters:\n      \t- Env\n      \t- ThingGroupName\n  \t- Label: {default: 'Optional parameters'}\n    \tParameters:\n      \t- ProjectName\n\nParameters:\n\n  Env:\n\tType: String\n\tDescription: \"Insert the environment\"\n\n  ProjectName:\n\tType: String\n\tDescription: \"Insert the name of the project\"\n\n  ThingGroupName:\n\tType: String\n\tDescription: \"Insert the Thing Group name\"\n\nResources:\n\n  GreengrassTokenExchangeRole:\n\tType: AWS::IAM::Role\n\tProperties:\n  \tAssumeRolePolicyDocument:\n    \tVersion: '2012-10-17'\n    \tStatement:\n      \t- Effect: 'Allow'\n        \tPrincipal:\n          \tService:\n            \t- 'credentials.iot.amazonaws.com'\n        \tAction:\n          \t- 'sts:AssumeRole'\n      \t- Effect: 'Allow'\n     \tPolicies:\n    \t- PolicyName: 'LogPersmission'\n      \tPolicyDocument:\n        \tVersion: '2012-10-17'\n        \tStatement:\n          \t- Effect: 'Allow'\n            \tAction:\n              \t- \"logs:CreateLogGroup\"\n              \t- \"logs:CreateLogStream\"\n              \t- \"logs:PutLogEvents\"\n              \t- \"logs:DescribeLogStreams\"\n              \t- \"s3:GetBucketLocation\"\n              \t- \"iam:PassRole\"\n            \tResource: '*'\n  \t  \tRoleName: !Sub '${ProjectName}-${Env}-V2TokenExchangeRole'\n\n  GreengrassTokenExchangeRoleAlias:\n\tType: AWS::IoT::RoleAlias\n\tProperties:\n  \tRoleAlias: !Sub '${ProjectName}-${Env}-CoreTokenExchangeRoleAlias'\n  \tRoleArn: !GetAtt GreengrassTokenExchangeRole.Arn\n  \tTags:\n    \t- Key: Name\n      \tValue: !Sub \"${ProjectName}-${Env}-CoreTokenExchangeRoleAlias\"\n\n  GreengrassV2IoTThingPolicy:\n\tType: AWS::IoT::Policy\n\tProperties:\n  \tPolicyDocument:\n    \tVersion: '2012-10-17'\n    \tStatement:\n      \t- Effect: 'Allow'\n        \tAction:\n          \t- \"iot:Publish\"\n          \t- \"iot:Subscribe\"\n          \t- \"iot:Receive\"\n          \t- \"iot:Connect\"\n          \t- \"greengrass:*\"\n        \tResource: \"*\"\n      \t- Effect: 'Allow'\n        \tAction:\n          \t- \"iot:AssumeRoleWithCertificate\"\n        \tResource: !GetAtt GreengrassTokenExchangeRoleAlias.RoleAliasArn\n  \tPolicyName: V2IoTThingPolicy\n\n  GreengrassFleetProvisioningRole:\n\tType: AWS::IAM::Role\n\tProperties:\n  \tAssumeRolePolicyDocument:\n    \tVersion: '2012-10-17'\n    \tStatement:\n      \t- Effect: 'Allow'\n        \tPrincipal:\n          \tService:\n            \t- 'iot.amazonaws.com'\n        \tAction:\n          \t- 'sts:AssumeRole'\n  \tPolicies:\n    \t- PolicyName: 'ECRAccess'\n      \tPolicyDocument:\n        \tVersion: '2012-10-17'\n        \tStatement:\n          \t- Effect: 'Allow'\n            \tAction:\n              \t- \"logs:CreateLogGroup\"\n              \t- \"logs:CreateLogStream\"\n              \t- \"logs:PutLogEvents\"\n              \t- \"logs:DescribeLogStreams\"\n              \t- \"s3:GetBucketLocation\"\n            \tResource: '*'\n  \tRoleName: !Sub '${ProjectName}-${Env}-FleetProvisioningRole'\n\n  GreengrassFleetProvisioningTemplate:\n\tType: AWS::IoT::ProvisioningTemplate\n\tProperties:\n  \tDescription: \"template to provision iot fleet resources\"\n  \tEnabled: true\n  \tProvisioningRoleArn: !GetAtt GreengrassFleetProvisioningRole.Arn\n  \tTemplateBody: |\n    \t{\n      \t\"Parameters\": {\n        \t\"ThingName\": {\n          \t\"Type\": \"String\"\n        \t},\n        \t\"ThingGroupName\": {\n          \t\"Type\": \"String\"\n        \t},\n        \t\"AWS::IoT::Certificate::Id\": {\n          \t\"Type\": \"String\"\n        \t}\n      \t},\n      \t\"Resources\": {\n        \t\"MyThing\": {\n          \t\"OverrideSettings\": {\n            \t\"AttributePayload\": \"REPLACE\",\n            \t\"ThingGroups\": \"REPLACE\",\n            \t\"ThingTypeName\": \"REPLACE\"\n          \t},\n          \t\"Properties\": {\n            \t\"AttributePayload\": {},\n            \t\"ThingGroups\": [\n              \t{\n                \t\"Ref\": \"ThingGroupName\"\n              \t}\n            \t],\n            \t\"ThingName\": {\n              \t\"Ref\": \"ThingName\"\n            \t}\n          \t},\n          \t\"Type\": \"AWS::IoT::Thing\"\n        \t},\n        \t\"MyPolicy\": {\n          \t\"Properties\": {\n            \t\"PolicyName\": \"V2IoTThingPolicy\"\n          \t},\n          \t\"Type\": \"AWS::IoT::Policy\"\n        \t},\n        \t\"MyCertificate\": {\n          \t\"Properties\": {\n            \t\"CertificateId\": {\n              \t\"Ref\": \"AWS::IoT::Certificate::Id\"\n            \t},\n            \t\"Status\": \"Active\"\n          \t},\n          \t\"Type\": \"AWS::IoT::Certificate\"\n        \t}\n      \t}\n    \t}\n  \tTemplateName: !Sub \"${ProjectName}-${Env}-FleetTemplate\"\n\n  GreengrassProvisioningClaimPolicy:\n\tType: AWS::IoT::Policy\n\tProperties:\n  \tPolicyDocument:\n    \tVersion: '2012-10-17'\n    \tStatement:\n      \t- Effect: 'Allow'\n        \tAction:\n          \t- \"iot:Connect\"\n        \tResource: \"*\"\n      \t- Effect: 'Allow'\n        \tAction:\n          \t- \"iot:Subscribe\"\n        \tResource:\n          \t- !Sub \"arn:aws:iot:${AWS::Region}:${AWS::AccountId}:topicfilter\/$aws\/certificates\/create\/*\"\n          \t- !Sub \"arn:aws:iot:${AWS::Region}:${AWS::AccountId}:topicfilter\/$aws\/provisioning-templates\/${GreengrassFleetProvisioningTemplate}\/provision\/*\"\n      \t- Effect: 'Allow'\n        \tAction:\n          \t- \"iot:Publish\"\n          \t- \"iot:Receive\"\n        \tResource:\n          \t- !Sub \"arn:aws:iot:${AWS::Region}:${AWS::AccountId}:topic\/$aws\/certificates\/create\/*\"\n          \t- !Sub \"arn:aws:iot:${AWS::Region}:${AWS::AccountId}:topic\/$aws\/provisioning-templates\/${GreengrassFleetProvisioningTemplate}\/provision\/*\"\n  \tPolicyName: GreengrassProvisioningClaimPolicy<\/code><\/pre>\n\n\n\n

    The <\/p>\n\n\n\n

    GreengrassFleetProvisioningTemplate <\/code><\/pre>\n\n\n\n

    resource will register our IoT device using a GroupName and a ThingName. You can personalize the template according to your needs. Later, you will see that “ThingName” will be our VM hostname.<\/p>\n\n\n\n

    If you want to get notified and run custom actions when a device registers, you can add a rule like this and the corresponding SNS topics (I will not include the complete code since it’s a simple lambda function)<\/p>\n\n\n\n

    ThingCreationIotRule:\n\tType: AWS::IoT::TopicRule\n\tProperties:\n  \tRuleName: !Sub '${ProjectName}_${Env}_greengrass_rule'\n  \tTopicRulePayload:\n    \tRuleDisabled: 'false'\n    \tSql: SELECT * FROM '$aws\/events\/thing\/#'\n    \tActions:\n      \t- Lambda:\n          \tFunctionArn: !GetAtt RegisterThingLambda.Arn\n    \tErrorAction:\n      \tSns:\n        \tTargetArn: !Ref SNSFailedNotificationTopic\n        \tRoleArn: !GetAtt NotificationRole.Arn<\/code><\/pre>\n\n\n\n

    Now it’s time to create our golden virtual machine image using Ubuntu 22.04 as a base install; you use VirtualBox or VMware as a testing and development environment.<\/p>\n\n\n\n

    The following script will install the required packages and retrieve claim certificates. To use it, you should set temporary AWS IAM credentials as environment variables or, for better, integrate everything in a packer template.<\/p>\n\n\n\n

    #!\/bin\/bash\n\nENV=${1}\n\nSECRETSMANAGER_PREFIX=\"MyAwesomeProjectSecret\"\n\nmkdir -p claim-certs\nSECRET_STRING=$(aws secretsmanager get-secret-value --secret-id $SECRETSMANAGER_PREFIX\/$ENV\/claims-certificate --query SecretString --output text)\n\necho $SECRET_STRING | cut -d '|' -f 1 | tr ';' '\\n' > claim-certs\/claim.pem.crt\necho $SECRET_STRING | cut -d '|' -f 2 | tr ';' '\\n' > claim-certs\/claim.private.pem.key\n\n\nexport DEBIAN_FRONTEND=noninteractive\napt update && apt upgrade -y\napt -yq install python3-pip zip open-vm-tools default-jdk libgl1-mesa-glx\n\n\nmkdir -p \/greengrass\/v2\/installer\nmkdir \/greengrass\/v2\/claim-certs\n\n\nmv claim-certs\/claim.private.pem.key \/greengrass\/v2\/claim-certs\/\nmv \/claim-certs\/claim.pem.crt \/greengrass\/v2\/claim-certs\/\n\n\n\ncd \/greengrass\/v2\ncurl -o \/greengrass\/v2\/AmazonRootCA1.pem https:\/\/www.amazontrust.com\/repository\/AmazonRootCA1.pem\ncurl -s https:\/\/d2s8p88vqu9w66.cloudfront.net\/releases\/greengrass-nucleus-latest.zip > greengrass-nucleus-latest.zip\nunzip greengrass-nucleus-latest.zip -d installer && rm greengrass-nucleus-latest.zip\ncurl -s https:\/\/d2s8p88vqu9w66.cloudfront.net\/releases\/aws-greengrass-FleetProvisioningByClaim\/fleetprovisioningbyclaim-latest.jar > installer\/aws.greengrass.FleetProvisioningByClaim.jar<\/code><\/pre>\n\n\n\n

    All the required AWS IoT Greengrass components are now installed. Let’s now add the ultimate lazy sysadmin touch to our solution: we definitely want to have something that, when started, configures itself without user intervention.\u00a0<\/p>\n\n\n\n

    We will define a template for our AWS IoT Greengrass configuration and, taking advantage of <\/p>\n\n\n\n

    systemd <\/code><\/pre>\n\n\n\n

    unit and scripting, use the virtual machine’s hostname as ThingName
    Create a file named config.yml in <\/p>\n\n\n\n

    \/greengrass\/v2\/installer\/ <\/code><\/pre>\n\n\n\n

    specifying that we will use the IoT fleet provisioning plugin.<\/p>\n\n\n\n

    ---\nservices:\n  aws.greengrass.Nucleus:\n\tversion: \"2.9.1\"\n  aws.greengrass.FleetProvisioningByClaim:\n\tconfiguration:\n  \trootPath: \"\/greengrass\/v2\"\n  \tawsRegion: \"eu-west-1\"\n  \tiotDataEndpoint: \"endpoint.iot.region.amazonaws.com\"\n  \tiotCredentialEndpoint: \"endpoint.credentials.iot.region.amazonaws.com\"\n  \tiotRoleAlias: \"myproject-environment-CoreTokenExchangeRoleAlias\"\n  \tprovisioningTemplate: \"myproject-environment-FleetTemplate\"\n  \tclaimCertificatePath: \"\/greengrass\/v2\/claim-certs\/claim.pem.crt\"\n  \tclaimCertificatePrivateKeyPath: \"\/greengrass\/v2\/claim-certs\/claim.private.pem.key\"\n  \trootCaPath: \"\/greengrass\/v2\/AmazonRootCA1.pem\"\n  \ttemplateParameters:\n    \tThingName: \"REPLACEME\"\n    \tThingGroupName: \"MyThingGroup\"<\/code><\/pre>\n\n\n\n

    Change this file according to your environment. You can obtain <\/p>\n\n\n\n

    iotDataEndpoint <\/code><\/pre>\n\n\n\n

    and <\/p>\n\n\n\n

    iotCredentialEndpoint <\/code><\/pre>\n\n\n\n

    values by issuing these commands:<\/p>\n\n\n\n

    aws iot describe-endpoint --endpoint-type iot:Data-ATS\naws iot describe-endpoint --endpoint-type iot:CredentialProvider<\/code><\/pre>\n\n\n\n

    As you can see, ThingName value is set as “REPLACEME<\/strong>“. A script <\/p>\n\n\n\n

    (\/greengrass\/configure-device.sh) <\/code><\/pre>\n\n\n\n

    will replace this value and a systemd service will run it at the first boot.<\/p>\n\n\n\n

    #!\/bin\/bash\n\nset -e\n\nsed -i s\/REPLACEME\/$(hostname)\/g \/greengrass\/v2\/installer\/config.yaml\necho \"********************** RUN SERVICE **************************\"\njava -Droot=\"\/greengrass\/v2\" -Dlog.store=FILE \\\n-jar \/greengrass\/v2\/installer\/lib\/Greengrass.jar \\\n--trusted-plugin \/greengrass\/v2\/installer\/aws.greengrass.FleetProvisioningByClaim.jar \\\n--init-config \/greengrass\/v2\/installer\/config.yaml \\\n--component-default-user ggc_user:ggc_group \\\n--setup-system-service true<\/code><\/pre>\n\n\n\n

    The first line <\/p>\n\n\n\n

    (sed -i s\/REPLACEME\/$(hostname)\/g \/greengrass\/v2\/installer\/config.yaml) <\/code><\/pre>\n\n\n\n

    replaces the value with the virtual machine’s current hostname.<\/p>\n\n\n\n

    Create now a unit file in the \/lib\/systemd\/system directory with a meaningful name (we used “greengrass-config.service”)<\/p>\n\n\n\n

    [Unit]\nBefore=systemd-user-sessions.service\nWants=network-online.target\nAfter=network-online.target\nConditionPathExists=!\/greengrass\/greengrass_installed\n\n[Service]\nType=oneshot\nExecStart=\/greengrass\/configure-device.sh\nExecStartPost=\/usr\/bin\/touch \/greengrass\/greengrass_installed\nRemainAfterExit=yes\n\n[Install]\nWantedBy=multi-user.target<\/code><\/pre>\n\n\n\n

    This is a pretty standard systemd unit, with an exception:<\/p>\n\n\n\n

    ConditionPathExists=!\/greengrass\/greengrass_installed<\/code><\/pre>\n\n\n\n

    tells systemd to run this unit only if this file does not exist.<\/p>\n\n\n\n

    ExecStartPost=\/usr\/bin\/touch \/greengrass\/greengrass_installed <\/code><\/pre>\n\n\n\n

    tells systemd to create the file that, so after the first time, the service will not run anymore.<\/p>\n\n\n\n

    Activate service at boot with<\/p>\n\n\n\n

    systemctl daemon-reload\nsystemctl enable greengrass-config.service<\/code><\/pre>\n\n\n\n

    Once you finish this configuration, just export your virtual machine image in a format such as OVA (or create a VMware template) and deploy it! <\/p>\n\n\n\n

    Remember: this is only a sample configuration; you may need to optimize and update your system to shrink disk size and disable unnecessary system services.<\/p>\n\n\n\n

    Once you deploy this solution, you can run functions on your distributed environment and take advantage of all the unused computing resources you may have at your disposal on edge.<\/p>\n\n\n\n

    Other AWS Services can use this solution as a base, like running managed SageMaker jobs at the edge, but let’s keep this topic for another time.<\/p>\n\n\n\n

    Today we saw how automation could relieve us from the execution of boring tasks, even if, at first glance, everything seems to get more complicated.<\/p>\n\n\n\n

    Did you ever find yourself in an automation frenzy to accommodate laziness? <\/p>\n\n\n\n

    Let us know in the comments!<\/p>\n\n\n\n

    See you in 14 days on #Proud2beCloud<\/strong><\/p>\n\n\n\n


    \n\n\n\n

    About Proud2beCloud<\/h4>\n\n\n\n

    Proud2beCloud is a blog by beSharp<\/a>, an Italian APN Premier Consulting Partner expert in designing, implementing, and managing complex Cloud infrastructures and advanced services on AWS. Before being writers, we are Cloud Experts working daily with AWS services since 2007. We are hungry readers, innovative builders, and gem-seekers. On Proud2beCloud, we regularly share our best AWS pro tips, configuration insights, in-depth news, tips&tricks, how-tos, and many other resources. Take part in the discussion!<\/p>\n","protected":false},"excerpt":{"rendered":"

    “If I had six hours to chop down a tree, I’d spend the first four hours sharpening the axe.” Abraham […]<\/p>\n","protected":false},"author":13,"featured_media":5406,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[478],"tags":[574,413],"yoast_head":"\nHow to onboard thousand of devices on AWS Greengrass and live happily - Proud2beCloud Blog<\/title>\n<meta name=\"description\" content=\"Today we're relying on Greengrass Fleet provisioning to automatically provision a fleet of devices avoiding manual onboarding of every VM\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/blog.besharp.it\/how-to-onboard-thousand-of-devices-on-aws-greengrass-and-live-happily\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"How to onboard thousand of devices on AWS Greengrass and live happily\" \/>\n<meta property=\"og:description\" content=\"Today we're relying on Greengrass Fleet provisioning to automatically provision a fleet of devices avoiding manual onboarding of every VM\" \/>\n<meta property=\"og:url\" content=\"https:\/\/blog.besharp.it\/how-to-onboard-thousand-of-devices-on-aws-greengrass-and-live-happily\/\" \/>\n<meta property=\"og:site_name\" content=\"Proud2beCloud Blog\" \/>\n<meta property=\"article:published_time\" content=\"2023-02-01T17:26:38+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-03-24T16:48:12+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/blog.besharp.it\/wp-content\/uploads\/2023\/02\/Copertina-blog-03-02-23_03-02-23-social-ita.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"628\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Damiano Giorgi\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:title\" content=\"How to onboard thousand of devices on AWS Greengrass and live happily\" \/>\n<meta name=\"twitter:description\" content=\"Today we're relying on Greengrass Fleet provisioning to automatically provision a fleet of devices avoiding manual onboarding of every VM\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/blog.besharp.it\/wp-content\/uploads\/2023\/02\/Copertina-blog-03-02-23_03-02-23-social-ita.png\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Damiano Giorgi\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"10 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/blog.besharp.it\/how-to-onboard-thousand-of-devices-on-aws-greengrass-and-live-happily\/\",\"url\":\"https:\/\/blog.besharp.it\/how-to-onboard-thousand-of-devices-on-aws-greengrass-and-live-happily\/\",\"name\":\"How to onboard thousand of devices on AWS Greengrass and live happily - Proud2beCloud Blog\",\"isPartOf\":{\"@id\":\"https:\/\/blog.besharp.it\/#website\"},\"datePublished\":\"2023-02-01T17:26:38+00:00\",\"dateModified\":\"2023-03-24T16:48:12+00:00\",\"author\":{\"@id\":\"https:\/\/blog.besharp.it\/#\/schema\/person\/a9195473e4a658b45cb12d3df3fdf293\"},\"description\":\"Today we're relying on Greengrass Fleet provisioning to automatically provision a fleet of devices avoiding manual onboarding of every VM\",\"breadcrumb\":{\"@id\":\"https:\/\/blog.besharp.it\/how-to-onboard-thousand-of-devices-on-aws-greengrass-and-live-happily\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/blog.besharp.it\/how-to-onboard-thousand-of-devices-on-aws-greengrass-and-live-happily\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/blog.besharp.it\/how-to-onboard-thousand-of-devices-on-aws-greengrass-and-live-happily\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/blog.besharp.it\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"How to onboard thousand of devices on AWS Greengrass and live happily\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/blog.besharp.it\/#website\",\"url\":\"https:\/\/blog.besharp.it\/\",\"name\":\"Proud2beCloud Blog\",\"description\":\"il blog di beSharp\",\"alternateName\":\"Proud2beCloud Blog\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/blog.besharp.it\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/blog.besharp.it\/#\/schema\/person\/a9195473e4a658b45cb12d3df3fdf293\",\"name\":\"Damiano Giorgi\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/blog.besharp.it\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/9a20b8c97250d4fb49857192f7e4bedf?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/9a20b8c97250d4fb49857192f7e4bedf?s=96&d=mm&r=g\",\"caption\":\"Damiano Giorgi\"},\"description\":\"Ex sistemista on-prem, pigro e incline all'automazione di task noiosi. Alla ricerca costante di novit\u00e0 tecnologiche e quindi passato al cloud per trovare nuovi stimoli. L'unico hardware a cui mi dedico ora \u00e8 quello del mio basso; se non mi trovate in ufficio o in sala prove provate al pub o in qualche aeroporto!\",\"url\":\"https:\/\/blog.besharp.it\/author\/damiano-giorgi\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"How to onboard thousand of devices on AWS Greengrass and live happily - Proud2beCloud Blog","description":"Today we're relying on Greengrass Fleet provisioning to automatically provision a fleet of devices avoiding manual onboarding of every VM","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/blog.besharp.it\/how-to-onboard-thousand-of-devices-on-aws-greengrass-and-live-happily\/","og_locale":"en_US","og_type":"article","og_title":"How to onboard thousand of devices on AWS Greengrass and live happily","og_description":"Today we're relying on Greengrass Fleet provisioning to automatically provision a fleet of devices avoiding manual onboarding of every VM","og_url":"https:\/\/blog.besharp.it\/how-to-onboard-thousand-of-devices-on-aws-greengrass-and-live-happily\/","og_site_name":"Proud2beCloud Blog","article_published_time":"2023-02-01T17:26:38+00:00","article_modified_time":"2023-03-24T16:48:12+00:00","og_image":[{"width":1200,"height":628,"url":"https:\/\/blog.besharp.it\/wp-content\/uploads\/2023\/02\/Copertina-blog-03-02-23_03-02-23-social-ita.png","type":"image\/png"}],"author":"Damiano Giorgi","twitter_card":"summary_large_image","twitter_title":"How to onboard thousand of devices on AWS Greengrass and live happily","twitter_description":"Today we're relying on Greengrass Fleet provisioning to automatically provision a fleet of devices avoiding manual onboarding of every VM","twitter_image":"https:\/\/blog.besharp.it\/wp-content\/uploads\/2023\/02\/Copertina-blog-03-02-23_03-02-23-social-ita.png","twitter_misc":{"Written by":"Damiano Giorgi","Est. reading time":"10 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/blog.besharp.it\/how-to-onboard-thousand-of-devices-on-aws-greengrass-and-live-happily\/","url":"https:\/\/blog.besharp.it\/how-to-onboard-thousand-of-devices-on-aws-greengrass-and-live-happily\/","name":"How to onboard thousand of devices on AWS Greengrass and live happily - Proud2beCloud Blog","isPartOf":{"@id":"https:\/\/blog.besharp.it\/#website"},"datePublished":"2023-02-01T17:26:38+00:00","dateModified":"2023-03-24T16:48:12+00:00","author":{"@id":"https:\/\/blog.besharp.it\/#\/schema\/person\/a9195473e4a658b45cb12d3df3fdf293"},"description":"Today we're relying on Greengrass Fleet provisioning to automatically provision a fleet of devices avoiding manual onboarding of every VM","breadcrumb":{"@id":"https:\/\/blog.besharp.it\/how-to-onboard-thousand-of-devices-on-aws-greengrass-and-live-happily\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/blog.besharp.it\/how-to-onboard-thousand-of-devices-on-aws-greengrass-and-live-happily\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/blog.besharp.it\/how-to-onboard-thousand-of-devices-on-aws-greengrass-and-live-happily\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/blog.besharp.it\/"},{"@type":"ListItem","position":2,"name":"How to onboard thousand of devices on AWS Greengrass and live happily"}]},{"@type":"WebSite","@id":"https:\/\/blog.besharp.it\/#website","url":"https:\/\/blog.besharp.it\/","name":"Proud2beCloud Blog","description":"il blog di beSharp","alternateName":"Proud2beCloud Blog","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/blog.besharp.it\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/blog.besharp.it\/#\/schema\/person\/a9195473e4a658b45cb12d3df3fdf293","name":"Damiano Giorgi","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/blog.besharp.it\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/9a20b8c97250d4fb49857192f7e4bedf?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/9a20b8c97250d4fb49857192f7e4bedf?s=96&d=mm&r=g","caption":"Damiano Giorgi"},"description":"Ex sistemista on-prem, pigro e incline all'automazione di task noiosi. Alla ricerca costante di novit\u00e0 tecnologiche e quindi passato al cloud per trovare nuovi stimoli. L'unico hardware a cui mi dedico ora \u00e8 quello del mio basso; se non mi trovate in ufficio o in sala prove provate al pub o in qualche aeroporto!","url":"https:\/\/blog.besharp.it\/author\/damiano-giorgi\/"}]}},"_links":{"self":[{"href":"https:\/\/blog.besharp.it\/wp-json\/wp\/v2\/posts\/5401"}],"collection":[{"href":"https:\/\/blog.besharp.it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.besharp.it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.besharp.it\/wp-json\/wp\/v2\/users\/13"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.besharp.it\/wp-json\/wp\/v2\/comments?post=5401"}],"version-history":[{"count":0,"href":"https:\/\/blog.besharp.it\/wp-json\/wp\/v2\/posts\/5401\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.besharp.it\/wp-json\/wp\/v2\/media\/5406"}],"wp:attachment":[{"href":"https:\/\/blog.besharp.it\/wp-json\/wp\/v2\/media?parent=5401"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.besharp.it\/wp-json\/wp\/v2\/categories?post=5401"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.besharp.it\/wp-json\/wp\/v2\/tags?post=5401"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}