The gcp:networkservices/edgeCacheService:EdgeCacheService resource, part of the Pulumi GCP provider, defines a Media CDN edge cache service: routing rules, cache policies, protocol options, and security configuration. This guide focuses on three capabilities: routing traffic to origins with cache policies, protocol control and advanced matching, and signed request authentication.
Edge cache services route requests to EdgeCacheOrigin resources and may reference EdgeCacheKeyset for signed requests. Hostnames configured in routing rules must resolve to the service’s IP addresses via DNS. The examples are intentionally small. Combine them with your own origins, certificates, and DNS configuration.
Route requests to a storage origin with caching
Most CDN deployments start by routing traffic to a storage bucket origin, applying cache policies to reduce origin load and improve response times.
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 how requests flow through the service. The hostRules array maps hostnames to pathMatchers, which contain routeRules that specify origins and cache behavior. In this configuration, requests to “sslcert.tf-test.club” match the “/” prefix and route to the origin with CACHE_ALL_STATIC mode, caching static content for 3600 seconds. The headerAction adds a response header showing cache status.
Configure protocol options and advanced routing
Production deployments often need to disable specific protocols for compatibility, route multiple hostnames, and apply different cache policies based on URL patterns and query parameters.
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
The disableQuic and disableHttp2 properties control which protocols the service advertises. Multiple hostRules route different hostnames to different pathMatchers. The routesAdvanced matcher demonstrates query parameter matching: requests to “/potato/” with a “debug” query parameter or exact “/apple” paths trigger specific routing. The matchRules array supports multiple conditions; any matching rule triggers the route. The cacheKeyPolicy controls what request attributes affect cache keys: includeProtocol, excludeHost, and specific query parameters, headers, and cookies determine cache granularity.
Protect content with signed URLs and tokens
Media streaming and protected content delivery require signed request validation to prevent unauthorized access and hotlinking.
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 set to REQUIRE_TOKENS enforces token validation on all requests. The signedRequestKeyset references an EdgeCacheKeyset containing public keys for verification. Different route rules handle different playlist types: the master playlist generates cookies, segment playlists generate cookieless tokens, and nested playlists propagate existing tokens. The pathTemplateMatch property uses glob patterns to match URL structures. The addSignatures configuration controls token generation: GENERATE_COOKIE creates Set-Cookie headers, GENERATE_TOKEN_HLS_COOKIELESS creates query parameter tokens, and PROPAGATE_TOKEN_HLS_COOKIELESS forwards existing tokens to nested requests.
Beyond these examples
These snippets focus on specific edge cache service features: routing and cache policies, protocol control, 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 public keys and validation secrets for signed requests, and DNS records pointing hostnames to service IP addresses. They focus on configuring the service rather than provisioning everything around it.
To keep things focused, common edge cache patterns are omitted, including:
- TLS certificate attachment (edgeSslCertificates, requireTls)
- Cloud Armor security policies (edgeSecurityPolicy)
- Request/response logging (logConfig)
- SSL policy configuration (sslPolicy)
These omissions are intentional: the goal is to illustrate how each edge cache 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 FREEFrequently Asked Questions
Access & Prerequisites
SSL/TLS & Certificates
requireTls to true requires at least one edgeSslCertificate to be specified. Clients connecting over HTTP (port 80) will receive a 301 redirect to HTTPS (port 443).EDGE_CACHE can be attached to an EdgeCacheService. Regional or other certificate types won’t work.sslPolicy isn’t set, the EdgeCacheService defaults to the COMPATIBLE policy.Protocol Configuration
disableHttp2 or disableQuic.Resource Configuration
name must be 1-64 characters long and match the regex [a-zA-Z][a-zA-Z0-9_-]*, meaning the first character must be a letter, and all following characters must be a dash, underscore, letter, or digit.name and project properties are immutable and cannot be changed after the service is created.labels field is non-authoritative and only manages labels present in your configuration. To see all labels on the resource (including those set by other clients or services), use the effectiveLabels output property.Networking
ipv4Addresses and ipv6Addresses are static for the lifetime of the service and cannot be changed.Using a different cloud?
Explore networking guides for other cloud providers: