1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
| // CloudFront Origin Access Control for S3
const originAccessControl = new cloudfront.OriginAccessControl(this, 'OAC', {
description: 'WordPress static content OAC',
});
// S3 bucket for static assets
const assetsBucket = new s3.Bucket(this, 'WordPressAssets', {
bucketName: `wordpress-assets-${cdk.Aws.ACCOUNT_ID}`,
versioned: true,
encryption: s3.BucketEncryption.S3_MANAGED,
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
removalPolicy: cdk.RemovalPolicy.DESTROY,
});
// CloudFront distribution
const distribution = new cloudfront.Distribution(this, 'WordPressDistribution', {
defaultRootObject: 'index.php',
// Origins
additionalBehaviors: {
// Static assets from S3
'/wp-content/uploads/*': {
origin: new origins.S3Origin(assetsBucket, {
originAccessControl,
}),
viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
cachePolicy: cloudfront.CachePolicy.CACHING_OPTIMIZED,
compress: true,
},
// WordPress admin (no caching)
'/wp-admin/*': {
origin: new origins.LoadBalancerV2Origin(alb, {
protocolPolicy: cloudfront.OriginProtocolPolicy.HTTP_ONLY,
}),
viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
cachePolicy: cloudfront.CachePolicy.CACHING_DISABLED,
allowedMethods: cloudfront.AllowedMethods.ALLOW_ALL,
},
// API endpoints (no caching)
'/wp-json/*': {
origin: new origins.LoadBalancerV2Origin(alb, {
protocolPolicy: cloudfront.OriginProtocolPolicy.HTTP_ONLY,
}),
viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
cachePolicy: cloudfront.CachePolicy.CACHING_DISABLED,
allowedMethods: cloudfront.AllowedMethods.ALLOW_ALL,
},
},
// Default behavior for dynamic content
defaultBehavior: {
origin: new origins.LoadBalancerV2Origin(alb, {
protocolPolicy: cloudfront.OriginProtocolPolicy.HTTP_ONLY,
}),
viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
cachePolicy: new cloudfront.CachePolicy(this, 'WordPressCachePolicy', {
cachePolicyName: 'WordPress-Dynamic-Content',
comment: 'Cache policy for WordPress dynamic content',
defaultTtl: cdk.Duration.seconds(0),
maxTtl: cdk.Duration.days(1),
minTtl: cdk.Duration.seconds(0),
cookieBehavior: cloudfront.CacheCookieBehavior.allowList(
'wordpress_*', 'wp-*', 'comment_*'
),
headerBehavior: cloudfront.CacheHeaderBehavior.allowList(
'Accept-Encoding', 'CloudFront-Viewer-Country', 'Host'
),
queryStringBehavior: cloudfront.CacheQueryStringBehavior.all(),
enableAcceptEncodingGzip: true,
enableAcceptEncodingBrotli: true,
}),
allowedMethods: cloudfront.AllowedMethods.ALLOW_ALL,
compress: true,
},
// Geographic restrictions
geoRestriction: cloudfront.GeoRestriction.allowlist('US', 'CA', 'GB', 'DE', 'FR'),
// Security headers
responseHeadersPolicy: new cloudfront.ResponseHeadersPolicy(this, 'SecurityHeaders', {
comment: 'Security headers for WordPress',
securityHeadersBehavior: {
contentTypeOptions: { override: true },
frameOptions: { frameOption: cloudfront.HeadersFrameOption.DENY, override: true },
referrerPolicy: { referrerPolicy: cloudfront.HeadersReferrerPolicy.STRICT_ORIGIN_WHEN_CROSS_ORIGIN, override: true },
strictTransportSecurity: {
accessControlMaxAge: cdk.Duration.seconds(31536000),
includeSubdomains: true,
preload: true,
override: true,
},
},
}),
});
|