aws:PrincipalOrgID: One Bucket Policy That Grants Access to Every Account in Your Organization

Ned
Ned Cloud Engineer
· Updated · 3 min read
aws:PrincipalOrgID: One Bucket Policy That Grants Access to Every Account in Your Organization

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.

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. Massive management burden.

Key Takeaways

  • aws:PrincipalOrgID is the least-overhead way to grant org-wide access
  • One policy, no updates when accounts are added or removed
  • Use aws:PrincipalOrgPaths for OU-level scoping, aws:PrincipalOrgID for org-wide
  • These condition keys work in any resource-based policy: S3, SNS, SQS, KMS, Secrets Manager
  • Combine with aws:SecureTransport and other conditions for defense in depth
Rating:
Share
Previous S3 Block Public Access + SCP: Two Layers That Make Accidental Public Buckets Impossible