Private access to S3 content
S3 presigned URLs, CloudFront signed URLs and signed cookies, origin access control, S3 Access Points, Multi-Region Access Points and Block Public Access.
Exam tasks: 2.3 (design security controls for data access, restrict access to content)
The decision: who is fetching the object (one user, many paying users, an application team, a global app), and must the request go through CloudFront, straight to S3, or both?
Choosing a mechanism
Side by side
| S3 presigned URL | CloudFront signed URL | CloudFront signed cookies | |
|---|---|---|---|
| Who signs | Any IAM principal allowed to access the object, with its own credentials | Your app, with a private key whose public key is in a CloudFront trusted key group | Same as signed URLs |
| Scope | One object and one operation (GET, PUT and so on) | One URL, or a wildcard with a custom policy | Many files, set once per session |
| Path | Straight to S3 | Through CloudFront, with caching | Through CloudFront, with caching |
| Upload support | Yes, PUT or POST | Yes, if the behavior allows it | Yes |
| Restrictions | Expiry only (plus bucket policy conditions) | Expiry, start time and source IP range with a custom policy | Same as signed URLs |
| Lifetime | Up to 7 days, and never longer than the signing credentials | You choose | You choose |
| URL changes needed | New URL per object | New URL per object | No. The URLs stay clean |
Exam signal
"Let users upload directly to S3 without going through our servers" is a presigned URL (or presigned POST). "Paying subscribers stream many HLS segments" is signed cookies. "Download link for one purchased file, cached globally" is a CloudFront signed URL.
Presigned URLs that expire early
A presigned URL stops working when the credentials that signed it expire. If a Lambda function's role session signs a 7-day URL, the URL dies with the session, often within hours. Use longer-lived credentials only when you truly need long links, or switch to CloudFront signed URLs.
Origin access control
Signed URLs restrict viewers. Origin access control (OAC) makes sure nobody skips CloudFront and reads the bucket directly.
- CloudFront signs its requests to S3 with SigV4 as the
cloudfront.amazonaws.comservice principal. - The bucket policy allows
s3:GetObjectfor that principal, with a condition onAWS:SourceArnequal to the distribution's ARN. - OAC supports SSE-KMS encrypted objects (add the distribution to the key policy), every Region, and PUT and DELETE requests.
- OAC also protects Lambda function URL and MediaPackage origins.
Legacy: use Origin access control (OAC) instead
Origin access identity (OAI) was the earlier way to lock a bucket to CloudFront. It doesn't support SSE-KMS, doesn't work in Regions launched after December 2022, and can't sign dynamic requests such as PUT. Migrate existing OAIs to OAC.
OAC and S3 website endpoints
OAC and OAI work only with the S3 REST endpoint. A bucket configured as a static website endpoint is a custom origin, so you can't use OAC with it. To restrict it, the usual workaround is a secret custom header that the bucket policy checks. Better: use the REST endpoint with OAC and set a default root object in CloudFront.
S3 Access Points
An access point is a named network endpoint on a bucket with its own policy. Instead of one huge bucket policy, each application or team gets an access point.
- Each access point can be restricted to a VPC, so requests must come through a VPC endpoint.
- The bucket policy delegates access control to access points, for example by allowing any request that comes through an access point owned by the account.
- Access points also work across accounts.
Exam signal
"Dozens of teams share a data lake bucket and the bucket policy is near its size limit" is solved with S3 Access Points, one per team, each with its own policy.
Multi-Region Access Points
- One global endpoint in front of buckets in several Regions. Requests travel over the AWS global network to the closest bucket, using Global Accelerator.
- Pair it with S3 Cross-Region Replication (which you configure) to keep the buckets in sync.
- Failover controls switch between active/active and active/passive routing in minutes.
- Requests are signed with SigV4A, which the AWS SDKs handle.
Block Public Access
- Four settings (block new public ACLs, ignore existing public ACLs, block new public bucket policies, restrict access to buckets with public policies), set at the account level or per bucket, or organization-wide with an SCP that denies changing them.
- On by default for new buckets, together with Object Ownership set to bucket owner enforced, which disables ACLs.
- The account-level setting overrides any bucket or object that tries to be public.
Public bucket behind CloudFront
An answer that makes the bucket public "so CloudFront can read it" is always wrong. Keep Block Public Access on and use OAC.
S3 Object Lambda
Object Lambda runs a Lambda function on GET, HEAD or LIST requests to transform data on the way out, for example to redact PII or resize images. It moved to maintenance in November 2025 and is no longer available to new customers, so prefer a Lambda function behind API Gateway or CloudFront, or transform at write time.
Scenarios
Signed cookies cover many files without changing the URLs, and OAC forces every request through CloudFront. Presigned URLs bypass CloudFront, so nothing is cached at the edge. A public bucket fails the "no direct download" rule, and signed URLs for 200 segments would mean rewriting every link.
A presigned PUT URL grants a single, time-limited upload to one key using the backend's permissions. A publicly writable prefix is unsafe, OAI can't sign PUT requests (and OAC wouldn't limit uploads to 15 minutes), and one access point per user doesn't scale and still needs credentials on the device.
Further reading
DDoS and edge security
Shield Standard and Advanced, AWS WAF rules, Firewall Manager, CloudFront and Global Accelerator as the edge, and where Network Firewall and security groups fit.
Route 53 routing
Route 53 routing policies, health checks, alias records, nested record trees for high availability, and DNSSEC signing.