IAM
AWS Identity and Access Management (IAM) decides who can do what on which resource in an AWS account. The platform uses IAM roles for every identity, human and machine, and never creates IAM users.
What it does
IAM has two kinds of identity. An IAM user is a permanent identity with a password or long-lived access keys. An IAM role is an identity that is assumed for a session and hands out temporary credentials. A role has a trust policy (who may assume it) and permission policies (what it may do). Policies are JSON documents of allow and deny statements. AWS also provides managed policies such as AdministratorAccess, PowerUserAccess and ReadOnlyAccess, and service-linked roles that a service creates for itself.
IAM is a global service: a role exists once per account, not per region. That is why the platform places IAM units in global/ folders.
How BuiltForProd uses it
The acme-security-guardrails SCP denies creating IAM users, login profiles and access keys in every member account. People sign in through IAM Identity Center, whose permission sets become IAM roles in each account. Machines use roles with narrow trust policies. The AWS Baseline creates these:
| Role | Account | Purpose |
|---|---|---|
acme-terraform-deployer | Every account, from modules/account-baseline | The single entry point for pipelines; carries AdministratorAccess; trusts only acme-*-deployer roles in core-auto and, in plat-* accounts, the secrets syncer |
acme-<repo>-deployer | core-auto, from modules/github-oidc | One role per infrastructure repository, assumed by GitHub Actions through OIDC |
acme-terraform-state-access | core-root | Read and write access to the state bucket for automation roles in every account |
acme-route53-cross-account | core-dns and core-network | Lets workload accounts write ACM validation and ExternalDNS records into the public and private zones |
acme-ssm-cross-account | core-auto | Read access to /acme/* parameters for workload accounts |
acme-secrets-syncer | core-security | Assumed by the secrets repository workflow to decrypt SOPS files and write parameters |
acme-<stage>-config-role | Member accounts | The AWS Config recorder role; the management account uses the service-linked role instead |
Every automation role carries the tag mfa-exempt = true so the guardrails SCP does not block it. Cross-account access always goes through one of these purpose-built roles, never through broad trust between accounts.
The blueprints add workload roles: EKS Pod Identity roles for the AWS Load Balancer Controller, ExternalDNS, the External Secrets Operator and the application service account; an IRSA role for Fluent Bit; the Glue job role; the Lambda execution role; and the Lake Formation service role. Each is scoped to its own log group, parameter path or bucket.
Two review tools watch the result. IAM Access Analyzer reports resources shared outside the organization and roles unused for 90 days. The SecurityAuditorAccess permission set can read IAM configuration but is explicitly denied data-plane reads such as s3:GetObject and ssm:GetParameter.
Terms you will see
| Term | Meaning |
|---|---|
| Role | An identity assumed for a session; the only identity type the platform creates. |
| Trust policy | The part of a role that names who may assume it. |
| Managed policy | An AWS-maintained policy such as ReadOnlyAccess, attached by ARN. |
| Inline policy | A policy written into one role or permission set. |
| Service-linked role | A role an AWS service creates and owns for its own use. |
| IRSA | IAM Roles for Service Accounts, the older way to give a Kubernetes pod a role. |
| Pod Identity | The EKS feature that associates a role with a Kubernetes service account. |
Where to read more
- AWS Baseline overview for where each account and role sits.
- STS and role assumption for how the roles above chain together.
- GitHub OIDC for how pipelines obtain a role without stored keys.