Keep Long-Lived AWS Credentials Out of Untrusted Environments

Generate and use short-lived AWS session credentials, keeping your AWS IAM keys secure

· 3 min read · 493 words

Update: Nowadays, using long-lived IAM credentials and IAM users is no longer considered an acceptable security practice. Instead of exchanging long-lived credentials for short-lived credentials, you should aim to never use long-lived credentials in the first place.

Short-lived. Photo by Erik Karits on Unsplash Short-lived. Photo by Erik Karits on Unsplash

I sometimes use AWS services or transfer credentials through environments that I feel I cannot fully “trust”, for example on shared EC2 instances such as bastion hosts, in a shared Gitpod session or through Slack. To keep my long-lived credentials (API key ID’s and secrets) out of configuration files, shell and chat histories, I authenticate using short-lived session credentials.

I generate these short-lived credentials on my own device using get-session-token, and export them as environment variables inside the instance.

I could do this “manually”, but the following little script, let’s call it generate_tmp_credentials, makes my life easier:

#!/bin/bash
duration=1800
export creds=$(aws sts get-session-token --duration-seconds $duration)
echo "export AWS_ACCESS_KEY_ID=\"$(jq -n --join-output 'env.creds | fromjson.Credentials.AccessKeyId')\""
echo "export AWS_SECRET_ACCESS_KEY=\"$(jq -n --join-output 'env.creds | fromjson.Credentials.SecretAccessKey')\""
echo "export AWS_SESSION_TOKEN=\"$(jq -n --join-output 'env.creds | fromjson.Credentials.SessionToken')\""

This prints exactly the commands for exporting the environment variables that authenticate you with AWS. Credentials remain valid for the specified duration.

Using the script

On my Mac machine, I copy credentials directly to the clipboard using pbcopy:

generate_tmp_credentials | pbcopy

On my Windows / WSL machine I use clip.exe instead:

generate_tmp_credentials | clip.exe

Sometimes I just run generate_tmp_credentials, then copy the output from the terminal.

Then, inside of the shell where I want access, I paste what is on my clipboard. This grants the access of the IAM user credentials that are active when running generate_tmp_credentials. Verify this by running:

aws sts get-caller-identity

Specifying profiles

To use another profile, simply run

AWS_PROFILE=profilename generate_tmp_credentials

instead of generate_tmp_credentials.

Limitations

Update: If you are already authenticated using short-lived credentials, consider using the command aws configure export-credentials --format env to export them in a convenient format.

It is not possible to generate session credentials using session credentials, so the source profile on your local machine has to use IAM key credentials (~IAM user).

If your source profile corresponds to a role, consider how you authenticate the profile. If there are no long-lived credentials to keep safe, for example because you use AWS SSO, you likely do not need a “solution” like this one. You may consider one of these options:

  • Generate short-lived credentials for the profile’s source profile and chaining from there on the remote.
  • Change the script to use assume-role / AssumeRole instead of get-session-token. Indeed: you can assume a role, which also yields session credentials, from session credentials.
  • Use the temporary credentials cached by your CLI from ~/.aws/cli/cache instead of using get-session-token.

When running on an EC2 instance, consider associating an appropriate role with the instance you connect to instead of transferring credentials yourself.