12

Prerequisites

I have a script that works with AWS but does not deal with credentials explicitly. It just calls AWS API, expecting the credentials to be there according to default credentials provider chain. In fact, the wrapper that calls this script obtains temporary credentials and passes them in environment variables (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_SESSION_TOKEN).

Problem

The wrapper usually reuses existing credentials, and only asks to re-authenticate explicitly when they are about to expire. So there is a possibility that it passes credentials that have a few minutes left to live, which may not be enough, as the script execution usually takes long time. Unfortunately, I don't have control over the wrapper, so I would like to make the script check how much time it has left before making a decision whether to start or abort early to prevent failure in mid-flight.

AWS doesn't seem provide a standard way to query "how much time I have before my current session expires?" If I had control over the wrapper, I would make it pass the expiry date in an environment variable as well. I was hoping that AWS_SESSION_TOKEN is a sort of a JWT token, but unfortunately it is not, and does not seem to contain any timestamp in it.

Can anyone suggest any other ways around the given problem?

Vlad Nikiforov
  • 6,052
  • 1
  • 12
  • 18
  • Are you using this on an EC2 instance? – Marko E Aug 11 '20 at 19:19
  • Nope, it's outside of AWS infrastructure. – Vlad Nikiforov Aug 11 '20 at 23:36
  • There's a simple way to get that data from an EC2 instance, but that won't work in your case. I found this document https://docs.aws.amazon.com/STS/latest/APIReference/API_GetSessionToken.html when looking for the problem you mention. Could that help? – Marko E Aug 12 '20 at 07:26
  • Did anyone get any of the answers to work? None of those work for me. I'm doing an over-optimization to improve my daily workflow, don't login if the session if valid, and need the expiry time. – Raaka Aug 10 '23 at 18:34

3 Answers3

2

One liners/bash functions for BSD date (tested in macOS).

Requires jq.

aws-expiry () {
  aws configure get x_security_token_expires --profile ${AWS_PROFILE} | xargs -I {} sh -c 'TZ="UTC" date -j -f "%Y-%m-%dT%H:%M:%S" "+%s" $1 2>/dev/null' -- {} | xargs date -j -f "%s"
}

To get expiry of AWS SSO session cache file.

Assumes cli_timestamp_format not configured for AWS CLI

