Large S3 Bucket With External Access -- Consider Requester Pays
What does ZopNight detect here?
S3 buckets over the 1 TiB size floor with public access enabled and Requester Pays off are pre-filtered as candidates, but ZopNight abstains on all of them today. The saving would be external egress GB and GET requests shifted to requesters, yet no authoritative per-bucket producer exists, and a fabricated figure is banned.
Signal and threshold
| Field | Value |
|---|---|
| Rule IDs | RC-175 |
| Category | rightsizing |
| Severity | low |
| Metric | none — pure configuration read |
| Source | s3_requester_pays.go |
Where it applies
Public access on a bucket over 1 TiB
- Metadata[“requester_pays”] (bool, s3.go:675): skip when already enabled.
- Metadata[“public_access_enabled”] (bool, s3.go:455/458), the external-access gate (a superset proxy; the prior external_access Tag was never written). Fail-closed when absent.
- size gate: sum of Metadata[“storageClasses”] class→GB ≥ 1024 GB (1 TiB floor; the prior size_large Tag was never written).
- PRODUCER-GAP: external_data_transfer_out_gb (monthly external DataTransfer-Out GB) and external_get_requests (monthly external GET/SELECT count): the per-bucket cross-account/anonymous egress quantities. No authoritative producer today.
The egress quantities no producer supplies
concrete-or-abstain (cost-driven rightsizing). The concrete saving is the external egress that shifts to the requester: SavingsUSD = external_data_transfer_out_gb × egressRate + external_get_requests × requestRate, at S3’s published data-transfer and request rates. Those quantities are unquantifiable from any authoritative, non-tag, lightweight source today (see (a)/(b)/(c)), so Part A abstains (returns nil) instead of emitting the banned $0 advisory or the over-counted aggregate; the size/public/not-already-enabled gates are retained as real pre-filters. Close condition (Part B): land external_data_transfer_out_gb/external_get_requests per bucket from source (c) (Requester-field-classified access-log/CloudTrail analytics, gated on that logging being enabled), then fire concretely on SavingsUSD >= floor. (The prior code returned Category=“advisory” SavingsUSD=0 specifically so shouldDropLowSavings would not drop it, which is the banned advisory-dump for a cost lever; the category is corrected to the true cost-driven axis.)
Turning on Requester Pays
- Verify external consumers can authenticate with AWS credentials
- Enable Requester Pays on the bucket
- Notify consumers that they must include x-amz-request-payer in requests
- Monitor for access errors from consumers not using the header