5.1 CloudFront Security Headers & Origin Access Control

Key Takeaways

  • Origin Access Control (OAC) replaces legacy Origin Access Identity (OAI) by utilizing AWS Signature Version 4 (SigV4), supporting all AWS Regions, server-side encryption with AWS KMS (SSE-KMS), and HTTP methods beyond GET and HEAD including PUT and DELETE.

  • S3 bucket policies for OAC must grant s3:GetObject (and s3:PutObject when client uploads are routed through CloudFront) to the cloudfront.amazonaws.com service principal, conditioned on a StringEquals check matching AWS:SourceArn to the CloudFront distribution ARN.

  • CloudFront response headers policies inject defensive security headers (HSTS, CSP, X-Content-Type-Options, X-Frame-Options) natively at edge points of presence with zero compute cost or latency compared to Lambda@Edge or CloudFront Functions.

  • Viewer protocol policy enforces encrypted transport with redirect-to-https (HTTP 301) or https-only (HTTP 403), while the origin protocol policy should require HTTPS with TLSv1.2 or later between CloudFront and custom origins.

  • Private content delivery utilizes CloudFront Signed URLs for discrete assets and Signed Cookies for multi-resource paths, managed modernly through IAM-managed Trusted Key Groups rather than deprecated AWS root-account CloudFront key pairs.

Last updated: September 2026

5.1 CloudFront Security Headers & Origin Access Control

Securing public-facing web applications begins at the network perimeter. Amazon CloudFront is a global Content Delivery Network (CDN) that terminates client transport connections across hundreds of Points of Presence (PoPs). In an enterprise security architecture, CloudFront acts as both a performance accelerator and a defensive shield. It isolates backend application origins, enforces strict transport encryption, filters geographic traffic, and injects critical browser-hardening headers.

Mastering CloudFront edge security for the AWS Certified Security – Specialty exam requires deep technical knowledge of Origin Access Control (OAC) versus legacy Origin Access Identity (OAI), bucket policy authorization patterns, response headers policies, viewer and origin protocol policies, and cryptographic private content distribution using Signed URLs and Signed Cookies.


Response Headers Policies: Edge-Native Browser Hardening

Modern web browsers implement robust security controls governed by HTTP response headers. Historically, injecting security headers into web responses required modifying origin application source code, configuring origin web server daemons (e.g., Apache or NGINX), or deploying compute-intensive Lambda@Edge or CloudFront Functions to modify responses on viewer-response events.

CloudFront Response Headers Policies eliminate edge compute overhead and latency by natively adding or overriding HTTP response headers directly at edge PoPs before responses are delivered to viewers.

Loading diagram...

Core Defensive Security Headers

When configuring a response headers policy (either using the AWS managed SecurityHeadersPolicy or a custom policy), security engineers enforce the following standard defensive headers:

Security HeaderDirective ExampleDefensive Security Function
Strict-Transport-Security (HSTS)max-age=31536000; includeSubDomains; preloadForces modern browsers to communicate exclusively over HTTPS for the specified duration (e.g., 1 year), mitigating man-in-the-middle (MitM) attacks, SSL stripping, and cookie interception. The preload directive allows domain inclusion in browser hardcoded HSTS lists.
Content-Security-Policy (CSP)default-src 'self'; script-src 'self' https://trusted.cdn.com; frame-ancestors 'none';Restricts the sources from which scripts, styles, images, and frames can be loaded. Prevents Cross-Site Scripting (XSS), malicious iframe embedding, and data injection attacks. Modern CSP frame-ancestors supersedes legacy X-Frame-Options.
X-Content-Type-OptionsnosniffDisables browser MIME-type sniffing. Forces the browser to strictly adhere to the declared Content-Type header, preventing attackers from disguising executable scripts or HTML inside user-uploaded image or text files.
X-Frame-OptionsDENY or SAMEORIGINMitigates clickjacking attacks by preventing malicious third-party websites from rendering the application inside an <iframe>, <frame>, <embed>, or <object> container.
Referrer-Policystrict-origin-when-cross-originControls how much referrer metadata (such as full path and query string parameters containing sensitive tokens) is transmitted in the Referer header during navigation to external origins.
Permissions-Policygeolocation=(), camera=(), microphone=()Explicitly disables sensitive browser features, hardware sensors, and Web APIs across the origin and embedded third-party frames.

Managed vs Custom Response Headers Policies

AWS provides preconfigured managed policies, including Managed-SecurityHeadersPolicy and Managed-CORS-and-SecurityHeadersPolicy. However, enterprise applications frequently require custom response headers policies to tailor CSP directives to internal content repositories or specify custom Access-Control-Allow-Origin values. Crucially, a response headers policy can be configured with Override = true or Override = false:

  • If Override is set to true, CloudFront replaces any corresponding header returned by the origin.
  • If Override is set to false, CloudFront injects the configured header only if the origin response does not already contain it.

Exam Tip: For the exam, recognize that CloudFront Response Headers Policies are the AWS recommended best practice for inserting security headers. They execute with zero compute cost and lower latency than Lambda@Edge or CloudFront Functions. Do not choose edge compute solutions for static header injection unless dynamic runtime calculation (such as inspecting user session tokens to construct unique per-user CSP nonces) is explicitly required.


Origin Access Control (OAC) vs Origin Access Identity (OAI)

When using Amazon S3 as a CloudFront origin, public read access must be disabled on the S3 bucket to prevent users from bypassing CloudFront caching, geographic restrictions, and AWS WAF inspection. Securing this communication requires an origin authorization mechanism.

Origin Access Identity (OAI) was the legacy mechanism introduced in earlier AWS architecture. Origin Access Control (OAC) is the modern, secure replacement introduced to overcome severe cryptographic and operational limitations of OAI.

Loading diagram...

Architectural Comparison: OAC vs OAI

Technical DimensionLegacy Origin Access Identity (OAI)Modern Origin Access Control (OAC)
Request SigningLegacy OAI identity (requests are not SigV4-signed by a service principal)AWS Signature Version 4 (SigV4) signed by cloudfront.amazonaws.com
AWS KMS Support (SSE-KMS)Unsupported. S3 buckets encrypted with customer-managed KMS keys cannot be accessed via OAI.Fully Supported. OAC signs requests with SigV4, allowing S3 to validate permissions against KMS key policies.
AWS Regional SupportNot supported for S3 buckets in opt-in Regions launched after December 2022.All AWS Regions supported globally, including opt-in Regions.
HTTP Methods SupportedDesigned for reads (GET, HEAD); AWS documents dynamic PUT and DELETE to S3 as an OAC capability.Supports GET, HEAD, OPTIONS, PUT, POST, PATCH, and DELETE for edge uploads.
Supported OriginsAmazon S3 only.Amazon S3, AWS Elemental MediaStore, and AWS Lambda function URLs.
Signing Behavior OptionsFixed legacy behavior.Configurable: always, never, or no-override (preserves existing authorization header from client).

Why OAI Fails with SSE-KMS

Understanding the mechanics of the SSE-KMS limitation is a cornerstone of the SCS-C03 exam. When an S3 object is encrypted with AWS Key Management Service (aws:kms), S3 must invoke kms:Decrypt using the identity of the caller. AWS lists SSE-KMS support as an OAC capability that OAI lacks: OAI requests are not SigV4-signed by the CloudFront service principal, so there is no principal a KMS key policy can authorize for the distribution. Requests through OAI for SSE-KMS objects therefore fail with Access Denied.

In contrast, OAC generates a full SigV4 signature using the CloudFront service principal (cloudfront.amazonaws.com). S3 evaluates this signature against its bucket policy and forwards the caller context to AWS KMS, which evaluates the KMS key policy granting decryption rights to CloudFront.


S3 Bucket Policy & KMS Key Policy Architecture for OAC

To lock down an S3 bucket so that objects are accessible exclusively through an authorized CloudFront distribution using OAC, two policies must be configured: the S3 Bucket Policy and, if SSE-KMS is enabled, the AWS KMS Key Policy.

S3 Bucket Policy Implementation

