@@ -19,7 +19,6 @@ import * as iam from 'aws-cdk-lib/aws-iam';
1919import * as s3 from 'aws-cdk-lib/aws-s3' ;
2020import { NagSuppressions } from 'cdk-nag' ;
2121import { Construct } from 'constructs' ;
22- import * as crypto from 'crypto' ;
2322
2423/**
2524 * Interface that defines properties required for the Static Website
@@ -82,6 +81,22 @@ export class StaticWebsite extends Construct {
8281 iam . Role . fromRoleArn ( this , 'BucketPolicyLambdaRole' , props . customResourceRoleArn )
8382 ) ;
8483
84+ const cloudfrontToS3 = new CloudFrontToS3 ( this , 'UI' , {
85+ existingBucketObj : this . webS3Bucket ,
86+ cloudFrontDistributionProps : {
87+ enableLogging : true ,
88+ errorResponses : [
89+ { httpStatus : 403 , responseHttpStatus : 200 , responsePagePath : '/index.html' } ,
90+ { httpStatus : 404 , responseHttpStatus : 200 , responsePagePath : '/index.html' }
91+ ] ,
92+ logFilePrefix : 'cloudfront/' ,
93+ minimumProtocolVersion : cloudfront . SecurityPolicyProtocol . TLS_V1_2_2019 ,
94+ defaultRootObject : 'login.html'
95+ }
96+ } ) ;
97+
98+ const cloudFrontLogsLoggingPrefix = 'cloudfrontlogs-logging' ;
99+
85100 const bucketPolicyUpdateCustomResource = new cdk . CustomResource ( this , 'UpdateBucketPolicy' , {
86101 resourceType : 'Custom::UpdateBucketPolicy' ,
87102 serviceToken : props . customResourceLambdaArn ,
@@ -93,21 +108,65 @@ export class StaticWebsite extends Construct {
93108 }
94109 } ) ;
95110 bucketPolicyUpdateCustomResource . node . addDependency ( bucketPolicyForLambda ) ;
111+ bucketPolicyUpdateCustomResource . node . addDependency ( this . webS3Bucket . policy ! ) ;
112+ bucketPolicyUpdateCustomResource . node . addDependency ( cloudfrontToS3 . cloudFrontWebDistribution ) ;
96113
97- const cloudfrontToS3 = new CloudFrontToS3 ( this , 'UI' , {
98- existingBucketObj : this . webS3Bucket ,
99- cloudFrontDistributionProps : {
100- enableLogging : true ,
101- errorResponses : [
102- { httpStatus : 403 , responseHttpStatus : 200 , responsePagePath : '/index.html' } ,
103- { httpStatus : 404 , responseHttpStatus : 200 , responsePagePath : '/index.html' }
104- ] ,
105- logFilePrefix : 'cloudfront/' ,
106- minimumProtocolVersion : cloudfront . SecurityPolicyProtocol . TLS_V1_2_2019 ,
107- defaultRootObject : 'login.html'
114+ const cloudFrontLoggingUpdateBucketPolicyCustomResource = new cdk . CustomResource (
115+ this ,
116+ 'CloudFrontLoggingUpdateBucketPolicy' ,
117+ {
118+ resourceType : 'Custom::UpdateBucketPolicy' ,
119+ serviceToken : props . customResourceLambdaArn ,
120+ properties : {
121+ Resource : 'UPDATE_BUCKET_POLICY' ,
122+ SOURCE_BUCKET_NAME : cloudfrontToS3 . cloudFrontLoggingBucket ?. bucketName ,
123+ LOGGING_BUCKET_NAME : props . accessLoggingBucket . bucketName ,
124+ SOURCE_PREFIX : cloudFrontLogsLoggingPrefix
125+ }
108126 }
127+ ) ;
128+ cloudFrontLoggingUpdateBucketPolicyCustomResource . node . addDependency ( bucketPolicyUpdateCustomResource ) ;
129+ cloudFrontLoggingUpdateBucketPolicyCustomResource . node . addDependency (
130+ cloudfrontToS3 . cloudFrontLoggingBucket ! . policy !
131+ ) ;
132+ cloudFrontLoggingUpdateBucketPolicyCustomResource . node . addDependency ( cloudfrontToS3 . cloudFrontWebDistribution ) ;
133+
134+ const cfnCloudFrontLoggingBucket = cloudfrontToS3 . cloudFrontLoggingBucket ?. node . defaultChild as s3 . CfnBucket ;
135+ cfnCloudFrontLoggingBucket . addPropertyOverride ( 'LoggingConfiguration' , {
136+ DestinationBucketName : {
137+ 'Fn::Select' : [
138+ 0 ,
139+ {
140+ 'Fn::Split' : [
141+ '/' ,
142+ {
143+ 'Fn::Select' : [
144+ 5 ,
145+ {
146+ 'Fn::Split' : [
147+ ':' ,
148+ {
149+ 'Ref' : 'AccessLoggingBucketArn'
150+ }
151+ ]
152+ }
153+ ]
154+ }
155+ ]
156+ }
157+ ]
158+ } ,
159+ LogFilePrefix : `${ cloudFrontLogsLoggingPrefix } /`
109160 } ) ;
110- cloudfrontToS3 . cloudFrontLoggingBucket ?. node . addDependency ( bucketPolicyUpdateCustomResource ) ;
161+ // disabling versioning, since it was disabled in a previous release, enabling
162+ // versioning now will create a new bucket with an update from the previous version
163+ cfnCloudFrontLoggingBucket . addPropertyDeletionOverride ( 'VersioningConfiguration' ) ;
164+
165+ cloudfrontToS3 . node . tryFindChild ( 'CloudfrontLoggingBucketAccessLog' ) ?. node . tryRemoveChild ( 'Resource' ) ;
166+ cloudfrontToS3 . node
167+ . tryFindChild ( 'CloudfrontLoggingBucketAccessLog' )
168+ ?. node . tryFindChild ( 'Policy' )
169+ ?. node . tryRemoveChild ( 'Resource' ) ;
111170
112171 const cloudfrontFunction = cloudfrontToS3 . node
113172 . tryFindChild ( 'SetHttpSecurityHeaders' )
@@ -120,73 +179,6 @@ export class StaticWebsite extends Construct {
120179 ) ;
121180
122181 this . cloudFrontDistribution = cloudfrontToS3 . cloudFrontWebDistribution ;
123- this . cloudFrontDistribution . node
124- . tryFindChild ( 'Origin1' )
125- ?. node . tryFindChild ( 'S3Origin' )
126- ?. node . tryRemoveChild ( 'Resource' ) ;
127-
128- const originAccessControl = new cloudfront . CfnOriginAccessControl ( this , 'OAC' , {
129- originAccessControlConfig : {
130- name : `BucketOriginAccessControl-${ cdk . Aws . REGION } ` ,
131- originAccessControlOriginType : 's3' ,
132- signingBehavior : 'always' ,
133- signingProtocol : 'sigv4'
134- }
135- } ) ;
136-
137- // prettier-ignore
138- let l1CloudFrontDistribution = this . cloudFrontDistribution . node . defaultChild as cdk . aws_cloudfront . CfnDistribution ;
139- // prettier-ignore
140- l1CloudFrontDistribution . addPropertyOverride ( 'DistributionConfig.Origins.0.OriginAccessControlId' , originAccessControl . getAtt ( 'Id' ) ) ;
141- // prettier-ignore
142- l1CloudFrontDistribution . addPropertyOverride ( 'DistributionConfig.Origins.0.S3OriginConfig.OriginAccessIdentity' , '' ) ;
143-
144- this . node . tryFindChild ( 'CloudfrontLoggingBucket' ) ?. node . tryRemoveChild ( 'Resource' ) ;
145- this . node . tryFindChild ( 'CloudfrontLoggingBucket' ) ?. node . tryFindChild ( 'Policy' ) ?. node . tryRemoveChild ( 'Resource' ) ;
146-
147- let l1BucketPolicy = this . webS3Bucket . node . tryFindChild ( 'Policy' ) ?. node . defaultChild as s3 . CfnBucketPolicy ;
148- l1BucketPolicy . addPropertyOverride ( 'PolicyDocument' , {
149- Statement : [
150- {
151- Action : 's3:*' ,
152- Condition : {
153- Bool : {
154- 'aws:SecureTransport' : 'false'
155- }
156- } ,
157- Effect : 'Deny' ,
158- Principal : {
159- AWS : '*'
160- } ,
161- Resource : [ `${ this . webS3Bucket . bucketArn } ` , `${ this . webS3Bucket . bucketArn } /*` ]
162- } ,
163- {
164- Action : 's3:GetObject' ,
165- Condition : {
166- StringEquals : {
167- 'AWS:SourceArn' : {
168- 'Fn::Join' : [
169- '' ,
170- [
171- 'arn:' ,
172- `${ cdk . Aws . PARTITION } ` ,
173- ':cloudfront::' ,
174- `${ cdk . Aws . ACCOUNT_ID } ` ,
175- ':distribution/' ,
176- `${ this . cloudFrontDistribution . distributionId } `
177- ]
178- ]
179- }
180- }
181- } ,
182- Effect : 'Allow' ,
183- Principal : {
184- Service : 'cloudfront.amazonaws.com'
185- } ,
186- Resource : `${ this . webS3Bucket . bucketArn } /*`
187- }
188- ]
189- } ) ;
190182
191183 // prettier-ignore
192184 new cdk . CfnOutput ( cdk . Stack . of ( this ) , 'WebUrl' , { // NOSONAR - Typescript construct instantiation
0 commit comments