AWS IAM Identity Center — Paved-Road Setup (Min-ClickOps / Max-IaC)
Audience: HITL/infrastructure operator
Read time: < 5 minutes
Purpose: Enable IAM Identity Center once; Terraform handles all other provisioning.
Principle: Maximum IaC, minimum ClickOps. Manually enable the service. Everything else is Terraform-declared in
infra/terraform-aws/identity/config/.
Safety Rules
Tenant Isolation: Each AWS Organization gets its own Identity Store directory (
d-xxxxxxxxxx). Do NOT reuse directory IDs from prior tenants; Terraform will create and manage a new one.
Automation Profile: The
<YOUR_ORG>-ReadOnlyprofile is the automation team's autonomous-safety layer. All READONLY queries (describe-*,list-*,get-*) run without HITL confirmation. All mutations (create-*,delete-*,modify-*) require HITL execution (Principle I).
Irreducible ClickOps (HITL Only)
Step 1 — Enable IAM Identity Center (One-Time)
- Log into management account → AWS Console
- Navigate to IAM Identity Center (search bar)
- Click Enable IAM Identity Center
- Note the AWS access portal URL (format:
https://<INSTANCE_ID>.awsapps.com/start)
Why not Terraform? No Terraform resource exists to CREATE Identity Center itself; only data.aws_ssoadmin_instances reads it. This is a precondition.
AWS docs: https://docs.aws.amazon.com/singlesignon/latest/userguide/get-started-enable-identity-center.html
Step 2 — First Login (One-Time)
aws sso login --profile <YOUR_ORG>-operations
# Browser opens → MFA → log in with work email → verify email link (if prompted)
Step 3 — Verify Identity (Critical)
aws sts get-caller-identity --profile <YOUR_ORG>-operations
Expected output: Your organization's workload account ID. If it shows a different account, STOP — you may be authenticated to the wrong tenant.
Everything Else Is Terraform
All permission sets, users, groups, and account assignments are declared in infra/terraform-aws/identity/ and driven from YAML config.
Do NOT create these manually in the console.
Deploy Flow
# 1. Set environment (once per session)
set -a; source .env; set +a
# 2. Edit config (specify your users, groups, permission sets)
# Location: infra/terraform-aws/identity/config/
# Files: permission_sets.yaml, account_assignments.yaml
# Details: see infra/terraform-aws/identity/README.md
# 3. Terraform plan (automation can do this)
cd infra/terraform-aws/identity
terraform init \
-backend-config="bucket=<YOUR_ACCOUNT_ID>-tfstate-<AWS_REGION>" \
-backend-config="region=<AWS_REGION>"
terraform plan
# 4. Terraform apply (HITL executes — Principle I)
terraform apply
After apply, all permission sets, users, groups, and account assignments are live and managed by code.
Config Pointers (Do NOT Duplicate Below)
- Consumer README (this deployment):
infra/terraform-aws/identity/README.md- Region override, prerequisites, YAML structure
- Module README (reusable component):
terraform-aws/modules/sso/README.md- Syntax, examples, advanced features (applications, external IdP, permissions boundaries)
CLI Profile Setup (One-Time)
After Terraform apply, configure your shell to use the profiles:
# Edit ~/.zshrc, ~/.bashrc, or .env (gitignored — never commit credentials)
export AWS_MANAGEMENT_PROFILE=<YOUR_ORG>-management
export AWS_OPERATIONS_PROFILE=<YOUR_ORG>-operations
export AWS_READONLY_PROFILE=<YOUR_ORG>-ReadOnly
export AWS_BILLING_PROFILE=<YOUR_ORG>-billing
export AWS_PROFILE=$AWS_OPERATIONS_PROFILE
export AWS_DEFAULT_REGION=<YOUR_AWS_REGION>
# Reload shell
source ~/.zshrc
Generate ~/.aws/config (IaC-Driven)
When the new task sso:config command is available (this session builds it), run:
task sso:config
# Output: copyable ~/.aws/config blocks (profiles auto-generated from Terraform)
Until then, manually configure profiles:
aws configure sso --profile <YOUR_ORG>-management
aws configure sso --profile <YOUR_ORG>-operations
aws configure sso --profile <YOUR_ORG>-ReadOnly
aws configure sso --profile <YOUR_ORG>-billing
Manual vs IaC Boundary
| Task | Owner | Method |
|---|---|---|
| Enable Identity Center instance | HITL | AWS Console (one-time, no TF resource) |
| First login + MFA + email verify | HITL | aws sso login + browser |
| Verify identity is correct | HITL | aws sts get-caller-identity |
| Create permission sets | Terraform | config/permission_sets.yaml |
| Create users/groups | Terraform | config/ YAML + sso_users, sso_groups |
| Assign users to accounts | Terraform | config/account_assignments.yaml |
| Configure CLI profiles | HITL | aws configure sso or task sso:config |
| Run READONLY queries | Automation | aws describe-*, aws list-* with $AWS_READONLY_PROFILE |
| Run mutations (create/delete) | HITL | aws create-*, terraform apply |
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
Token has expired and refresh failed | SSO session stale | aws sso login --profile <YOUR_ORG>-operations |
Invalid SSO start URL | Region/instance mismatch | Check IAM Identity Center → Dashboard |
aws sts get-caller-identity shows wrong account | Authenticated to wrong tenant | Log out; verify portal URL; re-login |
Terraform AccessDeniedException | Profile lacks permission | Verify user assigned correct permission set in account_assignments.yaml |
References
- This deployment:
infra/terraform-aws/identity/README.md(prerequisites, YAML config, Entra ID path) - Module docs:
terraform-aws/modules/sso/README.md(syntax, examples, edge cases) - AWS docs: https://docs.aws.amazon.com/singlesignon/latest/userguide/what-is.html
- CLI docs: https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-sso.html