| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209 | 
							- #!/usr/bin/env bash
 
- unset LD_LIBRARY_PATH
 
- function log {
 
-   if [ -t 1 ]; then
 
-     echo "$@" >&2
 
-   fi
 
- }
 
- function prompt_password {
 
-   if command -v kdialog >/dev/null; then
 
-     kdialog --password Password
 
-   else
 
-     zenity --password --timeout=60
 
-   fi
 
- }
 
- function prompt_mfa {
 
-   if command -v kdialog >/dev/null; then
 
-     kdialog --inputbox MFA
 
-   else
 
-     zenity --entry --text=MFA
 
-   fi
 
- }
 
- # ignore existing credentials
 
- unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN
 
- output="eval"
 
- duration=900
 
- use_cache=1
 
- eval set -- "$(getopt -o p:d:o: --long profile:,duration:,output: -- "$@")"
 
- while true; do
 
-   case "$1" in
 
-     -p|--profile)
 
-       profile=$2
 
-       shift 2
 
-       ;;
 
-     -d|--duration)
 
-       if [ -n "$2" ]; then
 
-         duration=$2
 
-         use_cache=0
 
-       fi
 
-       shift 2
 
-       ;;
 
-     -o|--output)
 
-       if [ -n "$2" ]; then
 
-         output=$2
 
-       fi
 
-       shift 2
 
-       ;;
 
-     --)
 
-       shift
 
-       break
 
-       ;;
 
-     *)
 
-       echo "Internal error!"
 
-       exit 1
 
-   esac
 
- done
 
- cache_key="aws-$profile"
 
- cache_gpg="$XDG_RUNTIME_DIR/$cache_key.gpg"
 
- function get_from_keepassxc {
 
-   keepassxc-cli show -q "$KEEPASS_FILE" "$KEEPASS_AWS_ENTRY" -a "$1" <<< "$2"
 
- }
 
- function get_role_arn {
 
-   if ! aws configure get "profile.$profile.source_role_arn"; then
 
-     log "source_role_arn not set for profile $profile"
 
-     log "run aws configure set profile.$profile.source_role_arn <role arn>"
 
-     return 1
 
-   fi
 
- }
 
- function get_cached_long_term_credentials {
 
-   if [ ! -f "$cache_gpg" ]; then
 
-     log "No cached long-term credentials, requesting new"
 
-     return 1
 
-   fi
 
-   if ! cached=$(gpg --batch -d --passphrase-file <(echo "$password") "$cache_gpg" 2>/dev/null); then
 
-     log "Error getting cached long-term credentials"
 
-     return 2
 
-   fi
 
-   expiration=$(date -d "$(jq -r '.Credentials.Expiration' <<< "$cached")" +%s)
 
-   if [ "$expiration" -lt "$(date +%s)" ]; then
 
-     log "Cached long-term credentials expired, requesting new"
 
-     return 1
 
-   fi
 
-   echo "$cached"
 
- }
 
- function get_long_term_credentials {
 
-   local duration
 
-   local password
 
-   duration="$1"
 
-   if ! password=$(prompt_password 2> /dev/null); then
 
-     log "Failed to get password"
 
-     return 1
 
-   fi
 
-   credentials=$(get_cached_long_term_credentials)
 
-   retcode=$?
 
-   if [ $retcode -eq 2 ]; then
 
-     exit 1
 
-   elif [ $retcode -eq 1 ]; then
 
-     if ! role_arn=$(get_role_arn); then
 
-       return 1
 
-     fi
 
-     if ! AWS_ACCESS_KEY_ID=$(get_from_keepassxc UserName "$password"); then
 
-       log "Failed to open vault"
 
-       exit 1
 
-     fi
 
-     if ! AWS_SECRET_ACCESS_KEY=$(get_from_keepassxc Password "$password"); then
 
-       log "Failed to open vault"
 
-       exit 1
 
-     fi
 
-     export AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY
 
-     export AWS_PROFILE=default
 
-     mfa_serial_number=$(aws configure get mfa_serial)
 
-     if ! mfa=$(prompt_mfa 2> /dev/null); then
 
-       log "Failed to get MFA"
 
-       return 1
 
-     fi
 
-     if credentials=$(aws sts assume-role --serial-number "$mfa_serial_number" --token-code "$mfa" --role-arn "$role_arn" --role-session-name "$(hostname)" --duration-seconds "$duration"); then
 
-       gpg --batch -c --passphrase-file <(echo "$password") <<< "$credentials" > "$cache_gpg"
 
-     else
 
-       return 1
 
-     fi
 
-   fi
 
-   echo "$credentials"
 
- }
 
- function get_cached_short_term_credentials {
 
-   if [ "$use_cache" -eq 0 ]; then
 
-     return 1
 
-   fi
 
-   keyctl pipe "%user:$cache_key" 2>/dev/null
 
- }
 
- function get_short_term_credentials {
 
-   if ! credentials=$(get_cached_short_term_credentials); then
 
-     if ! role_arn=$(get_role_arn); then
 
-       return 1
 
-     fi
 
-     if ! long_term_credentials="$(get_long_term_credentials 43200)"; then
 
-       return 1
 
-     fi
 
-     AWS_ACCESS_KEY_ID=$(jq -r .Credentials.AccessKeyId <<<"$long_term_credentials")
 
-     AWS_SECRET_ACCESS_KEY=$(jq -r .Credentials.SecretAccessKey <<<"$long_term_credentials")
 
-     AWS_SESSION_TOKEN=$(jq -r .Credentials.SessionToken <<<"$long_term_credentials")
 
-     export AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN
 
-     if credentials=$(aws sts assume-role --role-arn "$role_arn" --role-session-name "$(hostname)" --duration-seconds "$duration"); then
 
-       keyctl padd user "$cache_key" @s <<<"$credentials" >/dev/null
 
-       keyctl timeout "%user:$cache_key" "$duration" >/dev/null
 
-     else
 
-       return 1
 
-     fi
 
-   fi
 
-   echo "$credentials"
 
- }
 
- while keyctl read '%user:lock' >/dev/null 2>&1; do
 
-   sleep 1
 
- done
 
- keyctl add user lock lock @s >/dev/null 2>&1
 
- function finish {
 
-   keyctl revoke '%user:lock' 2>&1
 
- }
 
- trap finish EXIT
 
- if [ "$duration" -gt 3600 ]; then
 
-   if ! credentials=$(get_long_term_credentials "$duration"); then
 
-     exit 1
 
-   fi
 
- else
 
-   if ! credentials=$(get_short_term_credentials); then
 
-     exit 1
 
-   fi
 
- fi
 
- if [ "$output" = "credential_process" ]; then
 
-   jq '.Credentials | .Version=1' <<< "$credentials"
 
- else
 
-   jq <<< "$credentials" -r '.Credentials | @sh "
 
- export AWS_ACCESS_KEY_ID=\(.AccessKeyId)
 
- export AWS_SECRET_ACCESS_KEY=\(.SecretAccessKey)
 
- export AWS_SESSION_TOKEN=\(.SessionToken)"'
 
- fi
 
 
  |