Created
June 25, 2025 13:31
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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