Skip to content

Instantly share code, notes, and snippets.

@renatoargh
Last active January 9, 2024 18:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save renatoargh/3bc7ea01e5afefe6578464d18d5bfbcb to your computer and use it in GitHub Desktop.
Save renatoargh/3bc7ea01e5afefe6578464d18d5bfbcb to your computer and use it in GitHub Desktop.
Using temporary AWS STS credentials with AWS CLI and 1password

Summary

For those using 1password and AWS CLI, here is a cool trick to take advantage of 1pass and use temporary STS credentials instead of hardcoding long lived AWS creds, which are sensitive, on your /.aws/credentials file.

If MFA is enforced on AWS, this script will be very convenient once only STS credentials are accepted in this case.

Requirements

  1. Node.js installed
  2. AWS CLI installed
  3. 1password CLI installed

Usage

  1. Run npm install --global zx
  2. Paste both files above in your $HOME/.aws folder
  3. Run sudo chmod +x ~/.aws/resolve-credentials.mjs

Every time you need new credentials you just run ~/.aws/resolve-credentials.mjs personal.

PRO-TIP: Add an alias to ~/.aws/resolve-credentials.mjs on your ~/.zprofile file, like this alias c="~/.aws/resolve-credentials.mjs" usage will then become simpler, like this: c personal

References

Retrieving 1password secrets by reference: https://developer.1password.com/docs/cli/secret-references/#:~:text=Open%20and%20unlock%20the%201Password,then%20click%20Copy%20Secret%20Reference

# Take these values from 1password as explained here:
# https://developer.1password.com/docs/cli/secret-references/#:~:text=Open%20and%20unlock%20the%201Password,then%20click%20Copy%20Secret%20Reference.
{
"access_key_id": "op://Personal/AWS Personal Account/access key",
"secret_access_key": "op://Personal/AWS Personal Account/secret access key",
"mfa_device_identifier": "op://Personal/AWS Personal Account/MFA Device Identifier",
"mfa_token_code": "op://Personal/AWS Personal Account/one-time password",
"session_duration_seconds": 900,
"default_region": "us-east-1",
"default_output_format": "json"
}
#!/usr/bin/env zx
$.verbose = false;
import { writeFileSync } from 'fs'
const homePath = process.env.HOME;
const profile = process.argv.pop();
await spinner(`> Obtaining temporary AWS credentials for "${profile}"`, async () => {
const rawCredentialRefs = await $`cat ${homePath}/.aws/${profile}.json`;
const credentialRefs = JSON.parse(rawCredentialRefs);
const sessionDurationSeconds = credentialRefs.session_duration_seconds;
const awsDefaultRegion = credentialRefs.default_region;
const awsDefaultOutputFormat = credentialRefs.default_output_format;
const [accessKeyId, secretAccessKeyId, mfaDeviceId, tokenCode] = await Promise.all([
$`op read ${credentialRefs.access_key_id}`,
$`op read ${credentialRefs.secret_access_key}`,
$`op read ${credentialRefs.mfa_device_identifier}`,
$`op read ${credentialRefs.mfa_token_code}?attribute=otp`,
]);
const rawSessionTokenOutput = await $`
AWS_ACCESS_KEY_ID=${accessKeyId} \
AWS_SECRET_ACCESS_KEY=${secretAccessKeyId} \
AWS_DEFAULT_REGION=${awsDefaultRegion} \
aws sts get-session-token --output=json \
--serial-number ${mfaDeviceId} \
--token-code ${tokenCode} \
--duration-seconds ${sessionDurationSeconds}
`;
const { Credentials: credentials } = JSON.parse(rawSessionTokenOutput);
const credentialsFile = `#
# TEMPORARY CREDENTIALS FOR "${profile}" AWS ACCOUNT
# EXPIRES AT: ${new Date(credentials.Expiration).toLocaleString()}
# RUN \`~/.aws/resolve-credentials.mjs\ ${profile}\` TO REFRESH
# EDIT \`~/.aws/${profile}.json\` TO UPDATE CONFIGURATION
#
[default]
aws_access_key_id=${credentials.AccessKeyId}
aws_secret_access_key=${credentials.SecretAccessKey}
aws_session_token=${credentials.SessionToken}
region=${awsDefaultRegion}
output=${awsDefaultOutputFormat}
`.trim();
writeFileSync(`${process.env.HOME}/.aws/credentials`, credentialsFile);
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment