in packages/static-website/src/static-website.ts [134:252]
constructor(scope: Construct, id: string, props: StaticWebsiteProps) {
super(scope, id);
addMetric(scope, "static-website");
this.node.setContext(
"@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy",
true
);
this.validateProps(props);
const accessLogsBucket = new Bucket(this, "AccessLogsBucket", {
versioned: false,
enforceSSL: true,
autoDeleteObjects: true,
removalPolicy: RemovalPolicy.DESTROY,
encryption: BucketEncryption.S3_MANAGED,
objectOwnership: ObjectOwnership.OBJECT_WRITER,
publicReadAccess: false,
blockPublicAccess: BlockPublicAccess.BLOCK_ALL,
});
// S3 Bucket to hold website files
this.websiteBucket =
props.websiteBucket ??
new Bucket(this, "WebsiteBucket", {
versioned: true,
enforceSSL: true,
autoDeleteObjects: true,
removalPolicy: RemovalPolicy.DESTROY,
encryption:
props.defaultWebsiteBucketEncryption ?? BucketEncryption.S3_MANAGED,
objectOwnership: ObjectOwnership.BUCKET_OWNER_ENFORCED,
encryptionKey: props.defaultWebsiteBucketEncryptionKey,
publicReadAccess: false,
blockPublicAccess: BlockPublicAccess.BLOCK_ALL,
serverAccessLogsPrefix: "website-access-logs",
serverAccessLogsBucket: accessLogsBucket,
});
// Web ACL
const { distributionProps } = props;
const webAclArn =
distributionProps?.webAclId ??
(props.webAclProps?.disable
? undefined
: new CloudfrontWebAcl(this, "WebsiteAcl", props.webAclProps)
.webAclArn);
// Cloudfront Distribution
const logBucket =
props.distributionProps?.logBucket ||
new Bucket(this, "DistributionLogBucket", {
enforceSSL: true,
autoDeleteObjects: true,
removalPolicy: RemovalPolicy.DESTROY,
encryption:
props.defaultWebsiteBucketEncryption ?? BucketEncryption.S3_MANAGED,
objectOwnership: ObjectOwnership.BUCKET_OWNER_PREFERRED,
encryptionKey: props.defaultWebsiteBucketEncryptionKey,
publicReadAccess: false,
blockPublicAccess: BlockPublicAccess.BLOCK_ALL,
serverAccessLogsPrefix: "distribution-access-logs",
serverAccessLogsBucket: accessLogsBucket,
});
const defaultRootObject =
distributionProps?.defaultRootObject ?? "index.html";
this.cloudFrontDistribution = new Distribution(
this,
"CloudfrontDistribution",
{
...distributionProps,
webAclId: webAclArn,
enableLogging: true,
logBucket: logBucket,
defaultBehavior: {
...distributionProps?.defaultBehavior,
origin: S3BucketOrigin.withOriginAccessControl(this.websiteBucket),
viewerProtocolPolicy: ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
},
defaultRootObject,
errorResponses: distributionProps?.errorResponses ?? [
{
httpStatus: 404, // We need to redirect "key not found errors" to index.html for single page apps
responseHttpStatus: 200,
responsePagePath: `/${defaultRootObject}`,
},
],
}
);
// Deploy Website
this.bucketDeployment = new BucketDeployment(this, "WebsiteDeployment", {
...props.bucketDeploymentProps,
sources: [
Source.asset(props.websiteContentPath),
...(props.runtimeOptions
? [
Source.jsonData(
props.runtimeOptions?.jsonFileName ||
DEFAULT_RUNTIME_CONFIG_FILENAME,
lazilyRender(this, props.runtimeOptions.jsonPayload)
),
]
: []),
],
destinationBucket: this.websiteBucket,
// Files in the distribution's edge caches will be invalidated after files are uploaded to the destination bucket.
distribution: this.cloudFrontDistribution,
});
new CfnOutput(this, "DistributionDomainName", {
value: this.cloudFrontDistribution.domainName,
});
this.suppressCDKNagViolations(props);
}