Skip to content

Instantly share code, notes, and snippets.

@ab
Created June 25, 2025 13:31
Show Gist options
  • Save ab/ca70d9583bdffa2d17f6ca6f39a99159 to your computer and use it in GitHub Desktop.
Save ab/ca70d9583bdffa2d17f6ca6f39a99159 to your computer and use it in GitHub Desktop.
Automatically generate an AWS config file (~/.aws/config) for ALL available AWS accounts and roles seen via SSO login
#!/usr/bin/env bash
set -euo pipefail
SSO_SESSION_NAME="${SSO_SESSION_NAME-sso-session}"
ACCESS_TOKEN_CACHE_FILE="${ACCESS_TOKEN_CACHE_FILE-}"
usage() {
cat >&2 <<EOM
usage: $0 AWS_PROFILE_BOOTSTRAP OUTFILE
Generate AWS config for ALL available accounts and roles.
Write the config to OUTFILE.
If you don't want to overwrite your default ~/.aws/config, then you can tell
the aws CLI to use a different config file with AWS_CONFIG_FILE.
This script needs an SSO token for bootstrapping. It currently is designed to
read this out of ~/.aws/sso/cache/ from a manual call to \`aws sso login\`.
For bootstrapping, we need an existing profile in ~/.aws/config. Pass this as
AWS_PROFILE_BOOTSTRAP. We'll use that to run \`aws sso login\`, which will get
us an SSO token that can be used to list the available accounts and roles.
The SSO token will be read out of the most recently modified cache file in
~/.aws/sso/cache/.
Technically we could use \`aws sso-oidc create-token\` instead of piggybacking
off of the AWS CLI's token, but that would be more work.
This script uses \`aws sso list-accounts\` and \`aws sso list-account-roles\`
to discover available accounts and roles. This will list all accounts and roles
that the current user can see within the AWS partition.
Configuration env vars and their defaults:
SSO_SESSION_NAME=$SSO_SESSION_NAME
ACCESS_TOKEN_CACHE_FILE=$ACCESS_TOKEN_CACHE_FILE
Example usage:
SSO_SESSION_NAME=my-sso $0 existing-role autogen-standard.conf
EOM
}
run() {
echo >&2 "+ $*"
"$@"
}
get_sso_access_token() {
local cache_file
if [ -n "$ACCESS_TOKEN_CACHE_FILE" ]; then
cache_file="$ACCESS_TOKEN_CACHE_FILE"
else
run aws sso login --profile "$AWS_PROFILE_BOOTSTRAP" >&2
# shellcheck disable=SC2012
cache_file=$(ls -t ~/.aws/sso/cache/*.json | head -n 1)
if [ -z "$cache_file" ]; then
cat >&2 <<EOM
Error: Could not find any files at ~/.aws/sso/cache/*.json
Please run \`aws sso login\` with some existing profile to bootstrap.
EOM
return 2
fi
fi
echo >&2 "Loading accessToken, startUrl, region from $cache_file"
ACCESS_TOKEN=$(run jq -r '.accessToken' "$cache_file")
SSO_START_URL=$(run jq -r '.startUrl' "$cache_file")
SSO_REGION=$(run jq -r '.region' "$cache_file")
local expires_at now
expires_at=$(run jq -r '.expiresAt' "$cache_file")
now=$(date -u -Iseconds)
echo >&2 "Read access token from file:"
echo >&2 " token length ${#ACCESS_TOKEN}"
echo >&2 " sso_start_url: $SSO_START_URL"
echo >&2 " sso_region: $SSO_REGION"
echo >&2
if [[ $now > $expires_at ]]; then
echo >&2 "WARNING: token looks expired!"
echo >&2 "expiresAt: $expires_at"
echo >&2 "now: $now"
echo >&2
fi
}
generate_config() {
local account_id name email role
cat <<EOM
# Generated by $0 on $(date)
[sso-session $SSO_SESSION_NAME]
sso_start_url = $SSO_START_URL
sso_region = $SSO_REGION
sso_registration_scopes = sso:account:access
EOM
run aws sso list-accounts --profile "$AWS_PROFILE_BOOTSTRAP" --access-token "$ACCESS_TOKEN" --output text | sort -k3 | while read -r line; do
account_id=$(cut -f 2 <<< "$line")
name=$(cut -f 3 <<< "$line")
email=$(cut -f 4 <<< "$line")
echo >&2 "Account: $account_id -- $name"
echo
echo "# ---"
echo
echo "# Account: $account_id"
echo "# Name: $name"
echo "# Email address: $email"
local role roles roles_raw
roles_raw=$(run aws sso list-account-roles --profile "$AWS_PROFILE_BOOTSTRAP" --account-id "$account_id" --access-token "$ACCESS_TOKEN" --query 'roleList[*].roleName' --output text)
read -ra roles <<< "$roles_raw"
for role in "${roles[@]}"; do
echo
echo "[profile $account_id-$role]"
echo "sso_session = $SSO_SESSION_NAME"
echo "sso_account_id = $account_id"
echo "sso_role_name = $role"
echo "region = $SSO_REGION"
done
done
}
main() {
if [ $# -ne 2 ]; then
usage
exit 1
fi
trap 'echo >&2 ERROR' EXIT
local outfile
AWS_PROFILE_BOOTSTRAP="$1"
outfile="$2"
# don't take AWS_PROFILE from env
unset AWS_PROFILE
# redirect stdout to file
exec >"$outfile"
get_sso_access_token
generate_config
trap - EXIT
echo >&2 "Wrote config to $outfile"
}
main "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment