Cloud permissions with a tenant boundary

The billing service needs to download only Acme invoice objects. Its current role can read another tenant and write objects. Produce a narrower policy and an evidence-based verification plan.

Cloud · about 60 minutes. Fictional evidence; Python 3.10+ for local coding.

Prerequisites

Evidence

current-policy.json

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": "s3:*",
    "Resource": ["arn:aws:s3:::billing-prod", "arn:aws:s3:::billing-prod/*"]
  }]
}
This identity policy is attached to the fictional billing-api role.
Role trust, bucket policy, permission boundary, session policy, SCP and KMS grants are not included.

required-access.txt

Principal: billing-api
Action: s3:GetObject only
Object prefix: arn:aws:s3:::billing-prod/tenants/acme/
No bucket listing, writes, deletes, other tenant, lookalike bucket, or other principal.
The exercise models objects with a non-empty suffix under that prefix.
A real S3 prefix is a key prefix, not a filesystem path.
Scope assumes each deployed tenant has a separately trusted role assignment.

review-notes.txt

Observed: role can GetObject tenants/birch/invoice-7.pdf.
No evidence yet of historical downloads or data exfiltration.
A scanner marks the wildcard action as High.
A proposed fix changes s3:* to s3:GetObject but keeps billing-prod/*.
Another proposed fix grants tenants/acme* (also matches acme-backups).
Encryption, a public-access block, or a severity label does not narrow this authenticated role grant.

Tasks and expected evidence

  1. Write a minimal identity-policy statement for the required object downloads. Explain why a GetObject grant uses an object ARN and does not need a bucket ListBucket grant.
  2. Edit object_download_allowed to model the exact principal, action, bucket, and tenant-prefix contract. Run the iam suite without --reference.
  3. Design a real policy-validation matrix with one allow and at least five denies. State how you would inspect all applicable policy layers in an isolated authorized account.
  4. Write a finding that distinguishes observed access from unproven historical exfiltration. Include policy version, test principal, tested objects, and remaining KMS/resource-policy questions.

Run the coding exercise

Download the Python exercise. It uses only the standard library and no network.

python expert_security_lab.py --lab iam
python expert_security_lab.py --lab iam --reference

Starter mode initially fails. Edit the matching function and rerun without --reference. Reference mode tests supplied code, not your own fix.

Limits

The Python predicate is a small access contract, not an AWS IAM simulator. Real decisions can depend on explicit denies, resource policies, SCPs, boundaries, sessions, role trust, and KMS.

All expert cases