From 3157ac76aa6d9233510c767298daa159800eced8 Mon Sep 17 00:00:00 2001 From: Virgil Date: Mon, 15 Jul 2019 01:44:39 +1000 Subject: [PATCH] Change PROFILE to AWS_PROFILE Support official AWSCLI environment variables AWS_DEFAULT_PROFILE and AWS_SHARED_CREDENTIALS_FILE. Use integers and arithmatic for show* variables. Add short options to README.md --- README.md | 71 +++++++++++--------- get-aws-profile.sh | 157 +++++++++++++++++++++++++++------------------ 2 files changed, 136 insertions(+), 92 deletions(-) diff --git a/README.md b/README.md index cd030f1..ee9e970 100644 --- a/README.md +++ b/README.md @@ -6,56 +6,69 @@ ## Fetch AWS keys and secrets from a AWS credentials file -This is a pure bash script that can parse and extract AWS credentials (key id and secret) from a `~/.aws/credentials` file. +This is a pure bash script that can parse and extract AWS credentials (access_key and secret) from a `~/.aws/credentials` file. -```bash -$ ./get-aws-profile.sh --help -Usage: ./get-aws-profile.sh [--credentials=] [--profile=] [--key|--secret|--session-token] +```console +$ get-aws-profile.sh --help +Usage: get-aws-profile.sh [--credentials=] [--profile=] [--key|--secret|--session-token] - Default --credentials is '~/.aws/credentials' - Default --profile is 'default' +Options: + -p, --profile use profile + -f, --credentials read credentials from specified file + -k, --key get value of aws_access_key_id + -s, --secret get value of aws_secret_access_key + -t, --session-token get value of aws_session_token + -h, --help display this help text - By default environment variables are generated, e.g. - source $(./get-aws-profile.sh --profile=myprofile) +Default --credentials is '$AWS_SHARED_CREDENTIALS_FILE' or '~/.aws/credentials' +Default --profile is '$AWS_DEFAULT_PROFILE' or 'default' + +To generate environment variables for profile myprofile: + + $ source $(get-aws-profile.sh --profile=myprofile) + +You can specify one of --key, --secret or --session-token to +get just that value, with no line break: + + $ FOO_KEY=$(get-aws-profile.sh --profile myprofile --key) + $ FOO_SECRET=$(get-aws-profile.sh -p myprofile -s) + $ FOO_SESSION_TOKEN=$(get-aws-profile.sh -t --profile=myprofile) - You can specify one of --key, --secret, -or --session-token to get just that value, with no line break: - FOO_KEY=$(./get-aws-profile.sh --profile=myprofile --key) - FOO_SECRET=$(./get-aws-profile.sh --profile=myprofile --secret) - FOO_SESSION_TOKEN=$(./get-aws-profile.sh --profile=myprofile --session-token) ``` ## Examples -### Set environment variables for 'my-example' profile +### Set AWS environment variables for 'my-example' profile -```bash -$ ./get-aws-profile.sh --profile my-example +```console +$ get-aws-profile.sh --profile=my-example export AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE export AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - -$ eval $(./get-aws-profile.sh --profile my-example) +export AWS_SESSION_TOKEN=IYWKfEIM7SwWerymB0KpQLIKXeE6jBtX1iGKXVqHVEXAMPLETOKEN +$ source $(get-aws-profile.sh --profile=my-example) ``` -## Get key and secret for 'my-example' profile +### Get key and secret for 'my-example' profile -```bash -$ ./get-aws-profile.sh --profile my-example --key +```console +$ get-aws-profile.sh --profile=my-example --key AKIAIOSFODNN7EXAMPLE -$ ./get-aws-profile.sh --profile my-example --secret +$ get-aws-profile.sh --profile=my-example --secret wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY -$ export AWS_ACCESS_KEY_ID=$(./get-aws-profile.sh --profile my-example --key) -$ export AWS_SECRET_ACCESS_KEY=$(./get-aws-profile.sh --profile my-example --secret) +$ export AWS_DEFAULT_PROFILE=my-example +$ export AWS_ACCESS_KEY_ID=$(get-aws-profile.sh --key) +$ export AWS_SESSION_TOKEN=$(get-aws-profile.sh --session-token) ``` -## Get key and secret for 'default' profile from a custom 'ini' file +### Get key and secret for 'default' profile from a custom 'ini' file -```bash -$ ./get-aws-profile.sh --credentials /foo/bar/my-creds-file --key +```console +$ get-aws-profile.sh --credentials=/foo/bar/my-creds-file --key AKIAIOSFODNN7EXAMPLE -$ ./get-aws-profile.sh --credentials /foo/bar/my-creds-file --secret +$ get-aws-profile.sh --credentials=/foo/bar/my-creds-file --secret wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY ``` @@ -77,9 +90,9 @@ aws_secret_access_key=je7MtGbClwBF/2Zp9Utk/h3yCo8nvbEXAMPLEKEY I often need to include an AWS key id and secret in deployment scripts. Yet I don't want to actually include the credentials in the script or in the git repository. -Many AWS client tools support storing AWS credentials in the `~/.aws/credentials` file and using a `--profile` argument or `AWS_DEFAULT_PROFILE` environment variable. However other tools only work by setting the `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` environment variables. Sometimes you need to inject these credentials into stored secrets or configurations. +Many AWS client tools support storing AWS credentials in the `~/.aws/credentials` file and using a `--profile` argument or `AWS_DEFAULT_PROFILE` / `AWS_PROFILE` environment variable. However other tools only work by setting the `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` environment variables. Sometimes you need to inject these credentials into stored secrets or configurations. -This script helps script these tasks whilst keeping the credentials out of your scripts and repository. I wanted a pure bash solution I could include in automated build and deployment environments. +This script helps automate these tasks whilst keeping the credentials out of your scripts and repository. I wanted a pure bash solution I could include in automated build and deployment environments. ## Credits diff --git a/get-aws-profile.sh b/get-aws-profile.sh index 44040fe..e55ea0e 100755 --- a/get-aws-profile.sh +++ b/get-aws-profile.sh @@ -9,13 +9,13 @@ set -o nounset # Trigger error when expanding unset variables 'set -u' set -o pipefail # Do not hide errors within pipes 'set -o pipefail' IFS=$'\n\t' +script_name="${0##*/}" # -# Fetch the AWS access key and/or secret for an AWS profile +# Fetch the AWS access_key and/or secret from an AWS profile # stored in the ~/.aws/credentials file ini format # # Aaron Roydhouse , 2017 # https://github.com/whereisaaron/get-aws-profile-bash/ -# # # cfg_parser - Parse and ini files into variables @@ -25,28 +25,25 @@ IFS=$'\n\t' # http://pastebin.com/f61ef4979 (original) # http://pastebin.com/m4fe6bdaf (supports spaces in values) # - -# shellcheck disable=SC2206 +# shellcheck disable=SC2206,SC2116 cfg_parser () { - # IFS=$'\n' && ini=( $(<$1) ) # convert to line-array - mapfile ini <"${1:?Missing INI filename}" - ini=( ${ini[*]//;*/} ) # remove comments ; - ini=( ${ini[*]//\#*/} ) # remove comments # - ini=( ${ini[*]/\ =/=} ) # remove tabs before = - ini=( ${ini[*]/=\ /=} ) # remove tabs be = - ini=( ${ini[*]/\ *=\ /=} ) # remove anything with a space around = - ini=( ${ini[*]/#[/\}$'\n'cfg.section.} ) # set section prefix - ini=( ${ini[*]/%]/ \(} ) # convert text2function (1) - ini=( ${ini[*]/=/=\( } ) # convert item to array - ini=( ${ini[*]/%/ \)} ) # close array parenthesis - ini=( ${ini[*]/%\\ \)/ \\} ) # the multiline trick - ini=( ${ini[*]/%\( \)/\(\) \{} ) # convert text2function (2) - ini=( ${ini[*]/%\} \)/\}} ) # remove extra parenthesis - ini[0]="" # remove first element - ini[${#ini[*]} + 1]='}' # add the last brace - # shellcheck disable=SC2116 - eval "$(echo "${ini[*]}")" # eval the result + mapfile ini < "${1:?Missing INI filename}" # convert to line-array + ini=(${ini[*]//;*/}) # remove comments ; + ini=(${ini[*]//\#*/}) # remove comments # + ini=(${ini[*]/\ =/=}) # remove tabs before = + ini=(${ini[*]/=\ /=}) # remove tabs be = + ini=(${ini[*]/\ *=\ /=}) # remove anything with a space around = + ini=(${ini[*]/#[/\}$'\n'cfg.section.}) # set section prefix + ini=(${ini[*]/%]/ \(}) # convert text2function (1) + ini=(${ini[*]/=/=\( }) # convert item to array + ini=(${ini[*]/%/ \)}) # close array parenthesis + ini=(${ini[*]/%\\ \)/ \\}) # the multiline trick + ini=(${ini[*]/%\( \)/\(\) \{}) # convert text2function (2) + ini=(${ini[*]/%\} \)/\}}) # remove extra parenthesis + ini[0]="" # remove first element + ini[${#ini[*]} + 1]='}' # add the last brace + eval "$(echo "${ini[*]}")" # eval the result } # echo a message to standard error (used for messages not intended @@ -56,58 +53,92 @@ echo_stderr () printf '%s\n' "$@" >&2 } +# +# Set defaults +# See https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html +# +declare AWS_PROFILE CREDENTIALS +declare aws_access_key_id aws_secret_access_key aws_session_token +declare -i show_key show_secret show_session_token + +CREDENTIALS="${AWS_SHARED_CREDENTIALS_FILE:-"$HOME/.aws/credentials"}" +AWS_PROFILE=${AWS_PROFILE:-${AWS_DEFAULT_PROFILE:-default}} +show_key=0 +show_secret=0 +show_session_token=0 + # # Parse options # display_usage () { - echo_stderr "Usage: $0 [--credentials=] [--profile=] [--key|--secret|--session-token]" - echo_stderr "" - echo_stderr " Default --credentials is '${HOME}/.aws/credentials'" - echo_stderr " Default --profile is 'default'" - echo_stderr "" - echo_stderr " By default environment variables are generated, e.g." - echo_stderr " source \$($0 --profile=${PROFILE:-myprofile})" - echo_stderr "" - echo_stderr " You can specify one of --key, --secret, -or --session-token to get just that value, with no line break:" - echo_stderr " FOO_KEY=\$($0 --profile=${PROFILE:-myprofile} --key)" - echo_stderr " FOO_SECRET=\$($0 --profile=${PROFILE:-myprofile} --secret)" - echo_stderr " FOO_SESSION_TOKEN=\$($0 --profile=${PROFILE:-myprofile} --session-token)" + echo_stderr "Usage: $script_name [--credentials=] [--profile=] [--key|--secret|--session-token] + + +Options: + -p, --profile use profile + -f, --credentials read credentials from specified file + -k, --key get value of aws_access_key_id + -s, --secret get value of aws_secret_access_key + -t, --session-token get value of aws_session_token + -h, --help display this help text + +Default --credentials is '\$AWS_SHARED_CREDENTIALS_FILE' or '~/.aws/credentials' +Default --profile is '\$AWS_DEFAULT_PROFILE' or 'default' + +To generate environment variables for profile myprofile: + + \$ source \$($script_name --profile=myprofile) + +You can specify one of --key, --secret or --session-token to +get just that value, with no line break: + + \$ FOO_KEY=\$($script_name --profile myprofile --key) + \$ FOO_SECRET=\$($script_name -p myprofile -s) + \$ FOO_SESSION_TOKEN=\$($script_name -t --profile=myprofile)" } for i in "$@" do case $i in - -c=*|-f=*|--credentials=*) + --credentials=*) CREDENTIALS="${i#*=}" shift # past argument=value ;; - -p=*|--profile=*) - PROFILE="${i#*=}" + -f | --credentials) + CREDENTIALS="${2}" + shift 2 # past argument value + ;; + --profile=*) + AWS_PROFILE="${i#*=}" shift # past argument=value ;; - -k|--key) - SHOW_KEY=true + -p | --profile) + AWS_PROFILE="${2}" + shift 2 # past argument value + ;; + -k | --key) + show_key=1 shift # past argument with no value ;; - -s|--secret) - SHOW_SECRET=true + -s | --secret) + show_secret=1 shift # past argument with no value ;; - -t|--session-token) - SHOW_SESSION_TOKEN=true + -t | --session-token) + show_session_token=1 shift # past argument with no value ;; - -h*|--h*) + -h | --help) display_usage - exit 0 + exit 64 ;; *) # unknown option - echo_stderr "Unknown option $1" + echo_stderr "Unknown option $i" display_usage - exit 1 + exit 64 ;; esac done @@ -116,16 +147,10 @@ done # Check options # -CREDENTIALS="${CREDENTIALS:-"${HOME}/.aws/credentials"}" -PROFILE=${PROFILE:-default} -SHOW_KEY=${SHOW_KEY:-false} -SHOW_SECRET=${SHOW_SECRET:-false} -SHOW_SESSION_TOKEN=${SHOW_SESSION_TOKEN:-false} - -if [[ "${SHOW_KEY}" = true && "${SHOW_SECRET}" = true ]]; then - echo_stderr "Can only specify one of --key or --secret" +if [[ $((show_key + show_secret + show_session_token)) -gt 1 ]]; then + echo_stderr "Can only specify one of --key,--secret or --session-token" display_usage - exit 2 + exit 64 fi # @@ -142,26 +167,32 @@ if ! cfg_parser "${CREDENTIALS}"; then exit 4 fi -if ! cfg.section."${PROFILE}" >/dev/null; then - echo_stderr "Profile '${PROFILE}' not found" +if ! cfg.section."${AWS_PROFILE}" 2> /dev/null; then + echo_stderr "Profile '${AWS_PROFILE}' not found" exit 5 fi # shellcheck disable=SC2154 -if [[ "${SHOW_KEY}" = false && "${SHOW_SECRET}" = false && "${SHOW_SESSION_TOKEN}" = false ]]; then - echo_stderr "# Profile: ${PROFILE}" +if ! ((show_key + show_secret + show_session_token)); then + echo_stderr "# Profile '${AWS_PROFILE}'" printf 'export AWS_ACCESS_KEY_ID=%s\n' "${aws_access_key_id}" printf 'export AWS_SECRET_ACCESS_KEY=%s\n' "${aws_secret_access_key}" printf 'export AWS_SESSION_TOKEN=%s\n' "${aws_session_token}" -elif [[ "${SHOW_KEY}" = true ]]; then +elif ((show_key)); then printf '%s' "${aws_access_key_id}" -elif [[ "${SHOW_SECRET}" = true ]]; then +elif ((show_secret)); then printf '%s' "${aws_secret_access_key}" -elif [[ "${SHOW_SESSION_TOKEN}" = true ]]; then +elif ((show_session_token)); then printf '%s' "${aws_session_token}" else echo_stderr "Unknown error" exit 9 fi +unset -v CREDENTIALS +unset -v show_key show_secret show_session_token +unset -v aws_access_key_id aws_secret_access_key aws_session_token + exit 0 + +# vim: tabstop=2 shiftwidth=2 expandtab filetype=sh syntax=sh