#!/bin/sh -u | |
fileLocal="${1:-example-local-file.ext}" | |
bucket="${2:-example-bucket}" | |
remotePath="${3:-remote-path}" | |
region="${4:-}" | |
awsAccess="${5:-YOUR_AWS_ACCESS_KEY}" | |
awsSecret="${6:-YOUR_AWS_SECRET_KEY}" | |
m_openssl() { | |
if [ -f /usr/local/opt/openssl@1.1/bin/openssl ]; then | |
/usr/local/opt/openssl@1.1/bin/openssl "$@" | |
elif [ -f /usr/local/opt/openssl/bin/openssl ]; then | |
/usr/local/opt/openssl/bin/openssl "$@" | |
else | |
openssl "$@" | |
fi | |
} | |
m_sed() { | |
if which gsed > /dev/null 2>&1; then | |
gsed "$@" | |
else | |
sed "$@" | |
fi | |
} | |
awsStringSign4() { | |
kSecret="AWS4$1" | |
kDate=$(printf '%s' "$2" | m_openssl dgst -sha256 -hex -mac HMAC -macopt "key:${kSecret}" 2>/dev/null | m_sed 's/^.* //') | |
kRegion=$(printf '%s' "$3" | m_openssl dgst -sha256 -hex -mac HMAC -macopt "hexkey:${kDate}" 2>/dev/null | m_sed 's/^.* //') | |
kService=$(printf '%s' "$4" | m_openssl dgst -sha256 -hex -mac HMAC -macopt "hexkey:${kRegion}" 2>/dev/null | m_sed 's/^.* //') | |
kSigning=$(printf 'aws4_request' | m_openssl dgst -sha256 -hex -mac HMAC -macopt "hexkey:${kService}" 2>/dev/null | m_sed 's/^.* //') | |
signedString=$(printf '%s' "$5" | m_openssl dgst -sha256 -hex -mac HMAC -macopt "hexkey:${kSigning}" 2>/dev/null | m_sed 's/^.* //') | |
printf '%s' "${signedString}" | |
} | |
iniGet() { | |
# based on: https://stackoverflow.com/questions/22550265/read-certain-key-from-certain-section-of-ini-file-sed-awk#comment34321563_22550640 | |
printf '%s' "$(m_sed -n -E "/\[$2\]/,/\[.*\]/{/$3/s/(.*)=[ \\t]*(.*)/\2/p}" "$1")" | |
} | |
# Initialize defaults | |
fileRemote="${remotePath}/${fileLocal}" | |
echo "Downloading" "${fileLocal}" "->" "${bucket}" "${region}" | |
echo "| $(uname) | $(m_openssl version) " | |
# Initialize helper variables | |
httpReq='GET' | |
authType='AWS4-HMAC-SHA256' | |
service="s3" | |
baseUrl=".${service}.amazonaws.com" | |
dateValueS=$(date -u +'%Y%m%d') | |
dateValueL=$(date -u +'%Y%m%dT%H%M%SZ') | |
if hash file 2>/dev/null; then | |
contentType="$(file -b --mime-type "${fileLocal}")" | |
else | |
contentType='application/octet-stream' | |
fi | |
# 0. Hash empty string | |
payloadHash=$(printf "" | m_openssl dgst -sha256 -hex 2>/dev/null | m_sed 's/^.* //') | |
# 1. Create canonical request | |
# NOTE: order significant in ${headerList} and ${canonicalRequest} | |
headerList='content-type;host;x-amz-content-sha256;x-amz-date' | |
canonicalRequest="\ | |
${httpReq} | |
/${fileRemote} | |
content-type:${contentType} | |
host:${bucket}${baseUrl} | |
x-amz-content-sha256:${payloadHash} | |
x-amz-date:${dateValueL} | |
${headerList} | |
${payloadHash}" | |
# Hash it | |
canonicalRequestHash=$(printf '%s' "${canonicalRequest}" | m_openssl dgst -sha256 -hex 2>/dev/null | m_sed 's/^.* //') | |
# 2. Create string to sign | |
stringToSign="\ | |
${authType} | |
${dateValueL} | |
${dateValueS}/${region}/${service}/aws4_request | |
${canonicalRequestHash}" | |
# 3. Sign the string | |
signature=$(awsStringSign4 "${awsSecret}" "${dateValueS}" "${region}" "${service}" "${stringToSign}") | |
# Upload | |
curl -s -L --proto-redir =https -X "${httpReq}" \ | |
-H "Content-Type: ${contentType}" \ | |
-H "Host: ${bucket}${baseUrl}" \ | |
-H "X-Amz-Content-SHA256: ${payloadHash}" \ | |
-H "X-Amz-Date: ${dateValueL}" \ | |
-H "Authorization: ${authType} Credential=${awsAccess}/${dateValueS}/${region}/${service}/aws4_request, SignedHeaders=${headerList}, Signature=${signature}" \ | |
"https://${bucket}${baseUrl}/${fileRemote}" -o "${fileLocal}" | |
echo "https://${bucket}${baseUrl}/${fileRemote}" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment