Skip to content

Instantly share code, notes, and snippets.

@ansemjo
Forked from chrismdp/s3.sh
Last active November 25, 2022 07:18
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ansemjo/cc113ced5d133c018e95079ddb003bb0 to your computer and use it in GitHub Desktop.
Save ansemjo/cc113ced5d133c018e95079ddb003bb0 to your computer and use it in GitHub Desktop.
uploading files to S3 in shell with a little bit of curl and openssl
#!/usr/bin/env bash
# https://gist.github.com/ansemjo/cc113ced5d133c018e95079ddb003bb0
set -e -o pipefail
usage() { cat >&2 <<USAGE
usage: s3put [-a acl] [-p pinnedkey] [-h] endpoint file objectpath
-a acl : use a different acl for uploaded files
-p pinnedkey : sha256 pinned public key for certificate validation
-h : display this help
endpoint : endpoint url, e.g. https://s3.exmaple.com:9000
file : path to local file
objectpath : path to remote file
USAGE
}
err() { echo "err: $1" >&2; usage; }
# parse commandline options
while getopts ":a:p:h" OPT; do
case "$OPT" in
a) # use a different ACL
export ACL="$OPTARG" ;;
p) # pinned public key:
# curl "${1:?url required}" --ssl --pinnedpubkey sha256//invalid -kv 2>&1 | sed -n 's/.*public key hash: //p'
export PINNEDPUBKEY="$OPTARG" ;;
h) # display help
usage; exit 0 ;;
\?) # unknown option
err "invalid option: $OPT"; exit 1 ;;
:) # missing argument
err "invalid option: $OPT requires an argument"; exit 1 ;;
esac
done
shift $((OPTIND-1))
# remaining required arguments
ENDPOINT=$1
FILE=$2
OBJECTPATH=$3
if [[ ! $ENDPOINT ]] || [[ ! $FILE ]] || [[ ! $OBJECTPATH ]]; then
err "three arguments required"
exit 1
fi
# ACCESS_KEY and SECRET_KEY are required in environment
if [[ ! ${ACCESS_KEY+defined} ]] || [[ ! ${SECRET_KEY+defined} ]]; then
err "ACCESS_KEY and SECRET_KEY are required in env"
exit 1
fi
# prepare for object upload
# see: https://gist.github.com/chrismdp/6c6b6c825b07f680e710
ACL="${ACL:-x-amz-acl:public-read}"
CONTENTTYPE="application/octet-stream"
DATE="$(LC_ALL=en_US.utf8 date --utc +'%a, %d %b %Y %T %z')"
STRING="PUT\n\n$CONTENTTYPE\n$DATE\n$ACL\n/$OBJECTPATH"
SIGNATURE="$(echo -ne "$STRING" | openssl dgst -sha1 -hmac "$SECRET_KEY" -binary | openssl base64)"
# upload with curl
curl -f -X PUT -T "$FILE" \
-H "Host: $(basename "$ENDPOINT")" \
-H "Date: $DATE" \
-H "Content-Type: $CONTENTTYPE" \
-H "$ACL" \
-H "Authorization: AWS $ACCESS_KEY:$SIGNATURE" \
$([[ ${PINNEDPUBKEY+defined} ]] && echo -k --pinnedpubkey "$PINNEDPUBKEY") \
"$ENDPOINT/$OBJECTPATH" >/dev/null
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment