⚠️ Redaction statement: This repository contains no secrets, credentials, IPs, account IDs, or tenant identifiers. Values are placeholders only and must be provided via secure parameter stores (AWS SSM Parameter Store / Secrets Manager) at deploy time.
A production-ready reference for time-bound, auditable privileged access to AWS accounts using AWS IAM Identity Center (successor to AWS SSO). Requests are approved via Step Functions and EventBridge, access is granted by a Lambda that creates an account assignment to a chosen Permission Set, and a scheduled revocation ensures automatic expiry. All actions are logged to CloudTrail and surfaced in Security Hub for continuous assurance.
Key goals
- ⏱️ Least privilege with JIT elevation (minutes to hours, not permanent)
- 🔐 Centralized auth (Identity Center) and standardized permission sets
- 🧾 Full audit trail (CloudTrail + CloudWatch Logs + optional Detective)
- 🧯 Safe by default: automated revocation + cut-off if approvals time out
- 🌍 Optional: geo-/region-guardrails via SCP & GuardDuty findings
flowchart LR
subgraph User_Approver["User & Approver"]
RQ["Requester\n(requests elevation)"]
AP["Approver\n(Ops/Sec/On-Call)"]
end
RQ -->|Submit request| EVB["Amazon EventBridge\n(AccessRequest Bus)"]
EVB --> SFN["Step Functions\n(Approval State Machine)"]
SFN -->|Notify| SNS["SNS/ChatOps\n(Email/Slack/Teams)"]
AP -->|Approve/Deny| SFN
SFN -->|On Approve| L1["Lambda: GrantAssignment"]
L1 --> SSO["AWS IAM Identity Center\n(sso-admin API)"]
SSO --> ACC["Target Account"]
SFN -->|Schedule expiry| SCH["EventBridge Scheduler"]
SCH --> L2["Lambda: RevokeAssignment"]
L2 --> SSO
SFN --> CT["CloudTrail & CW Logs"]
CT --> HUB["Security Hub"]
- Plan — Define permission sets, target accounts, max durations, approver groups, and break-glass policy.
- Build — Deploy core stack (EventBridge bus, Step Functions, Lambdas, IAM roles, log groups). Register parameters (SSM/Secrets Manager).
- Test — Dry-run with non-prod account; validate approvals, assignment, expiry, and logs.
- Release — Promote to prod; enable alarms (CloudWatch, Security Hub standards).
- Operate — Use
RUNBOOK.mdfor day-to-day requests, on-call actions, and KPIs. - Monitor — Dashboards, error alarms, SLA/SLO reporting.
- Secure — Guardrails: SCPs (region allow-list), CloudTrail org-trail, GuardDuty, Access Analyzer.
- DR & Rollback — See
docs/ROLLBACK.mdanddocs/CUTOVER_CHECKLIST.mdfor safe change and recovery.
.
├── README.md
├── RUNBOOK.md
├── .gitignore
├── docs
│ ├── OVERVIEW.md
│ ├── ARCHITECTURE.md
│ ├── CUTOVER_CHECKLIST.md
│ ├── ROLLBACK.md
│ └── SECURITY.md
└── scripts
├── deploy.sh
├── create-permission-set.ps1
├── request_access_example.json
└── lambda
├── assignment_manager.py
└── template.yaml
# 1) Create and activate a Python venv for Lambda deps (optional)
python3 -m venv .venv && source .venv/bin/activate
# 2) Validate AWS credentials (no account IDs in repo)
aws sts get-caller-identity
# 3) Package & deploy (SAM) - see scripts/deploy.sh
./scripts/deploy.sh dev- No hard-coded account IDs, ARNs, or emails in this repository.
- No sample noise: all examples are minimal and redacted.
- SCIM/IdP provisioning is assumed present and managed outside this stack.
- Secrets: Use AWS Secrets Manager / SSM Parameter Store; never commit secrets.
- Policies: Permission sets should be least privilege, split by duty (e.g.,
ReadOnly,PowerUserScoped,BreakGlassLimited). - Logging: Lambda logs retained 90d+; CloudTrail org-trail active; Security Hub enabled in all regions in scope.
MIT — see LICENSE if you add one.