Configure GCP Edge Cache Services

The gcp:networkservices/edgeCacheService:EdgeCacheService resource, part of the Pulumi Google Cloud provider, defines a Media CDN service that routes requests to origins, applies caching policies, and optionally validates signed requests. This guide focuses on three capabilities: routing configuration with host and path matching, cache policies and TTL settings, and signed request authentication.

EdgeCacheService resources depend on EdgeCacheOrigin resources for content sources, and optionally EdgeCacheKeyset resources for signed request validation. The examples are intentionally small. Combine them with your own origins, DNS configuration, and TLS certificates.

Route requests to a storage bucket origin

Most CDN deployments start by routing traffic to a Cloud Storage bucket with basic caching rules to reduce origin load.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const dest = new gcp.storage.Bucket("dest", {
    name: "my-bucket",
    location: "US",
    forceDestroy: true,
});
const instance = new gcp.networkservices.EdgeCacheOrigin("instance", {
    name: "my-origin",
    originAddress: dest.url,
    description: "The default bucket for media edge test",
    maxAttempts: 2,
    timeout: {
        connectTimeout: "10s",
    },
});
const instanceEdgeCacheService = new gcp.networkservices.EdgeCacheService("instance", {
    name: "my-service",
    description: "some description",
    routing: {
        hostRules: [{
            description: "host rule description",
            hosts: ["sslcert.tf-test.club"],
            pathMatcher: "routes",
        }],
        pathMatchers: [{
            name: "routes",
            routeRules: [{
                description: "a route rule to match against",
                priority: "1",
                matchRules: [{
                    prefixMatch: "/",
                }],
                origin: instance.name,
                routeAction: {
                    cdnPolicy: {
                        cacheMode: "CACHE_ALL_STATIC",
                        defaultTtl: "3600s",
                    },
                },
                headerAction: {
                    responseHeaderToAdds: [{
                        headerName: "x-cache-status",
                        headerValue: "{cdn_cache_status}",
                    }],
                },
            }],
        }],
    },
});
import pulumi
import pulumi_gcp as gcp

dest = gcp.storage.Bucket("dest",
    name="my-bucket",
    location="US",
    force_destroy=True)
instance = gcp.networkservices.EdgeCacheOrigin("instance",
    name="my-origin",
    origin_address=dest.url,
    description="The default bucket for media edge test",
    max_attempts=2,
    timeout={
        "connect_timeout": "10s",
    })
instance_edge_cache_service = gcp.networkservices.EdgeCacheService("instance",
    name="my-service",
    description="some description",
    routing={
        "host_rules": [{
            "description": "host rule description",
            "hosts": ["sslcert.tf-test.club"],
            "path_matcher": "routes",
        }],
        "path_matchers": [{
            "name": "routes",
            "route_rules": [{
                "description": "a route rule to match against",
                "priority": "1",
                "match_rules": [{
                    "prefix_match": "/",
                }],
                "origin": instance.name,
                "route_action": {
                    "cdn_policy": {
                        "cache_mode": "CACHE_ALL_STATIC",
                        "default_ttl": "3600s",
                    },
                },
                "header_action": {
                    "response_header_to_adds": [{
                        "header_name": "x-cache-status",
                        "header_value": "{cdn_cache_status}",
                    }],
                },
            }],
        }],
    })
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/networkservices"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/storage"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		dest, err := storage.NewBucket(ctx, "dest", &storage.BucketArgs{
			Name:         pulumi.String("my-bucket"),
			Location:     pulumi.String("US"),
			ForceDestroy: pulumi.Bool(true),
		})
		if err != nil {
			return err
		}
		instance, err := networkservices.NewEdgeCacheOrigin(ctx, "instance", &networkservices.EdgeCacheOriginArgs{
			Name:          pulumi.String("my-origin"),
			OriginAddress: dest.Url,
			Description:   pulumi.String("The default bucket for media edge test"),
			MaxAttempts:   pulumi.Int(2),
			Timeout: &networkservices.EdgeCacheOriginTimeoutArgs{
				ConnectTimeout: pulumi.String("10s"),
			},
		})
		if err != nil {
			return err
		}
		_, err = networkservices.NewEdgeCacheService(ctx, "instance", &networkservices.EdgeCacheServiceArgs{
			Name:        pulumi.String("my-service"),
			Description: pulumi.String("some description"),
			Routing: &networkservices.EdgeCacheServiceRoutingArgs{
				HostRules: networkservices.EdgeCacheServiceRoutingHostRuleArray{
					&networkservices.EdgeCacheServiceRoutingHostRuleArgs{
						Description: pulumi.String("host rule description"),
						Hosts: pulumi.StringArray{
							pulumi.String("sslcert.tf-test.club"),
						},
						PathMatcher: pulumi.String("routes"),
					},
				},
				PathMatchers: networkservices.EdgeCacheServiceRoutingPathMatcherArray{
					&networkservices.EdgeCacheServiceRoutingPathMatcherArgs{
						Name: pulumi.String("routes"),
						RouteRules: networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleArray{
							&networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleArgs{
								Description: pulumi.String("a route rule to match against"),
								Priority:    pulumi.String("1"),
								MatchRules: networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleMatchRuleArray{
									&networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleMatchRuleArgs{
										PrefixMatch: pulumi.String("/"),
									},
								},
								Origin: instance.Name,
								RouteAction: &networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionArgs{
									CdnPolicy: &networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionCdnPolicyArgs{
										CacheMode:  pulumi.String("CACHE_ALL_STATIC"),
										DefaultTtl: pulumi.String("3600s"),
									},
								},
								HeaderAction: &networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleHeaderActionArgs{
									ResponseHeaderToAdds: networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleHeaderActionResponseHeaderToAddArray{
										&networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleHeaderActionResponseHeaderToAddArgs{
											HeaderName:  pulumi.String("x-cache-status"),
											HeaderValue: pulumi.String("{cdn_cache_status}"),
										},
									},
								},
							},
						},
					},
				},
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var dest = new Gcp.Storage.Bucket("dest", new()
    {
        Name = "my-bucket",
        Location = "US",
        ForceDestroy = true,
    });

    var instance = new Gcp.NetworkServices.EdgeCacheOrigin("instance", new()
    {
        Name = "my-origin",
        OriginAddress = dest.Url,
        Description = "The default bucket for media edge test",
        MaxAttempts = 2,
        Timeout = new Gcp.NetworkServices.Inputs.EdgeCacheOriginTimeoutArgs
        {
            ConnectTimeout = "10s",
        },
    });

    var instanceEdgeCacheService = new Gcp.NetworkServices.EdgeCacheService("instance", new()
    {
        Name = "my-service",
        Description = "some description",
        Routing = new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingArgs
        {
            HostRules = new[]
            {
                new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingHostRuleArgs
                {
                    Description = "host rule description",
                    Hosts = new[]
                    {
                        "sslcert.tf-test.club",
                    },
                    PathMatcher = "routes",
                },
            },
            PathMatchers = new[]
            {
                new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherArgs
                {
                    Name = "routes",
                    RouteRules = new[]
                    {
                        new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleArgs
                        {
                            Description = "a route rule to match against",
                            Priority = "1",
                            MatchRules = new[]
                            {
                                new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleMatchRuleArgs
                                {
                                    PrefixMatch = "/",
                                },
                            },
                            Origin = instance.Name,
                            RouteAction = new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionArgs
                            {
                                CdnPolicy = new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionCdnPolicyArgs
                                {
                                    CacheMode = "CACHE_ALL_STATIC",
                                    DefaultTtl = "3600s",
                                },
                            },
                            HeaderAction = new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleHeaderActionArgs
                            {
                                ResponseHeaderToAdds = new[]
                                {
                                    new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleHeaderActionResponseHeaderToAddArgs
                                    {
                                        HeaderName = "x-cache-status",
                                        HeaderValue = "{cdn_cache_status}",
                                    },
                                },
                            },
                        },
                    },
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.storage.Bucket;
import com.pulumi.gcp.storage.BucketArgs;
import com.pulumi.gcp.networkservices.EdgeCacheOrigin;
import com.pulumi.gcp.networkservices.EdgeCacheOriginArgs;
import com.pulumi.gcp.networkservices.inputs.EdgeCacheOriginTimeoutArgs;
import com.pulumi.gcp.networkservices.EdgeCacheService;
import com.pulumi.gcp.networkservices.EdgeCacheServiceArgs;
import com.pulumi.gcp.networkservices.inputs.EdgeCacheServiceRoutingArgs;
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 dest = new Bucket("dest", BucketArgs.builder()
            .name("my-bucket")
            .location("US")
            .forceDestroy(true)
            .build());

        var instance = new EdgeCacheOrigin("instance", EdgeCacheOriginArgs.builder()
            .name("my-origin")
            .originAddress(dest.url())
            .description("The default bucket for media edge test")
            .maxAttempts(2)
            .timeout(EdgeCacheOriginTimeoutArgs.builder()
                .connectTimeout("10s")
                .build())
            .build());

        var instanceEdgeCacheService = new EdgeCacheService("instanceEdgeCacheService", EdgeCacheServiceArgs.builder()
            .name("my-service")
            .description("some description")
            .routing(EdgeCacheServiceRoutingArgs.builder()
                .hostRules(EdgeCacheServiceRoutingHostRuleArgs.builder()
                    .description("host rule description")
                    .hosts("sslcert.tf-test.club")
                    .pathMatcher("routes")
                    .build())
                .pathMatchers(EdgeCacheServiceRoutingPathMatcherArgs.builder()
                    .name("routes")
                    .routeRules(EdgeCacheServiceRoutingPathMatcherRouteRuleArgs.builder()
                        .description("a route rule to match against")
                        .priority("1")
                        .matchRules(EdgeCacheServiceRoutingPathMatcherRouteRuleMatchRuleArgs.builder()
                            .prefixMatch("/")
                            .build())
                        .origin(instance.name())
                        .routeAction(EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionArgs.builder()
                            .cdnPolicy(EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionCdnPolicyArgs.builder()
                                .cacheMode("CACHE_ALL_STATIC")
                                .defaultTtl("3600s")
                                .build())
                            .build())
                        .headerAction(EdgeCacheServiceRoutingPathMatcherRouteRuleHeaderActionArgs.builder()
                            .responseHeaderToAdds(EdgeCacheServiceRoutingPathMatcherRouteRuleHeaderActionResponseHeaderToAddArgs.builder()
                                .headerName("x-cache-status")
                                .headerValue("{cdn_cache_status}")
                                .build())
                            .build())
                        .build())
                    .build())
                .build())
            .build());

    }
}
resources:
  dest:
    type: gcp:storage:Bucket
    properties:
      name: my-bucket
      location: US
      forceDestroy: true
  instance:
    type: gcp:networkservices:EdgeCacheOrigin
    properties:
      name: my-origin
      originAddress: ${dest.url}
      description: The default bucket for media edge test
      maxAttempts: 2
      timeout:
        connectTimeout: 10s
  instanceEdgeCacheService:
    type: gcp:networkservices:EdgeCacheService
    name: instance
    properties:
      name: my-service
      description: some description
      routing:
        hostRules:
          - description: host rule description
            hosts:
              - sslcert.tf-test.club
            pathMatcher: routes
        pathMatchers:
          - name: routes
            routeRules:
              - description: a route rule to match against
                priority: 1
                matchRules:
                  - prefixMatch: /
                origin: ${instance.name}
                routeAction:
                  cdnPolicy:
                    cacheMode: CACHE_ALL_STATIC
                    defaultTtl: 3600s
                headerAction:
                  responseHeaderToAdds:
                    - headerName: x-cache-status
                      headerValue: '{cdn_cache_status}'

The routing property defines a hierarchy: hostRules map hostnames to pathMatchers, which contain routeRules that match URL patterns and specify origins. The cdnPolicy within routeAction controls cache behavior. Here, cacheMode is set to “CACHE_ALL_STATIC” with a 3600-second TTL, and the headerAction adds a cache status header to responses.

Configure advanced routing with header manipulation and CORS

Production CDNs need fine-grained control over request routing, cache behavior, and cross-origin policies for different URL patterns.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const dest = new gcp.storage.Bucket("dest", {
    name: "my-bucket",
    location: "US",
    forceDestroy: true,
});
const google = new gcp.networkservices.EdgeCacheOrigin("google", {
    name: "origin-google",
    originAddress: "google.com",
    description: "The default bucket for media edge test",
    maxAttempts: 2,
    timeout: {
        connectTimeout: "10s",
    },
});
const instance = new gcp.networkservices.EdgeCacheOrigin("instance", {
    name: "my-origin",
    originAddress: dest.url,
    description: "The default bucket for media edge test",
    maxAttempts: 2,
    timeout: {
        connectTimeout: "10s",
    },
});
const instanceEdgeCacheService = new gcp.networkservices.EdgeCacheService("instance", {
    name: "my-service",
    description: "some description",
    disableQuic: true,
    disableHttp2: true,
    labels: {
        a: "b",
    },
    routing: {
        hostRules: [
            {
                description: "host rule description",
                hosts: ["sslcert.tf-test.club"],
                pathMatcher: "routes",
            },
            {
                description: "host rule2",
                hosts: ["sslcert.tf-test2.club"],
                pathMatcher: "routes",
            },
            {
                description: "host rule3",
                hosts: ["sslcert.tf-test3.club"],
                pathMatcher: "routesAdvanced",
            },
        ],
        pathMatchers: [
            {
                name: "routes",
                routeRules: [{
                    description: "a route rule to match against",
                    priority: "1",
                    matchRules: [{
                        prefixMatch: "/",
                    }],
                    origin: instance.name,
                    routeAction: {
                        cdnPolicy: {
                            cacheMode: "CACHE_ALL_STATIC",
                            defaultTtl: "3600s",
                        },
                    },
                    headerAction: {
                        responseHeaderToAdds: [{
                            headerName: "x-cache-status",
                            headerValue: "{cdn_cache_status}",
                        }],
                    },
                }],
            },
            {
                name: "routesAdvanced",
                description: "an advanced ruleset",
                routeRules: [
                    {
                        description: "an advanced route rule to match against",
                        priority: "1",
                        matchRules: [
                            {
                                prefixMatch: "/potato/",
                                queryParameterMatches: [
                                    {
                                        name: "debug",
                                        presentMatch: true,
                                    },
                                    {
                                        name: "state",
                                        exactMatch: "debug",
                                    },
                                ],
                            },
                            {
                                fullPathMatch: "/apple",
                            },
                        ],
                        headerAction: {
                            requestHeaderToAdds: [
                                {
                                    headerName: "debug",
                                    headerValue: "true",
                                    replace: true,
                                },
                                {
                                    headerName: "potato",
                                    headerValue: "plant",
                                },
                            ],
                            responseHeaderToAdds: [{
                                headerName: "potato",
                                headerValue: "plant",
                                replace: true,
                            }],
                            requestHeaderToRemoves: [{
                                headerName: "prod",
                            }],
                            responseHeaderToRemoves: [{
                                headerName: "prod",
                            }],
                        },
                        origin: instance.name,
                        routeAction: {
                            cdnPolicy: {
                                cacheMode: "CACHE_ALL_STATIC",
                                defaultTtl: "3800s",
                                clientTtl: "3600s",
                                maxTtl: "9000s",
                                cacheKeyPolicy: {
                                    includeProtocol: true,
                                    excludeHost: true,
                                    includedQueryParameters: [
                                        "apple",
                                        "dev",
                                        "santa",
                                        "claus",
                                    ],
                                    includedHeaderNames: ["banana"],
                                    includedCookieNames: ["orange"],
                                },
                                negativeCaching: true,
                                signedRequestMode: "DISABLED",
                                negativeCachingPolicy: {
                                    "500": "3000s",
                                },
                            },
                            urlRewrite: {
                                pathPrefixRewrite: "/dev",
                                hostRewrite: "dev.club",
                            },
                            corsPolicy: {
                                maxAge: "2500s",
                                allowCredentials: true,
                                allowOrigins: ["*"],
                                allowMethods: ["GET"],
                                allowHeaders: ["dev"],
                                exposeHeaders: ["prod"],
                            },
                        },
                    },
                    {
                        description: "a second route rule to match against",
                        priority: "2",
                        matchRules: [{
                            fullPathMatch: "/yay",
                        }],
                        origin: instance.name,
                        routeAction: {
                            cdnPolicy: {
                                cacheMode: "CACHE_ALL_STATIC",
                                defaultTtl: "3600s",
                                cacheKeyPolicy: {
                                    excludedQueryParameters: ["dev"],
                                },
                            },
                            corsPolicy: {
                                maxAge: "3000s",
                                allowHeaders: ["dev"],
                                disabled: true,
                            },
                        },
                    },
                ],
            },
        ],
    },
    logConfig: {
        enable: true,
        sampleRate: 0.01,
    },
});
import pulumi
import pulumi_gcp as gcp

dest = gcp.storage.Bucket("dest",
    name="my-bucket",
    location="US",
    force_destroy=True)
google = gcp.networkservices.EdgeCacheOrigin("google",
    name="origin-google",
    origin_address="google.com",
    description="The default bucket for media edge test",
    max_attempts=2,
    timeout={
        "connect_timeout": "10s",
    })
instance = gcp.networkservices.EdgeCacheOrigin("instance",
    name="my-origin",
    origin_address=dest.url,
    description="The default bucket for media edge test",
    max_attempts=2,
    timeout={
        "connect_timeout": "10s",
    })
instance_edge_cache_service = gcp.networkservices.EdgeCacheService("instance",
    name="my-service",
    description="some description",
    disable_quic=True,
    disable_http2=True,
    labels={
        "a": "b",
    },
    routing={
        "host_rules": [
            {
                "description": "host rule description",
                "hosts": ["sslcert.tf-test.club"],
                "path_matcher": "routes",
            },
            {
                "description": "host rule2",
                "hosts": ["sslcert.tf-test2.club"],
                "path_matcher": "routes",
            },
            {
                "description": "host rule3",
                "hosts": ["sslcert.tf-test3.club"],
                "path_matcher": "routesAdvanced",
            },
        ],
        "path_matchers": [
            {
                "name": "routes",
                "route_rules": [{
                    "description": "a route rule to match against",
                    "priority": "1",
                    "match_rules": [{
                        "prefix_match": "/",
                    }],
                    "origin": instance.name,
                    "route_action": {
                        "cdn_policy": {
                            "cache_mode": "CACHE_ALL_STATIC",
                            "default_ttl": "3600s",
                        },
                    },
                    "header_action": {
                        "response_header_to_adds": [{
                            "header_name": "x-cache-status",
                            "header_value": "{cdn_cache_status}",
                        }],
                    },
                }],
            },
            {
                "name": "routesAdvanced",
                "description": "an advanced ruleset",
                "route_rules": [
                    {
                        "description": "an advanced route rule to match against",
                        "priority": "1",
                        "match_rules": [
                            {
                                "prefix_match": "/potato/",
                                "query_parameter_matches": [
                                    {
                                        "name": "debug",
                                        "present_match": True,
                                    },
                                    {
                                        "name": "state",
                                        "exact_match": "debug",
                                    },
                                ],
                            },
                            {
                                "full_path_match": "/apple",
                            },
                        ],
                        "header_action": {
                            "request_header_to_adds": [
                                {
                                    "header_name": "debug",
                                    "header_value": "true",
                                    "replace": True,
                                },
                                {
                                    "header_name": "potato",
                                    "header_value": "plant",
                                },
                            ],
                            "response_header_to_adds": [{
                                "header_name": "potato",
                                "header_value": "plant",
                                "replace": True,
                            }],
                            "request_header_to_removes": [{
                                "header_name": "prod",
                            }],
                            "response_header_to_removes": [{
                                "header_name": "prod",
                            }],
                        },
                        "origin": instance.name,
                        "route_action": {
                            "cdn_policy": {
                                "cache_mode": "CACHE_ALL_STATIC",
                                "default_ttl": "3800s",
                                "client_ttl": "3600s",
                                "max_ttl": "9000s",
                                "cache_key_policy": {
                                    "include_protocol": True,
                                    "exclude_host": True,
                                    "included_query_parameters": [
                                        "apple",
                                        "dev",
                                        "santa",
                                        "claus",
                                    ],
                                    "included_header_names": ["banana"],
                                    "included_cookie_names": ["orange"],
                                },
                                "negative_caching": True,
                                "signed_request_mode": "DISABLED",
                                "negative_caching_policy": {
                                    "500": "3000s",
                                },
                            },
                            "url_rewrite": {
                                "path_prefix_rewrite": "/dev",
                                "host_rewrite": "dev.club",
                            },
                            "cors_policy": {
                                "max_age": "2500s",
                                "allow_credentials": True,
                                "allow_origins": ["*"],
                                "allow_methods": ["GET"],
                                "allow_headers": ["dev"],
                                "expose_headers": ["prod"],
                            },
                        },
                    },
                    {
                        "description": "a second route rule to match against",
                        "priority": "2",
                        "match_rules": [{
                            "full_path_match": "/yay",
                        }],
                        "origin": instance.name,
                        "route_action": {
                            "cdn_policy": {
                                "cache_mode": "CACHE_ALL_STATIC",
                                "default_ttl": "3600s",
                                "cache_key_policy": {
                                    "excluded_query_parameters": ["dev"],
                                },
                            },
                            "cors_policy": {
                                "max_age": "3000s",
                                "allow_headers": ["dev"],
                                "disabled": True,
                            },
                        },
                    },
                ],
            },
        ],
    },
    log_config={
        "enable": True,
        "sample_rate": 0.01,
    })
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/networkservices"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/storage"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		dest, err := storage.NewBucket(ctx, "dest", &storage.BucketArgs{
			Name:         pulumi.String("my-bucket"),
			Location:     pulumi.String("US"),
			ForceDestroy: pulumi.Bool(true),
		})
		if err != nil {
			return err
		}
		_, err = networkservices.NewEdgeCacheOrigin(ctx, "google", &networkservices.EdgeCacheOriginArgs{
			Name:          pulumi.String("origin-google"),
			OriginAddress: pulumi.String("google.com"),
			Description:   pulumi.String("The default bucket for media edge test"),
			MaxAttempts:   pulumi.Int(2),
			Timeout: &networkservices.EdgeCacheOriginTimeoutArgs{
				ConnectTimeout: pulumi.String("10s"),
			},
		})
		if err != nil {
			return err
		}
		instance, err := networkservices.NewEdgeCacheOrigin(ctx, "instance", &networkservices.EdgeCacheOriginArgs{
			Name:          pulumi.String("my-origin"),
			OriginAddress: dest.Url,
			Description:   pulumi.String("The default bucket for media edge test"),
			MaxAttempts:   pulumi.Int(2),
			Timeout: &networkservices.EdgeCacheOriginTimeoutArgs{
				ConnectTimeout: pulumi.String("10s"),
			},
		})
		if err != nil {
			return err
		}
		_, err = networkservices.NewEdgeCacheService(ctx, "instance", &networkservices.EdgeCacheServiceArgs{
			Name:         pulumi.String("my-service"),
			Description:  pulumi.String("some description"),
			DisableQuic:  pulumi.Bool(true),
			DisableHttp2: pulumi.Bool(true),
			Labels: pulumi.StringMap{
				"a": pulumi.String("b"),
			},
			Routing: &networkservices.EdgeCacheServiceRoutingArgs{
				HostRules: networkservices.EdgeCacheServiceRoutingHostRuleArray{
					&networkservices.EdgeCacheServiceRoutingHostRuleArgs{
						Description: pulumi.String("host rule description"),
						Hosts: pulumi.StringArray{
							pulumi.String("sslcert.tf-test.club"),
						},
						PathMatcher: pulumi.String("routes"),
					},
					&networkservices.EdgeCacheServiceRoutingHostRuleArgs{
						Description: pulumi.String("host rule2"),
						Hosts: pulumi.StringArray{
							pulumi.String("sslcert.tf-test2.club"),
						},
						PathMatcher: pulumi.String("routes"),
					},
					&networkservices.EdgeCacheServiceRoutingHostRuleArgs{
						Description: pulumi.String("host rule3"),
						Hosts: pulumi.StringArray{
							pulumi.String("sslcert.tf-test3.club"),
						},
						PathMatcher: pulumi.String("routesAdvanced"),
					},
				},
				PathMatchers: networkservices.EdgeCacheServiceRoutingPathMatcherArray{
					&networkservices.EdgeCacheServiceRoutingPathMatcherArgs{
						Name: pulumi.String("routes"),
						RouteRules: networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleArray{
							&networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleArgs{
								Description: pulumi.String("a route rule to match against"),
								Priority:    pulumi.String("1"),
								MatchRules: networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleMatchRuleArray{
									&networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleMatchRuleArgs{
										PrefixMatch: pulumi.String("/"),
									},
								},
								Origin: instance.Name,
								RouteAction: &networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionArgs{
									CdnPolicy: &networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionCdnPolicyArgs{
										CacheMode:  pulumi.String("CACHE_ALL_STATIC"),
										DefaultTtl: pulumi.String("3600s"),
									},
								},
								HeaderAction: &networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleHeaderActionArgs{
									ResponseHeaderToAdds: networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleHeaderActionResponseHeaderToAddArray{
										&networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleHeaderActionResponseHeaderToAddArgs{
											HeaderName:  pulumi.String("x-cache-status"),
											HeaderValue: pulumi.String("{cdn_cache_status}"),
										},
									},
								},
							},
						},
					},
					&networkservices.EdgeCacheServiceRoutingPathMatcherArgs{
						Name:        pulumi.String("routesAdvanced"),
						Description: pulumi.String("an advanced ruleset"),
						RouteRules: networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleArray{
							&networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleArgs{
								Description: pulumi.String("an advanced route rule to match against"),
								Priority:    pulumi.String("1"),
								MatchRules: networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleMatchRuleArray{
									&networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleMatchRuleArgs{
										PrefixMatch: pulumi.String("/potato/"),
										QueryParameterMatches: networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleMatchRuleQueryParameterMatchArray{
											&networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleMatchRuleQueryParameterMatchArgs{
												Name:         pulumi.String("debug"),
												PresentMatch: pulumi.Bool(true),
											},
											&networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleMatchRuleQueryParameterMatchArgs{
												Name:       pulumi.String("state"),
												ExactMatch: pulumi.String("debug"),
											},
										},
									},
									&networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleMatchRuleArgs{
										FullPathMatch: pulumi.String("/apple"),
									},
								},
								HeaderAction: &networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleHeaderActionArgs{
									RequestHeaderToAdds: networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleHeaderActionRequestHeaderToAddArray{
										&networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleHeaderActionRequestHeaderToAddArgs{
											HeaderName:  pulumi.String("debug"),
											HeaderValue: pulumi.String("true"),
											Replace:     pulumi.Bool(true),
										},
										&networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleHeaderActionRequestHeaderToAddArgs{
											HeaderName:  pulumi.String("potato"),
											HeaderValue: pulumi.String("plant"),
										},
									},
									ResponseHeaderToAdds: networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleHeaderActionResponseHeaderToAddArray{
										&networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleHeaderActionResponseHeaderToAddArgs{
											HeaderName:  pulumi.String("potato"),
											HeaderValue: pulumi.String("plant"),
											Replace:     pulumi.Bool(true),
										},
									},
									RequestHeaderToRemoves: networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleHeaderActionRequestHeaderToRemoveArray{
										&networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleHeaderActionRequestHeaderToRemoveArgs{
											HeaderName: pulumi.String("prod"),
										},
									},
									ResponseHeaderToRemoves: networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleHeaderActionResponseHeaderToRemoveArray{
										&networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleHeaderActionResponseHeaderToRemoveArgs{
											HeaderName: pulumi.String("prod"),
										},
									},
								},
								Origin: instance.Name,
								RouteAction: &networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionArgs{
									CdnPolicy: &networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionCdnPolicyArgs{
										CacheMode:  pulumi.String("CACHE_ALL_STATIC"),
										DefaultTtl: pulumi.String("3800s"),
										ClientTtl:  pulumi.String("3600s"),
										MaxTtl:     pulumi.String("9000s"),
										CacheKeyPolicy: &networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionCdnPolicyCacheKeyPolicyArgs{
											IncludeProtocol: pulumi.Bool(true),
											ExcludeHost:     pulumi.Bool(true),
											IncludedQueryParameters: pulumi.StringArray{
												pulumi.String("apple"),
												pulumi.String("dev"),
												pulumi.String("santa"),
												pulumi.String("claus"),
											},
											IncludedHeaderNames: pulumi.StringArray{
												pulumi.String("banana"),
											},
											IncludedCookieNames: pulumi.StringArray{
												pulumi.String("orange"),
											},
										},
										NegativeCaching:   pulumi.Bool(true),
										SignedRequestMode: pulumi.String("DISABLED"),
										NegativeCachingPolicy: pulumi.StringMap{
											"500": pulumi.String("3000s"),
										},
									},
									UrlRewrite: &networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionUrlRewriteArgs{
										PathPrefixRewrite: pulumi.String("/dev"),
										HostRewrite:       pulumi.String("dev.club"),
									},
									CorsPolicy: &networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionCorsPolicyArgs{
										MaxAge:           pulumi.String("2500s"),
										AllowCredentials: pulumi.Bool(true),
										AllowOrigins: pulumi.StringArray{
											pulumi.String("*"),
										},
										AllowMethods: pulumi.StringArray{
											pulumi.String("GET"),
										},
										AllowHeaders: pulumi.StringArray{
											pulumi.String("dev"),
										},
										ExposeHeaders: pulumi.StringArray{
											pulumi.String("prod"),
										},
									},
								},
							},
							&networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleArgs{
								Description: pulumi.String("a second route rule to match against"),
								Priority:    pulumi.String("2"),
								MatchRules: networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleMatchRuleArray{
									&networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleMatchRuleArgs{
										FullPathMatch: pulumi.String("/yay"),
									},
								},
								Origin: instance.Name,
								RouteAction: &networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionArgs{
									CdnPolicy: &networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionCdnPolicyArgs{
										CacheMode:  pulumi.String("CACHE_ALL_STATIC"),
										DefaultTtl: pulumi.String("3600s"),
										CacheKeyPolicy: &networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionCdnPolicyCacheKeyPolicyArgs{
											ExcludedQueryParameters: pulumi.StringArray{
												pulumi.String("dev"),
											},
										},
									},
									CorsPolicy: &networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionCorsPolicyArgs{
										MaxAge: pulumi.String("3000s"),
										AllowHeaders: pulumi.StringArray{
											pulumi.String("dev"),
										},
										Disabled: pulumi.Bool(true),
									},
								},
							},
						},
					},
				},
			},
			LogConfig: &networkservices.EdgeCacheServiceLogConfigArgs{
				Enable:     pulumi.Bool(true),
				SampleRate: pulumi.Float64(0.01),
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var dest = new Gcp.Storage.Bucket("dest", new()
    {
        Name = "my-bucket",
        Location = "US",
        ForceDestroy = true,
    });

    var google = new Gcp.NetworkServices.EdgeCacheOrigin("google", new()
    {
        Name = "origin-google",
        OriginAddress = "google.com",
        Description = "The default bucket for media edge test",
        MaxAttempts = 2,
        Timeout = new Gcp.NetworkServices.Inputs.EdgeCacheOriginTimeoutArgs
        {
            ConnectTimeout = "10s",
        },
    });

    var instance = new Gcp.NetworkServices.EdgeCacheOrigin("instance", new()
    {
        Name = "my-origin",
        OriginAddress = dest.Url,
        Description = "The default bucket for media edge test",
        MaxAttempts = 2,
        Timeout = new Gcp.NetworkServices.Inputs.EdgeCacheOriginTimeoutArgs
        {
            ConnectTimeout = "10s",
        },
    });

    var instanceEdgeCacheService = new Gcp.NetworkServices.EdgeCacheService("instance", new()
    {
        Name = "my-service",
        Description = "some description",
        DisableQuic = true,
        DisableHttp2 = true,
        Labels = 
        {
            { "a", "b" },
        },
        Routing = new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingArgs
        {
            HostRules = new[]
            {
                new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingHostRuleArgs
                {
                    Description = "host rule description",
                    Hosts = new[]
                    {
                        "sslcert.tf-test.club",
                    },
                    PathMatcher = "routes",
                },
                new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingHostRuleArgs
                {
                    Description = "host rule2",
                    Hosts = new[]
                    {
                        "sslcert.tf-test2.club",
                    },
                    PathMatcher = "routes",
                },
                new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingHostRuleArgs
                {
                    Description = "host rule3",
                    Hosts = new[]
                    {
                        "sslcert.tf-test3.club",
                    },
                    PathMatcher = "routesAdvanced",
                },
            },
            PathMatchers = new[]
            {
                new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherArgs
                {
                    Name = "routes",
                    RouteRules = new[]
                    {
                        new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleArgs
                        {
                            Description = "a route rule to match against",
                            Priority = "1",
                            MatchRules = new[]
                            {
                                new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleMatchRuleArgs
                                {
                                    PrefixMatch = "/",
                                },
                            },
                            Origin = instance.Name,
                            RouteAction = new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionArgs
                            {
                                CdnPolicy = new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionCdnPolicyArgs
                                {
                                    CacheMode = "CACHE_ALL_STATIC",
                                    DefaultTtl = "3600s",
                                },
                            },
                            HeaderAction = new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleHeaderActionArgs
                            {
                                ResponseHeaderToAdds = new[]
                                {
                                    new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleHeaderActionResponseHeaderToAddArgs
                                    {
                                        HeaderName = "x-cache-status",
                                        HeaderValue = "{cdn_cache_status}",
                                    },
                                },
                            },
                        },
                    },
                },
                new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherArgs
                {
                    Name = "routesAdvanced",
                    Description = "an advanced ruleset",
                    RouteRules = new[]
                    {
                        new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleArgs
                        {
                            Description = "an advanced route rule to match against",
                            Priority = "1",
                            MatchRules = new[]
                            {
                                new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleMatchRuleArgs
                                {
                                    PrefixMatch = "/potato/",
                                    QueryParameterMatches = new[]
                                    {
                                        new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleMatchRuleQueryParameterMatchArgs
                                        {
                                            Name = "debug",
                                            PresentMatch = true,
                                        },
                                        new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleMatchRuleQueryParameterMatchArgs
                                        {
                                            Name = "state",
                                            ExactMatch = "debug",
                                        },
                                    },
                                },
                                new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleMatchRuleArgs
                                {
                                    FullPathMatch = "/apple",
                                },
                            },
                            HeaderAction = new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleHeaderActionArgs
                            {
                                RequestHeaderToAdds = new[]
                                {
                                    new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleHeaderActionRequestHeaderToAddArgs
                                    {
                                        HeaderName = "debug",
                                        HeaderValue = "true",
                                        Replace = true,
                                    },
                                    new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleHeaderActionRequestHeaderToAddArgs
                                    {
                                        HeaderName = "potato",
                                        HeaderValue = "plant",
                                    },
                                },
                                ResponseHeaderToAdds = new[]
                                {
                                    new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleHeaderActionResponseHeaderToAddArgs
                                    {
                                        HeaderName = "potato",
                                        HeaderValue = "plant",
                                        Replace = true,
                                    },
                                },
                                RequestHeaderToRemoves = new[]
                                {
                                    new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleHeaderActionRequestHeaderToRemoveArgs
                                    {
                                        HeaderName = "prod",
                                    },
                                },
                                ResponseHeaderToRemoves = new[]
                                {
                                    new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleHeaderActionResponseHeaderToRemoveArgs
                                    {
                                        HeaderName = "prod",
                                    },
                                },
                            },
                            Origin = instance.Name,
                            RouteAction = new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionArgs
                            {
                                CdnPolicy = new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionCdnPolicyArgs
                                {
                                    CacheMode = "CACHE_ALL_STATIC",
                                    DefaultTtl = "3800s",
                                    ClientTtl = "3600s",
                                    MaxTtl = "9000s",
                                    CacheKeyPolicy = new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionCdnPolicyCacheKeyPolicyArgs
                                    {
                                        IncludeProtocol = true,
                                        ExcludeHost = true,
                                        IncludedQueryParameters = new[]
                                        {
                                            "apple",
                                            "dev",
                                            "santa",
                                            "claus",
                                        },
                                        IncludedHeaderNames = new[]
                                        {
                                            "banana",
                                        },
                                        IncludedCookieNames = new[]
                                        {
                                            "orange",
                                        },
                                    },
                                    NegativeCaching = true,
                                    SignedRequestMode = "DISABLED",
                                    NegativeCachingPolicy = 
                                    {
                                        { "500", "3000s" },
                                    },
                                },
                                UrlRewrite = new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionUrlRewriteArgs
                                {
                                    PathPrefixRewrite = "/dev",
                                    HostRewrite = "dev.club",
                                },
                                CorsPolicy = new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionCorsPolicyArgs
                                {
                                    MaxAge = "2500s",
                                    AllowCredentials = true,
                                    AllowOrigins = new[]
                                    {
                                        "*",
                                    },
                                    AllowMethods = new[]
                                    {
                                        "GET",
                                    },
                                    AllowHeaders = new[]
                                    {
                                        "dev",
                                    },
                                    ExposeHeaders = new[]
                                    {
                                        "prod",
                                    },
                                },
                            },
                        },
                        new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleArgs
                        {
                            Description = "a second route rule to match against",
                            Priority = "2",
                            MatchRules = new[]
                            {
                                new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleMatchRuleArgs
                                {
                                    FullPathMatch = "/yay",
                                },
                            },
                            Origin = instance.Name,
                            RouteAction = new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionArgs
                            {
                                CdnPolicy = new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionCdnPolicyArgs
                                {
                                    CacheMode = "CACHE_ALL_STATIC",
                                    DefaultTtl = "3600s",
                                    CacheKeyPolicy = new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionCdnPolicyCacheKeyPolicyArgs
                                    {
                                        ExcludedQueryParameters = new[]
                                        {
                                            "dev",
                                        },
                                    },
                                },
                                CorsPolicy = new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionCorsPolicyArgs
                                {
                                    MaxAge = "3000s",
                                    AllowHeaders = new[]
                                    {
                                        "dev",
                                    },
                                    Disabled = true,
                                },
                            },
                        },
                    },
                },
            },
        },
        LogConfig = new Gcp.NetworkServices.Inputs.EdgeCacheServiceLogConfigArgs
        {
            Enable = true,
            SampleRate = 0.01,
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.storage.Bucket;
import com.pulumi.gcp.storage.BucketArgs;
import com.pulumi.gcp.networkservices.EdgeCacheOrigin;
import com.pulumi.gcp.networkservices.EdgeCacheOriginArgs;
import com.pulumi.gcp.networkservices.inputs.EdgeCacheOriginTimeoutArgs;
import com.pulumi.gcp.networkservices.EdgeCacheService;
import com.pulumi.gcp.networkservices.EdgeCacheServiceArgs;
import com.pulumi.gcp.networkservices.inputs.EdgeCacheServiceRoutingArgs;
import com.pulumi.gcp.networkservices.inputs.EdgeCacheServiceLogConfigArgs;
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 dest = new Bucket("dest", BucketArgs.builder()
            .name("my-bucket")
            .location("US")
            .forceDestroy(true)
            .build());

        var google = new EdgeCacheOrigin("google", EdgeCacheOriginArgs.builder()
            .name("origin-google")
            .originAddress("google.com")
            .description("The default bucket for media edge test")
            .maxAttempts(2)
            .timeout(EdgeCacheOriginTimeoutArgs.builder()
                .connectTimeout("10s")
                .build())
            .build());

        var instance = new EdgeCacheOrigin("instance", EdgeCacheOriginArgs.builder()
            .name("my-origin")
            .originAddress(dest.url())
            .description("The default bucket for media edge test")
            .maxAttempts(2)
            .timeout(EdgeCacheOriginTimeoutArgs.builder()
                .connectTimeout("10s")
                .build())
            .build());

        var instanceEdgeCacheService = new EdgeCacheService("instanceEdgeCacheService", EdgeCacheServiceArgs.builder()
            .name("my-service")
            .description("some description")
            .disableQuic(true)
            .disableHttp2(true)
            .labels(Map.of("a", "b"))
            .routing(EdgeCacheServiceRoutingArgs.builder()
                .hostRules(                
                    EdgeCacheServiceRoutingHostRuleArgs.builder()
                        .description("host rule description")
                        .hosts("sslcert.tf-test.club")
                        .pathMatcher("routes")
                        .build(),
                    EdgeCacheServiceRoutingHostRuleArgs.builder()
                        .description("host rule2")
                        .hosts("sslcert.tf-test2.club")
                        .pathMatcher("routes")
                        .build(),
                    EdgeCacheServiceRoutingHostRuleArgs.builder()
                        .description("host rule3")
                        .hosts("sslcert.tf-test3.club")
                        .pathMatcher("routesAdvanced")
                        .build())
                .pathMatchers(                
                    EdgeCacheServiceRoutingPathMatcherArgs.builder()
                        .name("routes")
                        .routeRules(EdgeCacheServiceRoutingPathMatcherRouteRuleArgs.builder()
                            .description("a route rule to match against")
                            .priority("1")
                            .matchRules(EdgeCacheServiceRoutingPathMatcherRouteRuleMatchRuleArgs.builder()
                                .prefixMatch("/")
                                .build())
                            .origin(instance.name())
                            .routeAction(EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionArgs.builder()
                                .cdnPolicy(EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionCdnPolicyArgs.builder()
                                    .cacheMode("CACHE_ALL_STATIC")
                                    .defaultTtl("3600s")
                                    .build())
                                .build())
                            .headerAction(EdgeCacheServiceRoutingPathMatcherRouteRuleHeaderActionArgs.builder()
                                .responseHeaderToAdds(EdgeCacheServiceRoutingPathMatcherRouteRuleHeaderActionResponseHeaderToAddArgs.builder()
                                    .headerName("x-cache-status")
                                    .headerValue("{cdn_cache_status}")
                                    .build())
                                .build())
                            .build())
                        .build(),
                    EdgeCacheServiceRoutingPathMatcherArgs.builder()
                        .name("routesAdvanced")
                        .description("an advanced ruleset")
                        .routeRules(                        
                            EdgeCacheServiceRoutingPathMatcherRouteRuleArgs.builder()
                                .description("an advanced route rule to match against")
                                .priority("1")
                                .matchRules(                                
                                    EdgeCacheServiceRoutingPathMatcherRouteRuleMatchRuleArgs.builder()
                                        .prefixMatch("/potato/")
                                        .queryParameterMatches(                                        
                                            EdgeCacheServiceRoutingPathMatcherRouteRuleMatchRuleQueryParameterMatchArgs.builder()
                                                .name("debug")
                                                .presentMatch(true)
                                                .build(),
                                            EdgeCacheServiceRoutingPathMatcherRouteRuleMatchRuleQueryParameterMatchArgs.builder()
                                                .name("state")
                                                .exactMatch("debug")
                                                .build())
                                        .build(),
                                    EdgeCacheServiceRoutingPathMatcherRouteRuleMatchRuleArgs.builder()
                                        .fullPathMatch("/apple")
                                        .build())
                                .headerAction(EdgeCacheServiceRoutingPathMatcherRouteRuleHeaderActionArgs.builder()
                                    .requestHeaderToAdds(                                    
                                        EdgeCacheServiceRoutingPathMatcherRouteRuleHeaderActionRequestHeaderToAddArgs.builder()
                                            .headerName("debug")
                                            .headerValue("true")
                                            .replace(true)
                                            .build(),
                                        EdgeCacheServiceRoutingPathMatcherRouteRuleHeaderActionRequestHeaderToAddArgs.builder()
                                            .headerName("potato")
                                            .headerValue("plant")
                                            .build())
                                    .responseHeaderToAdds(EdgeCacheServiceRoutingPathMatcherRouteRuleHeaderActionResponseHeaderToAddArgs.builder()
                                        .headerName("potato")
                                        .headerValue("plant")
                                        .replace(true)
                                        .build())
                                    .requestHeaderToRemoves(EdgeCacheServiceRoutingPathMatcherRouteRuleHeaderActionRequestHeaderToRemoveArgs.builder()
                                        .headerName("prod")
                                        .build())
                                    .responseHeaderToRemoves(EdgeCacheServiceRoutingPathMatcherRouteRuleHeaderActionResponseHeaderToRemoveArgs.builder()
                                        .headerName("prod")
                                        .build())
                                    .build())
                                .origin(instance.name())
                                .routeAction(EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionArgs.builder()
                                    .cdnPolicy(EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionCdnPolicyArgs.builder()
                                        .cacheMode("CACHE_ALL_STATIC")
                                        .defaultTtl("3800s")
                                        .clientTtl("3600s")
                                        .maxTtl("9000s")
                                        .cacheKeyPolicy(EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionCdnPolicyCacheKeyPolicyArgs.builder()
                                            .includeProtocol(true)
                                            .excludeHost(true)
                                            .includedQueryParameters(                                            
                                                "apple",
                                                "dev",
                                                "santa",
                                                "claus")
                                            .includedHeaderNames("banana")
                                            .includedCookieNames("orange")
                                            .build())
                                        .negativeCaching(true)
                                        .signedRequestMode("DISABLED")
                                        .negativeCachingPolicy(Map.of("500", "3000s"))
                                        .build())
                                    .urlRewrite(EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionUrlRewriteArgs.builder()
                                        .pathPrefixRewrite("/dev")
                                        .hostRewrite("dev.club")
                                        .build())
                                    .corsPolicy(EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionCorsPolicyArgs.builder()
                                        .maxAge("2500s")
                                        .allowCredentials(true)
                                        .allowOrigins("*")
                                        .allowMethods("GET")
                                        .allowHeaders("dev")
                                        .exposeHeaders("prod")
                                        .build())
                                    .build())
                                .build(),
                            EdgeCacheServiceRoutingPathMatcherRouteRuleArgs.builder()
                                .description("a second route rule to match against")
                                .priority("2")
                                .matchRules(EdgeCacheServiceRoutingPathMatcherRouteRuleMatchRuleArgs.builder()
                                    .fullPathMatch("/yay")
                                    .build())
                                .origin(instance.name())
                                .routeAction(EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionArgs.builder()
                                    .cdnPolicy(EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionCdnPolicyArgs.builder()
                                        .cacheMode("CACHE_ALL_STATIC")
                                        .defaultTtl("3600s")
                                        .cacheKeyPolicy(EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionCdnPolicyCacheKeyPolicyArgs.builder()
                                            .excludedQueryParameters("dev")
                                            .build())
                                        .build())
                                    .corsPolicy(EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionCorsPolicyArgs.builder()
                                        .maxAge("3000s")
                                        .allowHeaders("dev")
                                        .disabled(true)
                                        .build())
                                    .build())
                                .build())
                        .build())
                .build())
            .logConfig(EdgeCacheServiceLogConfigArgs.builder()
                .enable(true)
                .sampleRate(0.01)
                .build())
            .build());

    }
}
resources:
  dest:
    type: gcp:storage:Bucket
    properties:
      name: my-bucket
      location: US
      forceDestroy: true
  google:
    type: gcp:networkservices:EdgeCacheOrigin
    properties:
      name: origin-google
      originAddress: google.com
      description: The default bucket for media edge test
      maxAttempts: 2
      timeout:
        connectTimeout: 10s
  instance:
    type: gcp:networkservices:EdgeCacheOrigin
    properties:
      name: my-origin
      originAddress: ${dest.url}
      description: The default bucket for media edge test
      maxAttempts: 2
      timeout:
        connectTimeout: 10s
  instanceEdgeCacheService:
    type: gcp:networkservices:EdgeCacheService
    name: instance
    properties:
      name: my-service
      description: some description
      disableQuic: true
      disableHttp2: true
      labels:
        a: b
      routing:
        hostRules:
          - description: host rule description
            hosts:
              - sslcert.tf-test.club
            pathMatcher: routes
          - description: host rule2
            hosts:
              - sslcert.tf-test2.club
            pathMatcher: routes
          - description: host rule3
            hosts:
              - sslcert.tf-test3.club
            pathMatcher: routesAdvanced
        pathMatchers:
          - name: routes
            routeRules:
              - description: a route rule to match against
                priority: 1
                matchRules:
                  - prefixMatch: /
                origin: ${instance.name}
                routeAction:
                  cdnPolicy:
                    cacheMode: CACHE_ALL_STATIC
                    defaultTtl: 3600s
                headerAction:
                  responseHeaderToAdds:
                    - headerName: x-cache-status
                      headerValue: '{cdn_cache_status}'
          - name: routesAdvanced
            description: an advanced ruleset
            routeRules:
              - description: an advanced route rule to match against
                priority: 1
                matchRules:
                  - prefixMatch: /potato/
                    queryParameterMatches:
                      - name: debug
                        presentMatch: true
                      - name: state
                        exactMatch: debug
                  - fullPathMatch: /apple
                headerAction:
                  requestHeaderToAdds:
                    - headerName: debug
                      headerValue: 'true'
                      replace: true
                    - headerName: potato
                      headerValue: plant
                  responseHeaderToAdds:
                    - headerName: potato
                      headerValue: plant
                      replace: true
                  requestHeaderToRemoves:
                    - headerName: prod
                  responseHeaderToRemoves:
                    - headerName: prod
                origin: ${instance.name}
                routeAction:
                  cdnPolicy:
                    cacheMode: CACHE_ALL_STATIC
                    defaultTtl: 3800s
                    clientTtl: 3600s
                    maxTtl: 9000s
                    cacheKeyPolicy:
                      includeProtocol: true
                      excludeHost: true
                      includedQueryParameters:
                        - apple
                        - dev
                        - santa
                        - claus
                      includedHeaderNames:
                        - banana
                      includedCookieNames:
                        - orange
                    negativeCaching: true
                    signedRequestMode: DISABLED
                    negativeCachingPolicy:
                      '500': 3000s
                  urlRewrite:
                    pathPrefixRewrite: /dev
                    hostRewrite: dev.club
                  corsPolicy:
                    maxAge: 2500s
                    allowCredentials: true
                    allowOrigins:
                      - '*'
                    allowMethods:
                      - GET
                    allowHeaders:
                      - dev
                    exposeHeaders:
                      - prod
              - description: a second route rule to match against
                priority: 2
                matchRules:
                  - fullPathMatch: /yay
                origin: ${instance.name}
                routeAction:
                  cdnPolicy:
                    cacheMode: CACHE_ALL_STATIC
                    defaultTtl: 3600s
                    cacheKeyPolicy:
                      excludedQueryParameters:
                        - dev
                  corsPolicy:
                    maxAge: 3000s
                    allowHeaders:
                      - dev
                    disabled: true
      logConfig:
        enable: true
        sampleRate: 0.01

Multiple pathMatchers allow different routing strategies per hostname. The matchRules array supports query parameter matching (queryParameterMatches) and path matching (prefixMatch, fullPathMatch). The headerAction manipulates request and response headers, while cacheKeyPolicy controls what’s included in cache keys (query parameters, headers, cookies). The corsPolicy configures cross-origin access, and urlRewrite modifies paths and hosts before forwarding to origins.

Protect content with signed URLs and token authentication

Media streaming and premium content require signed request validation to prevent unauthorized access.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const secret_basic = new gcp.secretmanager.Secret("secret-basic", {
    secretId: "secret-name",
    replication: {
        auto: {},
    },
});
const secret_version_basic = new gcp.secretmanager.SecretVersion("secret-version-basic", {
    secret: secret_basic.id,
    secretData: "secret-data",
});
const keyset = new gcp.networkservices.EdgeCacheKeyset("keyset", {
    name: "keyset-name",
    description: "The default keyset",
    publicKeys: [{
        id: "my-public-key",
        managed: true,
    }],
    validationSharedKeys: [{
        secretVersion: secret_version_basic.id,
    }],
});
const instance = new gcp.networkservices.EdgeCacheOrigin("instance", {
    name: "my-origin",
    originAddress: "gs://media-edge-default",
    description: "The default bucket for media edge test",
});
const instanceEdgeCacheService = new gcp.networkservices.EdgeCacheService("instance", {
    name: "my-service",
    description: "some description",
    routing: {
        hostRules: [{
            description: "host rule description",
            hosts: ["sslcert.tf-test.club"],
            pathMatcher: "routes",
        }],
        pathMatchers: [{
            name: "routes",
            routeRules: [
                {
                    description: "a route rule to match against master playlist",
                    priority: "1",
                    matchRules: [{
                        pathTemplateMatch: "/master.m3u8",
                    }],
                    origin: instance.name,
                    routeAction: {
                        cdnPolicy: {
                            signedRequestMode: "REQUIRE_TOKENS",
                            signedRequestKeyset: keyset.id,
                            signedTokenOptions: {
                                tokenQueryParameter: "edge-cache-token",
                            },
                            signedRequestMaximumExpirationTtl: "600s",
                            addSignatures: {
                                actions: "GENERATE_COOKIE",
                                keyset: keyset.id,
                                copiedParameters: [
                                    "PathGlobs",
                                    "SessionID",
                                ],
                            },
                        },
                    },
                },
                {
                    description: "a route rule to match against all playlists",
                    priority: "2",
                    matchRules: [{
                        pathTemplateMatch: "/*.m3u8",
                    }],
                    origin: instance.name,
                    routeAction: {
                        cdnPolicy: {
                            signedRequestMode: "REQUIRE_TOKENS",
                            signedRequestKeyset: keyset.id,
                            signedTokenOptions: {
                                tokenQueryParameter: "hdnts",
                                allowedSignatureAlgorithms: [
                                    "ED25519",
                                    "HMAC_SHA_256",
                                    "HMAC_SHA1",
                                ],
                            },
                            addSignatures: {
                                actions: "GENERATE_TOKEN_HLS_COOKIELESS",
                                keyset: keyset.id,
                                tokenTtl: "1200s",
                                tokenQueryParameter: "hdntl",
                                copiedParameters: ["URLPrefix"],
                            },
                        },
                    },
                },
                {
                    description: "a route rule to match against",
                    priority: "3",
                    matchRules: [{
                        pathTemplateMatch: "/**.m3u8",
                    }],
                    origin: instance.name,
                    routeAction: {
                        cdnPolicy: {
                            signedRequestMode: "REQUIRE_TOKENS",
                            signedRequestKeyset: keyset.id,
                            signedTokenOptions: {
                                tokenQueryParameter: "hdntl",
                            },
                            addSignatures: {
                                actions: "PROPAGATE_TOKEN_HLS_COOKIELESS",
                                tokenQueryParameter: "hdntl",
                            },
                        },
                    },
                },
            ],
        }],
    },
});
import pulumi
import pulumi_gcp as gcp

secret_basic = gcp.secretmanager.Secret("secret-basic",
    secret_id="secret-name",
    replication={
        "auto": {},
    })
secret_version_basic = gcp.secretmanager.SecretVersion("secret-version-basic",
    secret=secret_basic.id,
    secret_data="secret-data")
keyset = gcp.networkservices.EdgeCacheKeyset("keyset",
    name="keyset-name",
    description="The default keyset",
    public_keys=[{
        "id": "my-public-key",
        "managed": True,
    }],
    validation_shared_keys=[{
        "secret_version": secret_version_basic.id,
    }])
instance = gcp.networkservices.EdgeCacheOrigin("instance",
    name="my-origin",
    origin_address="gs://media-edge-default",
    description="The default bucket for media edge test")
instance_edge_cache_service = gcp.networkservices.EdgeCacheService("instance",
    name="my-service",
    description="some description",
    routing={
        "host_rules": [{
            "description": "host rule description",
            "hosts": ["sslcert.tf-test.club"],
            "path_matcher": "routes",
        }],
        "path_matchers": [{
            "name": "routes",
            "route_rules": [
                {
                    "description": "a route rule to match against master playlist",
                    "priority": "1",
                    "match_rules": [{
                        "path_template_match": "/master.m3u8",
                    }],
                    "origin": instance.name,
                    "route_action": {
                        "cdn_policy": {
                            "signed_request_mode": "REQUIRE_TOKENS",
                            "signed_request_keyset": keyset.id,
                            "signed_token_options": {
                                "token_query_parameter": "edge-cache-token",
                            },
                            "signed_request_maximum_expiration_ttl": "600s",
                            "add_signatures": {
                                "actions": "GENERATE_COOKIE",
                                "keyset": keyset.id,
                                "copied_parameters": [
                                    "PathGlobs",
                                    "SessionID",
                                ],
                            },
                        },
                    },
                },
                {
                    "description": "a route rule to match against all playlists",
                    "priority": "2",
                    "match_rules": [{
                        "path_template_match": "/*.m3u8",
                    }],
                    "origin": instance.name,
                    "route_action": {
                        "cdn_policy": {
                            "signed_request_mode": "REQUIRE_TOKENS",
                            "signed_request_keyset": keyset.id,
                            "signed_token_options": {
                                "token_query_parameter": "hdnts",
                                "allowed_signature_algorithms": [
                                    "ED25519",
                                    "HMAC_SHA_256",
                                    "HMAC_SHA1",
                                ],
                            },
                            "add_signatures": {
                                "actions": "GENERATE_TOKEN_HLS_COOKIELESS",
                                "keyset": keyset.id,
                                "token_ttl": "1200s",
                                "token_query_parameter": "hdntl",
                                "copied_parameters": ["URLPrefix"],
                            },
                        },
                    },
                },
                {
                    "description": "a route rule to match against",
                    "priority": "3",
                    "match_rules": [{
                        "path_template_match": "/**.m3u8",
                    }],
                    "origin": instance.name,
                    "route_action": {
                        "cdn_policy": {
                            "signed_request_mode": "REQUIRE_TOKENS",
                            "signed_request_keyset": keyset.id,
                            "signed_token_options": {
                                "token_query_parameter": "hdntl",
                            },
                            "add_signatures": {
                                "actions": "PROPAGATE_TOKEN_HLS_COOKIELESS",
                                "token_query_parameter": "hdntl",
                            },
                        },
                    },
                },
            ],
        }],
    })
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/networkservices"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/secretmanager"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		secret_basic, err := secretmanager.NewSecret(ctx, "secret-basic", &secretmanager.SecretArgs{
			SecretId: pulumi.String("secret-name"),
			Replication: &secretmanager.SecretReplicationArgs{
				Auto: &secretmanager.SecretReplicationAutoArgs{},
			},
		})
		if err != nil {
			return err
		}
		secret_version_basic, err := secretmanager.NewSecretVersion(ctx, "secret-version-basic", &secretmanager.SecretVersionArgs{
			Secret:     secret_basic.ID(),
			SecretData: pulumi.String("secret-data"),
		})
		if err != nil {
			return err
		}
		keyset, err := networkservices.NewEdgeCacheKeyset(ctx, "keyset", &networkservices.EdgeCacheKeysetArgs{
			Name:        pulumi.String("keyset-name"),
			Description: pulumi.String("The default keyset"),
			PublicKeys: networkservices.EdgeCacheKeysetPublicKeyArray{
				&networkservices.EdgeCacheKeysetPublicKeyArgs{
					Id:      pulumi.String("my-public-key"),
					Managed: pulumi.Bool(true),
				},
			},
			ValidationSharedKeys: networkservices.EdgeCacheKeysetValidationSharedKeyArray{
				&networkservices.EdgeCacheKeysetValidationSharedKeyArgs{
					SecretVersion: secret_version_basic.ID(),
				},
			},
		})
		if err != nil {
			return err
		}
		instance, err := networkservices.NewEdgeCacheOrigin(ctx, "instance", &networkservices.EdgeCacheOriginArgs{
			Name:          pulumi.String("my-origin"),
			OriginAddress: pulumi.String("gs://media-edge-default"),
			Description:   pulumi.String("The default bucket for media edge test"),
		})
		if err != nil {
			return err
		}
		_, err = networkservices.NewEdgeCacheService(ctx, "instance", &networkservices.EdgeCacheServiceArgs{
			Name:        pulumi.String("my-service"),
			Description: pulumi.String("some description"),
			Routing: &networkservices.EdgeCacheServiceRoutingArgs{
				HostRules: networkservices.EdgeCacheServiceRoutingHostRuleArray{
					&networkservices.EdgeCacheServiceRoutingHostRuleArgs{
						Description: pulumi.String("host rule description"),
						Hosts: pulumi.StringArray{
							pulumi.String("sslcert.tf-test.club"),
						},
						PathMatcher: pulumi.String("routes"),
					},
				},
				PathMatchers: networkservices.EdgeCacheServiceRoutingPathMatcherArray{
					&networkservices.EdgeCacheServiceRoutingPathMatcherArgs{
						Name: pulumi.String("routes"),
						RouteRules: networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleArray{
							&networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleArgs{
								Description: pulumi.String("a route rule to match against master playlist"),
								Priority:    pulumi.String("1"),
								MatchRules: networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleMatchRuleArray{
									&networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleMatchRuleArgs{
										PathTemplateMatch: pulumi.String("/master.m3u8"),
									},
								},
								Origin: instance.Name,
								RouteAction: &networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionArgs{
									CdnPolicy: &networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionCdnPolicyArgs{
										SignedRequestMode:   pulumi.String("REQUIRE_TOKENS"),
										SignedRequestKeyset: keyset.ID(),
										SignedTokenOptions: &networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionCdnPolicySignedTokenOptionsArgs{
											TokenQueryParameter: pulumi.String("edge-cache-token"),
										},
										SignedRequestMaximumExpirationTtl: pulumi.String("600s"),
										AddSignatures: &networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionCdnPolicyAddSignaturesArgs{
											Actions: pulumi.String("GENERATE_COOKIE"),
											Keyset:  keyset.ID(),
											CopiedParameters: pulumi.StringArray{
												pulumi.String("PathGlobs"),
												pulumi.String("SessionID"),
											},
										},
									},
								},
							},
							&networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleArgs{
								Description: pulumi.String("a route rule to match against all playlists"),
								Priority:    pulumi.String("2"),
								MatchRules: networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleMatchRuleArray{
									&networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleMatchRuleArgs{
										PathTemplateMatch: pulumi.String("/*.m3u8"),
									},
								},
								Origin: instance.Name,
								RouteAction: &networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionArgs{
									CdnPolicy: &networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionCdnPolicyArgs{
										SignedRequestMode:   pulumi.String("REQUIRE_TOKENS"),
										SignedRequestKeyset: keyset.ID(),
										SignedTokenOptions: &networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionCdnPolicySignedTokenOptionsArgs{
											TokenQueryParameter: pulumi.String("hdnts"),
											AllowedSignatureAlgorithms: pulumi.StringArray{
												pulumi.String("ED25519"),
												pulumi.String("HMAC_SHA_256"),
												pulumi.String("HMAC_SHA1"),
											},
										},
										AddSignatures: &networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionCdnPolicyAddSignaturesArgs{
											Actions:             pulumi.String("GENERATE_TOKEN_HLS_COOKIELESS"),
											Keyset:              keyset.ID(),
											TokenTtl:            pulumi.String("1200s"),
											TokenQueryParameter: pulumi.String("hdntl"),
											CopiedParameters: pulumi.StringArray{
												pulumi.String("URLPrefix"),
											},
										},
									},
								},
							},
							&networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleArgs{
								Description: pulumi.String("a route rule to match against"),
								Priority:    pulumi.String("3"),
								MatchRules: networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleMatchRuleArray{
									&networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleMatchRuleArgs{
										PathTemplateMatch: pulumi.String("/**.m3u8"),
									},
								},
								Origin: instance.Name,
								RouteAction: &networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionArgs{
									CdnPolicy: &networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionCdnPolicyArgs{
										SignedRequestMode:   pulumi.String("REQUIRE_TOKENS"),
										SignedRequestKeyset: keyset.ID(),
										SignedTokenOptions: &networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionCdnPolicySignedTokenOptionsArgs{
											TokenQueryParameter: pulumi.String("hdntl"),
										},
										AddSignatures: &networkservices.EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionCdnPolicyAddSignaturesArgs{
											Actions:             pulumi.String("PROPAGATE_TOKEN_HLS_COOKIELESS"),
											TokenQueryParameter: pulumi.String("hdntl"),
										},
									},
								},
							},
						},
					},
				},
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var secret_basic = new Gcp.SecretManager.Secret("secret-basic", new()
    {
        SecretId = "secret-name",
        Replication = new Gcp.SecretManager.Inputs.SecretReplicationArgs
        {
            Auto = null,
        },
    });

    var secret_version_basic = new Gcp.SecretManager.SecretVersion("secret-version-basic", new()
    {
        Secret = secret_basic.Id,
        SecretData = "secret-data",
    });

    var keyset = new Gcp.NetworkServices.EdgeCacheKeyset("keyset", new()
    {
        Name = "keyset-name",
        Description = "The default keyset",
        PublicKeys = new[]
        {
            new Gcp.NetworkServices.Inputs.EdgeCacheKeysetPublicKeyArgs
            {
                Id = "my-public-key",
                Managed = true,
            },
        },
        ValidationSharedKeys = new[]
        {
            new Gcp.NetworkServices.Inputs.EdgeCacheKeysetValidationSharedKeyArgs
            {
                SecretVersion = secret_version_basic.Id,
            },
        },
    });

    var instance = new Gcp.NetworkServices.EdgeCacheOrigin("instance", new()
    {
        Name = "my-origin",
        OriginAddress = "gs://media-edge-default",
        Description = "The default bucket for media edge test",
    });

    var instanceEdgeCacheService = new Gcp.NetworkServices.EdgeCacheService("instance", new()
    {
        Name = "my-service",
        Description = "some description",
        Routing = new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingArgs
        {
            HostRules = new[]
            {
                new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingHostRuleArgs
                {
                    Description = "host rule description",
                    Hosts = new[]
                    {
                        "sslcert.tf-test.club",
                    },
                    PathMatcher = "routes",
                },
            },
            PathMatchers = new[]
            {
                new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherArgs
                {
                    Name = "routes",
                    RouteRules = new[]
                    {
                        new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleArgs
                        {
                            Description = "a route rule to match against master playlist",
                            Priority = "1",
                            MatchRules = new[]
                            {
                                new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleMatchRuleArgs
                                {
                                    PathTemplateMatch = "/master.m3u8",
                                },
                            },
                            Origin = instance.Name,
                            RouteAction = new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionArgs
                            {
                                CdnPolicy = new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionCdnPolicyArgs
                                {
                                    SignedRequestMode = "REQUIRE_TOKENS",
                                    SignedRequestKeyset = keyset.Id,
                                    SignedTokenOptions = new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionCdnPolicySignedTokenOptionsArgs
                                    {
                                        TokenQueryParameter = "edge-cache-token",
                                    },
                                    SignedRequestMaximumExpirationTtl = "600s",
                                    AddSignatures = new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionCdnPolicyAddSignaturesArgs
                                    {
                                        Actions = "GENERATE_COOKIE",
                                        Keyset = keyset.Id,
                                        CopiedParameters = new[]
                                        {
                                            "PathGlobs",
                                            "SessionID",
                                        },
                                    },
                                },
                            },
                        },
                        new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleArgs
                        {
                            Description = "a route rule to match against all playlists",
                            Priority = "2",
                            MatchRules = new[]
                            {
                                new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleMatchRuleArgs
                                {
                                    PathTemplateMatch = "/*.m3u8",
                                },
                            },
                            Origin = instance.Name,
                            RouteAction = new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionArgs
                            {
                                CdnPolicy = new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionCdnPolicyArgs
                                {
                                    SignedRequestMode = "REQUIRE_TOKENS",
                                    SignedRequestKeyset = keyset.Id,
                                    SignedTokenOptions = new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionCdnPolicySignedTokenOptionsArgs
                                    {
                                        TokenQueryParameter = "hdnts",
                                        AllowedSignatureAlgorithms = new[]
                                        {
                                            "ED25519",
                                            "HMAC_SHA_256",
                                            "HMAC_SHA1",
                                        },
                                    },
                                    AddSignatures = new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionCdnPolicyAddSignaturesArgs
                                    {
                                        Actions = "GENERATE_TOKEN_HLS_COOKIELESS",
                                        Keyset = keyset.Id,
                                        TokenTtl = "1200s",
                                        TokenQueryParameter = "hdntl",
                                        CopiedParameters = new[]
                                        {
                                            "URLPrefix",
                                        },
                                    },
                                },
                            },
                        },
                        new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleArgs
                        {
                            Description = "a route rule to match against",
                            Priority = "3",
                            MatchRules = new[]
                            {
                                new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleMatchRuleArgs
                                {
                                    PathTemplateMatch = "/**.m3u8",
                                },
                            },
                            Origin = instance.Name,
                            RouteAction = new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionArgs
                            {
                                CdnPolicy = new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionCdnPolicyArgs
                                {
                                    SignedRequestMode = "REQUIRE_TOKENS",
                                    SignedRequestKeyset = keyset.Id,
                                    SignedTokenOptions = new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionCdnPolicySignedTokenOptionsArgs
                                    {
                                        TokenQueryParameter = "hdntl",
                                    },
                                    AddSignatures = new Gcp.NetworkServices.Inputs.EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionCdnPolicyAddSignaturesArgs
                                    {
                                        Actions = "PROPAGATE_TOKEN_HLS_COOKIELESS",
                                        TokenQueryParameter = "hdntl",
                                    },
                                },
                            },
                        },
                    },
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.secretmanager.Secret;
import com.pulumi.gcp.secretmanager.SecretArgs;
import com.pulumi.gcp.secretmanager.inputs.SecretReplicationArgs;
import com.pulumi.gcp.secretmanager.inputs.SecretReplicationAutoArgs;
import com.pulumi.gcp.secretmanager.SecretVersion;
import com.pulumi.gcp.secretmanager.SecretVersionArgs;
import com.pulumi.gcp.networkservices.EdgeCacheKeyset;
import com.pulumi.gcp.networkservices.EdgeCacheKeysetArgs;
import com.pulumi.gcp.networkservices.inputs.EdgeCacheKeysetPublicKeyArgs;
import com.pulumi.gcp.networkservices.inputs.EdgeCacheKeysetValidationSharedKeyArgs;
import com.pulumi.gcp.networkservices.EdgeCacheOrigin;
import com.pulumi.gcp.networkservices.EdgeCacheOriginArgs;
import com.pulumi.gcp.networkservices.EdgeCacheService;
import com.pulumi.gcp.networkservices.EdgeCacheServiceArgs;
import com.pulumi.gcp.networkservices.inputs.EdgeCacheServiceRoutingArgs;
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 secret_basic = new Secret("secret-basic", SecretArgs.builder()
            .secretId("secret-name")
            .replication(SecretReplicationArgs.builder()
                .auto(SecretReplicationAutoArgs.builder()
                    .build())
                .build())
            .build());

        var secret_version_basic = new SecretVersion("secret-version-basic", SecretVersionArgs.builder()
            .secret(secret_basic.id())
            .secretData("secret-data")
            .build());

        var keyset = new EdgeCacheKeyset("keyset", EdgeCacheKeysetArgs.builder()
            .name("keyset-name")
            .description("The default keyset")
            .publicKeys(EdgeCacheKeysetPublicKeyArgs.builder()
                .id("my-public-key")
                .managed(true)
                .build())
            .validationSharedKeys(EdgeCacheKeysetValidationSharedKeyArgs.builder()
                .secretVersion(secret_version_basic.id())
                .build())
            .build());

        var instance = new EdgeCacheOrigin("instance", EdgeCacheOriginArgs.builder()
            .name("my-origin")
            .originAddress("gs://media-edge-default")
            .description("The default bucket for media edge test")
            .build());

        var instanceEdgeCacheService = new EdgeCacheService("instanceEdgeCacheService", EdgeCacheServiceArgs.builder()
            .name("my-service")
            .description("some description")
            .routing(EdgeCacheServiceRoutingArgs.builder()
                .hostRules(EdgeCacheServiceRoutingHostRuleArgs.builder()
                    .description("host rule description")
                    .hosts("sslcert.tf-test.club")
                    .pathMatcher("routes")
                    .build())
                .pathMatchers(EdgeCacheServiceRoutingPathMatcherArgs.builder()
                    .name("routes")
                    .routeRules(                    
                        EdgeCacheServiceRoutingPathMatcherRouteRuleArgs.builder()
                            .description("a route rule to match against master playlist")
                            .priority("1")
                            .matchRules(EdgeCacheServiceRoutingPathMatcherRouteRuleMatchRuleArgs.builder()
                                .pathTemplateMatch("/master.m3u8")
                                .build())
                            .origin(instance.name())
                            .routeAction(EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionArgs.builder()
                                .cdnPolicy(EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionCdnPolicyArgs.builder()
                                    .signedRequestMode("REQUIRE_TOKENS")
                                    .signedRequestKeyset(keyset.id())
                                    .signedTokenOptions(EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionCdnPolicySignedTokenOptionsArgs.builder()
                                        .tokenQueryParameter("edge-cache-token")
                                        .build())
                                    .signedRequestMaximumExpirationTtl("600s")
                                    .addSignatures(EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionCdnPolicyAddSignaturesArgs.builder()
                                        .actions("GENERATE_COOKIE")
                                        .keyset(keyset.id())
                                        .copiedParameters(                                        
                                            "PathGlobs",
                                            "SessionID")
                                        .build())
                                    .build())
                                .build())
                            .build(),
                        EdgeCacheServiceRoutingPathMatcherRouteRuleArgs.builder()
                            .description("a route rule to match against all playlists")
                            .priority("2")
                            .matchRules(EdgeCacheServiceRoutingPathMatcherRouteRuleMatchRuleArgs.builder()
                                .pathTemplateMatch("/*.m3u8")
                                .build())
                            .origin(instance.name())
                            .routeAction(EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionArgs.builder()
                                .cdnPolicy(EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionCdnPolicyArgs.builder()
                                    .signedRequestMode("REQUIRE_TOKENS")
                                    .signedRequestKeyset(keyset.id())
                                    .signedTokenOptions(EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionCdnPolicySignedTokenOptionsArgs.builder()
                                        .tokenQueryParameter("hdnts")
                                        .allowedSignatureAlgorithms(                                        
                                            "ED25519",
                                            "HMAC_SHA_256",
                                            "HMAC_SHA1")
                                        .build())
                                    .addSignatures(EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionCdnPolicyAddSignaturesArgs.builder()
                                        .actions("GENERATE_TOKEN_HLS_COOKIELESS")
                                        .keyset(keyset.id())
                                        .tokenTtl("1200s")
                                        .tokenQueryParameter("hdntl")
                                        .copiedParameters("URLPrefix")
                                        .build())
                                    .build())
                                .build())
                            .build(),
                        EdgeCacheServiceRoutingPathMatcherRouteRuleArgs.builder()
                            .description("a route rule to match against")
                            .priority("3")
                            .matchRules(EdgeCacheServiceRoutingPathMatcherRouteRuleMatchRuleArgs.builder()
                                .pathTemplateMatch("/**.m3u8")
                                .build())
                            .origin(instance.name())
                            .routeAction(EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionArgs.builder()
                                .cdnPolicy(EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionCdnPolicyArgs.builder()
                                    .signedRequestMode("REQUIRE_TOKENS")
                                    .signedRequestKeyset(keyset.id())
                                    .signedTokenOptions(EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionCdnPolicySignedTokenOptionsArgs.builder()
                                        .tokenQueryParameter("hdntl")
                                        .build())
                                    .addSignatures(EdgeCacheServiceRoutingPathMatcherRouteRuleRouteActionCdnPolicyAddSignaturesArgs.builder()
                                        .actions("PROPAGATE_TOKEN_HLS_COOKIELESS")
                                        .tokenQueryParameter("hdntl")
                                        .build())
                                    .build())
                                .build())
                            .build())
                    .build())
                .build())
            .build());

    }
}
resources:
  secret-basic:
    type: gcp:secretmanager:Secret
    properties:
      secretId: secret-name
      replication:
        auto: {}
  secret-version-basic:
    type: gcp:secretmanager:SecretVersion
    properties:
      secret: ${["secret-basic"].id}
      secretData: secret-data
  keyset:
    type: gcp:networkservices:EdgeCacheKeyset
    properties:
      name: keyset-name
      description: The default keyset
      publicKeys:
        - id: my-public-key
          managed: true
      validationSharedKeys:
        - secretVersion: ${["secret-version-basic"].id}
  instance:
    type: gcp:networkservices:EdgeCacheOrigin
    properties:
      name: my-origin
      originAddress: gs://media-edge-default
      description: The default bucket for media edge test
  instanceEdgeCacheService:
    type: gcp:networkservices:EdgeCacheService
    name: instance
    properties:
      name: my-service
      description: some description
      routing:
        hostRules:
          - description: host rule description
            hosts:
              - sslcert.tf-test.club
            pathMatcher: routes
        pathMatchers:
          - name: routes
            routeRules:
              - description: a route rule to match against master playlist
                priority: 1
                matchRules:
                  - pathTemplateMatch: /master.m3u8
                origin: ${instance.name}
                routeAction:
                  cdnPolicy:
                    signedRequestMode: REQUIRE_TOKENS
                    signedRequestKeyset: ${keyset.id}
                    signedTokenOptions:
                      tokenQueryParameter: edge-cache-token
                    signedRequestMaximumExpirationTtl: 600s
                    addSignatures:
                      actions: GENERATE_COOKIE
                      keyset: ${keyset.id}
                      copiedParameters:
                        - PathGlobs
                        - SessionID
              - description: a route rule to match against all playlists
                priority: 2
                matchRules:
                  - pathTemplateMatch: /*.m3u8
                origin: ${instance.name}
                routeAction:
                  cdnPolicy:
                    signedRequestMode: REQUIRE_TOKENS
                    signedRequestKeyset: ${keyset.id}
                    signedTokenOptions:
                      tokenQueryParameter: hdnts
                      allowedSignatureAlgorithms:
                        - ED25519
                        - HMAC_SHA_256
                        - HMAC_SHA1
                    addSignatures:
                      actions: GENERATE_TOKEN_HLS_COOKIELESS
                      keyset: ${keyset.id}
                      tokenTtl: 1200s
                      tokenQueryParameter: hdntl
                      copiedParameters:
                        - URLPrefix
              - description: a route rule to match against
                priority: 3
                matchRules:
                  - pathTemplateMatch: /**.m3u8
                origin: ${instance.name}
                routeAction:
                  cdnPolicy:
                    signedRequestMode: REQUIRE_TOKENS
                    signedRequestKeyset: ${keyset.id}
                    signedTokenOptions:
                      tokenQueryParameter: hdntl
                    addSignatures:
                      actions: PROPAGATE_TOKEN_HLS_COOKIELESS
                      tokenQueryParameter: hdntl

The signedRequestMode property enforces token validation using keys from the referenced EdgeCacheKeyset. The signedTokenOptions specify which query parameter carries the token. The addSignatures block generates new tokens for downstream requests: GENERATE_COOKIE creates cookies for master playlists, GENERATE_TOKEN_HLS_COOKIELESS creates tokens for segment playlists, and PROPAGATE_TOKEN_HLS_COOKIELESS forwards existing tokens. The pathTemplateMatch property uses wildcards to match HLS manifest patterns.

Beyond these examples

These snippets focus on specific EdgeCacheService features: routing and path matching, cache policies and TTL configuration, and signed request authentication. They’re intentionally minimal rather than full CDN deployments.

The examples rely on pre-existing infrastructure such as EdgeCacheOrigin resources pointing to storage buckets or external origins, EdgeCacheKeyset resources with validation keys (for signed requests), Secret Manager secrets (for keyset validation), and DNS records pointing to service IP addresses. They focus on configuring the service rather than provisioning everything around it.

To keep things focused, common EdgeCacheService patterns are omitted, including:

  • TLS certificate attachment (edgeSslCertificates, requireTls)
  • Protocol controls (disableHttp2, disableQuic)
  • Cloud Armor security policies (edgeSecurityPolicy)
  • Request/response logging (logConfig)

These omissions are intentional: the goal is to illustrate how each EdgeCacheService feature is wired, not provide drop-in CDN modules. See the EdgeCacheService resource reference for all available configuration options.

Let's configure GCP Edge Cache Services

Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.

Try Pulumi Cloud for FREE

Frequently Asked Questions

Access & Prerequisites
Why can't I create an EdgeCacheService?
EdgeCacheService requires allow-listing and is not openly available to all Cloud customers. Engage with your Cloud account team to discuss onboarding.
Configuration & Setup
What are the naming requirements and can I change the name later?
The name must be 1-64 characters, start with a letter, and contain only letters, digits, dashes, or underscores (matching [a-zA-Z][a-zA-Z0-9_-]*). The name is immutable and cannot be changed after creation.
How do I enable HTTPS for my EdgeCacheService?
Set requireTls to true to force HTTPS (clients connecting via HTTP port 80 receive a 301 redirect to HTTPS port 443). You must specify at least one edgeSslCertificate to enable this.
What SSL certificates can I use with EdgeCacheService?
Only “global” certificates with a scope of “EDGE_CACHE” can be attached. Regular SSL certificates won’t work.
What SSL policy is used if I don't specify one?
EdgeCacheService defaults to the “COMPATIBLE” policy when sslPolicy is not set.
Protocol & Performance
What protocols does EdgeCacheService support and what's enabled by default?
HTTP/2 and HTTP/3 (IETF QUIC and Google QUIC) are enabled by default and recommended for performance. You can disable HTTP/2 with disableHttp2 or QUIC with disableQuic.
Why would I disable HTTP/2?
Some legacy HTTP clients have issues with HTTP/2 connections due to broken implementations. Setting disableHttp2 to true prevents HTTP/2 from being advertised and negotiated.
Routing & Traffic Management
How do I configure routing for my EdgeCacheService?
Configure the routing property with hostRules (mapping hosts to path matchers), pathMatchers (defining route rules), and routeRules (specifying match conditions, origins, and actions like caching and header manipulation).
How do I set up signed requests with authentication tokens?
Configure signedRequestMode with a keyset and signedTokenOptions in the cdnPolicy. You can generate cookies or tokens using addSignatures with actions like GENERATE_COOKIE or GENERATE_TOKEN_HLS_COOKIELESS.
Immutability & Lifecycle
How are IP addresses assigned to my EdgeCacheService?
IPv4 and IPv6 addresses are automatically assigned and static for the lifetime of the service. They appear in the ipv4Addresses and ipv6Addresses output properties.

Using a different cloud?

Explore networking guides for other cloud providers: