Skip to content

Instantly share code, notes, and snippets.

@up209d
Created September 1, 2020 00:49
Show Gist options
  • Save up209d/7f38c7e316f4c688f7dd4f3846454574 to your computer and use it in GitHub Desktop.
Save up209d/7f38c7e316f4c688f7dd4f3846454574 to your computer and use it in GitHub Desktop.
Signed request for AWS Elasticsearch
#!/bin/bash
sha256Hash() {
local output=$(printf "$1" | shasum -a 256)
echo "${output%% *}"
}
hex256() {
printf "$(printf "$1" | od -A n -t x1 | sed -E -e 's/[ \t\n]*//g' | tr -d '\n')\n"
}
hmac_sha256() {
printf "$2" | openssl dgst -binary -hex -sha256 -mac HMAC -macopt hexkey:$1 | sed 's/^.* //'
}
sign() {
hmac_sha256 $(hmac_sha256 $(hmac_sha256 $(hmac_sha256 $(hex256 "AWS4$1") $2) $3) $4) "aws4_request"
}
urlencode_for_hash() {
# Unreserved characters that should not be escaped: ALPHA / DIGIT / "-" / "." / "_" / "~" / "/" / "="
# Spaces should be encoded as %20 instead of +</li>
# Reserved characters that should be escaped include: ? ## [ ] @ ! $ & ' ( ) * + , ;
old_lc_collate=$LC_COLLATE
LC_COLLATE=C
local length="${#1}"
for (( i = 0; i < length; i++ )); do
local c="${1:i:1}"
case $c in
[a-zA-Z0-9\.\~\_\-\/\=]) printf "$c" ;;
*) printf '%%%%%02X' "'$c" ;; # Escape % as we use printf
esac
done
LC_COLLATE=$old_lc_collate
}
SERVICE=es
SERVICE_PROTOCOL=http
SERVICE_HOST=${1}
SERVICE_RESOURCE_PATH=${3:-/}
SERVICE_RESOURCE_PATH_SAFE=$(urlencode_for_hash "${SERVICE_RESOURCE_PATH}")
METHOD=${2:-GET}
QUERY=$4
QUERY_SAFE=$(urlencode_for_hash "${QUERY}")
BODY=${5:-"{}"}
# EXAMPLE
# https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-auth-using-authorization-header.html
# Authorization: AWS4-HMAC-SHA256
# Credential=AKIAIOSFODNN7EXAMPLE/20130524/us-east-1/s3/aws4_request,
# SignedHeaders=host;range;x-amz-date,
# Signature=fe5f80f77d5fa3beca038a248ff027d0445342fe2855ddc963176630326f1024
PAYLOAD_HASH=$(sha256Hash "$BODY")
ISO_TIMESTAMP=$(date -u +%Y%m%dT%H%M%SZ) #20200808T090023Z
DATE_SCOPE=$(date -u +%Y%m%d) #20200808
SIGNED_HEADERS="host;x-amz-date;x-amz-security-token"
CANONICAL_HEADERS=$"host:${SERVICE_HOST}\nx-amz-date:${ISO_TIMESTAMP}\nx-amz-security-token:${AWS_SESSION_TOKEN}\n"
CANONICAL_REQUEST="${METHOD}
${SERVICE_RESOURCE_PATH_SAFE}
${QUERY_SAFE}
${CANONICAL_HEADERS}
${SIGNED_HEADERS}
${PAYLOAD_HASH}"
SIGNING_KEY=$(sign "${AWS_SECRET_ACCESS_KEY}" "${DATE_SCOPE}" "${AWS_REGION}" "${SERVICE}")
SIGNATURE="AWS4-HMAC-SHA256\n${ISO_TIMESTAMP}\n${DATE_SCOPE}/${AWS_REGION}/${SERVICE}/aws4_request\n$(sha256Hash "${CANONICAL_REQUEST}")"
SIGNED_SIGNATURE=$(hmac_sha256 ${SIGNING_KEY} "${SIGNATURE}")
AUTHORIZATION="AWS4-HMAC-SHA256 Credential=${AWS_ACCESS_KEY_ID}/${DATE_SCOPE}/${AWS_REGION}/${SERVICE}/aws4_request, SignedHeaders=${SIGNED_HEADERS}, Signature=${SIGNED_SIGNATURE}"
# printf "${CANONICAL_REQUEST}"
# printf "${QUERY_SAFE}"
RESULT=$(curl -X "${METHOD}" \
-H "Authorization:${AUTHORIZATION}" \
-H "Content-Type:application/json" \
-H "x-amz-date:${ISO_TIMESTAMP}" \
-H "x-amz-security-token:${AWS_SESSION_TOKEN}" \
-d "$BODY" \
"${SERVICE_PROTOCOL}://${SERVICE_HOST}${SERVICE_RESOURCE_PATH}?$(printf "${QUERY_SAFE}")")
if [[ "${RESULT:0:1}" == "{" ]]; then
# Pretty json response and remove all jq color scheme
echo "${RESULT}" | jq . | sed -e "s/\x1B\[([0-9]{1,3}(;[0-9]{1,2})?)?[mGK]//g"
else
echo "${RESULT}"
fi
echo "
REQUEST RETURNED FOR: ${SERVICE_PROTOCOL}://${SERVICE_HOST}${SERVICE_RESOURCE_PATH}?${QUERY}
"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment