Skip to content

Why AWS access is split into four groups

Access to our twelve AWS accounts comes from four SSO groups. This page explains why we shaped them this way. The reasoning should survive the next person who wonders whether four groups could be three.

Group Role Accounts
IAM AWS-SSO Marketplaces-Mobility-NonProd-ReadOnly ReadOnly 7 non-prod
IAM AWS-SSO Marketplaces-Mobility-NonProd-Developer DevAdmin + ReadOnly 7 non-prod
IAM AWS-SSO Marketplaces-Mobility-Prod-ReadOnly ReadOnly 5 prod
IAM AWS-SSO Marketplaces-Mobility-Prod-Developer DevAdmin + ReadOnly 5 prod

The account lists live in tools/aws-sso/accounts.json.

In prod, the whole team is in the Prod-ReadOnly group. The Prod-Developer group holds the few people who know what to do when prod breaks, and who run releases. We have no formal on-call rotation, so this is a named handful rather than a rota. Read-only access covers logs, metrics and nearly all debugging, so the narrow group is needed far less often than it first appears.

This buys one property: you can answer “who can change prod?” by reading a single membership list. That is what makes a quarterly review cheap. It is also why we did not add more prod groups. Each extra group granting prod write turns that question into a union of lists. More lists mean more owners maintaining them, and more places to forget someone when they rotate off.

The four groups are the standing set, not a ceiling. A custom group with its own permission set can be created when a need appears that none of the four fits — a narrow role for one service, say, or write access to a single kind of resource. None exists yet. Raise the need through the access guide in Confluence MONE, and hold it to the same bar that keeps prod write in one list: a new group must grant something the existing four cannot, not merely save someone a membership.

Non-prod has the same two groups as prod, and the NonProd-Developer group already contains everything the NonProd-ReadOnly group grants. We made that overlap deliberately. Blast radius in non-prod is low and no narrow tier is worth protecting, so saving engineers a second membership beats audit sharpness. Pick one group per person rather than stacking them.

The NonProd-ReadOnly group exists for analysts, marketing, externals and new joiners — and as the landing spot for someone whose write access is being wound down.

alma-ajo-common-infra-prod sits in the same group as the application prod accounts. It has the widest blast radius of the twelve: a mistake there degrades everything else. We accepted that bundling to keep the group count at four, which means membership is the only remaining control on it. Two consequences:

  • Keep the Prod-Developer group to the handful who handle prod incidents and releases, and treat membership as tied to that responsibility rather than permanent.
  • Deploy through per-account GitHub OIDC roles so routine releases never require a human in that group. If a deploy needs a person with the DevAdmin role in prod, that is a pipeline gap, not an access request.

Before Identity Center, access worked in two hops. A long-lived access key authenticated you against the alma-iam account (142020163350) with MFA, and aws-mfa then assumed a *-CAM role into whichever account you needed. SSO replaces both hops, so nothing in that setup needs to survive.

alma-iam never appears in accounts.json because it was never a destination — only the door.

Some repositories still carry the old setup instructions, and so does Confluence: the AWS IAM page in space ALMA is the canonical description of the old way — alma-iam, aws-mfa, AWS CLI v1 in a virtualenv, and *-CAM roles. It is worth recognising, because none of it applies any more. Retiring your own old credentials is step 5 of the how-to.

Alma’s convention is IAM AWS-SSO {segment}-{team}-{environment}-{role}, so our groups read Marketplaces-Mobility-…. The AWS accounts keep their older ajo-* / alma-ajo-* prefixes. The team token and the account prefix intentionally do not match: one names the team, the other is naming history.

The role half of a group name comes from the permission sets assigned to it. Developer is Alma’s predefined bundle of DevAdmin + ReadOnly, and the Cloud team owns that mapping. Treat it as current behaviour, not a contract. When a group’s effective permissions matter to a decision, ask the Cloud team through the access guide in Confluence MONE rather than inferring from the name.