CAP-C01 study materials
CAP-C01 study resources

Over-Permissive IAM Role in a Multi-Account Cloud

CAP-C01 · Put your knowledge to work in context.

All case studies

Over-Permissive IAM Role in a Multi-Account Cloud

A cloud org has 40 AWS accounts under an organization. A CI/CD role in the shared-services account has an inline policy granting s3:* and iam:PassRole on *, plus sts:AssumeRole on *. The role is assumable by any principal in the organization via a trust policy with Principal: "*" and a condition on aws:PrincipalOrgID. Build logs show the role is used by 12 pipelines. A developer's compromised laptop holds long-lived access keys for a low-privilege account. An auditor flags the role as 'critical.' The platform team says the org-ID condition makes it safe.

1. Evaluate the org-ID condition as a control and the actual blast radius.

Read the worked answer

The org-ID condition restricts who can assume to accounts in the org - it does not restrict what the role can do once assumed. Any compromised principal in any of the 40 accounts (including the developer's low-privilege account) can assume the role and inherit s3:*, iam:PassRole on *, and sts:AssumeRole on *. iam:PassRole on * plus role assumption is a privilege-escalation path: pass a more privileged role to a service and act through it. So the condition narrows the entry point to 'any of 40 accounts' - which, given one compromised low-priv account, is effectively the whole org. Blast radius: all S3 data in reachable accounts and potential escalation to admin-equivalent roles. The auditor is right.

2. Design the least-privilege replacement and the detection you would add, given 12 pipelines depend on it.

Read the worked answer

Replacement: scope s3:* to the specific buckets/prefixes each pipeline needs (or split into per-pipeline roles), remove iam:PassRole on * and grant it only on the exact roles the pipelines must pass, and replace sts:AssumeRole on * with named target roles. Tighten the trust policy from Principal: "*" + org condition to specific role ARNs (or at least specific accounts) with aws:SourceAccount/aws:ExternalId where applicable. Because 12 pipelines depend on it, migrate incrementally: inventory actual API calls via CloudTrail, right-size per pipeline, run in parallel, then cut over. Detection: alert on AssumeRole into this role from unexpected principals, on PassRole to roles outside an allow-list, and on s3:* calls to buckets outside the expected set - so drift is caught even after the policy is tightened.