Skip to content

Commit ac0e4ca

Browse files
authored
feat(s3-tables): add KMS support for TableBucket L2 construct (#34281)
### Reason for this change This adds support for encryption settings for TableBucket including providing KMS keys for server side encryption. ### Description of changes L1 reference: [CfnTableBucket#encryptionConfiguration](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3tables.CfnTableBucket.html#encryptionconfiguration) Backwards compatible changes were made to the TableBucket construct in the following places: - TableBucketProps now include optional fields `encryption` and `encryptionKey` - grant methods now provide permissions to the bucket encryptionKey, if applicable - A new KMS key is created if the user provides KMS encryptionType but no key - Updated README with rosetta support #### Usage ```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'), '*'); // If no key is provided, one will be created automatically const encryptedBucketAuto = new TableBucket(scope, 'EncryptedTableBucketAuto', { tableBucketName: 'table-bucket-2', encryption: TableBucketEncryption.KMS, }); // Use S3 managed server side encryption (default) const encryptedBucketDefault = new TableBucket(scope, 'EncryptedTableBucketDefault', { tableBucketName: 'table-bucket-3', encryption: TableBucketEncryption.S3_MANAGED, }); ``` ### Describe any new or updated permissions being added These permissions were added for KMS support: ```ts export const KEY_READ_ACCESS = [ 'kms:Decrypt', ]; export const KEY_WRITE_ACCESS = [ 'kms:Decrypt', 'kms:GenerateDataKey*', ]; ``` When grant methods are used, these policies are applied to the principal for the TableBucket's encryption key. For example, giving read access to an encrypted bucket without giving decrypt permissions to the bucket key will not be sufficient permissions for the principal to read the bucket data. ### Description of how you validated changes - Added unit test coverage for all possible scenarios of bucket encryption config, as well as all grant methods for each valid encryption config. - Added integration tests with snapshot and assertions. The assertions are currently disabled due to the aws-sdk version not supporting `GetTableBucketEncryptionCommand` but will be included once resolved. ### Checklist - [x] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent 145796c commit ac0e4ca

22 files changed

+1668
-9
lines changed

packages/@aws-cdk/aws-s3tables-alpha/README.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,11 @@ Learn more about table buckets maintenance operations and default behavior from
4747
// Grant the principal read permissions to the bucket and all tables within
4848
const accountId = '123456789012'
4949
tableBucket.grantRead(new iam.AccountPrincipal(accountId), '*');
50+
5051
// Grant the role write permissions to the bucket and all tables within
5152
const role = new iam.Role(stack, 'MyRole', { assumedBy: new iam.ServicePrincipal('sample') });
5253
tableBucket.grantWrite(role, '*');
54+
5355
// Grant the user read and write permissions to the bucket and all tables within
5456
tableBucket.grantReadWrite(new iam.User(stack, 'MyUser'), '*');
5557

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

73+
### Controlling Table Bucket Encryption Settings
74+
75+
S3 TableBuckets have SSE (server-side encryption with AES-256) enabled by default with S3 managed keys.
76+
You can also bring your own KMS key for KMS-SSE or have S3 create a KMS key for you.
77+
78+
If a bucket is encrypted with KMS, grant functions on the bucket will also grant access
79+
to the TableBucket's associated KMS key.
80+
81+
```ts
82+
// Provide a user defined KMS Key:
83+
const key = new kms.Key(scope, 'UserKey', {});
84+
const encryptedBucket = new TableBucket(scope, 'EncryptedTableBucket', {
85+
tableBucketName: 'table-bucket-1',
86+
encryption: TableBucketEncryption.KMS,
87+
encryptionKey: key,
88+
});
89+
// This account principal will also receive kms:Decrypt access to the KMS key
90+
encryptedBucket.grantRead(new iam.AccountPrincipal('123456789012'), '*');
91+
92+
// Use S3 managed server side encryption (default)
93+
const encryptedBucketDefault = new TableBucket(scope, 'EncryptedTableBucketDefault', {
94+
tableBucketName: 'table-bucket-3',
95+
encryption: TableBucketEncryption.S3_MANAGED, // Uses AES-256 encryption by default
96+
});
97+
```
98+
99+
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.
100+
101+
```ts
102+
// If no key is provided, one will be created automatically
103+
const encryptedBucketAuto = new TableBucket(scope, 'EncryptedTableBucketAuto', {
104+
tableBucketName: 'table-bucket-2',
105+
encryption: TableBucketEncryption.KMS,
106+
});
107+
```
108+
71109
## Coming Soon
72110

73111
L2 Construct support for:

packages/@aws-cdk/aws-s3tables-alpha/lib/permissions.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,19 @@ export const TABLE_BUCKET_READ_WRITE_ACCESS = [...new Set([
2020
...TABLE_BUCKET_READ_ACCESS,
2121
...TABLE_BUCKET_WRITE_ACCESS,
2222
])];
23+
24+
// Permissions for user defined KMS Keys
25+
// https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-tables-kms-permissions.html
26+
export const KEY_READ_ACCESS = [
27+
'kms:Decrypt',
28+
];
29+
30+
export const KEY_WRITE_ACCESS = [
31+
'kms:Decrypt',
32+
'kms:GenerateDataKey*',
33+
];
34+
35+
export const KEY_READ_WRITE_ACCESS = [...new Set([
36+
...KEY_READ_ACCESS,
37+
...KEY_WRITE_ACCESS,
38+
])];

0 commit comments

Comments
 (0)