Skip to content

Instantly share code, notes, and snippets.

@atheiman
Last active November 4, 2025 22:48
Show Gist options
  • Select an option

  • Save atheiman/b99f8f98308ad1b3df9d9cf3a6e12a98 to your computer and use it in GitHub Desktop.

Select an option

Save atheiman/b99f8f98308ad1b3df9d9cf3a6e12a98 to your computer and use it in GitHub Desktop.
AWS SSO Identity Center accounts and roles config generator - ~/.aws/config
#!/usr/bin/env python3
# Write content for an AWS config file (~/.aws/config) to stdout based on available SSO accounts and roles
# from the previously executed `aws sso login`.
#
# Example usage:
#
# aws sso login --profile my-existing-sso-profile
# python ./aws_config_generator.py
#
# SSO session name will default to the region of the connected Identity Center / SSO instance. It can be
# customized with environment variable SSO_SESSION_NAME. This is useful if you have multiple Identity Center
# instances to interact with, ie. multiple AWS organizations or Commercial + GovCloud.
#
# aws sso login --profile org1-sso-profile
# SSO_SESSION_NAME=org1 python ~/aws_config_generator.py
# aws sso login --profile org2-sso-profile
# SSO_SESSION_NAME=org2 python ~/aws_config_generator.py
#
# The closest equivalent to this with AWS CLI is:
#
# CACHE_FILE="$(ls -t ~/.aws/sso/cache/*.json | head -n 1)"
# ACCESS_TOKEN="$(jq -r .accessToken "$CACHE_FILE")"
# aws sso list-accounts --access-token $ACCESS_TOKEN --region us-east-1 --output yaml
#
# for ACCOUNT_ID in $(aws sso list-accounts --access-token $ACCESS_TOKEN --region us-east-1 --output text --query 'accountList[].accountId'); do
#   aws sso list-account-roles --access-token "$ACCESS_TOKEN" --account-id "$ACCOUNT_ID" --region us-gov-west-1 --output text --query 'roleList[]'
# done
#
import boto3
import botocore
import configparser
from datetime import datetime, timezone
import glob
import json
import os
import sys
def main():
sso_cache_files_glob_path = os.path.join(
os.environ["HOME"], ".aws", "sso", "cache", "*.json"
)
sso_cache_files = glob.glob(sso_cache_files_glob_path)
if not sso_cache_files:
raise Exception(
f"No AWS SSO access tokens found at path '{sso_cache_files_glob_path}'. Login using `aws sso login` before running this script. A valid SSO access token needs to be read from this path."
)
latest_cache_file_path = max(sso_cache_files, key=os.path.getmtime)
# print("SSO cache JSON file:", latest_cache_file_path)
with open(latest_cache_file_path) as fp:
sso_cache_data = json.load(fp)
# print(json.dumps(sso_cache_data, default=str, indent=2))
expires_dt = datetime.strptime(sso_cache_data["expiresAt"], "%Y-%m-%dT%H:%M:%SZ")
expires_dt = expires_dt.replace(tzinfo=timezone.utc)
config = configparser.ConfigParser()
sso_session_name = os.environ.get("SSO_SESSION_NAME", sso_cache_data["region"])
config[f"sso-session {sso_session_name}"] = {
"sso_start_url": sso_cache_data["startUrl"],
"sso_region": sso_cache_data["region"],
"sso_registration_scopes": "sso:account:access",
}
sso = boto3.client("sso", region_name=sso_cache_data["region"])
accts = []
try:
for pg in sso.get_paginator("list_accounts").paginate(
accessToken=sso_cache_data["accessToken"]
):
accts += pg["accountList"]
except sso.exceptions.UnauthorizedException as err:
if datetime.now(timezone.utc) > expires_dt:
raise Exception(
f"accessToken loaded from '{latest_cache_file_path}' is expired (expiresAt: '{expires_dt}'). Login again with `aws sso login` to renew the access token."
) from err
else:
raise err
for acct in accts:
# print(json.dumps(acct, default=str, indent=2))
for pg in sso.get_paginator("list_account_roles").paginate(
accessToken=sso_cache_data["accessToken"],
accountId=acct["accountId"],
):
for role in pg["roleList"]:
# print(json.dumps(role, default=str, indent=2))
config[f"profile {acct['accountName']}-{role['roleName']}"] = {
"sso_session": sso_session_name,
"sso_account_id": acct["accountId"],
"sso_role_name": role["roleName"],
"region": sso_cache_data["region"],
}
print()
config.write(sys.stdout)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment