Skip to content

Instantly share code, notes, and snippets.

@dataday
Created March 23, 2018 13:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dataday/c32d1206da42b60942181430d7665a66 to your computer and use it in GitHub Desktop.
Save dataday/c32d1206da42b60942181430d7665a66 to your computer and use it in GitHub Desktop.
A wrapper to assume a specified role via AWS Security Token Service (STS)
#!/usr/bin/env bash
## A wrapper to assume a specified role via AWS Security Token Service (STS)
#
# Access to some AWS services can require specific role privileges in order to work
# The script requests and returns the AWS credentials needed to perform certain tasks by assuming a specified role
# The script interacts with AWS Security Token Service (STS) in order to assume the desired role
#
# The following command could be used if you wanted to assume the JenkinsAutomationRole to query AWS services
# Please note not all options are required as it will depend on the environment the script is invoked against
#
# $ assume_role.sh --project=nswws --env=stg --region=eu-west-2 --role=JenkinsAutomationRole --output=json
#
# Exports via --output=env:
# AWS_ACCESS_KEY_ID=*, AWS_SECRET_ACCESS_KEY=*, AWS_SESSION_TOKEN=*
#
# Returns via --output=json:
# {"AWS_ACCESS_KEY_ID": "*", "AWS_SECRET_ACCESS_KEY": "*", "AWS_SESSION_TOKEN": "*"}
#
##
EXEC=$(realpath -L "${0#./}")
EXEC_BASE="${EXEC%/*}"
EXEC_NAME=$(basename "$EXEC")
# set defaults
PROJECT_REGION="eu-west-2"
PROJECT_NAME="nswws"
PROJECT_ENVIRONMENT="stg"
PROJECT_ROLE="JenkinsAutomationRole"
declare -a AWS_ACCOUNTS
AWS_OUTPUT="env"
AWS_ACCOUNTS=(["stg"]="" ["dev"]="" ["prd"]="")
AWS_SESSION_TIMEOUT=3600
# displays usage information
function usage () {
printf %s "Usage: $EXEC_NAME [--region=REGION --project=PROJECT --env=ENV --role=ROLE --output=(json|env)]
A wrapper to AWS assume role services
Options:
--region - AWS region, default: eu-west-2
--project - Project name, default: nswws
--env - Project environment, default: stg
--role - Project Role, default: JenkinsAutomationRole
--output - Specified output type (env|json), default: env
" 1>&2
exit $?
}
# checks for options
if (($# == 0)); then
usage
fi
# assumes specified role via the AWS Security Token Service (STS)
function assume_role () {
# print without line breaks and search and replace single quotes for double
local json="$(printf %s ${1//\'/\"})"
# confirm the OS the script is running under (detects quasi-unix under windows)
[[ `uname` = "MINGW64"* ]] && exec="aws.cmd" || exec="aws"
# calls AWS Security Token Service (STS) to assume a specified role
printf %s $("$exec" sts assume-role --region "$PROJECT_REGION" --cli-input-json "$json")
}
# gets credentials information from the AWS assume role response
function get_credential () {
local exec=$(which python)
# ensure exports of credential data are kept private during execution
printf %s $(
export KEY="$1"
export VAL="$2"
"$exec" -c "import json,os;k=os.environ['KEY'];v=os.environ['VAL'];obj=json.loads(v);res=obj.get('Credentials');print(res.get(k,''))"
)
}
# assigns supported options
while getopts ":-:" opt; do
case "$opt" in
-)
case $OPTARG in
region=*) PROJECT_REGION="${OPTARG#*=}";;
project=*) PROJECT_NAME="${OPTARG#*=}";;
env=*) PROJECT_ENVIRONMENT="${OPTARG#*=}";;
role=*) PROJECT_ROLE="${OPTARG#*=}";;
output=*) AWS_OUTPUT="${OPTARG#*=}";;
esac
;;
\?) log "error: -$OPTARG" && usage;;
*) usage;;
esac
done
# initiate
function init () {
AWS_ACCOUNT="${AWS_ACCOUNTS[$ENVIRONMENT]}"
AWS_INPUT="{
'RoleArn': 'arn:aws:iam::$AWS_ACCOUNT:role/$PROJECT_ROLE',
'RoleSessionName': 'jenkins-$(date +%s)',
'DurationSeconds': $AWS_SESSION_TIMEOUT
}"
# executes AWS CLI request to assume a specified role
local credentials=$(assume_role "$AWS_INPUT")
if [[ -n "$credentials" ]]; then
# assigns AWS specific credentials
local ACCESS_KEY_ID=$(get_credential "AccessKeyId" "$credentials")
local SECRET_ACCESS_KEY=$(get_credential "SecretAccessKey" "$credentials")
local SESSION_TOKEN=$(get_credential "SessionToken" "$credentials")
case "$AWS_OUTPUT" in
# exports AWS specific environment variables
"env")
export AWS_ACCESS_KEY_ID="$ACCESS_KEY_ID"
export AWS_SECRET_ACCESS_KEY="$SECRET_ACCESS_KEY"
export AWS_SESSION_TOKEN="$SESSION_TOKEN"
;;
# prints JSON formatted credentials
"json")
local json="{
'AWS_ACCESS_KEY_ID': '$ACCESS_KEY_ID',
'AWS_SECRET_ACCESS_KEY': '$SECRET_ACCESS_KEY',
'AWS_SESSION_TOKEN': '$SESSION_TOKEN'
}"
# print without line breaks and search and replace single quotes for double
printf %s ${json//\'/\"}
;;
# default
*)
printf %s "error: unsupported output $AWS_OUTPUT"
exit 1
esac
fi
}
init
exit $?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment