diff --git a/aws_helper.sh b/aws_helper.sh index e814802..ff828e7 100755 --- a/aws_helper.sh +++ b/aws_helper.sh @@ -178,6 +178,102 @@ EOF $GREP "^\[" $CREDENTIALS |$CUT -d ']' -f 1 | $TR -d '[' } +function __extract_config_from_file() { + # Check for tools and get most compatible + local GREP=$(which ggrep 2>/dev/null || which grep 2>/dev/null) + if [ -z "$GREP" ]; then + __aws_helper_log 'error' 'Cannot locate tool: grep'; + return 1 + fi + + local CUT=$(which cut 2>/dev/null) + if [ -z "$CUT" ]; then + __aws_helper_log 'error' 'Cannot locate tool: cut'; + return 1 + fi + +local AWK=$(which gawk 2>/dev/null || which awk 2>/dev/null ) + if [ -z "$AWK" ]; then + __aws_helper_log 'error' 'Cannot locate tool: awk'; + return 1 + fi + +local HEAD=$(which ghead 2>/dev/null || which head 2>/dev/null ) + if [ -z "$HEAD" ]; then + __aws_helper_log 'error' 'Cannot locate tool: head'; + return 1 + fi + +local SED=$(which gsed 2>/dev/null || which sed 2>/dev/null ) + if [ -z "$SED" ]; then + __aws_helper_log 'error' 'Cannot locate tool: sed'; + return 1 + fi + +local XARGS=$(which gxargs 2>/dev/null || which xargs 2>/dev/null ) + if [ -z "$XARGS" ]; then + __aws_helper_log 'error' 'Cannot locate tool: xargs'; + return 1 + fi + +# Default Config File +CREDENTIALS="$HOME/.aws/credentials" + +# Extract data from the config section +__header="[${AWS_PROFILE}]" + +# Find the first line in the section +local __start=$($GREP -nF -- "$__header" "$CREDENTIALS" | $CUT -d: -f1 | $HEAD -n1) +if [ -z "$__start" ]; then + __aws_helper_log "Section '$__header' not found" >&2 + exit 1 +fi + +# find the next section +local __next=$($AWK -v s="$__start" 'NR>s && /^\[/{print NR; exit}' "$CREDENTIALS") + +if [ -z "$__next" ]; then + # no following section: extract output from from start+1 to EOF + local __output=$($SED -n "$((__start+1)),\$p" "$CREDENTIALS"| $SED -E 's/^[[:space:]]+//; s/[[:space:]]+$//; s/[[:space:]]*=[[:space:]]*/=/') +else + # extract between the two line numbers + local __output=$($SED -n "$((__start+1)),$((__next-1))p" "$CREDENTIALS"| $SED -E 's/^[[:space:]]+//; s/[[:space:]]+$//; s/[[:space:]]*=[[:space:]]*/=/') +fi + +#parse output into variables +while IFS='=' read -r __key __value; do + # skip empty or comment lines + [[ -z "$__key" || "$__key" =~ ^[[:space:]]*# ]] && continue + + # trim whitespace + __key=$(echo "$__key" | $XARGS) + __value=$(echo "$__value" | $XARGS) + + # assign variable + printf -v "$__key" '%s' "$__value" +done < <(echo "${__output}") + +# clean variables + +unset __discovered_aws_access_key_id +unset __discovered_aws_secret_access_key +unset __discovered_mfa_serial + +# if there are variables we need we can export them as new ones as to not clobber any other references +if [[ -n $aws_access_key_id ]]; then + export __discovered_aws_access_key_id=${aws_access_key_id} +fi + +if [[ -n $aws_secret_access_key ]]; then + export __discovered_aws_secret_access_key=${aws_secret_access_key} +fi + +if [[ -n $mfa_serial ]]; then + export __discovered_mfa_serial=${mfa_serial} +fi + +} + ## # Get list of aliases in ./aws-helper/config ## @@ -462,8 +558,29 @@ EOF return 1; fi; +# Try and extract useful information from existing credentials file +__extract_config_from_file + + iam_user_name="$(echo ${AWS_ARN} | sed 's|[^/]*/||g')"; - mfa_serial="arn:aws:iam::${AWS_ACCOUNT_ID}:mfa/${iam_user_name}"; + +#If we've been told the serial use it + if [[ -n ${__discovered_mfa_serial} ]]; then + mfa_serial=${__discovered_mfa_serial} + else + # Try to query "iam list-mfa-devices" if it is permitted without MFA + mfa_serial="$(aws iam list-mfa-devices --query 'MFADevices[*].SerialNumber' --output text)"; + if ! [ "${?}" -eq 0 ]; then + # this did not work - Fallback to old method + mfa_serial="arn:aws:iam::${AWS_ACCOUNT_ID}:mfa/${iam_user_name}"; + fi + fi +__aws_helper_log "Using mfa_serial : $mfa_serial" + +# Prevent Data leakage +unset __discovered_aws_access_key_id +unset __discovered_aws_secret_access_key +unset __discovered_mfa_serial if [ -z "${mfa_token}" ]; then __aws_helper_log 'info' 'Enter MFA token: ' '-n'; @@ -523,11 +640,20 @@ EOF local expiry_epoch; + # Select best date tool , work around weaknesses in MacOS date command + + local DATE=$(which gdate 2>/dev/null || which date 2>/dev/null) + if [ -z "$DATE" ]; then + __aws_helper_log 'error' 'Cannot locate tool: date'; + return 1 + fi + # Workaround for OSX date - if [ "$(uname)" == "Darwin" ]; then - expiry_epoch="$(date -j -f \"%Y-%m-%dT%H:%M:%SZ\" \"${AWS_MFA_EXPIRY}\" +%s)"; + if [ "$(uname)" == "Darwin" -a "$DATE" == "/bin/date" ] ; then + __aws_helper_log 'Please Install the Gnu Date tool' + exit 1 else - expiry_epoch="$(date -d ${AWS_MFA_EXPIRY} +%s)"; + expiry_epoch="$($DATE -d ${AWS_MFA_EXPIRY} +%s)"; fi local current_epoch="$(date -u +%s)";