Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

aws sts support #42

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,21 @@
[![Build Status](https://travis-ci.org/leflamm/afpre.svg?branch=master)](https://travis-ci.org/leflamm/afpre) [![GitHub release](https://img.shields.io/github/release/leflamm/afpre.svg)](https://github.com/leflamm/afpre/releases/latest)

Simple script to access the AWS Federation Proxy (AFP). Its main use case is starting a new shell where your temporary AWS credentials have been exported into the environment.
Simple script to access the [AWS Federation Proxy (AFP)](https://docs.aws.amazon.com/amp/latest/userguide/install-option-connector.html) or [AWS Security Token Service (STS)](https://docs.aws.amazon.com/STS/latest/APIReference/Welcome.html). Its main use case is starting a new shell where your temporary AWS credentials have been exported into the environment.

Inspired by https://github.com/ImmobilienScout24/afp-cli

# Flavours

## AWS Federation Proxy (AFP)

When used with an AFP server, performs basic auth towards the configured host, obtains and extracts temporary credentials.

## AWS Security Token Service

When used with the AWS STS, performs `aws sts assume-role` call with configured role and account, obtains and extracts temporary credentials.

# Features

## No Expired Tokens
The started `bash` will notice when the AWS tokens are about to expire. It will then renew the necessary tokens itself. No need to log out and in again.

Expand Down Expand Up @@ -63,7 +75,7 @@ Commands can also be Bash functions. Make sure to export them using `export -f <
$ cat ~/.afpre
ACCOUNT=<your desired account>
ROLE=<your desired role>
HOST=<your afp host>
HOST=<your afp host> # not mandatory if STS mode used
_PATH=<your path to service endpoint, typically "/afp-api/latest/account">
NAME=<your username> # optional
PW=<your password> # optional, I wouldn't put it here
Expand Down
48 changes: 31 additions & 17 deletions afpre
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,11 @@ usage: ${0} [OPTIONS] (-- COMMAND)
OPTIONS
--help ... print this help
--account=<my.account> ... authenticate for this account, supersedes
any definition in ${CFG}
any definition in ${CFG}
--role=<my.role> ... authenticate as this role, supersedes
any definition in ${CFG}
any definition in ${CFG}
--example-cfg ... create an example config file at ${CFG}
--sts ... go through aws sts login process instead of federation proxy
--debug ... enable debugging
--version ... print version
EOF
Expand All @@ -73,11 +74,11 @@ do_example_cfg() {
echo saving existing ${CFG} to ${CFG}.bak
mv ${CFG} ${CFG}.bak
}

cat > $CFG << EOF
ACCOUNT=my.account
ROLE=my.role
HOST=my.afp.host
HOST=my.afp.host # not mandatory if --sts used
_PATH=/afp-api/latest/account
#PATTERN=\\\${ACCOUNT}/\\\${ROLE} # This will appear in front of the prompt
#NAME=my.name
Expand All @@ -88,14 +89,15 @@ EOF
}

longoption_value() {
grep -o -- "--${1}=[^ ]*" <<< $ARGS| cut -d"=" -f2
grep -o -- "--${1}=[^ ]*" <<< $ARGS| cut -d"=" -f2
}

get_command() {
grep -o -- '-- .*' <<< ${ARGS} | sed 's/^-- //g'
}

DEBUG=false
AWS_NATIVE=false
ARGS="${@}"

options_contain '--help' && do_help
Expand All @@ -104,6 +106,7 @@ options_contain '--account' && ADHOC_ACCOUNT=$(longoption_value account)
options_contain '--role' && ADHOC_ROLE=$(longoption_value role)
options_contain '--example-cfg' && do_example_cfg
options_contain '--debug' && DEBUG=true
options_contain '--sts' && AWS_NATIVE=true

$DEBUG && set -x

Expand All @@ -113,14 +116,15 @@ variable_empty "${ADHOC_ACCOUNT}" && check_config_key ACCOUNT
variable_empty "${ADHOC_ROLE}" && check_config_key ROLE
check_config_key ROLE
check_config_key _PATH
check_config_key HOST
! "${AWS_NATIVE}" && check_config_key HOST

source $CFG

variable_empty "${ADHOC_ACCOUNT}" || ACCOUNT="${ADHOC_ACCOUNT}"
variable_empty "${ADHOC_ROLE}" || ROLE="${ADHOC_ROLE}"
variable_empty "${NAME}" && read -p "username: " NAME
variable_empty "${PW}" && {

! "${AWS_NATIVE}" && variable_empty "${PW}" && {
read -p "password: " -s PW
echo
}
Expand All @@ -141,8 +145,8 @@ RCFILE=$(mktemp)
cat > $RCFILE <<EOF
$DEBUG && set -x

AWS_VALID_SECONDS=0
RENEW_INT=$RENEW_INT
AWS_VALID_SECONDS=0
RENEW_INT=$RENEW_INT
ACCOUNT=$ACCOUNT
ROLE=$ROLE
export AWS_ACCOUNT=$ACCOUNT
Expand Down Expand Up @@ -194,15 +198,25 @@ ctrl_c () {
renew() {
trap ctrl_c INT

echo authenticating as ${NAME} for ${ACCOUNT}/${ROLE} against ${HOST}
JSON=\$(basic_auth https://${HOST}${_PATH}/${ACCOUNT}/${ROLE} ${X1XBN02R}) || error_msg "... failed!"
export AWS_ACCESS_KEY_ID=\$(json_value "\${JSON}" AccessKeyId)
export AWS_SECRET_ACCESS_KEY=\$(json_value "\${JSON}" SecretAccessKey)
export AWS_SESSION_TOKEN=\$(json_value "\${JSON}" Token)
export AWS_SECURITY_TOKEN=\$(json_value "\${JSON}" Token)
export AWS_VALID_SECONDS=\$((\$(secs_since_epoch \$(json_value "\${JSON}" Expiration))-\$(date +%s)))
SECONDS=0
if [[ "${AWS_NATIVE}" == "true" ]]
then
echo authenticating as ${NAME} for ${ACCOUNT}/${ROLE}
JSON=\$(aws sts assume-role --role-arn arn:aws:iam::${ACCOUNT}:role/${ROLE} --role-session-name ${NAME}_session) || error_msg "... failed!"
export AWS_ACCESS_KEY_ID=\$(json_value "\${JSON}" Credentials.AccessKeyId)
export AWS_SECRET_ACCESS_KEY=\$(json_value "\${JSON}" Credentials.SecretAccessKey)
export AWS_SESSION_TOKEN=\$(json_value "\${JSON}" Credentials.SessionToken)
export AWS_VALID_SECONDS=\$((\$(secs_since_epoch \$(json_value "\${JSON}" Credentials.Expiration))-\$(date +%s)))
else
echo authenticating as ${NAME} for ${ACCOUNT}/${ROLE} against ${HOST}
JSON=\$(basic_auth https://${HOST}${_PATH}/${ACCOUNT}/${ROLE} ${X1XBN02R}) || error_msg "... failed!"
export AWS_ACCESS_KEY_ID=\$(json_value "\${JSON}" AccessKeyId)
export AWS_SECRET_ACCESS_KEY=\$(json_value "\${JSON}" SecretAccessKey)
export AWS_SESSION_TOKEN=\$(json_value "\${JSON}" Token)
export AWS_SECURITY_TOKEN=\$(json_value "\${JSON}" Token)
export AWS_VALID_SECONDS=\$((\$(secs_since_epoch \$(json_value "\${JSON}" Expiration))-\$(date +%s)))
fi

SECONDS=0
trap - INT
}

Expand Down