Skip to content

Commit ec324a8

Browse files
feat(cloudfront): add response policy configuration
1 parent 8a0ee20 commit ec324a8

9 files changed

Lines changed: 104 additions & 0 deletions

File tree

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ The following annotation controls how origins and behaviors are attached to Clou
2828
- `cdn-origin-controller.gympass.com/cf.alternate-domain-names`: a comma-separated list of alternate domains to be configured on the CloudFront distribution. Duplicates on the same or different Ingress resources from the same group cause no harm. Example: `alias1.foo,alias2.foo`
2929
- `cdn-origin-controller.gympass.com/cf.origin-request-policy`: the ID of the origin request policy that should be associated with the behaviors defined by the Ingress resource. Defaults to the ID of the AWS pre-defined policy "Managed-AllViewer" (ID: 216adef6-5c7f-47e4-b989-5492eafa07d3) for Public origins, and "Managed-CORS-S3Origin" (ID: 88a5eaf4-2fd4-4709-b370-b4c650ea3fcf) for Bucket origins, however these defaults can be overriden through configuration by setting the `CF_DEFAULT_PUBLIC_ORIGIN_ACCESS_REQUEST_POLICY_ID` or `CF_DEFAULT_PUBLIC_ORIGIN_ACCESS_REQUEST_POLICY_ID` environment variables. If set to`"None"` no policy will be associated.
3030
- `cdn-origin-controller.gympass.com/cf.cache-policy`: the ID of the cache policy that should be associated with the behaviors defined by the Ingress resource. Defaults to the ID of the AWS pre-defined policy "CachingDisabled" (ID: 4135ea2d-6df8-44a3-9df3-4b5a84be39ad), this default can be overriden by setting the `CF_DEFAULT_CACHE_REQUEST_POLICY_ID` environment variable. More details about managed cache policies [see](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/using-managed-cache-policies.html).
31+
- `cdn-origin-controller.gympass.com/cf.response-policy`: the ID of the response headers policy that should be associated with the behaviors defined by the Ingress resource. No policy is associated by default. If set to `"None"` no policy will be associated. More details about managed response headers policies [see](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/using-managed-response-headers-policies.html).
3132
- `cdn-origin-controller.gympass.com/cf.origin-response-timeout`: the number of seconds that CloudFront waits for a response from the origin, from 1 to 60. Example: `"30"`
3233
- `cdn-origin-controller.gympass.com/cf.function-associations`: configures Function Association to behaviors defined as Ingress paths. Refer to the [dedicated section](#function-associations) for details.
3334
- `cdn-origin-controller.gympass.com/cf.viewer-function-arn`: deprecated in favor of the more generic `cdn-origin-controller.gympass.com/cf.function-associations`, and will be removed at a later release.
@@ -242,6 +243,7 @@ metadata:
242243
- host: bar.com
243244
originAccess: Public
244245
originRequestPolicy: None
246+
responsePolicy: 67f7725c-6f97-4210-82d7-5512b31e9d03
245247
webACLARN: "arn:aws:wafv2:us-east-1:123456789012:global/webacl/ExampleWebACL/473e64fd-f30b-4765-81a0-62ad96dd167a"
246248
behaviors:
247249
- path: /bar
@@ -273,6 +275,7 @@ The table below maps remaining available fields of an entry in this list to an a
273275
| .responseTimeout | cdn-origin-controller.gympass.com/cf.origin-response-timeout | - |
274276
| .viewerFunctionARN | cdn-origin-controller.gympass.com/cf.viewer-function-arn | deprecated, prefer defining associtions in .behaviors[].functionAssociations |
275277
| .cachePolicy | cdn-origin-controller.gympass.com/cf.cache-policy | - |
278+
| .responsePolicy | cdn-origin-controller.gympass.com/cf.response-policy | - |
276279
| .webACLARN | cdn-origin-controller.gympass.com/cf.web-acl-arn | - |
277280
| .headers | cdn-origin-controller.gympass.com/cf.origin-headers | - |
278281

internal/cloudfront/aws_models.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,5 +253,9 @@ func baseCacheBehavior(b Behavior) *cloudfront.CacheBehavior {
253253
cb.OriginRequestPolicyId = nil
254254
}
255255

256+
if len(b.ResponsePolicy) > 0 && b.ResponsePolicy != "None" {
257+
cb.ResponseHeadersPolicyId = aws.String(b.ResponsePolicy)
258+
}
259+
256260
return cb
257261
}

internal/cloudfront/origin.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@ type Behavior struct {
103103
RequestPolicy string
104104
// CachePolicy is the ID of the cache policy to be associated with this Behavior
105105
CachePolicy string
106+
// ResponsePolicy is the ID of the response headers policy to be associated with this Behavior
107+
ResponsePolicy string
106108
// OriginHost the origin's host this behavior belongs to
107109
OriginHost string
108110
// FunctionAssociations is a slice of Function that should be bound to this Behavior
@@ -116,6 +118,7 @@ type OriginBuilder struct {
116118
requestPolicy string
117119
distributionName string
118120
cachePolicy string
121+
responsePolicy string
119122
respTimeout int64
120123
accessType string
121124
behaviors map[string][]Function
@@ -170,6 +173,14 @@ func (b OriginBuilder) WithCachePolicy(policy string) OriginBuilder {
170173
return b
171174
}
172175

176+
// WithResponsePolicy associates a given response headers policy ID with all Behaviors in the Origin being built
177+
func (b OriginBuilder) WithResponsePolicy(policy string) OriginBuilder {
178+
if len(policy) > 0 {
179+
b.responsePolicy = policy
180+
}
181+
return b
182+
}
183+
173184
// WithResponseTimeout associates a custom response timeout to custom origin
174185
func (b OriginBuilder) WithResponseTimeout(rpTimeout int64) OriginBuilder {
175186
if rpTimeout > 0 {
@@ -197,6 +208,7 @@ func (b OriginBuilder) Build() Origin {
197208

198209
origin = b.addCachePolicyBehaviors(origin)
199210
origin = b.addRequestPolicyToBehaviors(origin)
211+
origin = b.addResponsePolicyToBehaviors(origin)
200212

201213
origin.Access = b.accessType
202214

@@ -226,6 +238,13 @@ func (b OriginBuilder) addCachePolicyBehaviors(origin Origin) Origin {
226238
return origin
227239
}
228240

241+
func (b OriginBuilder) addResponsePolicyToBehaviors(origin Origin) Origin {
242+
for i := range origin.Behaviors {
243+
origin.Behaviors[i].ResponsePolicy = b.responsePolicy
244+
}
245+
return origin
246+
}
247+
229248
func (b OriginBuilder) addOriginAccessConfiguration(origin Origin) Origin {
230249
if origin.Access != OriginAccessBucket {
231250
return origin

internal/cloudfront/origin_test.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,25 @@ func (s *OriginTestSuite) TestNewOriginBuilder_WithRequestPolicy() {
127127
s.Equal("some-policy", o.Behaviors[1].RequestPolicy)
128128
}
129129

130+
func (s *OriginTestSuite) TestNewOriginBuilder_WithResponsePolicy() {
131+
o := NewOriginBuilder("dist", "origin", "Public", s.cfg).
132+
WithBehavior("/").
133+
WithBehavior("/foo").
134+
WithResponsePolicy("some-response-policy").
135+
Build()
136+
s.Equal("origin", o.Host)
137+
s.Len(o.Behaviors, 2)
138+
s.Equal("some-response-policy", o.Behaviors[0].ResponsePolicy)
139+
s.Equal("some-response-policy", o.Behaviors[1].ResponsePolicy)
140+
}
141+
142+
func (s *OriginTestSuite) TestNewOriginBuilder_ResponsePolicyDefaultsToEmpty() {
143+
o := NewOriginBuilder("dist", "origin", "Public", s.cfg).
144+
WithBehavior("/").
145+
Build()
146+
s.Empty(o.Behaviors[0].ResponsePolicy)
147+
}
148+
130149
func (s *OriginTestSuite) TestNewOriginBuilder_WithBucketType() {
131150
o := NewOriginBuilder("dist", "origin", "Bucket", s.cfg).
132151
Build()

internal/cloudfront/repository_test.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1074,3 +1074,35 @@ func (s *DistributionRepositoryTestSuite) Test_baseCacheBehavior_PolicySetToNone
10741074
)
10751075
s.Nil(cb.OriginRequestPolicyId)
10761076
}
1077+
1078+
func (s *DistributionRepositoryTestSuite) Test_baseCacheBehavior_ResponsePolicySet() {
1079+
cb := baseCacheBehavior(
1080+
Behavior{
1081+
OriginHost: "host",
1082+
PathPattern: "path",
1083+
ResponsePolicy: "67f7725c-6f97-4210-82d7-5512b31e9d03",
1084+
},
1085+
)
1086+
s.Equal("67f7725c-6f97-4210-82d7-5512b31e9d03", *cb.ResponseHeadersPolicyId)
1087+
}
1088+
1089+
func (s *DistributionRepositoryTestSuite) Test_baseCacheBehavior_ResponsePolicySetToNone() {
1090+
cb := baseCacheBehavior(
1091+
Behavior{
1092+
OriginHost: "host",
1093+
PathPattern: "path",
1094+
ResponsePolicy: "None",
1095+
},
1096+
)
1097+
s.Nil(cb.ResponseHeadersPolicyId)
1098+
}
1099+
1100+
func (s *DistributionRepositoryTestSuite) Test_baseCacheBehavior_ResponsePolicyEmpty() {
1101+
cb := baseCacheBehavior(
1102+
Behavior{
1103+
OriginHost: "host",
1104+
PathPattern: "path",
1105+
},
1106+
)
1107+
s.Nil(cb.ResponseHeadersPolicyId)
1108+
}

internal/cloudfront/service_helpers.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ func newOrigin(ing k8s.CDNIngress, cfg config.Config, shared k8s.SharedIngressPa
3939
WithResponseTimeout(ing.OriginRespTimeout).
4040
WithRequestPolicy(ing.OriginReqPolicy).
4141
WithCachePolicy(ing.CachePolicy).
42+
WithResponsePolicy(ing.ResponsePolicy).
4243
WithOriginHeaders(ing.OriginHeaders)
4344

4445
for _, p := range shared.PathsFromOrigin(ing.OriginHost) {

internal/k8s/ingress.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ const (
4747
cfViewerFnAnnotation = "cdn-origin-controller.gympass.com/cf.viewer-function-arn"
4848
cfOrigReqPolicyAnnotation = "cdn-origin-controller.gympass.com/cf.origin-request-policy"
4949
cfCachePolicyAnnotation = "cdn-origin-controller.gympass.com/cf.cache-policy"
50+
cfResponsePolicyAnnotation = "cdn-origin-controller.gympass.com/cf.response-policy"
5051
cfOrigRespTimeoutAnnotation = "cdn-origin-controller.gympass.com/cf.origin-response-timeout"
5152
cfAlternateDomainNamesAnnotation = "cdn-origin-controller.gympass.com/cf.alternate-domain-names"
5253
cfWebACLARNAnnotation = "cdn-origin-controller.gympass.com/cf.web-acl-arn"
@@ -70,6 +71,7 @@ type CDNIngress struct {
7071
OriginReqPolicy string
7172
OriginHeaders map[string]string
7273
CachePolicy string
74+
ResponsePolicy string
7375
OriginRespTimeout int64
7476
AlternateDomainNames []string
7577
UnmergedWebACLARN string
@@ -226,6 +228,7 @@ func NewCDNIngressFromV1(ctx context.Context, ing *networkingv1.Ingress, class C
226228
OriginReqPolicy: originReqPolicy(ing),
227229
OriginHeaders: headers,
228230
CachePolicy: cachePolicy(ing),
231+
ResponsePolicy: responsePolicy(ing),
229232
OriginRespTimeout: originRespTimeout(ing),
230233
AlternateDomainNames: alternateDomainNames(ing),
231234
UnmergedWebACLARN: webACLARN(ing),
@@ -365,6 +368,10 @@ func cachePolicy(obj client.Object) string {
365368
return obj.GetAnnotations()[cfCachePolicyAnnotation]
366369
}
367370

371+
func responsePolicy(obj client.Object) string {
372+
return obj.GetAnnotations()[cfResponsePolicyAnnotation]
373+
}
374+
368375
func groupAnnotationValue(obj client.Object) string {
369376
return obj.GetAnnotations()[CDNGroupAnnotation]
370377
}

internal/k8s/user_origin.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ func cdnIngressesForUserOrigins(obj client.Object) ([]CDNIngress, error) {
6060
UnmergedPaths: o.paths(),
6161
OriginReqPolicy: o.RequestPolicy,
6262
CachePolicy: o.CachePolicy,
63+
ResponsePolicy: o.ResponsePolicy,
6364
OriginRespTimeout: o.ResponseTimeout,
6465
UnmergedWebACLARN: o.WebACLARN,
6566
OriginAccess: o.OriginAccess,
@@ -79,6 +80,7 @@ type userOrigin struct {
7980
ViewerFunctionARN string `yaml:"viewerFunctionARN"` // deprecated in favor of Behaviors
8081
RequestPolicy string `yaml:"originRequestPolicy"`
8182
CachePolicy string `yaml:"cachePolicy"`
83+
ResponsePolicy string `yaml:"responsePolicy"`
8284
WebACLARN string `yaml:"webACLARN"`
8385
OriginAccess string `yaml:"originAccess" default:"Public"`
8486
}

internal/k8s/user_origin_test.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,23 @@ func (s *userOriginSuite) Test_cdnIngressesForUserOrigins_Success() {
9999
},
100100
},
101101
},
102+
{
103+
name: "Has a single user origin with response policy",
104+
annotationValue: `
105+
- host: foo.com
106+
paths:
107+
- /foo
108+
responsePolicy: 67f7725c-6f97-4210-82d7-5512b31e9d03`,
109+
expectedIngs: []CDNIngress{
110+
{
111+
Group: "group",
112+
OriginHost: "foo.com",
113+
UnmergedPaths: []Path{{PathPattern: "/foo"}},
114+
ResponsePolicy: "67f7725c-6f97-4210-82d7-5512b31e9d03",
115+
OriginAccess: "Public",
116+
},
117+
},
118+
},
102119
{
103120
name: "Has multiple user origins",
104121
annotationValue: `

0 commit comments

Comments
 (0)