diff --git a/aws-py-static-website/__main__.py b/aws-py-static-website/__main__.py index 9c3274909..7f6b279f9 100644 --- a/aws-py-static-website/__main__.py +++ b/aws-py-static-website/__main__.py @@ -59,8 +59,7 @@ def get_domain_and_subdomain(domain): certificate_arn = stack_config.get('certificateArn') # Create an S3 bucket configured as a website bucket. -content_bucket = pulumi_aws.s3.BucketV2('contentBucket', bucket=target_domain) -setup_acl('contentBucket', content_bucket, 'public-read') +content_bucket = pulumi_aws.s3.BucketV2(f'{target_domain}-content') content_bucket_website = pulumi_aws.s3.BucketWebsiteConfigurationV2('content-bucket', @@ -92,7 +91,6 @@ def bucket_object_converter(filepath): content_file = pulumi_aws.s3.BucketObject( relative_path, key=relative_path, - acl='public-read', bucket=content_bucket.id, content_type=mime_type, source=FileAsset(filepath), @@ -139,7 +137,7 @@ def bucket_object_converter(filepath): certificate_arn = cert_validation.certificate_arn # Create a logs bucket for the CloudFront logs -logs_bucket = pulumi_aws.s3.BucketV2('requestLogs', bucket=f'{target_domain}-logs') +logs_bucket = pulumi_aws.s3.BucketV2(f'{target_domain}-logs') setup_acl('requestLogs', logs_bucket, 'private') # Create the CloudFront distribution diff --git a/aws-ts-static-website/acl.ts b/aws-ts-static-website/acl.ts new file mode 100644 index 000000000..7fa4722be --- /dev/null +++ b/aws-ts-static-website/acl.ts @@ -0,0 +1,26 @@ +// Copyright 2016-2024, Pulumi Corporation. All rights reserved. + +import * as aws from "@pulumi/aws"; + +export function configureACL(bucketName: string, bucket: aws.s3.BucketV2, acl: string): aws.s3.BucketAclV2 { + const ownership = new aws.s3.BucketOwnershipControls(bucketName, { + bucket: bucket.bucket, + rule: { + objectOwnership: "BucketOwnerPreferred", + }, + }); + const publicAccessBlock = new aws.s3.BucketPublicAccessBlock(bucketName, { + bucket: bucket.bucket, + blockPublicAcls: false, + blockPublicPolicy: false, + ignorePublicAcls: false, + restrictPublicBuckets: false, + }); + const bucketACL = new aws.s3.BucketAclV2(bucketName, { + bucket: bucket.bucket, + acl: acl, + }, { + dependsOn: [ownership, publicAccessBlock], + }); + return bucketACL; +} diff --git a/aws-ts-static-website/index.ts b/aws-ts-static-website/index.ts index 394956641..1359d2bd9 100644 --- a/aws-ts-static-website/index.ts +++ b/aws-ts-static-website/index.ts @@ -5,7 +5,7 @@ import * as pulumi from "@pulumi/pulumi"; import * as fs from "fs"; import * as mime from "mime"; import * as path from "path"; - +import { configureACL } from "./acl"; // Load the Pulumi program configuration. These act as the "parameters" to the Pulumi program, // so that different Pulumi Stacks can be brought up using the same code. @@ -26,16 +26,13 @@ const config = { }; // contentBucket is the S3 bucket that the website's contents will be stored in. -const contentBucket = new aws.s3.Bucket("contentBucket", - { - bucket: config.targetDomain, - // Configure S3 to serve bucket contents as a website. This way S3 will automatically convert - // requests for "foo/" to "foo/index.html". - website: { - indexDocument: "index.html", - errorDocument: "404.html", - }, - }); +const contentBucket = new aws.s3.BucketV2(`${config.targetDomain}-content`); + +const contentBucketWebsite = new aws.s3.BucketWebsiteConfigurationV2("contentBucketWebsite", { + bucket: contentBucket.bucket, + indexDocument: {suffix: "index.html"}, + errorDocument: {key: "404.html"}, +}); // crawlDirectory recursive crawls the provided directory, applying the provided function // to every file it contains. Doesn't handle cycles from symlinks. @@ -64,9 +61,7 @@ crawlDirectory( relativeFilePath, { key: relativeFilePath, - - acl: "public-read", - bucket: contentBucket, + bucket: contentBucket.bucket, contentType: mime.getType(filePath) || undefined, source: new pulumi.asset.FileAsset(filePath), }, @@ -76,11 +71,8 @@ crawlDirectory( }); // logsBucket is an S3 bucket that will contain the CDN's request logs. -const logsBucket = new aws.s3.Bucket("requestLogs", - { - bucket: `${config.targetDomain}-logs`, - acl: "private", - }); +const logsBucket = new aws.s3.BucketV2(`${config.targetDomain}-logs`); +configureACL("requestLogs", logsBucket, "private"); const tenMinutes = 60 * 10; @@ -320,6 +312,6 @@ if (config.includeWWW) { // Export properties from this stack. This prints them at the end of `pulumi up` and // makes them easier to access from pulumi.com. export const contentBucketUri = pulumi.interpolate`s3://${contentBucket.bucket}`; -export const contentBucketWebsiteEndpoint = contentBucket.websiteEndpoint; +export const contentBucketWebsiteEndpoint = contentBucketWebsite.websiteEndpoint; export const cloudFrontDomain = cdn.domainName; export const targetDomainEndpoint = `https://${config.targetDomain}/`;