Keep Long-Lived AWS Credentials Out of Untrusted Environments
Generate and use short-lived AWS session credentials, keeping your AWS IAM keys secure
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
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 envto 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/cacheinstead of usingget-session-token.
When running on an EC2 instance, consider associating an appropriate role with the instance you connect to instead of transferring credentials yourself.