aws-sso-expiry () {
  aws configure get sso_start_url --profile ${AWS_PROFILE} | xargs -I {} grep -h {} ~/.aws/sso/cache/*.json | jq .expiresAt | xargs -I {} sh -c 'TZ="UTC" date -j -f "%Y-%m-%dT%H:%M:%S" "+%s" $1 2>/dev/null' -- {} | xargs date -j -f "%s"
}
Efren
  • 4,003
  • 4
  • 33
  • 75
  • I don't know where is the first answer getting "AWS_SESSION_EXPIRATION" from. But I am using AWS SSO and the second line definitely does the trick! Thanks @Efren – David Velarde Mar 22 '23 at 09:05
1

IMPORTANT Update: now $AWS_CREDENTIAL_EXPIRATION replaces $AWS_SESSION_EXPIRATION

TODO: amend the answer below based on the important update above!

You probably need to check for the value of $AWS_SESSION_EXPIRATION

echo $AWS_SESSION_EXPIRATION

It should be giving you the expiration using the Zulu Time (Coordinated Universal Time) like below

2022-05-17T20:20:40Z

Then would need to compare the date on your system against it.

Instructions below work on macOS, for Linux you may have to modify the date function params

Let's check the current system time in Zulu Time:

date -u +'%Y-%m-%dT%H:%M:%SZ'

this should give something like the example:

2022-05-17T20:21:14Z

To automate things you can create a bash function to add to your ~/.bashrc or favorite terminal theme

aws_session_time_left() {
  zulu_time_now=$1

  aws_session_expiration_epoch="`date -j -u -f '%Y-%m-%dT%H:%M:%SZ' $AWS_SESSION_EXPIRATION '+%s'`"
  zulu_time_now_epoch="`date -j -u -f '%Y-%m-%dT%H:%M:%SZ' $zulu_time_now '+%s'`"

  if [[ $zulu_time_now < $AWS_SESSION_EXPIRATION ]]; then
    secs="`expr $aws_session_expiration_epoch - $zulu_time_now_epoch`"
    echo "+`printf '%dh:%02dm:%02ds\n' $((secs/3600)) $((secs%3600/60)) $((secs%60))`"
  else
    secs="`expr $zulu_time_now_epoch - $aws_session_expiration_epoch`"
    echo "-`printf '%dh:%02dm:%02ds\n' $((secs/3600)) $((secs%3600/60)) $((secs%60))`"
  fi
}

To consult the result of your function you can run:

aws_session_time_left "`date -u +'%Y-%m-%dT%H:%M:%SZ'`"

When your session is still active can give you something like:

+0h:56m:35s

or (when the session has expired) can give you how long since it expired:

-28h:13m:42s

NOTE the hours can be over 24h

BONUS: simplified standalone script version without parameters below

for example, you can also have as a standalone file get-aws-session-time-left.sh

#!/bin/bash

# Use to find out IF "aws session expiration" exist AND compare the current system time to IT
# These are the expected result types we want to have:
# - "no aws session found" (NOTE: this does not mean there is no aws session open in another terminal)
# - how long until the session expires (for example +0h:59m:45s)
# - how long since the session expired (for example -49h:41m:12s)
# NOTE: the hours do not reset at every 24 hours, we do not require to display the days
# IMPORTANT: the date function arguments work on macOS, for other OS types may need adapting

if [[ $AWS_SESSION_EXPIRATION != '' ]]; then
  zulu_time_now="`date -u +'%Y-%m-%dT%H:%M:%SZ'`" # TODO: see important note above

  aws_session_expiration_epoch="`date -j -u -f '%Y-%m-%dT%H:%M:%SZ' $AWS_SESSION_EXPIRATION '+%s'`" # TODO: see important note above
  zulu_time_now_epoch="`date -j -u -f '%Y-%m-%dT%H:%M:%SZ' $zulu_time_now '+%s'`"                   # TODO: see important note above

  if [[ $zulu_time_now < $AWS_SESSION_EXPIRATION ]]; then
    secs="`expr $aws_session_expiration_epoch - $zulu_time_now_epoch`"
    echo "+`printf '%dh:%02dm:%02ds\n' $((secs/3600)) $((secs%3600/60)) $((secs%60))`"
  else
    secs="`expr $zulu_time_now_epoch - $aws_session_expiration_epoch`"
    echo "-`printf '%dh:%02dm:%02ds\n' $((secs/3600)) $((secs%3600/60)) $((secs%60))`"
  fi
else
  echo "no aws session found"
fi

Then to consult the AWS session expiration, you can just run:

bash get-aws-session-time-left.sh

---EDITS---

IMPORTANT: Some info about the origin of AWS_SESSION_EXPIRATION can be found here

NOTE: aws sso login does not appear to set this environment variable, would be curious if someone can clarify if AWS_SESSION_EXPIRATION is only present when using aws-vault

dankilev
  • 720
  • 2
  • 10
  • 32
0

you can use aws configure get to get the expiry time:

AWS_SESSION_EXPIRATION=$(aws configure get ${AWS_PROFILE}.x_security_token_expires)

(obviously replace MYPROFILE with your profile name.)

  • 2
    `aws configure get ${AWS_PROFILE}.x_security_token_expires` was empty for me, even immediately after running `aws sso login`. – shadowtalker Dec 08 '22 at 16:26
  • if you use a source_profile then the command changes a little: ```aws configure get "$(aws configure get ${AWS_PROFILE}.source_profile)".x_security_token_expires``` – khanh nguyen Dec 10 '22 at 09:44