Skip to content

Instantly share code, notes, and snippets.

@francesco-racciatti
Last active December 13, 2022 13:18
Show Gist options
  • Save francesco-racciatti/c90a302d1c7b426fa9ac937df369c5a3 to your computer and use it in GitHub Desktop.
Save francesco-racciatti/c90a302d1c7b426fa9ac937df369c5a3 to your computer and use it in GitHub Desktop.
Interact with AWS API via cURL
#!/bin/bash
set -ex
# References:
# - https://docs.aws.amazon.com/general/latest/gr/create-signed-request.html#create-canonical-request
# - https://docs.aws.amazon.com/secretsmanager/latest/apireference/Welcome.html
sha256() {
local data="$1"
echo $(echo -e -n "$data" | openssl dgst -sha256 | sed 's/(stdin)=[[:space:]]//')
}
hmacSha256() {
local key="$1"
local data="$2"
echo $(echo -e -n "$data" | openssl dgst -sha256 -mac HMAC -macopt $key | sed 's/(stdin)=[[:space:]]//')
}
callAwsApi() {
local service="$1"
local target="$2"
local requestPayload="$3"
# Step 0 - Fetch ECS metadata
local metadataHost=$(echo "$ECS_CONTAINER_METADATA_URI_V4" | grep -Eo "([0-9]{1,3}[\.]){3}[0-9]{1,3}")
local ecsSecrets=$(curl http://$metadataHost$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI)
local accessKeyId=$(jq -r '.AccessKeyId' <<< $ecsSecrets)
local secretAccessKey=$(jq -r '.SecretAccessKey' <<< $ecsSecrets)
local token=$(jq -r '.Token' <<< $ecsSecrets)
local amzDateAndTime=$(date -u +"%Y%m%dT%H%M%SZ")
local date=$(date -u +"%Y%m%d")
local region=$AWS_REGION
local host="$service.$region.amazonaws.com"
local endpoint="https://$host/"
# Step 1 - Create Canonical Request
local httpMethod="POST"
local canonicalURI="/"
local canonicalQueryString=""
local canonicalHeaders="content-type:application/x-amz-json-1.1\nhost:$host\nx-amz-date:$amzDateAndTime\nx-amz-security-token:$token\nx-amz-target:$target"
local signedHeaders="content-type;host;x-amz-date;x-amz-security-token;x-amz-target"
local hashedPayload=$(sha256 $requestPayload)
local canonicalRequest="$httpMethod\n$canonicalURI\n$canonicalQueryString\n$canonicalHeaders\n\n$signedHeaders\n$hashedPayload"
# Step 2 - Create a hash of the Canonical Request
local canonicalRequestHash=$(sha256 $canonicalRequest)
# Step 3 - Create the string to sign
local algorithm="AWS4-HMAC-SHA256"
local requestDateTime="$amzDateAndTime"
local credentialScope="$date/$region/$service/aws4_request"
local hashedCanonicalRequest="$canonicalRequestHash"
local stringToSign="$algorithm\n$requestDateTime\n$credentialScope\n$hashedCanonicalRequest"
# Step 4 - Calculate the signature
local kDate=$(hmacSha256 "key:AWS4$secretAccessKey" $date)
local kRegion=$(hmacSha256 "hexkey:$kDate" $region)
local kService=$(hmacSha256 "hexkey:$kRegion" $service)
local kSigning=$(hmacSha256 "hexkey:$kService" "aws4_request")
local signature=$(hmacSha256 "hexkey:$kSigning" "$stringToSign")
# Step 5 - Add the signature to the request
curl -vvv $endpoint \
-X $httpMethod \
-H "content-type: application/x-amz-json-1.1" \
-H "host: $service.$region.amazonaws.com" \
-H "x-amz-date: $amzDateAndTime" \
-H "x-amz-target: $target" \
-H "x-amz-content-sha256: $hashedPayload" \
-H "x-amz-security-token: $token" \
-H "authorization: $algorithm Credential=$accessKeyId/$date/$region/$service/aws4_request, SignedHeaders=content-type;host;x-amz-date;x-amz-security-token;x-amz-target, Signature=$signature" \
-d $requestPayload
}
fetchAsmSecret() {
local secretId="$1"
local service="secretsmanager"
local target="$service.GetSecretValue"
local requestPayload="{\"SecretId\":\"$secretId\"}"
callAwsApi $service $target $requestPayload
}
checkBinaries() {
local binaries=(curl openssl jq)
for b in "${binaries[@]}"
do
if ! command -v $b &> /dev/null
then
echo "$b could not be found"
exit 1
fi
done
}
checkBinaries
fetchAsmSecret $1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment