@@ -23,6 +23,8 @@ import {
2323 AllowedMethods ,
2424 CachePolicy ,
2525 Distribution ,
26+ HeadersFrameOption ,
27+ HeadersReferrerPolicy ,
2628 OriginAccessIdentity ,
2729 OriginProtocolPolicy ,
2830 OriginRequestPolicy ,
@@ -43,6 +45,7 @@ import {
4345} from "aws-cdk-lib/aws-cloudfront-origins" ;
4446import { ICertificate } from "aws-cdk-lib/aws-certificatemanager" ;
4547import { Dns } from "./dns" ;
48+ import { Duration } from "aws-cdk-lib" ;
4649
4750export interface NetworkProps {
4851 env : string ;
@@ -161,7 +164,82 @@ export class Network extends Construct {
161164 comment : `OAI for stickerlandia web frontend ${ props . env } ` ,
162165 } ) ;
163166 webFrontendBucket . grantRead ( originIdentity ) ;
164-
167+
168+ const corsWithTracingHeadersPolicy = new ResponseHeadersPolicy (
169+ this ,
170+ "CorsWithTracingHeadersPolicy" ,
171+ {
172+ responseHeadersPolicyName : `Stickerlandia-CORS-Tracing-${ props . env } ` ,
173+ comment :
174+ "CORS policy with W3C Trace Context and Datadog headers for RUM-APM correlation" ,
175+ // Enable browser profiling for Datadog RUM
176+ // See: https://docs.datadoghq.com/real_user_monitoring/correlate_with_other_telemetry/profiling/browser_profiling/
177+ customHeadersBehavior : {
178+ customHeaders : [
179+ {
180+ header : "Document-Policy" ,
181+ value : "js-profiling" ,
182+ override : true ,
183+ } ,
184+ ] ,
185+ } ,
186+ corsBehavior : {
187+ accessControlAllowCredentials : true ,
188+ accessControlAllowHeaders : [
189+ "Content-Type" ,
190+ "Authorization" ,
191+ "Accept" ,
192+ // W3C Trace Context headers for distributed tracing
193+ "traceparent" ,
194+ "tracestate" ,
195+ // Datadog-specific headers for RUM-APM correlation
196+ "x-datadog-trace-id" ,
197+ "x-datadog-parent-id" ,
198+ "x-datadog-origin" ,
199+ "x-datadog-sampling-priority" ,
200+ ] ,
201+ accessControlAllowMethods : [
202+ "GET" ,
203+ "POST" ,
204+ "PUT" ,
205+ "DELETE" ,
206+ "PATCH" ,
207+ "OPTIONS" ,
208+ ] ,
209+ accessControlAllowOrigins : [
210+ `https://${ props . dns . getPrimaryDomainName ( props . env ) } ` ,
211+ ] ,
212+ accessControlExposeHeaders : [
213+ // Allow browser to read trace headers from responses
214+ "traceparent" ,
215+ "tracestate" ,
216+ "x-datadog-trace-id" ,
217+ "x-datadog-parent-id" ,
218+ ] ,
219+ accessControlMaxAge : Duration . hours ( 1 ) ,
220+ originOverride : true ,
221+ } ,
222+ securityHeadersBehavior : {
223+ contentTypeOptions : { override : true } ,
224+ frameOptions : {
225+ frameOption : HeadersFrameOption . SAMEORIGIN ,
226+ override : true ,
227+ } ,
228+ referrerPolicy : {
229+ referrerPolicy :
230+ HeadersReferrerPolicy . STRICT_ORIGIN_WHEN_CROSS_ORIGIN ,
231+ override : true ,
232+ } ,
233+ strictTransportSecurity : {
234+ accessControlMaxAge : Duration . days ( 365 ) ,
235+ includeSubdomains : true ,
236+ override : true ,
237+ } ,
238+ xssProtection : { protection : true , modeBlock : true , override : true } ,
239+ } ,
240+ } ,
241+ ) ;
242+
165243 this . distribution = new Distribution ( this , `Stickerlandia-${ props . env } ` , {
166244 certificate : props . dns . certificate ,
167245 domainNames : props . dns . getPrimaryDomainName ( props . env )
@@ -188,6 +266,7 @@ export class Network extends Construct {
188266 origin : S3BucketOrigin . withOriginAccessIdentity ( webFrontendBucket , {
189267 originAccessIdentity : originIdentity ,
190268 } ) ,
269+ responseHeadersPolicy : corsWithTracingHeadersPolicy ,
191270 } ,
192271 } ) ;
193272
0 commit comments