지난번에 게시한 AWS Signature v4를 이용한 S3 객체 다운로드/업로드의 ShellScript도 함께 작성하게 되었다.
(AWS Signature 소개 및 PowerShell 버전 참조)
ShellScript 버전은 PowerShell보다 참조할 자료가 많아 AWS4-HMAC-SHA256 알고리즘 구현이 쉬웠고, 필요했던 기능인 s3에 대해서만 객체 다운로드/업로드 기능을 구현했다.
#!bin/bash ## Set my credential ## ACCESS_KEY=############### SECRET_KEY=######################### REGION=ap-northeast-2 urlEncode() { LINE="$1" LENGTH="${#LINE}" I=0 while [ $I -lt $LENGTH ] do C="${LINE:I:1}" case $C in [a-zA-Z0-9.~_-]) printf "$C" ;; *) printf '%%%02X' "'$C" ;; esac let I=I+1 done } getHexaDecimalString() { read LINE LENGTH="${#LINE}" I=0 while [ $I -lt $LENGTH ] do C="${LINE:I:1}" printf '%2x' "'$C" let I=I+1 done } getSignatureKey() { SECRET_KEY=$1 DATESTAMP=$2 REGIONNAME=$3 SERVICENAME=$4 STRING_TO_SIGN=$5 HEX_KEY=$(echo -n "AWS4${SECRET_KEY}" | getHexaDecimalString) HEX_KEY=$(echo -n "${DATESTAMP}" | openssl dgst -sha256 -mac HMAC -macopt hexkey:${HEX_KEY}) HEX_KEY=$(echo -n "${REGIONNAME}" | openssl dgst -sha256 -mac HMAC -macopt hexkey:${HEX_KEY#* }) HEX_KEY=$(echo -n "${SERVICENAME}" | openssl dgst -sha256 -mac HMAC -macopt hexkey:${HEX_KEY#* }) SIGNING_KEY=$(echo -n "aws4_request" | openssl dgst -sha256 -mac HMAC -macopt hexkey:${HEX_KEY#* }) SIGNATURE=$(echo -en "${STRING_TO_SIGN}" | openssl dgst -binary -hex -sha256 -mac HMAC -macopt hexkey:${SIGNING_KEY#* }) echo "${SIGNATURE#* }" } getHexaHash() { PAYLOAD="$@" HASH=$(echo -n "${PAYLOAD}" | openssl dgst -sha256) echo "${HASH#* }" } ### Main ### if [ -z $REGION ] || [ -z $ACCESS_KEY ] || [ -z $SECRET_KEY ] then echo "Please set ACCESS_KEY, SECRET_KEY and REGION variables" exit 1 fi AK="$ACCESS_KEY" SK="$SECRET_KEY" REGION="$REGION" [ $# -ne 8 ] && exit 2 while getopts ":m:b:k:e:" OPT; do case $OPT in m) HTTPMETHOD=$OPTARG # GET or PUT ;; b) BUCKET=$OPTARG ;; k) S3KEY=$OPTARG ;; e) EXPIRES=$OPTARG ;; *) echo "Invalid option: -$OPTARG" >&2 exit 3 ;; esac done SERVICENAME="s3" HOST="${BUCKET}.${SERVICENAME}.${REGION}.amazonaws.com" ENDPOINT="https://${BUCKET}.${SERVICENAME}.${REGION}.amazonaws.com" # step 1. Create a Canonical request AMZ_DATE=$(date -u +%Y%m%dT%H%M%SZ) DATESTAMP=$(date -u +%Y%m%d) AMZ_EXPIRES=$((${EXPIRES}*60)) # min CANONICAL_URI="/${S3KEY}" CANONICAL_HEADERS="host:${HOST}\n" SIGNED_HEADERS="host" PAYLOAD_HASH="UNSIGNED-PAYLOAD" ALGORITHM="AWS4-HMAC-SHA256" CREDENTIAL_SCOPE="${DATESTAMP}/${REGION}/${SERVICENAME}/aws4_request" CANONICAL_QUERYSTRING="X-Amz-Algorithm=${ALGORITHM}" CANONICAL_QUERYSTRING="${CANONICAL_QUERYSTRING}&X-Amz-Credential=$(urlEncode "${AK}/${CREDENTIAL_SCOPE}")" CANONICAL_QUERYSTRING="${CANONICAL_QUERYSTRING}&X-Amz-Date=${AMZ_DATE}" CANONICAL_QUERYSTRING="${CANONICAL_QUERYSTRING}&X-Amz-Expires=${AMZ_EXPIRES}" CANONICAL_QUERYSTRING="${CANONICAL_QUERYSTRING}&X-Amz-SignedHeaders=${SIGNED_HEADERS}" CANONICAL_REQUEST="${HTTPMETHOD}\n${CANONICAL_URI}\n${CANONICAL_QUERYSTRING}\n${CANONICAL_HEADERS}\n${SIGNED_HEADERS}\n${PAYLOAD_HASH}" # step 2. String To Sign STRING_TO_SIGN="${ALGORITHM}\n${AMZ_DATE}\n${CREDENTIAL_SCOPE}\n$(getHexaHash "$(echo -e "${CANONICAL_REQUEST}")")" # step 3. Signature SIGNATURE="$(getSignatureKey $SK $DATESTAMP $REGION $SERVICENAME $STRING_TO_SIGN)" # step 4. Create a request URL CANONICAL_QUERYSTRING="${CANONICAL_QUERYSTRING}&X-Amz-Signature=${SIGNATURE}" REQUEST_URL=${ENDPOINT}/${S3KEY}?${CANONICAL_QUERYSTRING} CLI="curl $(if [[ "$HTTPMETHOD" == "GET" ]]; then echo "-o"; else echo "-T"; fi) \"${S3KEY##*/}\" \"$REQUEST_URL\"" echo "$CLI"
사용방법은 ACCESS_KEY, SECRET_KEY, REGION 값을 자신의 설정에 알맞게 입력하고 쉘 스크립트 실행 시 argument 값을 각각 지정하면 해당 파라미터에 대해 curl + Request URL을 출력한다.
실행 시 입력해야 하는 argument 목록은 다음과 같다.
Argument | Value |
m (method) | GET 또는 PUT (다운로드/업로드) |
b (bucket) | Bucket Name |
k (key) | Key Name |
e (expires) | 120 (분) |
(ex. bash s3web.sh -m GET -b s3-mybucket -k mydir/myobj -e 120)
PowerShell 버전과는 달리 실행 시 인자 값을 입력받도록 했는데, 필요에 따라 입력받는 부분을 고정 값으로 변경하여 사용하면 된다.
만약 Request URL 실행문을 출력하는 대신 스크립트 자체에서 실행되도록 하고 싶다면 마지막 줄에 eval "${CLI}" 를 추가하도록 한다.