Skip to content

feat(s3-tables): add KMS support for TableBucket L2 construct #34281

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

Merged
merged 10 commits into from
May 14, 2025
Merged
Show file tree
Hide file tree
Changes from all 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
38 changes: 38 additions & 0 deletions packages/@aws-cdk/aws-s3tables-alpha/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,11 @@ Learn more about table buckets maintenance operations and default behavior from
// Grant the principal read permissions to the bucket and all tables within
const accountId = '123456789012'
tableBucket.grantRead(new iam.AccountPrincipal(accountId), '*');

// Grant the role write permissions to the bucket and all tables within
const role = new iam.Role(stack, 'MyRole', { assumedBy: new iam.ServicePrincipal('sample') });
tableBucket.grantWrite(role, '*');

// Grant the user read and write permissions to the bucket and all tables within
tableBucket.grantReadWrite(new iam.User(stack, 'MyUser'), '*');

Expand All @@ -68,6 +70,42 @@ const permissions = new iam.PolicyStatement({
tableBucket.addToResourcePolicy(permissions);
```

### Controlling Table Bucket Encryption Settings

S3 TableBuckets have SSE (server-side encryption with AES-256) enabled by default with S3 managed keys.
You can also bring your own KMS key for KMS-SSE or have S3 create a KMS key for you.

If a bucket is encrypted with KMS, grant functions on the bucket will also grant access
to the TableBucket's associated KMS key.

```ts
// Provide a user defined KMS Key:
const key = new kms.Key(scope, 'UserKey', {});
const encryptedBucket = new TableBucket(scope, 'EncryptedTableBucket', {
tableBucketName: 'table-bucket-1',
encryption: TableBucketEncryption.KMS,
encryptionKey: key,
});
// This account principal will also receive kms:Decrypt access to the KMS key
encryptedBucket.grantRead(new iam.AccountPrincipal('123456789012'), '*');

// Use S3 managed server side encryption (default)
const encryptedBucketDefault = new TableBucket(scope, 'EncryptedTableBucketDefault', {
tableBucketName: 'table-bucket-3',
encryption: TableBucketEncryption.S3_MANAGED, // Uses AES-256 encryption by default
});
```

When using KMS encryption (`TableBucketEncryption.KMS`), if no encryption key is provided, CDK will automatically create a new KMS key for the table bucket with necessary permissions.

```ts
// If no key is provided, one will be created automatically
const encryptedBucketAuto = new TableBucket(scope, 'EncryptedTableBucketAuto', {
tableBucketName: 'table-bucket-2',
encryption: TableBucketEncryption.KMS,
});
Comment on lines +102 to +106
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since S3 TableBuckets already have S3-managed SSE enabled by default (which I assume is free and secure for most use cases), having an auto-generated KMS key option might lead to unexpected costs for users ($1/month per key plus API call costs - here). Organizations that require KMS encryption typically either have existing KMS keys or want explicit control over key management to align with their security policies.

I suggest we simplify the API to just support customer-provided KMS keys while keeping S3-managed SSE as the default. This would eliminate the need for the TableBucketEncryption enum since the only encryption option a user would need to specify is their KMS key. This approach would reduce complexity, avoid unexpected costs, and better align with real-world usage patterns.

What are your thoughts on this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

having an auto-generated KMS key option might lead to unexpected costs for users

This could be true for some users, however there are advantages for customers with auto-generated keys

  1. This is consistent with the general purpose S3 Bucket construct, which auto-generates KMS keys
  2. Customers can leverage autogenerated keys by not having to explicitly create keys, and these keys will also contain all of the necessary access policies (for example allowlisting S3 Tables Maintenance)

I suggest we simplify the API to just support customer-provided KMS keys while keeping S3-managed SSE as the default

Since both encryptionKey and encryption are optional parameters, this behavior already exists. We would like to keep the interface with TableBucketEncryption since it is more in-sync with the S3 Tables API and CloudFormation resource definitions, and can easily extend to other encryption formats that may be supported in the future.

Comment on lines +102 to +106
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be good to elaborate this in the readme about CDK creating the new KMS key if it is not provided when KMS encryption type is selected.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you clarify what additional information we can include in the README?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For eg:

When using KMS encryption (`TableBucketEncryption.KMS`), if no encryption key is provided, CDK will automatically create a new KMS key for the table bucket with necessary permissions.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Elaborated in the latest commit. Thanks for the suggestion!

```

## Coming Soon

L2 Construct support for:
Expand Down
16 changes: 16 additions & 0 deletions packages/@aws-cdk/aws-s3tables-alpha/lib/permissions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,19 @@ export const TABLE_BUCKET_READ_WRITE_ACCESS = [...new Set([
...TABLE_BUCKET_READ_ACCESS,
...TABLE_BUCKET_WRITE_ACCESS,
])];

// Permissions for user defined KMS Keys
// https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-tables-kms-permissions.html
export const KEY_READ_ACCESS = [
'kms:Decrypt',
];

export const KEY_WRITE_ACCESS = [
'kms:Decrypt',
'kms:GenerateDataKey*',
];

export const KEY_READ_WRITE_ACCESS = [...new Set([
...KEY_READ_ACCESS,
...KEY_WRITE_ACCESS,
])];
Loading
Loading