Skip to content

Instantly share code, notes, and snippets.

@quinnjr
Created July 15, 2026 20:43
Show Gist options
  • Select an option

  • Save quinnjr/83468b963742d52e0e99860aa20ac63b to your computer and use it in GitHub Desktop.

Select an option

Save quinnjr/83468b963742d52e0e99860aa20ac63b to your computer and use it in GitHub Desktop.
Moving AWS credentials into libsecret (credential_process + secret-tool)

Moving AWS credentials into libsecret

Keep long-term AWS access keys out of ~/.aws/credentials (plaintext on disk) by storing them in your desktop keyring via libsecret, and letting the AWS CLI/SDKs fetch them on demand with credential_process.

Works with anything that uses the standard AWS credential chain: aws CLI, boto3, Go/JS/Rust SDKs, Terraform, Pulumi, etc.

Prerequisites

  • libsecret and its CLI (secret-tool) — package libsecret on Arch, libsecret-tools on Debian/Ubuntu.
  • A running Secret Service keyring (GNOME Keyring, KWallet ≥ 5.97, or KeePassXC with Secret Service integration), unlocked with your session.

1. Store the keys

printf '%s' 'AKIAXXXXXXXXXXXXXXXX' | secret-tool store --label='AWS access key ID' service aws key access-key-id
printf '%s' 'your-secret-access-key' | secret-tool store --label='AWS secret access key' service aws key secret-access-key

The service aws key ... pairs are arbitrary attribute/value lookup tags — pick any scheme, just be consistent. Verify:

secret-tool lookup service aws key access-key-id

Prefer printf '%s' over echo so no trailing newline gets stored.

2. Create a credential_process helper

credential_process is a hook in the AWS config: instead of reading static keys, the SDK runs a program and parses JSON from its stdout.

~/.local/bin/aws-libsecret-creds:

#!/bin/sh
printf '{"Version":1,"AccessKeyId":"%s","SecretAccessKey":"%s"}' \
  "$(secret-tool lookup service aws key access-key-id)" \
  "$(secret-tool lookup service aws key secret-access-key)"
chmod +x ~/.local/bin/aws-libsecret-creds

3. Wire it into ~/.aws/config

[profile myprofile]
region = us-east-1
credential_process = /home/you/.local/bin/aws-libsecret-creds

Use an absolute path — ~ is not expanded in credential_process.

4. Remove the plaintext keys and verify

Delete the profile's aws_access_key_id / aws_secret_access_key lines from ~/.aws/credentials. This matters: static keys in the credentials file take precedence over credential_process, so leftovers silently win.

aws sts get-caller-identity --profile myprofile

Bonus: MFA TOTP seeds too

If you use a virtual MFA device with an auto-refresh tool (aws-mfa, aws-mfa-auto, oathtool scripts), the TOTP seed is just as sensitive as the secret key — store it the same way:

printf '%s' 'BASE32TOTPSEED...' | secret-tool store --label='AWS MFA TOTP seed' service aws key mfa-secret

Then call your refresh tool with a lookup instead of a hardcoded seed, e.g. in .zshrc/.bashrc:

aws-mfa-auto --profile myprofile --secret "$(secret-tool lookup service aws key mfa-secret)"

Gotchas

  • Precedence: env vars (AWS_ACCESS_KEY_ID) beat everything; static keys in ~/.aws/credentials beat credential_process. Clean both up or the keyring never gets consulted.
  • Headless/SSH sessions: secret-tool needs D-Bus and an unlocked keyring. Over plain SSH with no session keyring, lookups fail — the error surfaces as a credential_process failure. CI and servers should use roles/SSO instead anyway.
  • Tools that parse the credentials file directly (some MFA helpers, old scripts using configparser instead of the SDK) may require the profile section header to exist in ~/.aws/credentials. An empty [myprofile-long-term] section satisfies the check while boto3 falls through to credential_process.
  • Rotation: rerun the two secret-tool store commands — same attributes overwrite in place, nothing else to touch.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment