The aws:cloudfront/responseHeadersPolicy:ResponseHeadersPolicy resource, part of the Pulumi AWS provider, defines a reusable set of HTTP response headers that CloudFront adds to responses for matching cache behaviors. This guide focuses on three capabilities: CORS header configuration, custom header injection, and header removal with performance monitoring.
Response headers policies are attached to cache behaviors in CloudFront distributions. The policy defines which headers to add or remove; you attach it to one or more cache behaviors to apply those headers to matching requests. The examples are intentionally small. Combine them with your own CloudFront distribution and cache behavior configuration.
Configure CORS headers for cross-origin requests
Web applications serving content to browsers on different domains need CORS headers to allow cross-origin requests.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.cloudfront.ResponseHeadersPolicy("example", {
name: "example-policy",
comment: "test comment",
corsConfig: {
accessControlAllowCredentials: true,
accessControlAllowHeaders: {
items: ["test"],
},
accessControlAllowMethods: {
items: ["GET"],
},
accessControlAllowOrigins: {
items: ["test.example.comtest"],
},
originOverride: true,
},
});
import pulumi
import pulumi_aws as aws
example = aws.cloudfront.ResponseHeadersPolicy("example",
name="example-policy",
comment="test comment",
cors_config={
"access_control_allow_credentials": True,
"access_control_allow_headers": {
"items": ["test"],
},
"access_control_allow_methods": {
"items": ["GET"],
},
"access_control_allow_origins": {
"items": ["test.example.comtest"],
},
"origin_override": True,
})
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/cloudfront"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := cloudfront.NewResponseHeadersPolicy(ctx, "example", &cloudfront.ResponseHeadersPolicyArgs{
Name: pulumi.String("example-policy"),
Comment: pulumi.String("test comment"),
CorsConfig: &cloudfront.ResponseHeadersPolicyCorsConfigArgs{
AccessControlAllowCredentials: pulumi.Bool(true),
AccessControlAllowHeaders: &cloudfront.ResponseHeadersPolicyCorsConfigAccessControlAllowHeadersArgs{
Items: pulumi.StringArray{
pulumi.String("test"),
},
},
AccessControlAllowMethods: &cloudfront.ResponseHeadersPolicyCorsConfigAccessControlAllowMethodsArgs{
Items: pulumi.StringArray{
pulumi.String("GET"),
},
},
AccessControlAllowOrigins: &cloudfront.ResponseHeadersPolicyCorsConfigAccessControlAllowOriginsArgs{
Items: pulumi.StringArray{
pulumi.String("test.example.comtest"),
},
},
OriginOverride: pulumi.Bool(true),
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var example = new Aws.CloudFront.ResponseHeadersPolicy("example", new()
{
Name = "example-policy",
Comment = "test comment",
CorsConfig = new Aws.CloudFront.Inputs.ResponseHeadersPolicyCorsConfigArgs
{
AccessControlAllowCredentials = true,
AccessControlAllowHeaders = new Aws.CloudFront.Inputs.ResponseHeadersPolicyCorsConfigAccessControlAllowHeadersArgs
{
Items = new[]
{
"test",
},
},
AccessControlAllowMethods = new Aws.CloudFront.Inputs.ResponseHeadersPolicyCorsConfigAccessControlAllowMethodsArgs
{
Items = new[]
{
"GET",
},
},
AccessControlAllowOrigins = new Aws.CloudFront.Inputs.ResponseHeadersPolicyCorsConfigAccessControlAllowOriginsArgs
{
Items = new[]
{
"test.example.comtest",
},
},
OriginOverride = true,
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.cloudfront.ResponseHeadersPolicy;
import com.pulumi.aws.cloudfront.ResponseHeadersPolicyArgs;
import com.pulumi.aws.cloudfront.inputs.ResponseHeadersPolicyCorsConfigArgs;
import com.pulumi.aws.cloudfront.inputs.ResponseHeadersPolicyCorsConfigAccessControlAllowHeadersArgs;
import com.pulumi.aws.cloudfront.inputs.ResponseHeadersPolicyCorsConfigAccessControlAllowMethodsArgs;
import com.pulumi.aws.cloudfront.inputs.ResponseHeadersPolicyCorsConfigAccessControlAllowOriginsArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var example = new ResponseHeadersPolicy("example", ResponseHeadersPolicyArgs.builder()
.name("example-policy")
.comment("test comment")
.corsConfig(ResponseHeadersPolicyCorsConfigArgs.builder()
.accessControlAllowCredentials(true)
.accessControlAllowHeaders(ResponseHeadersPolicyCorsConfigAccessControlAllowHeadersArgs.builder()
.items("test")
.build())
.accessControlAllowMethods(ResponseHeadersPolicyCorsConfigAccessControlAllowMethodsArgs.builder()
.items("GET")
.build())
.accessControlAllowOrigins(ResponseHeadersPolicyCorsConfigAccessControlAllowOriginsArgs.builder()
.items("test.example.comtest")
.build())
.originOverride(true)
.build())
.build());
}
}
resources:
example:
type: aws:cloudfront:ResponseHeadersPolicy
properties:
name: example-policy
comment: test comment
corsConfig:
accessControlAllowCredentials: true
accessControlAllowHeaders:
items:
- test
accessControlAllowMethods:
items:
- GET
accessControlAllowOrigins:
items:
- test.example.comtest
originOverride: true
When attached to a cache behavior, CloudFront injects the specified CORS headers into every response. The accessControlAllowOrigins property lists domains that can make cross-origin requests. The accessControlAllowMethods property specifies which HTTP methods are permitted. The originOverride property controls whether CloudFront’s headers replace any CORS headers from the origin server.
Add custom headers to responses
Applications often inject custom headers for security policies or client-side behavior without modifying origin servers.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.cloudfront.ResponseHeadersPolicy("example", {
name: "example-headers-policy",
customHeadersConfig: {
items: [
{
header: "X-Permitted-Cross-Domain-Policies",
override: true,
value: "none",
},
{
header: "X-Test",
override: true,
value: "none",
},
],
},
});
import pulumi
import pulumi_aws as aws
example = aws.cloudfront.ResponseHeadersPolicy("example",
name="example-headers-policy",
custom_headers_config={
"items": [
{
"header": "X-Permitted-Cross-Domain-Policies",
"override": True,
"value": "none",
},
{
"header": "X-Test",
"override": True,
"value": "none",
},
],
})
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/cloudfront"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := cloudfront.NewResponseHeadersPolicy(ctx, "example", &cloudfront.ResponseHeadersPolicyArgs{
Name: pulumi.String("example-headers-policy"),
CustomHeadersConfig: &cloudfront.ResponseHeadersPolicyCustomHeadersConfigArgs{
Items: cloudfront.ResponseHeadersPolicyCustomHeadersConfigItemArray{
&cloudfront.ResponseHeadersPolicyCustomHeadersConfigItemArgs{
Header: pulumi.String("X-Permitted-Cross-Domain-Policies"),
Override: pulumi.Bool(true),
Value: pulumi.String("none"),
},
&cloudfront.ResponseHeadersPolicyCustomHeadersConfigItemArgs{
Header: pulumi.String("X-Test"),
Override: pulumi.Bool(true),
Value: pulumi.String("none"),
},
},
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var example = new Aws.CloudFront.ResponseHeadersPolicy("example", new()
{
Name = "example-headers-policy",
CustomHeadersConfig = new Aws.CloudFront.Inputs.ResponseHeadersPolicyCustomHeadersConfigArgs
{
Items = new[]
{
new Aws.CloudFront.Inputs.ResponseHeadersPolicyCustomHeadersConfigItemArgs
{
Header = "X-Permitted-Cross-Domain-Policies",
Override = true,
Value = "none",
},
new Aws.CloudFront.Inputs.ResponseHeadersPolicyCustomHeadersConfigItemArgs
{
Header = "X-Test",
Override = true,
Value = "none",
},
},
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.cloudfront.ResponseHeadersPolicy;
import com.pulumi.aws.cloudfront.ResponseHeadersPolicyArgs;
import com.pulumi.aws.cloudfront.inputs.ResponseHeadersPolicyCustomHeadersConfigArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var example = new ResponseHeadersPolicy("example", ResponseHeadersPolicyArgs.builder()
.name("example-headers-policy")
.customHeadersConfig(ResponseHeadersPolicyCustomHeadersConfigArgs.builder()
.items(
ResponseHeadersPolicyCustomHeadersConfigItemArgs.builder()
.header("X-Permitted-Cross-Domain-Policies")
.override(true)
.value("none")
.build(),
ResponseHeadersPolicyCustomHeadersConfigItemArgs.builder()
.header("X-Test")
.override(true)
.value("none")
.build())
.build())
.build());
}
}
resources:
example:
type: aws:cloudfront:ResponseHeadersPolicy
properties:
name: example-headers-policy
customHeadersConfig:
items:
- header: X-Permitted-Cross-Domain-Policies
override: true
value: none
- header: X-Test
override: true
value: none
The customHeadersConfig property defines headers CloudFront adds to responses. Each item specifies a header name, value, and whether to override existing headers with the same name. This example adds X-Permitted-Cross-Domain-Policies and X-Test headers to every response for cache behaviors using this policy.
Combine custom headers with header removal and timing
Production deployments often add custom headers while removing sensitive ones and enabling performance monitoring.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.cloudfront.ResponseHeadersPolicy("example", {
name: "example-headers-policy",
customHeadersConfig: {
items: [{
header: "X-Permitted-Cross-Domain-Policies",
override: true,
value: "none",
}],
},
removeHeadersConfig: {
items: [{
header: "Set-Cookie",
}],
},
serverTimingHeadersConfig: {
enabled: true,
samplingRate: 50,
},
});
import pulumi
import pulumi_aws as aws
example = aws.cloudfront.ResponseHeadersPolicy("example",
name="example-headers-policy",
custom_headers_config={
"items": [{
"header": "X-Permitted-Cross-Domain-Policies",
"override": True,
"value": "none",
}],
},
remove_headers_config={
"items": [{
"header": "Set-Cookie",
}],
},
server_timing_headers_config={
"enabled": True,
"sampling_rate": 50,
})
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/cloudfront"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := cloudfront.NewResponseHeadersPolicy(ctx, "example", &cloudfront.ResponseHeadersPolicyArgs{
Name: pulumi.String("example-headers-policy"),
CustomHeadersConfig: &cloudfront.ResponseHeadersPolicyCustomHeadersConfigArgs{
Items: cloudfront.ResponseHeadersPolicyCustomHeadersConfigItemArray{
&cloudfront.ResponseHeadersPolicyCustomHeadersConfigItemArgs{
Header: pulumi.String("X-Permitted-Cross-Domain-Policies"),
Override: pulumi.Bool(true),
Value: pulumi.String("none"),
},
},
},
RemoveHeadersConfig: &cloudfront.ResponseHeadersPolicyRemoveHeadersConfigArgs{
Items: cloudfront.ResponseHeadersPolicyRemoveHeadersConfigItemArray{
&cloudfront.ResponseHeadersPolicyRemoveHeadersConfigItemArgs{
Header: pulumi.String("Set-Cookie"),
},
},
},
ServerTimingHeadersConfig: &cloudfront.ResponseHeadersPolicyServerTimingHeadersConfigArgs{
Enabled: pulumi.Bool(true),
SamplingRate: pulumi.Float64(50),
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var example = new Aws.CloudFront.ResponseHeadersPolicy("example", new()
{
Name = "example-headers-policy",
CustomHeadersConfig = new Aws.CloudFront.Inputs.ResponseHeadersPolicyCustomHeadersConfigArgs
{
Items = new[]
{
new Aws.CloudFront.Inputs.ResponseHeadersPolicyCustomHeadersConfigItemArgs
{
Header = "X-Permitted-Cross-Domain-Policies",
Override = true,
Value = "none",
},
},
},
RemoveHeadersConfig = new Aws.CloudFront.Inputs.ResponseHeadersPolicyRemoveHeadersConfigArgs
{
Items = new[]
{
new Aws.CloudFront.Inputs.ResponseHeadersPolicyRemoveHeadersConfigItemArgs
{
Header = "Set-Cookie",
},
},
},
ServerTimingHeadersConfig = new Aws.CloudFront.Inputs.ResponseHeadersPolicyServerTimingHeadersConfigArgs
{
Enabled = true,
SamplingRate = 50,
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.cloudfront.ResponseHeadersPolicy;
import com.pulumi.aws.cloudfront.ResponseHeadersPolicyArgs;
import com.pulumi.aws.cloudfront.inputs.ResponseHeadersPolicyCustomHeadersConfigArgs;
import com.pulumi.aws.cloudfront.inputs.ResponseHeadersPolicyRemoveHeadersConfigArgs;
import com.pulumi.aws.cloudfront.inputs.ResponseHeadersPolicyServerTimingHeadersConfigArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var example = new ResponseHeadersPolicy("example", ResponseHeadersPolicyArgs.builder()
.name("example-headers-policy")
.customHeadersConfig(ResponseHeadersPolicyCustomHeadersConfigArgs.builder()
.items(ResponseHeadersPolicyCustomHeadersConfigItemArgs.builder()
.header("X-Permitted-Cross-Domain-Policies")
.override(true)
.value("none")
.build())
.build())
.removeHeadersConfig(ResponseHeadersPolicyRemoveHeadersConfigArgs.builder()
.items(ResponseHeadersPolicyRemoveHeadersConfigItemArgs.builder()
.header("Set-Cookie")
.build())
.build())
.serverTimingHeadersConfig(ResponseHeadersPolicyServerTimingHeadersConfigArgs.builder()
.enabled(true)
.samplingRate(50.0)
.build())
.build());
}
}
resources:
example:
type: aws:cloudfront:ResponseHeadersPolicy
properties:
name: example-headers-policy
customHeadersConfig:
items:
- header: X-Permitted-Cross-Domain-Policies
override: true
value: none
removeHeadersConfig:
items:
- header: Set-Cookie
serverTimingHeadersConfig:
enabled: true
samplingRate: 50
This configuration extends the custom headers pattern by adding removeHeadersConfig to strip Set-Cookie headers from responses, preventing cookie leakage. The serverTimingHeadersConfig enables Server-Timing headers for performance monitoring, with samplingRate controlling what percentage of responses include timing data.
Beyond these examples
These snippets focus on specific response headers policy features: CORS configuration, custom header injection, and header removal and Server-Timing. They’re intentionally minimal rather than full CloudFront configurations.
The examples assume pre-existing infrastructure such as CloudFront distributions with cache behaviors. They focus on defining the policy rather than attaching it to distributions.
To keep things focused, common policy patterns are omitted, including:
- Security headers (Content-Security-Policy, X-Frame-Options, etc.)
- Policy attachment to cache behaviors
- Multiple header configurations in a single policy
- Conditional header logic based on request properties
These omissions are intentional: the goal is to illustrate how each policy feature is wired, not provide drop-in CloudFront modules. See the CloudFront ResponseHeadersPolicy resource reference for all available configuration options.
Let's configure AWS CloudFront Response Headers Policies
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Policy Basics
name.corsConfig), custom headers (customHeadersConfig), security headers (securityHeadersConfig), headers to remove (removeHeadersConfig), and Server-Timing headers (serverTimingHeadersConfig).Header Configuration
corsConfig with accessControlAllowCredentials, accessControlAllowHeaders, accessControlAllowMethods, accessControlAllowOrigins, and originOverride. Each allow property contains an items array with the allowed values.customHeadersConfig with an items array. Each item specifies a header name, value, and override flag to control whether CloudFront overrides existing headers.removeHeadersConfig with an items array specifying which headers to remove. For example, you can remove Set-Cookie headers from responses.override flag controls whether CloudFront overrides existing headers with the same name. When set to true, CloudFront replaces any existing header; when false, it only adds the header if it doesn’t already exist.serverTimingHeadersConfig with enabled: true and a samplingRate (0-100) to control what percentage of requests include the Server-Timing header. For example, samplingRate: 50 enables it for 50% of requests.Using a different cloud?
Explore networking guides for other cloud providers: