-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @xuxey for adding KMS encryption support to the S3 TableBucket L2 construct. I have left some thoughts for your considerations. Also since we are adding the encryption support, this would required a security review. I'll initiate the security review in parallel.
// If no key is provided, one will be created automatically | ||
const encryptedBucketAuto = new TableBucket(scope, 'EncryptedTableBucketAuto', { | ||
tableBucketName: 'table-bucket-2', | ||
encryption: TableBucketEncryption.KMS, | ||
}); |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
- This is consistent with the general purpose S3 Bucket construct, which auto-generates KMS keys
- 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.
/** | ||
* Use S3 managed encryption keys with AES256 encryption | ||
*/ | ||
S3_MANAGED = 'AES256', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to explicity pass AES256
algorithm to enable the default encryption (S3 managed keys - SSE-S3
)? Based on this doc, seems by default SSE encryption with S3 managed keys will be already with AES256
algorithm to encrypt the data. So I assume CDK users not required to pass this explicitly.
If we don't need to explicitly set this in CloudFormation (as it's already the default behavior), then perhaps we don't need the TableBucketEncryption
enum at all? The API could be simpler - if a user wants to use KMS encryption, they just provide a KMS key, otherwise it defaults to S3-managed encryption (AES-256).
The construct could look something like:
interface TableBucketProps {
tableBucketName: string;
encryptionKey?: kms.IKey; // If provided, uses KMS encryption
// ... other props
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
by default SSE encryption with S3 managed keys will be already with AES256 algorithm to encrypt the data. So I assume CDK users not required to pass this explicitly.
That's correct, this is not explicitly needed since AES256 is the default.
The API could be simpler - if a user wants to use KMS encryption, they just provide a KMS key, otherwise it defaults to S3-managed encryption (AES-256).
Addressed this in the other comment -- we would like to keep our interface extensible for the future if we add more encryption support, and keep the interface in-line with the Tables API & resource defs.
That said, the behavior you described (use kms key if provided) is still supported by the current interface
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the feedback, Godwin! I spoke with the team about the interface decisions and have left some follow-ups in the replies. Let me know what you think :)
// If no key is provided, one will be created automatically | ||
const encryptedBucketAuto = new TableBucket(scope, 'EncryptedTableBucketAuto', { | ||
tableBucketName: 'table-bucket-2', | ||
encryption: TableBucketEncryption.KMS, | ||
}); |
There was a problem hiding this comment.
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
- This is consistent with the general purpose S3 Bucket construct, which auto-generates KMS keys
- 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.
/** | ||
* Use S3 managed encryption keys with AES256 encryption | ||
*/ | ||
S3_MANAGED = 'AES256', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
by default SSE encryption with S3 managed keys will be already with AES256 algorithm to encrypt the data. So I assume CDK users not required to pass this explicitly.
That's correct, this is not explicitly needed since AES256 is the default.
The API could be simpler - if a user wants to use KMS encryption, they just provide a KMS key, otherwise it defaults to S3-managed encryption (AES-256).
Addressed this in the other comment -- we would like to keep our interface extensible for the future if we add more encryption support, and keep the interface in-line with the Tables API & resource defs.
That said, the behavior you described (use kms key if provided) is still supported by the current interface
// If no key is provided, one will be created automatically | ||
const encryptedBucketAuto = new TableBucket(scope, 'EncryptedTableBucketAuto', { | ||
tableBucketName: 'table-bucket-2', | ||
encryption: TableBucketEncryption.KMS, | ||
}); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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!
encryptionKey.addToResourcePolicy(new iam.PolicyStatement({ | ||
sid: 'AllowS3TablesMaintenanceAccess', | ||
effect: iam.Effect.ALLOW, | ||
principals: [ | ||
new iam.ServicePrincipal('maintenance.s3tables.amazonaws.com'), | ||
], | ||
actions: [ | ||
'kms:GenerateDataKey', | ||
'kms:Decrypt', | ||
], | ||
resources: ['*'], | ||
})); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Can we scope down the resource to specific table arn instead of using wildcard?
- Can we able to use grant method to provide access to the encryption key?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Unfortunately this is not possible because of circular dependencies. The
TableBucket
construct depends on the creation of the KMS key to be passed in as theencryptionKey
parameter. If we include a policy to scope down to the table bucket ARN, the KMS key will take a dependency on the table bucket which has not been created at this point. - The KMS key grant methods don't have an option to provide this combination of policies (See here), so it made more sense to create the IAM policy here directly for the specific actions that are needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @xuxey for the contribution. LGTM.
Thank you for contributing! Your pull request will be updated from main and then merged automatically (do not update manually, and be sure to allow changes to be pushed to your fork). |
This pull request has been removed from the queue for the following reason: The pull request can't be updated. You should update or rebase your pull request manually. If you do, this pull request will automatically be requeued once the queue conditions match again. |
AWS CodeBuild CI Report
Powered by github-codebuild-logs, available on the AWS Serverless Application Repository |
Thank you for contributing! Your pull request will be updated from main and then merged automatically (do not update manually, and be sure to allow changes to be pushed to your fork). |
Comments on closed issues and PRs are hard for our team to see. |
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
Backwards compatible changes were made to the TableBucket construct in the following places:
encryption
andencryptionKey
Usage
Describe any new or updated permissions being added
These permissions were added for KMS support:
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
GetTableBucketEncryptionCommand
but will be included once resolved.Checklist
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license