The S3 bucket policy must grant s3:GetObject permissions to the cloudfront.amazonaws.com service principal. To prevent the Confused Deputy Problem—where an attacker provisions their own CloudFront distribution in another AWS account pointing at your bucket—the policy must enforce an AWS:SourceArn condition matching the specific distribution ARN:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowCloudFrontServicePrincipalReadOnly",
      "Effect": "Allow",
      "Principal": {
        "Service": "cloudfront.amazonaws.com"
      },
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::production-secure-content-bucket/*",
      "Condition": {
        "StringEquals": {
          "AWS:SourceArn": "arn:aws:cloudfront::123456789012:distribution/EDFDVBD6EXAMPLE"
        }
      }
    }
  ]
}

Exam Trap: Pay close attention to the Resource ARN in the bucket policy. The action s3:GetObject applies to objects inside the bucket (arn:aws:s3:::bucket-name/*), not the bucket itself (arn:aws:s3:::bucket-name). Omitting the /* wildcard results in an Access Denied error when CloudFront fetches objects. If the distribution supports file uploads via PUT or POST, you must also include s3:PutObject in the Action array.

AWS KMS Key Policy for SSE-KMS Encryption

If the S3 bucket is encrypted using a customer-managed key (CMK), the KMS key policy must grant CloudFront permission to decrypt the data keys. Using the default AWS-managed key aws/s3 will not work because the AWS-managed key policy cannot be modified to grant permissions to the CloudFront service principal.

The customer-managed KMS key policy must contain the following statement:

{
  "Sid": "AllowCloudFrontServicePrincipalKMSDecryption",
  "Effect": "Allow",
  "Principal": {
    "Service": "cloudfront.amazonaws.com"
  },
  "Action": [
    "kms:Decrypt",
    "kms:GenerateDataKey*"
  ],
  "Resource": "*",
  "Condition": {
    "StringEquals": {
      "AWS:SourceArn": "arn:aws:cloudfront::123456789012:distribution/EDFDVBD6EXAMPLE"
    }
  }
}

Viewer & Origin Protocol Policies

CloudFront sits between viewers (clients) and origins. Transport security must be configured across both network segments.

Loading diagram...

Viewer Protocol Policy

The Viewer Protocol Policy governs how CloudFront responds to client connections over HTTP:

  • redirect-to-https: If a viewer sends an unencrypted HTTP request, CloudFront automatically responds with an HTTP status code 301 Moved Permanently redirecting the client to the HTTPS equivalent URL on port 443. This provides the best user experience for human web visitors who type plain domain names into address bars.
  • https-only: CloudFront terminates the connection or returns an HTTP status code 403 Forbidden if a request arrives over unencrypted HTTP. This is standard for REST APIs, mobile backends, and programmatic machine-to-machine integrations where clients must never transmit credentials or payloads over cleartext.
  • allow-all: CloudFront accepts both HTTP and HTTPS requests without redirecting. This is an anti-pattern in security architectures and should never be used for protected workloads.

Origin Protocol Policy

The Origin Protocol Policy governs the connection between CloudFront edge PoPs and custom origins (such as an Application Load Balancer or EC2 instance):

  • https-only: CloudFront initiates connections to the origin strictly over TLS port 443, regardless of the protocol used by the viewer. This ensures end-to-end encryption.
  • match-viewer: CloudFront mirrors the viewer's protocol. If the viewer connected via HTTP, CloudFront calls the origin via HTTP. If the viewer connected via HTTPS, CloudFront calls the origin via HTTPS.
  • Origin SSL Protocols: Security engineers configure the minimum SSL/TLS version supported between CloudFront and the origin (e.g., enforcing TLSv1.2 or TLSv1.3 and disabling legacy TLSv1.0 and TLSv1.1).
  • Host Header and Certificate Validation: When CloudFront connects to a custom origin over HTTPS, it validates the origin server's TLS certificate. The domain name on the origin's certificate must match the Origin Domain Name configured in the CloudFront distribution settings.

Private Content Distribution: Signed URLs vs Signed Cookies

To restrict access to premium, subscription-based, or confidential content, CloudFront provides two cryptographic mechanisms: Signed URLs and Signed Cookies.

Architectural Comparison

FeatureSigned URLsSigned Cookies
Primary Use CaseIndividual files, direct downloads, media players that do not support cookies, or links shared via email.Providing access to multiple restricted files (e.g., an entire subscriber section https://example.com/courses/module-1/*) or a single page with dozens of embedded assets.
URL AppearanceURLs are modified to append query string parameters containing policy, signature, and key ID.URLs remain clean and standard; authentication data is carried in HTTP Cookie request headers.
Client SupportUniversal. Any HTTP client, mobile app, or media streaming library supports URL query strings.Requires a client capable of storing and sending HTTP cookies (standard web browsers). Often problematic for smart TVs or embedded media players.
Caching BehaviorEvery signed URL containing distinct query parameters can bypass edge cache unless query string forwarding is specifically tuned.Content can be cached at the edge by URL path; edge PoPs validate cookies locally before serving cached content.

Canned Policy vs Custom Policy

Both signed URLs and signed cookies can be constructed using either a Canned Policy or a Custom Policy:

Canned Policy Attributes:
  - Resource URL (exact match, no wildcards)
  - Expiration Date/Time (Epoch timestamp)

Custom Policy Attributes:
  - Resource URL (supports wildcards, e.g., https://example.com/premium/*)
  - Expiration Date/Time (Epoch timestamp)
  - Optional: Activation Date/Time (Epoch timestamp - link valid only starting in the future)
  - Optional: IP Address Restriction (CIDR block, e.g., 198.51.100.0/24)

Exam Tip: If an exam question requires granting temporary access to a single video file that expires in 15 minutes, choose a Signed URL with a Canned Policy. If the scenario requires granting access to an entire directory of files, restricting access to a corporate IP address range, or setting a future start time, you must use a Custom Policy (with Signed Cookies or Signed URLs).

Trusted Key Groups vs Legacy Trusted Signers

When verifying signatures on signed URLs or cookies, CloudFront must validate the signature against a public key:

  • Legacy Trusted Signers: Required an AWS account root user to create CloudFront key pairs in the AWS account management console. Sharing keys required adding AWS account IDs as trusted signers. Security anti-pattern: Violates the principle of avoiding root user usage.
  • Trusted Key Groups (Current Standard): Allows security engineers to create an asymmetric public-private key pair (RSA 2048-bit), upload the public key to CloudFront using the CreatePublicKey API, and add the public key to a Key Group (CreateKeyGroup). IAM users or roles with appropriate permissions can rotate keys programmatically without root account access.

CloudFront Geographic Restrictions

Organizations frequently face regulatory mandates (e.g., export compliance, OFAC sanctions) or digital rights licensing agreements that require restricting access by geographic origin.

CloudFront offers built-in Geographic Restrictions (Geo-blocking):

  • Allowlist: Only viewers in specified countries (identified by two-letter ISO 3166-1 alpha-2 country codes) can access content. Viewers from any other country receive an HTTP 403 Forbidden response.
  • Blocklist: Viewers in specified countries are denied access with an HTTP 403 Forbidden response, while viewers from all other countries are permitted.
  • Edge Evaluation: Geographic restrictions are evaluated directly at the edge PoP using an internal GeoIP database before the request reaches the cache or origin.

CloudFront Geo-Restriction vs AWS WAF Geo-Match

DimensionCloudFront Built-in Geo-RestrictionAWS WAF Geo-Match Rule
GranularityCoarse: Applies across the entire distribution or cache behavior.Highly granular: Can be scoped to specific URI paths, HTTP methods, or query parameters.
Rule LogicSimple binary choice: Global Allowlist OR Global Blocklist.Complex Boolean logic: Can combine country match with IP reputation, rate limits, headers, or bot tokens.
ActionsFixed HTTP 403 Forbidden response.Flexible: Block (custom HTML/JSON error page), Allow, Count, CAPTCHA, or Challenge.
CostNo additional charge.Incurs standard AWS WAF WebACL and rule evaluation fees.

Specialty Exam Pitfalls & Architectural Traps

  1. Migrating from OAI to OAC without Updating Bucket Policies: When updating a CloudFront distribution from OAI to OAC, the S3 bucket policy must be updated to grant permissions to cloudfront.amazonaws.com with AWS:SourceArn. If you switch the distribution origin to OAC while retaining the old OAI principal (arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity EXXXXX), all origin requests will immediately fail with HTTP 403.
  2. Confused Deputy in OAC Bucket Policies: A bucket policy that grants s3:GetObject to cloudfront.amazonaws.com without a Condition block containing AWS:SourceArn or AWS:SourceAccount allows any CloudFront distribution in any AWS account to read your bucket objects. Always enforce AWS:SourceArn targeting your specific distribution ARN.
  3. Using AWS-Managed Keys (aws/s3) with CloudFront OAC: S3 server-side encryption with AWS-managed keys (SSE-KMS using alias/aws/s3) does not allow modifying the key policy. Because CloudFront OAC requires explicit kms:Decrypt permissions granted in the KMS key policy, you must use a customer-managed key (CMK) when encrypting S3 objects intended for OAC distribution.
  4. Cookie Domain Scope for Signed Cookies: When issuing CloudFront signed cookies, the Domain attribute in the Set-Cookie header must match or be a parent domain of the CloudFront distribution domain (e.g., Domain=.example.com for cdn.example.com). If the domain attributes mismatch, the browser will not send the cookies on subsequent asset requests, resulting in HTTP 403 errors.
Loading diagram...
CloudFront Origin Access Control (OAC) with SSE-KMS & Edge Security Enforcement
Test Your Knowledge

A media streaming enterprise hosts proprietary video assets in an Amazon S3 bucket encrypted with an AWS KMS customer-managed key (CMK). The security team configures an Amazon CloudFront distribution to serve these videos globally and deploys an Origin Access Identity (OAI) to prevent users from bypassing CloudFront. However, viewers report HTTP 403 Access Denied errors on all requests. What is the root cause of this failure and what architectural modification resolves it?

A

The S3 bucket policy lacks the s3:ListBucket permission for the OAI identity; adding s3:ListBucket resolves the permission failure.

B

OAI requires S3 bucket objects to be encrypted exclusively with Amazon S3 managed keys (SSE-S3); decrypting the bucket objects with SSE-S3 resolves the failure.

C

OAI does not support SSE-KMS because its requests cannot be authorized by a KMS key policy; replacing OAI with Origin Access Control (OAC) and updating the KMS key policy resolves the failure.

D

The CloudFront distribution is missing an AWS WAF WebACL association with the Amazon IP Reputation list; associating WAF resolves the failure.

Test Your Knowledge

A financial application team must ensure that web browser clients communicating with their CloudFront distribution are strictly prohibited from rendering the application inside malicious iframes, running MIME-type sniffing, or loading unauthorized external scripts. The security team mandates that this protection must be enforced at the edge with zero compute invocation costs and minimal latency. How should the security engineer implement this requirement?

A

Attach a CloudFront Response Headers Policy to the distribution cache behavior configured to inject Content-Security-Policy, X-Frame-Options, and X-Content-Type-Options: nosniff headers.

B

Deploy a Lambda@Edge viewer-response function that parses the response status code and dynamically appends HTTP defensive headers using Node.js.

C

Configure a CloudFront Function on the viewer-request event to inspect incoming client headers and reject clients that do not present a Sec-Fetch-Dest header.

D

Create an AWS WAF custom response rule in the associated WebACL that injects custom response headers on HTTP 200 OK responses.

Test Your Knowledge

An architect must restrict an Amazon S3 bucket containing confidential medical reports so that objects can only be accessed through a dedicated Amazon CloudFront distribution (distribution ID: EDFDVBD6EXAMPLE in account 123456789012). The bucket has public access blocked. Which S3 bucket policy statement correctly implements this origin access lockdown while preventing confused deputy attacks from other AWS accounts or distributions?

A

Allow s3:GetObject to Principal '*' with Condition StringEquals AWS:PrincipalArn matching arn:aws:iam::123456789012:role/CloudFrontOriginRole.

B

Allow s3:GetObject to Principal Service: 'cloudfront.amazonaws.com' without conditions because CloudFront is an AWS internal service.

C

Allow s3:GetObject to Principal Service: 's3.amazonaws.com' with Condition StringEquals AWS:SourceArn matching arn:aws:cloudfront::123456789012:distribution/EDFDVBD6EXAMPLE.

D

Allow s3:GetObject to Principal Service: 'cloudfront.amazonaws.com' with Condition StringEquals AWS:SourceArn matching arn:aws:cloudfront::123456789012:distribution/EDFDVBD6EXAMPLE on Resource arn:aws:s3:::medical-reports/*.

Test Your Knowledge

An online learning portal serves hundreds of individual lesson assets (PDFs, HTML files, video clips) within a paid subscriber course directory located at the URL path /premium/courses/c03/*. The security team needs to grant authenticated students access to all files within this directory for a 4-hour study session while keeping public URLs clean and avoiding unique query string parameters that fragment browser and edge caches. Which mechanism should the team deploy?

A

CloudFront Signed URLs configured with a Canned Policy for each individual file, regenerated every 15 minutes by the backend application.

B

CloudFront Signed Cookies configured with a Custom Policy matching the resource path /premium/courses/c03/* and signed using a Trusted Key Group.

C

An AWS WAF WebACL rule matching the subscriber session cookie and rewriting the URI path to an internal S3 bucket location.

D

A CloudFront Geographic Restriction allowlist permitting only the student's registered country code for the course directory.

Sections you finish are checked off in the contents.