The Problem
Your management account has an S3 bucket with project reports. You want all accounts in your AWS Organization to be able to access it (including future accounts you have not created yet) with the least operational overhead.
The Solution
Add the aws:PrincipalOrgID global condition key to the bucket policy. One static policy, evaluated against the caller’s organization at request time.
How It Works
The Bucket Policy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"Version": "2012-10-17",
"Statement": [{
"Sid": "AllowOrgAccess",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::project-reports/*",
"Condition": {
"StringEquals": {
"aws:PrincipalOrgID": "o-abcd1234"
}
}
}]
}
At request time, AWS looks up the caller’s organization ID and compares it to o-abcd1234. Match → allowed. Mismatch or not in an org → denied.
Why This Beats Enumerating Accounts
Without aws:PrincipalOrgID, you would list every account ID in the Principal field:
1
2
3
4
5
6
7
8
"Principal": {
"AWS": [
"arn:aws:iam::111111111111:root",
"arn:aws:iam::222222222222:root",
"arn:aws:iam::333333333333:root",
...
]
}
Every new account requires a policy update. aws:PrincipalOrgID eliminates this entirely.
Related Condition Keys
| Key | Purpose |
|---|---|
aws:PrincipalOrgID |
Match a specific organization |
aws:PrincipalOrgPaths |
Match a specific OU path (e.g., only Finance OU) |
aws:SourceOrgID |
Match the caller’s org (for cross-account service calls) |
aws:PrincipalAccount |
Match a specific account ID |
aws:PrincipalTag/<key> |
Match a tag on the caller |
Use PrincipalOrgID when you want everyone in the org. Use PrincipalOrgPaths when you want a specific OU subtree.
Getting Your Organization ID
1
2
aws organizations describe-organization \
--query 'Organization.Id' --output text
Returns something like o-abcd1234.
Why Not the Alternatives?
aws:PrincipalOrgPaths with per-department OUs: works but more complex than needed. Use PrincipalOrgID when the whole org gets access.
CloudTrail monitoring account events + policy updates: reactive and high overhead. Every account change triggers a policy rewrite. Terrible operational model.
Tagging every user + aws:PrincipalTag: requires tagging every principal in every account, then keeping the tags in sync.
Key Takeaways
aws:PrincipalOrgIDis the least-overhead way to grant org-wide access- One policy, no updates when accounts are added or removed
- Use
aws:PrincipalOrgPathsfor OU-level scoping,aws:PrincipalOrgIDfor org-wide - These condition keys work in any resource-based policy: S3, SNS, SQS, KMS, Secrets Manager
- Combine with
aws:SecureTransportand other conditions for defense in depth
Never miss a story from us, subscribe to our newsletter