Skip to content

Commit 488f0db

Browse files
feat(s3tables): server-side encryption by customer managed KMS key (#34229)
### Issue # (if applicable) None ### Reason for this change AWS S3 Tables supports for server side encryption by customer managed KMS keys. https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-tables-kms-encryption.html And cloudformation have supported for this feature. https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3tables-tablebucket-encryptionconfiguration.html ### Description of changes - Add `kmsKey` prop to `TableBucketProps` - Add kms key resource policy which enables S3 Tables to execute automatic table maintenance - https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-tables-kms-permissions.html ### Describe any new or updated permissions being added Add resource policy to the kms key. ```ts // add resource policy to the encryption key // see https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-tables-kms-permissions.html#tables-kms-maintenance-permissions props?.kmsKey?.addToResourcePolicy( new iam.PolicyStatement({ actions: ['kms:Decrypt', 'kms:GenerateDataKey'], resources: ['*'], effect: iam.Effect.ALLOW, principals: [new iam.ServicePrincipal('maintenance.s3tables.amazonaws.com')], conditions: { StringLike: { 'kms:EncryptionContext:aws:s3:arn': `${Stack.of(this).formatArn({ service: 's3tables', resource: 'bucket', resourceName: props.tableBucketName, })}/*`, }, }, }), ); ``` ### Description of how you validated changes Add both unit and integ tests. ### 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 c8b98e7 commit 488f0db

13 files changed

+509
-1
lines changed

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,22 @@ const sampleTableBucket = new TableBucket(scope, 'ExampleTableBucket', {
4141

4242
Learn more about table buckets maintenance operations and default behavior from the [S3 Tables User Guide](https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-table-buckets-maintenance.html)
4343

44+
### Server-side Encryption
45+
46+
By default, S3 Tables buckets are encrypted using Amazon S3-managed keys (SSE-S3). You can also use AWS Key Management Service (AWS KMS) keys to encrypt your data.
47+
To do this, you can specify the `kmsKey` property when creating the bucket:
48+
49+
```ts
50+
declare const kmsKey: kms.IKey;
51+
52+
new TableBucket(this, 'TableBucket', {
53+
tableBucketName: 'kms-key-s3tables-bucket',
54+
kmsKey,
55+
});
56+
```
57+
58+
**Note**: AWS CDK automatically add a resource policy to the KMS key to allow the S3 Tables service to use it for automatic table maintenance. Detail information can be found in the [security for S3 tables](https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-tables-kms-permissions.html) documentation.
59+
4460
### Controlling Table Bucket Permissions
4561

4662
```ts

packages/@aws-cdk/aws-s3tables-alpha/lib/table-bucket.ts

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ import { TableBucketPolicy } from './table-bucket-policy';
55
import * as perms from './permissions';
66
import { validateTableBucketAttributes } from './util';
77
import * as iam from 'aws-cdk-lib/aws-iam';
8-
import { Resource, IResource, UnscopedValidationError, RemovalPolicy, Token } from 'aws-cdk-lib/core';
8+
import * as kms from 'aws-cdk-lib/aws-kms';
9+
import { Resource, IResource, UnscopedValidationError, RemovalPolicy, Token, Stack } from 'aws-cdk-lib/core';
910
import { addConstructMetadata } from 'aws-cdk-lib/core/lib/metadata-resource';
1011

1112
/**
@@ -258,6 +259,13 @@ export interface TableBucketProps {
258259
* @default RETAIN
259260
*/
260261
readonly removalPolicy?: RemovalPolicy;
262+
263+
/**
264+
* The KMS key to use for server-side encryption.
265+
*
266+
* @default - Server-side encryption with Amazon S3-managed keys (SSE-S3)
267+
*/
268+
readonly kmsKey?: kms.IKey;
261269
}
262270

263271
/**
@@ -498,8 +506,34 @@ export class TableBucket extends TableBucketBase {
498506
noncurrentDays: props.unreferencedFileRemoval?.noncurrentDays,
499507
unreferencedDays: props.unreferencedFileRemoval?.unreferencedDays,
500508
},
509+
encryptionConfiguration: props?.kmsKey
510+
? {
511+
sseAlgorithm: 'aws:kms',
512+
kmsKeyArn: props.kmsKey.keyArn,
513+
}
514+
: undefined,
501515
});
502516

517+
// add resource policy to the encryption key
518+
// see https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-tables-kms-permissions.html#tables-kms-maintenance-permissions
519+
props?.kmsKey?.addToResourcePolicy(
520+
new iam.PolicyStatement({
521+
actions: ['kms:Decrypt', 'kms:GenerateDataKey'],
522+
resources: ['*'],
523+
effect: iam.Effect.ALLOW,
524+
principals: [new iam.ServicePrincipal('maintenance.s3tables.amazonaws.com')],
525+
conditions: {
526+
StringLike: {
527+
'kms:EncryptionContext:aws:s3:arn': `${Stack.of(this).formatArn({
528+
service: 's3tables',
529+
resource: 'bucket',
530+
resourceName: props.tableBucketName,
531+
})}/*`,
532+
},
533+
},
534+
}),
535+
);
536+
503537
this.tableBucketName = this.getResourceNameAttribute(this._resource.ref);
504538
this.tableBucketArn = this._resource.attrTableBucketArn;
505539
this._resource.applyRemovalPolicy(props.removalPolicy);

packages/@aws-cdk/aws-s3tables-alpha/rosetta/default.ts-fixture

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { Construct } from 'constructs';
22
import { Stack } from 'aws-cdk-lib';
33
import { TableBucket, UnreferencedFileRemovalStatus } from '@aws-cdk/aws-s3tables-alpha';
44
import * as iam from 'aws-cdk-lib/aws-iam';
5+
import * as kms from 'aws-cdk-lib/aws-kms';
56

67
class Fixture extends Stack {
78
constructor(scope: Construct, id: string) {

packages/@aws-cdk/aws-s3tables-alpha/test/integration/integ.table-bucket-kms-key.js.snapshot/cdk.out

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/@aws-cdk/aws-s3tables-alpha/test/integration/integ.table-bucket-kms-key.js.snapshot/integ.json

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/@aws-cdk/aws-s3tables-alpha/test/integration/integ.table-bucket-kms-key.js.snapshot/kms-key-s3tables-stack.assets.json

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
{
2+
"Resources": {
3+
"KmsKey46693ADD": {
4+
"Type": "AWS::KMS::Key",
5+
"Properties": {
6+
"KeyPolicy": {
7+
"Statement": [
8+
{
9+
"Action": "kms:*",
10+
"Effect": "Allow",
11+
"Principal": {
12+
"AWS": {
13+
"Fn::Join": [
14+
"",
15+
[
16+
"arn:",
17+
{
18+
"Ref": "AWS::Partition"
19+
},
20+
":iam::",
21+
{
22+
"Ref": "AWS::AccountId"
23+
},
24+
":root"
25+
]
26+
]
27+
}
28+
},
29+
"Resource": "*"
30+
},
31+
{
32+
"Action": [
33+
"kms:Decrypt",
34+
"kms:GenerateDataKey"
35+
],
36+
"Condition": {
37+
"StringLike": {
38+
"kms:EncryptionContext:aws:s3:arn": {
39+
"Fn::Join": [
40+
"",
41+
[
42+
"arn:",
43+
{
44+
"Ref": "AWS::Partition"
45+
},
46+
":s3tables:",
47+
{
48+
"Ref": "AWS::Region"
49+
},
50+
":",
51+
{
52+
"Ref": "AWS::AccountId"
53+
},
54+
":bucket/kms-key-s3tables-bucket/*"
55+
]
56+
]
57+
}
58+
}
59+
},
60+
"Effect": "Allow",
61+
"Principal": {
62+
"Service": "maintenance.s3tables.amazonaws.com"
63+
},
64+
"Resource": "*"
65+
}
66+
],
67+
"Version": "2012-10-17"
68+
}
69+
},
70+
"UpdateReplacePolicy": "Delete",
71+
"DeletionPolicy": "Delete"
72+
},
73+
"TableBucket0BF18B0D": {
74+
"Type": "AWS::S3Tables::TableBucket",
75+
"Properties": {
76+
"EncryptionConfiguration": {
77+
"KMSKeyArn": {
78+
"Fn::GetAtt": [
79+
"KmsKey46693ADD",
80+
"Arn"
81+
]
82+
},
83+
"SSEAlgorithm": "aws:kms"
84+
},
85+
"TableBucketName": "kms-key-s3tables-bucket",
86+
"UnreferencedFileRemoval": {}
87+
},
88+
"UpdateReplacePolicy": "Delete",
89+
"DeletionPolicy": "Delete"
90+
}
91+
},
92+
"Parameters": {
93+
"BootstrapVersion": {
94+
"Type": "AWS::SSM::Parameter::Value<String>",
95+
"Default": "/cdk-bootstrap/hnb659fds/version",
96+
"Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]"
97+
}
98+
},
99+
"Rules": {
100+
"CheckBootstrapVersion": {
101+
"Assertions": [
102+
{
103+
"Assert": {
104+
"Fn::Not": [
105+
{
106+
"Fn::Contains": [
107+
[
108+
"1",
109+
"2",
110+
"3",
111+
"4",
112+
"5"
113+
],
114+
{
115+
"Ref": "BootstrapVersion"
116+
}
117+
]
118+
}
119+
]
120+
},
121+
"AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI."
122+
}
123+
]
124+
}
125+
}
126+
}

packages/@aws-cdk/aws-s3tables-alpha/test/integration/integ.table-bucket-kms-key.js.snapshot/kmskeys3tablesintegDefaultTestDeployAssertC8AB8C4E.assets.json

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/@aws-cdk/aws-s3tables-alpha/test/integration/integ.table-bucket-kms-key.js.snapshot/kmskeys3tablesintegDefaultTestDeployAssertC8AB8C4E.template.json

Lines changed: 36 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)