Allowlist
Progress checklist
Overview
Section titled “Overview”demo.sh allowlist rewrites package bucket policies from .lab-state.json.
The public catalog UI bucket is not touched — it stays a public website.
Same shape on primary and replica; only the gateway ID list changes.
Who can read packages from the replica (…-pkgs-…-akl):
- Auckland S3 gateway VPCE (
aws:SourceVpce):GetObject/ListBucketfor the Akl probes - SSO admin, CRR, publisher, rebuild Lambda: bypass principals
- Everyone else (internet, wrong Region gateway): denied on Get
The Sydney gateway is not on the replica allowlist.
Policy SIDs (package buckets):
- AllowAdminAndRoles: full
s3:*for admin + CRR + publisher + Lambda - AllowSSLRequestsOnly: deny non-TLS
- DenyGetUnlessVpce: deny
GetObjectunlessaws:SourceVpcematches (bypass ARNs exempt) - AllowVpceRead: allow
GetObject/ListBucketvia that VPCE
If a Region has no consumer yet, that package bucket only gets the bypass + TLS
statements (no VPCE lock). Run up-consumer in both Regions first, then
allowlist once.
-
Apply policies from state (needs Syd and Akl gateway VPCE IDs):
Terminal window export AWS_PROFILE=sandbox./scripts/demo.sh allowlistallowlist applied to package buckets only (syd=["vpce-<id>"] akl=["vpce-<id>"]); UI bucket unchanged
Verify
Section titled “Verify”PRIMARY="$(jq -r .primary_bucket .lab-state.json)"REPLICA="$(jq -r .replica_bucket .lab-state.json)"UI="$(jq -r .ui_bucket .lab-state.json)"KEY=repos/_lab/allowlist-verify.txtSYD_AL="$(jq -r .consumers.syd.al2023.instance_id .lab-state.json)"Seed object (admin bypass)
Section titled “Seed object (admin bypass)”echo "allowlist verify" | aws s3 cp - "s3://${PRIMARY}/${KEY}" --region ap-southeast-2upload: - to s3://ps3p-pkgs-**ACCOUNT**-syd/repos/_lab/allowlist-verify.txtPrimary (Sydney pkgs)
Section titled “Primary (Sydney pkgs)”aws s3api get-bucket-policy --bucket "$PRIMARY" --region ap-southeast-2 \ --query Policy --output text | jq '.Statement[] | {Sid, Effect}'{ "Sid": "AllowAdminAndRoles", "Effect": "Allow" }{ "Sid": "AllowSSLRequestsOnly", "Effect": "Deny" }{ "Sid": "DenyGetUnlessVpce", "Effect": "Deny" }{ "Sid": "AllowVpceRead", "Effect": "Allow" }aws s3api get-bucket-policy --bucket "$PRIMARY" --region ap-southeast-2 \ --query Policy --output text \ | jq -r '.Statement[] | select(.Sid=="DenyGetUnlessVpce") | .Condition.StringNotEquals["aws:SourceVpce"]'vpce-<id>(With a single gateway ID, IAM stores aws:SourceVpce as a string; multiple
IDs would be an array.)
Replica (Auckland pkgs)
Section titled “Replica (Auckland pkgs)”aws s3api get-bucket-policy --bucket "$REPLICA" --region ap-southeast-6 \ --query Policy --output text | jq '.Statement[] | {Sid, Effect}'{ "Sid": "AllowAdminAndRoles", "Effect": "Allow" }{ "Sid": "AllowSSLRequestsOnly", "Effect": "Deny" }{ "Sid": "DenyGetUnlessVpce", "Effect": "Deny" }{ "Sid": "AllowVpceRead", "Effect": "Allow" }aws s3api get-bucket-policy --bucket "$REPLICA" --region ap-southeast-6 \ --query Policy --output text \ | jq -r '.Statement[] | select(.Sid=="DenyGetUnlessVpce") | .Condition.StringNotEquals["aws:SourceVpce"]'vpce-<id>UI bucket (unchanged / still public)
Section titled “UI bucket (unchanged / still public)”aws s3api get-bucket-policy --bucket "$UI" --region ap-southeast-2 \ --query Policy --output text | jq '.Statement[] | {Sid, Effect}'{ "Sid": "PublicReadWebsite", "Effect": "Allow" }curl -sS -o /dev/null -w "ui_index %{http_code}\n" \ "http://${UI}.s3-website-ap-southeast-2.amazonaws.com/"ui_index 200Deny anonymous package Get
Section titled “Deny anonymous package Get”curl -sS -o /tmp/allowlist-curl.body -w 'http_code=%{http_code}\n' \ "https://${PRIMARY}.s3.ap-southeast-2.amazonaws.com/${KEY}"head -c 160 /tmp/allowlist-curl.body; echohttp_code=403<?xml version="1.0" encoding="UTF-8"?><Error><Code>AccessDenied</Code><Message>Access Denied</Message>...aws s3api head-object --bucket "$PRIMARY" --key "$KEY" \ --region ap-southeast-2 --no-sign-requestaws: [ERROR]: An error occurred (403) when calling the HeadObject operation: ForbiddenAllow admin + Syd probe
Section titled “Allow admin + Syd probe”aws s3api head-object --bucket "$PRIMARY" --key "$KEY" \ --region ap-southeast-2 --query ContentLength --output text17CMD_ID=$(aws ssm send-command \ --instance-ids "$SYD_AL" \ --document-name AWS-RunShellScript \ --parameters "commands=[\"aws s3api head-object --bucket $PRIMARY --key $KEY --region ap-southeast-2 --query ContentLength --output text\"]" \ --region ap-southeast-2 \ --query 'Command.CommandId' --output text)aws ssm get-command-invocation --command-id "$CMD_ID" --instance-id "$SYD_AL" \ --region ap-southeast-2 \ --query '{Status:Status,StdOut:StandardOutputContent}' --output json{ "Status": "Success", "StdOut": "17\n"}