Skip to content

Instantly share code, notes, and snippets.

@kauffmanes
Last active January 17, 2020 00:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kauffmanes/0a2dcac87cf71fc6173d2b7b8b2bc001 to your computer and use it in GitHub Desktop.
Save kauffmanes/0a2dcac87cf71fc6173d2b7b8b2bc001 to your computer and use it in GitHub Desktop.
Creating robomaker resources using the CLI
#!/bin/bash
set -e
echo "Enter the robot's serial number (ex. FX250123)"
read ROBOT_SN
if [ -z $ROBOT_SN ]
then
echo "A robot serial number is required."
exit
fi
THING_NAME=$ROBOT_SN-thing # thing name is used in AWS IoT
THING_GROUP=$ROBOT_SN-group # for greegrass group
THING_POLICY=$ROBOT_SN-policy # for greengrass policy
THING_CORE=$ROBOT_SN-core # for greengrass core
IOT_GROUP_NAME=<first_group_name>
IOT_GROUP_ARN=<name_of_first_group>
echo "Enter the customer's name (if no customer, leave blank)."
read CUSTOMER
if [ -z $CUSTOMER ]
then
CUSTOMER=Discovery
fi
TODAY=$(date '+%Y-%m-%d') # used as a thing attribute (optional)
ARCH=X86_64 # architecture of robot (can be ARMHF, ARM64, or X86_64)
ROLE_ARN=<your_role_arn> # the deployment role, assumes its already created (https://docs.aws.amazon.com/robomaker/latest/dg/create-robot.html#create-robot-role)
FLEET_ARN=<your_fleet_arn> # the fleet ARN that you want your robot to be initialized into
# ----------------------------------------------------------------------------------------
# Setup Environment
# This makes an output for your greengrass certs/config that go on the robot. PRefixed by the
# robot name so that you can make multiple robots at once.
# ----------------------------------------------------------------------------------------
mkdir -p robots/$ROBOT_SN/certs
mkdir -p robots/$ROBOT_SN/config
# ----------------------------------------------------------------------------------------
# IoT: createKeysAndCertificate
# returns: certificateArn, certificateId, certificatePem, keyPair (PublicKey, PrivateKey)
# ----------------------------------------------------------------------------------------
CERTS_RESPONSE=$(aws iot create-keys-and-certificate \
--set-as-active \
--certificate-pem-outfile robots/$ROBOT_SN/certs/$ROBOT_SN.cert.pem \
--public-key-outfile robots/$ROBOT_SN/certs/$ROBOT_SN.public.key \
--private-key-outfile robots/$ROBOT_SN/certs/$ROBOT_SN.private.key | jq -r '.')
CERT_ARN=$(echo $CERTS_RESPONSE | jq -r '.certificateArn')
CERT_ID=$(echo $CERTS_RESPONSE | jq -r '.certificateId')
if [ ! -z $CERT_ID ]
then
echo "A new set of certs was created with ID $CERT_ID"
else
echo "Certs could not be created."
exit
fi
# ----------------------------------------------------------------------------------------
# Download the root CA
# ----------------------------------------------------------------------------------------
wget -O robots/$ROBOT_SN/certs/root.ca.pem sudo wget -O root.ca.pem https://www.amazontrust.com/repository/AmazonRootCA1.pem
# ----------------------------------------------------------------------------------------
# IoT: createThing
# returns: thingName, thingArn, thingId
# ----------------------------------------------------------------------------------------
THING_ARN=$(aws iot create-thing \
--thing-name $THING_NAME \
--thing-type-name FX250_Chassis \
--attribute-payload "{\"attributes\": {\"customer\":\"$CUSTOMER\", \"date_provisioned\":\"$TODAY\", \"softwareVersion\":\"0.0.0\"}}" | jq -r '.thingArn')
if [ ! -z $THING_ARN ]
then
echo "A new thing was created for $THING_NAME"
else
echo "Thing thing could not be created. Rolling back."
aws iot detach-thing-principal --thing-name $THING_NAME --principal $CERT_ARN
aws iot update-certificate --certificate-id $CERT_ID --new-status INACTIVE
aws iot delete-certificate --certificate-id $CERT_ID
exit
fi
# ----------------------------------------------------------------------------------------
# IoT: attachThingPrincipal
# returns: {}
# ----------------------------------------------------------------------------------------
aws iot attach-thing-principal --thing-name $THING_NAME --principal $CERT_ARN
# ----------------------------------------------------------------------------------------
# IoT: createPolicy (name: <robo_name>-policy)
# returns: policyArn, policyDocument, policyName, policyVersionId
# ----------------------------------------------------------------------------------------
POLICY_DETAILS=$(aws iot create-policy \
--policy-name $THING_POLICY \
--policy-document "{\"Version\": \"2012-10-17\",\"Statement\": [{\"Effect\": \"Allow\",\"Action\": [\"iot:Publish\",\"iot:Subscribe\",\"iot:Connect\",\"iot:Receive\"],\"Resource\": [\"*\"]},{\"Effect\": \"Allow\",\"Action\": [\"iot:GetThingShadow\",\"iot:UpdateThingShadow\",\"iot:DeleteThingShadow\"],\"Resource\": [\"*\"]},{\"Effect\": \"Allow\",\"Action\": [\"greengrass:*\"],\"Resource\": [\"*\"]}]}" | jq -r '.')
POLICY_ARN=$(echo $POLICY_DETAILS | jq -r '.policyArn')
if [ ! -z $POLICY_ARN ]
then
echo "A new policy called $THING_POLICY was created."
else
echo "Policy could not be created. Rolling back."
aws iot detach-thing-principal --thing-name $THING_NAME --principal $CERT_ARN
aws iot update-certificate --certificate-id $CERT_ID --new-status INACTIVE
aws iot delete-certificate --certificate-id $CERT_ID
aws iot delete-thing --thing-name $THING_NAME
aws iot delete-policy --policy-name $THING_POLICY
exit
fi
# ----------------------------------------------------------------------------------------
# # IoT: attachPolicy
# # returns: nothing
# ----------------------------------------------------------------------------------------
aws iot attach-policy --policy-name $THING_POLICY --target $CERT_ARN
# ----------------------------------------------------------------------------------------
# Greengrass: createGroup
# ----------------------------------------------------------------------------------------
GG_GRP_ID=$(aws greengrass create-group --name $THING_GROUP| jq -r '.Id')
if [ ! -z $GG_GRP_ID ]
then
echo "The group ID is $GG_GRP_ID"
else
echo "The group ID wasn't set."
aws iot detach-thing-principal --thing-name $THING_NAME --principal $CERT_ARN
aws iot update-certificate --certificate-id $CERT_ID --new-status INACTIVE
aws iot delete-certificate --certificate-id $CERT_ID
aws iot detach-policy --policy-name $THING_POLICY --target $CERT_ARN
aws iot delete-policy --policy-name $THING_POLICY
aws iot delete-thing --thing-name $THING_NAME
exit
fi
# ----------------------------------------------------------------------------------------
# Greengrass: associateRole to group
# assign role so group can access robomaker
# ----------------------------------------------------------------------------------------
RESPONSE=$(aws greengrass associate-role-to-group --group-id $GG_GRP_ID --role-arn $ROLE_ARN | jq --raw-output '.AssociatedAt')
if [ ! -z $RESPONSE ]
then
echo "The group was associated with the role at $RESPONSE"
else
echo "The group could not be associated with this role. Rolling back."
aws greengrass delete-role --group-id $GG_GRP_ID
exit
fi
# ----------------------------------------------------------------------------------------
# Greengrass: createCoreDefinition
# returns Name, Id, Arn, CreationTimestamp, LastUpdatedTimestamp
# ----------------------------------------------------------------------------------------
CORE_ID=$(aws greengrass create-core-definition --name $THING_CORE | jq -r '.Id')
if [ ! -z $CORE_ID ]
then
echo "The core was created with core ID $CORE_ID"
else
echo "The core could not be created. Rolling back."
aws iot detach-thing-principal --thing-name $THING_NAME --principal $CERT_ARN
aws iot update-certificate --certificate-id $CERT_ID --new-status INACTIVE
aws iot detach-policy --policy-name $THING_POLICY --target $CERT_ARN
aws iot delete-policy --policy-name $THING_POLICY
aws iot delete-certificate --certificate-id $CERT_ID
aws iot delete-thing --thing-name $THING_NAME
aws greengrass delete-group --group-id $GG_GRP_ID
aws greengrass delete-role --group-id $GG_GRP_ID
exit
fi
# ----------------------------------------------------------------------------------------
# Greengrass: createCoreDefinitionVersion
# returns Arn, Version, CreationTimestamp, Id
# ----------------------------------------------------------------------------------------
CORE_DEFINITION_VERSION_ARN=$(aws greengrass create-core-definition-version \
--core-definition-id $CORE_ID \
--cores CertificateArn=$CERT_ARN,Id=$CORE_ID,SyncShadow=true,ThingArn=$THING_ARN | jq -r '.Arn')
if [ ! -z $CORE_DEFINITION_VERSION_ARN ]
then
echo "The core definition version was created with ARN $CORE_DEFINITION_VERSION_ARN"
else
echo "The core definition version could not be created. Rolling back."
aws iot detach-thing-principal --thing-name $THING_NAME --principal $CERT_ARN
aws iot update-certificate --certificate-id $CERT_ID --new-status INACTIVE
aws iot detach-policy --policy-name $THING_POLICY --target $CERT_ARN
aws iot delete-policy --policy-name $THING_POLICY
aws iot delete-certificate --certificate-id $CERT_ID
aws iot delete-thing --thing-name $THING_NAME
aws greengrass delete-group --group-id $GG_GRP_ID
aws greengrass delete-role --group-id $GG_GRP_ID
aws greengrass delete-core-definition --core-definition-id $CORE_ID
exit
fi
# ----------------------------------------------------------------------------------------
# Greengrass: createGroupVersion
# returns Arn, Id, Version, CreationTimestamp
# ----------------------------------------------------------------------------------------
GROUP_VERSION_ARN=$(aws greengrass create-group-version \
--core-definition-version-arn $CORE_DEFINITION_VERSION_ARN \
--group-id $GG_GRP_ID | jq -r '.Arn')
if [ ! -z $GROUP_VERSION_ARN ]
then
echo "The new group version was created: $GROUP_VERSION_ARN"
else
echo "The new group version could not be created. Rolling back."
aws iot detach-thing-principal --thing-name $THING_NAME --principal $CERT_ARN
aws iot update-certificate --certificate-id $CERT_ID --new-status INACTIVE
aws iot detach-policy --policy-name $THING_POLICY --target $CERT_ARN
aws iot delete-policy --policy-name $THING_POLICY
aws iot delete-certificate --certificate-id $CERT_ID
aws iot delete-thing --thing-name $THING_NAME
aws greengrass disassociate-role-from-group --group-id $GG_GRP_ID
aws greengrass delete-group --group-id $GG_GRP_ID
aws greengrass delete-core-definition --core-definition-id $CORE_ID
exit
fi
# ----------------------------------------------------------------------------------------
# Greengrass: create robot
# ----------------------------------------------------------------------------------------
ROBOT_DETAILS=$(aws robomaker create-robot --name $ROBOT_SN --architecture $ARCH --greengrass-group-id $GG_GRP_ID | jq -r '.')
ROBOT_ARN=$(echo $ROBOT_DETAILS | jq -r '.arn')
if [ ! -z $ROBOT_ARN ]
then
echo "The robot with ARN $ROBOT_ARN was successfully created."
else
echo "The robot could not be created. Rolling back."
aws iot detach-thing-principal --thing-name $THING_NAME --principal $CERT_ARN
aws iot update-certificate --certificate-id $CERT_ID --new-status INACTIVE
aws iot detach-policy --policy-name $THING_POLICY --target $CERT_ARN
aws iot delete-policy --policy-name $THING_POLICY
aws iot delete-certificate --certificate-id $CERT_ID
aws iot delete-thing --thing-name $THING_NAME
aws greengrass disassociate-role-from-group --group-id $GG_GRP_ID
aws greengrass delete-group --group-id $GG_GRP_ID
aws greengrass delete-core-definition --core-definition-id $CORE_ID
exit
fi
# ----------------------------------------------------------------------------------------
# Robomaker: assign robot to new fleet
# Assumes the fleet has already been created (I register all new ones to a new robots fleet)
# ----------------------------------------------------------------------------------------
FLEET_DETAILS=$(aws robomaker register-robot --fleet $FLEET_ARN --robot $ROBOT_ARN | jq -r '.')
FLEET_ARN=$(echo $FLEET_DETAILS | jq -r '.fleet')
if [ ! -z $FLEET_ARN ]
then
echo "The robot was successfully associated with the fleet $FLEET_ARN"
else
echo "The robot could not be associated with the fleet. Rolling back."
aws iot detach-thing-principal --thing-name $THING_NAME --principal $CERT_ARN
aws iot update-certificate --certificate-id $CERT_ID --new-status INACTIVE
aws iot detach-policy --policy-name $THING_POLICY --target $CERT_ARN
aws iot delete-policy --policy-name $THING_POLICY
aws iot delete-certificate --certificate-id $CERT_ID
aws iot delete-thing --thing-name $THING_NAME
aws greengrass disassociate-role-from-group --group-id $GG_GRP_ID
aws greengrass delete-group --group-id $GG_GRP_ID
aws greengrass delete-core-definition --core-definition-id $CORE_ID
aws robomaker delete-robot --robot $ROBOT_ARN
exit
fi
# ----------------------------------------------------------------------------------------
# IoT: add-thing-to-thing-group
# Returns: none
# ----------------------------------------------------------------------------------------
aws add-thing-to-thing-group \
--thing-group-name $IOT_GROUP_NAME \
--thing-group-arn $IOT_GROUP_ARN \
--thing-name $THING_NAME \
--thing-arn $THING_ARN \
--override-dynamic-groups
# ----------------------------------------------------------------------------------------
# IoT: describe-endpoint
# response: endpointAddress
# ----------------------------------------------------------------------------------------
ENDPOINT_ADDR=$(aws iot describe-endpoint --endpoint-type iot:Data-ATS | jq -r '.endpointAddress')
# ----------------------------------------------------------------------------------------
# Create config and save to robot folder
# ----------------------------------------------------------------------------------------
echo "{\"coreThing\":{\"caPath\":\"root.ca.pem\",\"certPath\":\"$ROBOT_SN.cert.pem\",\"ggHost\":\"greengrass-ats.iot.us-east-1.amazonaws.com\",\"iotHost\":\"$ENDPOINT_ADDR\",\"keepAlive\":600,\"keyPath\":\"$ROBOT_SN.private.key\",\"thingArn\":\"$THING_ARN\"},\"crypto\":{\"caPath\":\"file:///greengrass/certs/root.ca.pem\",\"principals\":{\"IoTCertificate\":{\"CertificatePath\":\"file:///greengrass/certs/$ROBOT_SN.cert.pem\",\"PrivateKeyPath\":\"file:///greengrass/certs/$ROBOT_SN.private.key\"},\"SecretsManager\":{\"PrivateKeyPath\":\"file:///greengrass/certs/$ROBOT_SN.private.key\"}}},\"managedRespawn\":false,\"runtime\":{\"allowFunctionsToRunAsRoot\":\"yes\",\"cgroup\":{\"useSystemd\":\"yes\"}}}" > robots/$ROBOT_SN/config/config.json
# # TESTING CLEANUP
# TBD make this into a function that is called on failures
# echo "Starting clean up"
# aws iot detach-thing-principal --thing-name $THING_NAME --principal $CERT_ARN
# aws iot update-certificate --certificate-id $CERT_ID --new-status INACTIVE
# aws iot detach-policy --policy-name $THING_POLICY --target $CERT_ARN
# aws iot delete-policy --policy-name $THING_POLICY
# aws iot delete-certificate --certificate-id $CERT_ID
# aws iot delete-thing --thing-name $THING_NAME
# aws greengrass disassociate-role-from-group --group-id $GG_GRP_ID
# aws greengrass delete-group --group-id $GG_GRP_ID
# aws greengrass delete-core-definition --core-definition-id $CORE_ID
# aws robomaker delete-robot --robot $ROBOT_ARN
# rm -rf $ROBOT_SN
# echo "Finished cleaning up"
@kauffmanes
Copy link
Author

This is a work in progress. I'm trying to figure out everything that Robomaker does when it creates a new robot. Feel free to comment additions and I'll update.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment