Skip to content

AWS Access

AWS account: 696081601609 (region us-east-1).

This doc explains how to authenticate to AWS day-to-day, what each identity is for, and the 2026-09-05 migration that moved us off root credentials.

TL;DR β€” daily use

Terminal window
aws sso login # opens browser, approve, done. Creds last ~8h.
aws sts get-caller-identity
# β†’ arn:aws:sts::696081601609:assumed-role/AWSReservedSSO_AdministratorAccess_.../larry

Your default profile is IAM Identity Center (SSO). When the CLI says credentials are expired, run aws sso login again and re-approve in the browser. That is the only recurring step. Nothing stores a long-lived key on disk.

Access portal (browser console sign-in): https://d-90667c73d1.awsapps.com/start β€” username larry + password + MFA. Click the account tile β†’ AdministratorAccess.

The three ways to authenticate

IdentityUse it forHowCredential type
IAM Identity Center (SSO) β€” user larryEverything day-to-day (CLI + console)aws sso login / access portalTemporary (~8h), MFA-gated
Root user β€” [email protected]~Never. Only root-only account tasks (see below)Console sign-in as β€œRoot user” + MFAPassword + MFA (no access keys)
cdk-deployer IAM user (accessible profile)Break-glass only, if SSO is ever unavailable--profile accessibleLong-lived access key (the only one left)

CI/CD does not use any of these β€” GitHub Actions authenticates via OIDC (below).

Local profiles (~/.aws/config / ~/.aws/credentials)

  • [default] and [profile accessible-sso] β†’ SSO, AdministratorAccess, us-east-1.
  • [profile accessible] β†’ cdk-deployer static key (break-glass).
  • [sso-session anglinai] β†’ start URL https://d-90667c73d1.awsapps.com/start.

Root-only tasks (the rare reasons to sign in as root)

AdministratorAccess (your SSO role) can do essentially everything. A small set of account-level actions are reserved to root and cannot be granted to any IAM/SSO identity:

  • Change the root email, root password, or account name
  • Close the AWS account
  • Change or cancel the AWS Support plan
  • Restore access after an IAM/policy lockout
  • Toggle IAM access to billing data
  • Enable S3 MFA Delete on a bucket
  • Register as a Reserved Instance Marketplace seller; sign up for GovCloud

For these: sign in as root with MFA, do the one task, sign out. Root has no access keys and must never have any.

Note: enabling Identity Center also created an AWS Organization with this account as the management account. There are no Service Control Policies (SCPs) today, so the SSO admin role is effectively equal to root for daily work. If SCPs are ever added they constrain IAM/SSO principals but never the management account’s root β€” root remains the ultimate backstop.

CI/CD authentication (GitHub OIDC)

Workflows (deploy-aws.yml, rotate-secrets.yml) assume an IAM role via GitHub’s OIDC provider β€” no AWS keys are stored in GitHub.

  • OIDC provider: token.actions.githubusercontent.com (audience sts.amazonaws.com)
  • Role: github-actions-deploy, trust scoped to repo:LarryAnglin/theaccessible-platform:*, AdministratorAccess attached
  • Repo secrets: AWS_DEPLOY_ROLE_ARN (the role ARN) and AWS_ACCOUNT_ID. Neither is a live credential.

Workflows need permissions: id-token: write and use:

- uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_DEPLOY_ROLE_ARN }}
aws-region: us-east-1

deploy-aws.yml auto-runs on push to main under a path filter (workers/**, infra/cdk/**, services/**, select packages/**). Changes to .github/** alone do not trigger it β€” dispatch manually to test: gh workflow run deploy-aws.yml.

What we did β€” 2026-09-05 migration off root

Before: root had active access keys sitting in the local default CLI profile, and CI used static AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY repo secrets. A leaked root key = unscoped, unrevocable total account compromise. We moved to the AWS-recommended model: root has zero keys, humans use SSO temporary creds, CI uses OIDC.

  1. CI β†’ OIDC. Created the GitHub OIDC provider + github-actions-deploy role; rewired deploy-aws.yml and rotate-secrets.yml to role-to-assume (PR #2679). Verified with a full production deploy, then deleted the static AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY repo secrets.
  2. Humans β†’ IAM Identity Center (SSO). Enabled Identity Center (us-east-1, single region), created user larry + an AdministratorAccess permission set (8h sessions) assigned to the account. Repointed the local default profile to SSO and removed the root key from ~/.aws/credentials. Enforced MFA in Identity Center settings.
  3. Deleted the root access keys. Root can hold up to two β€” deleted both (an old inactive one was easy to miss). Confirmed AccountAccessKeysPresent: 0, AccountMFAEnabled: 1. Root login/password/MFA retained as break-glass.
  4. Rotated the break-glass key. Replaced cdk-deployer’s long-lived key with a fresh one so no credential predates the migration.

End state

  • Root: zero access keys, MFA on, console-only.
  • Humans: SSO temporary creds, MFA enforced.
  • CI: OIDC temporary creds, no stored secrets.
  • One long-lived key remains by design: cdk-deployer break-glass.

Troubleshooting

  • β€œThe security token included in the request is expired” / SSO errors β†’ aws sso login (session lapsed; ~8h TTL).
  • Locked out of SSO β†’ use the break-glass profile: aws ... --profile accessible. If that key is also lost, sign in as root (console) and re-mint a key or fix Identity Center.
  • A deploy didn’t fire after merging to main β†’ check the path filter; if the change was outside it, run gh workflow run deploy-aws.yml manually.
  • Rotate the break-glass key (driven from an SSO admin session so it isn’t self-dependent):
    Terminal window
    export AWS_PROFILE=accessible-sso
    aws iam create-access-key --user-name cdk-deployer # put new key in [accessible]
    # verify: aws sts get-caller-identity --profile accessible
    aws iam delete-access-key --user-name cdk-deployer --access-key-id <OLD_ID>