Skip to content

Instantly share code, notes, and snippets.

@MathiasKoch
Last active April 25, 2023 05:45
Show Gist options
  • Save MathiasKoch/19161eb3c8ce137bfcdbdafc614caf6e to your computer and use it in GitHub Desktop.
Save MathiasKoch/19161eb3c8ce137bfcdbdafc614caf6e to your computer and use it in GitHub Desktop.
Migrate `Device` DynamoDB table in mgmt account to support new Duo v2
#!/usr/bin/env bash
declare -gA CRED_MAP=()
assume_role() {
CREDENTIALS=`aws sts assume-role --role-arn arn:aws:iam::$1:role/ExternalAccessProvisionIoT --role-session-name "VERSION-MIGRATION" --duration-seconds 3600 --output=json`
AWS_ACCESS_KEY_ID=`echo ${CREDENTIALS} | jq -r '.Credentials.AccessKeyId'`
AWS_SECRET_ACCESS_KEY=`echo ${CREDENTIALS} | jq -r '.Credentials.SecretAccessKey'`
AWS_SESSION_TOKEN=`echo ${CREDENTIALS} | jq -r '.Credentials.SessionToken'`
AWS_EXPIRATION=`echo ${CREDENTIALS} | jq -r '.Credentials.Expiration'`
echo "AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN=$AWS_SESSION_TOKEN AWS_EXPIRATION=$AWS_EXPIRATION"
}
DRY_RUN=0
DEVICES=`aws dynamodb scan --table-name Devices --no-paginate --filter-expression 'attribute_not_exists(hardwareMinor) AND deviceType = :devType' --expression-attribute-values '{":devType":{"S":"FbDuo"}}' | jq '.Items'`
TOTAL=`echo $DEVICES | jq 'length'`
I=0
for UUID in $(echo $DEVICES | jq '.[] | .uuid.S' | xargs); do
((I=I+1))
echo -n "[$I/$TOTAL] Running migration for $UUID.. "
VERSION=`echo $DEVICES | jq -r --arg uuid $UUID '.[] | select(.uuid.S == $uuid) | .hardwareVersion.S'`
MINOR=`echo $DEVICES | jq -r --arg uuid $UUID '.[] | select(.uuid.S == $uuid) | .hardwareMinor.S // empty'`
CLAIMED_BY_ACC=`echo $DEVICES | jq -r --arg uuid $UUID '.[] | select(.uuid.S == $uuid) | .claimedBy.M.awsAcc.S // empty'`
if [[ -z "$MINOR" ]]; then
IFS=._ read -r MAJOR MINOR <<< $VERSION
else
echo -e "\xE2\x98\x85"
continue
fi
# Validate MAJOR & MINOR
if [[ -z "$MAJOR" ]]; then
>&2 echo "MAJOR NOT SET?!"
echo -e "\xE2\x9D\x8C"
continue
fi
if [[ -z "$MINOR" ]]; then
>&2 echo "MINOR NOT SET"
fi
# Strip prefixed 'v' if it exists, as we add that to all instances upon insert
MAJOR=${MAJOR#"v"}
UPDATE_EXPR="SET hardwareVersion = :hardwareVersion, hardwareMinor = :hardwareMinor"
EXPR_ATTR_VALUES="{\":hardwareVersion\":{\"S\":\"v$MAJOR\"},\":hardwareMinor\":{\"S\":\"$MINOR\"}"
if [[ ! -z "$CLAIMED_BY_ACC" ]]; then
if [[ -v CRED_MAP["$CLAIMED_BY_ACC"] ]]; then
CREDS=`echo "${CRED_MAP[$CLAIMED_BY_ACC]}"`
else
CREDS=`assume_role $CLAIMED_BY_ACC`
CRED_MAP+=(["$CLAIMED_BY_ACC"]="$CREDS")
fi
STATUS=`export $CREDS; aws iot-data get-thing-shadow --thing-name $UUID --shadow-name status shadow 2>/dev/null && jq '.state.reported.firmware_versions' shadow && rm shadow`
if [ $? -ne 0 ]; then
# "No status shadow found. Checking S3 healthdump.."
OBJECTS=`export $CREDS; aws s3 ls s3://$CLAIMED_BY_ACC-eu-west-1-duo-healthdump/fbduo/status/$UUID/ 2>/dev/null`
if [ $? -eq 0 ]; then
if [ "$(echo $OBJECTS | wc -l)" == "1000" ]; then
echo "MORE THAN ONE PAGE FOUND?!"
fi
LATEST=`echo $OBJECTS | tail -n 1 | awk '{print $4}'`
FIRMWARE=`export $CREDS; aws s3 cp --quiet s3://$CLAIMED_BY_ACC-eu-west-1-duo-healthdump/fbduo/status/$UUID/$LATEST version.txt && jq -r '.version | "\(.[2]).\(.[1]).\(.[0])"' version.txt && rm version.txt`
fi
BOOTLOADER="2.0.0"
else
FIRMWARE=`echo $STATUS | jq -r '.application'`
BOOTLOADER=`echo $STATUS | jq -r '.bootloader'`
WIFI=`echo $STATUS | jq -r '.wifi // empty'`
fi
UPDATE_EXPR="$UPDATE_EXPR, firmwareVersions = :firmwareVersions"
EXPR_ATTR_VALUES="$EXPR_ATTR_VALUES,\":firmwareVersions\":{\"M\":{\"application\":{\"S\":\"$FIRMWARE\"},\"bootloader\":{\"S\":\"$BOOTLOADER\"}"
if [[ ! -z "$WIFI" ]]; then
EXPR_ATTR_VALUES="$EXPR_ATTR_VALUES,\"wifi\":{\"S\":\"$WIFI\"}"
fi
EXPR_ATTR_VALUES="$EXPR_ATTR_VALUES}}"
fi
EXPR_ATTR_VALUES="$EXPR_ATTR_VALUES}"
if [[ $DRY_RUN == "1" ]]; then
echo -e "\n"
# echo $UPDATE_EXPR
echo $EXPR_ATTR_VALUES
echo -e "\n"
else
aws dynamodb update-item --table-name Devices --key "{\"uuid\": {\"S\": \"$UUID\"}}" --update-expression "$UPDATE_EXPR" --expression-attribute-values "$EXPR_ATTR_VALUES"
fi
if [ $? -ne 0 ]; then
echo -e "\xE2\x9D\x8C"
else
echo -e "\xE2\x9C\x94"
fi
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment