Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(s3): readme update with mixing L1 and L2 bucket policy #31437

Merged
merged 5 commits into from
Sep 13, 2024
Merged
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 111 additions & 0 deletions packages/aws-cdk-lib/aws-s3/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,117 @@ const bucket = new s3.Bucket(this, 'MyBucket', {
});
```

The above code will create a new bucket policy if none exists or update the
existing bucket policy otherwise to allow access log delivery.
GavinZZ marked this conversation as resolved.
Show resolved Hide resolved

However, there could be an edge case if the `accessLogsBucket` also defines a bucket
policy resource using the L1 Construct. Although the mix of L1 and L2 Constructs are not
recommended, there is nothing stopping users to do this at the moment.
GavinZZ marked this conversation as resolved.
Show resolved Hide resolved

```ts
const bucketName = "my-favorite-bucket-name";
GavinZZ marked this conversation as resolved.
Show resolved Hide resolved
const accessLogsBucket = new s3.Bucket(this, 'AccessLogsBucket', {
objectOwnership: s3.ObjectOwnership.BUCKET_OWNER_ENFORCED,
bucketName,
});

// Creating a bucket policy using L1
const bucketPolicy = new s3.CfnBucketPolicy(this, "BucketPolicy", {
bucket: bucketName,
policyDocument: {
Statement: [
{
Action: 's3:*',
Effect: 'Deny',
Principal: {
AWS: '*',
},
Resource: [
accessLogsBucket.bucketArn,
`${accessLogsBucket.bucketArn}/*`
],
},
],
Version: '2012-10-17',
},
});

// 'serverAccessLogsBucket' will create a new L2 bucket policy
// to allow log delivery and overwrite the L1 bucket policy.
const bucket = new s3.Bucket(this, 'MyBucket', {
serverAccessLogsBucket: accessLogsBucket,
serverAccessLogsPrefix: 'logs',
});
```

The above example uses L2 Bucket Construct with L1 CfnBucketPolicy Construct. However,
when `serverAccessLogsBucket` is used, it will attempt to create a new L2 Bucket Policy
resource and overwrite the permissions defined in the L1 Bucket Policy, causing unintended
behaviours.
GavinZZ marked this conversation as resolved.
Show resolved Hide resolved

As noted above, we highly discourage the mixed usage of L1 and L2 Constructs. The recommended
approach would to define the bucket policy using `addToResourcePolicy` method.

```ts
const accessLogsBucket = new s3.Bucket(this, 'AccessLogsBucket', {
objectOwnership: s3.ObjectOwnership.BUCKET_OWNER_ENFORCED,
});

accessLogsBucket.addToResourcePolicy(
new iam.PolicyStatement({
actions: ['s3:*'],
resources: [accessLogsBucket.bucketArn, accessLogsBucket.arnForObjects('*')],
principals: [new iam.AnyPrincipal()],
})
)

const bucket = new s3.Bucket(this, 'MyBucket', {
serverAccessLogsBucket: accessLogsBucket,
serverAccessLogsPrefix: 'logs',
});
```

Alternatively, users can use the L2 Bucket Policy Construct
`BucketPolicy.fromCfnBucketPolicy` to wrap around `CfnBucketPolicy` Construct. This will allow the subsequent bucket policy generated by `serverAccessLogsBucket` usage to append to the existing bucket policy instead of overwriting.

```ts
const bucketName = "my-favorite-bucket-name";
const accessLogsBucket = new s3.Bucket(this, 'AccessLogsBucket', {
objectOwnership: s3.ObjectOwnership.BUCKET_OWNER_ENFORCED,
bucketName,
});

const bucketPolicy = new s3.CfnBucketPolicy(this, "BucketPolicy", {
bucket: bucketName,
policyDocument: {
Statement: [
{
Action: 's3:*',
Effect: 'Deny',
Principal: {
AWS: '*',
},
Resource: [
accessLogsBucket.bucketArn,
`${accessLogsBucket.bucketArn}/*`
],
},
],
Version: '2012-10-17',
},
});

// Wrap L1 Construct with L2 Bucket Policy Construct. Subsequent
// generated bucket policy to allow access log delivery would append
// to the current policy.
s3.BucketPolicy.fromCfnBucketPolicy(bucketPolicy);

const bucket = new s3.Bucket(this, 'MyBucket', {
serverAccessLogsBucket: accessLogsBucket,
serverAccessLogsPrefix: 'logs',
});
```

## S3 Inventory

An [inventory](https://docs.aws.amazon.com/AmazonS3/latest/dev/storage-inventory.html) contains a list of the objects in the source bucket and metadata for each object. The inventory lists are stored in the destination bucket as a CSV file compressed with GZIP, as an Apache optimized row columnar (ORC) file compressed with ZLIB, or as an Apache Parquet (Parquet) file compressed with Snappy.
Expand Down
Loading