Configure AWS CloudFront Response Headers Policies

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 timing.

Response headers policies are attached to cache behaviors in CloudFront distributions. 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 two custom headers that control cross-domain policies and application-specific behavior.

Combine custom headers with header removal and timing

Production deployments often add some headers while removing others, and may want performance timing data.

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 applies three operations: customHeadersConfig adds headers, removeHeadersConfig strips headers from origin responses (like Set-Cookie for caching), and serverTimingHeadersConfig enables the Server-Timing header for performance monitoring. The samplingRate property controls 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 complete CloudFront configurations.

The examples assume pre-existing infrastructure such as a CloudFront distribution with cache behaviors, since policies attach to cache behaviors rather than existing independently. They focus on policy configuration without showing the attachment process.

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 CORS origin patterns
  • 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 FREE

Frequently Asked Questions

Policy Configuration
Can I combine multiple header configuration types in one policy?
Yes, you can combine corsConfig, customHeadersConfig, removeHeadersConfig, securityHeadersConfig, and serverTimingHeadersConfig in a single response headers policy.
What's the maximum length for the comment field?
The comment cannot be longer than 128 characters.
Header Management
How do I remove headers from CloudFront responses?
Use removeHeadersConfig with an items list containing the headers to remove. For example, you can remove the Set-Cookie header by specifying it in the items list.
How do I enable server timing headers for debugging?
Configure serverTimingHeadersConfig with enabled: true and set a samplingRate (0-100) to control what percentage of requests include the Server-Timing header.

Using a different cloud?

Explore networking guides for other cloud providers: