-
Notifications
You must be signed in to change notification settings - Fork 3.9k
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
feat(synthetics): add artifactS3Encryption
property to the Canary Construct.
#30197
Conversation
@@ -296,6 +344,31 @@ export class Canary extends cdk.Resource implements ec2.IConnectable { | |||
this._connections = new ec2.Connections({}); | |||
} | |||
|
|||
if (props.runtime.family !== RuntimeFamily.NODEJS && props.artifactS3Encryption) { |
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.
Artifact encryption functionality is available only for canaries that use Synthetics runtime version syn-nodejs-puppeteer-3.3 or later.
However, versions prior to 3.3 are deprecated and can no longer be configured, which is why I implemented it this way.
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.
Makes sense 👍 Can you please add a short comment about it before the check?
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. I've added a comment.
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 👍 Left some comments for some initial adjustments
* | ||
* @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Synthetics_artifact_encryption.html | ||
*/ | ||
readonly artifactS3Encryption?: ArtifactS3Encryption; |
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.
readonly artifactS3Encryption?: ArtifactS3Encryption; | |
readonly artifactS3EncryptionMode?: ArtifactsEncryptionMode; | |
/** | |
* The KMS key used to encrypt the data. | |
* | |
* @default - A KMS key is automatically created if `artifactS3EncryptionMode` is set to `SSE_KMS`. Otherwise, no key is generated. | |
*/ | |
readonly artifactS3EncryptionKey?: kms.IKey; |
What about keeping this flat? (guidelines)
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.
Thank you. Canary Construct is implemented to flatten other properties as well, so I agree that it would be better to flatten it in this case as you suggested. I will modify it to make it flat.
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.
I've changed it to flat.
@@ -296,6 +344,31 @@ export class Canary extends cdk.Resource implements ec2.IConnectable { | |||
this._connections = new ec2.Connections({}); | |||
} | |||
|
|||
if (props.runtime.family !== RuntimeFamily.NODEJS && props.artifactS3Encryption) { |
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.
Makes sense 👍 Can you please add a short comment about it before the check?
@@ -296,6 +335,18 @@ export class Canary extends cdk.Resource implements ec2.IConnectable { | |||
this._connections = new ec2.Connections({}); | |||
} | |||
|
|||
if (!cdk.Token.isUnresolved(props.artifactS3EncryptionMode) && |
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.
I refactored the creation of artifactConfig into createArtifactConfig.
However, since kmsKey needs to be set as a property, I made it so that checking and setting are done here.
Please provide your opinion if there is a better way to do 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.
I like the approach, just a couple of adjustments:
- Why not move all validations inside the method?
- No need to declare the
public readonly encryptionKey?: kms.IKey;
variable - Watch out for the typo in the function name
Suggestion:
private createArtifactConfig(props: CanaryProps): CfnCanary.ArtifactConfigProperty | undefined {
if (!props.artifactS3EncryptionMode) {
return undefined;
}
const isNodeRuntime = !cdk.Token.isUnresolved(props.runtime) && props.runtime.family === RuntimeFamily.NODEJS;
const isArtifactS3EncryptionModeDefined = !cdk.Token.isUnresolved(props.artifactS3EncryptionMode) && props.artifactS3EncryptionMode;
const isArtifactS3KmsKeyDefined = !cdk.Token.isUnresolved(props.artifactS3KmsKey) && props.artifactS3KmsKey;
if (isArtifactS3EncryptionModeDefined &&
props.artifactS3EncryptionMode !== ArtifactsEncryptionMode.KMS &&
isArtifactS3KmsKeyDefined
) {
throw new Error('A customer-managed KMS key was provided, but the encryption mode is not set to SSE-KMS.');
}
// Only check runtime family is nodejs because versions prior to syn-nodejs-puppeteer-3.3 are deprecated and can no longer be configured.
if (!isNodeRuntime && isArtifactS3EncryptionModeDefined) {
throw new Error(`Artifact encryption is only supported for canaries that use Synthetics runtime version syn-nodejs-puppeteer-3.3 or later, got ${props.runtime.name}.`);
}
let encryptionKey: kms.IKey | undefined;
if (props.artifactS3EncryptionMode === ArtifactsEncryptionMode.KMS) {
// Kms Key is set or generated for using `createArtifactConfig`
encryptionKey = props.artifactS3KmsKey ?? new kms.Key(this, 'Key', { description: `Created by ${this.node.path}` });
}
encryptionKey?.grantEncryptDecrypt(this.role);
return {
s3Encryption: {
encryptionMode: props.artifactS3EncryptionMode,
artifactS3KmsKeyArn: encryptionKey?.keyArn,
},
};
}
Thank you for the review. I incorporated the comments and refactored. |
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 👍 Left comments for some final adjustments
@@ -296,6 +335,18 @@ export class Canary extends cdk.Resource implements ec2.IConnectable { | |||
this._connections = new ec2.Connections({}); | |||
} | |||
|
|||
if (!cdk.Token.isUnresolved(props.artifactS3EncryptionMode) && |
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.
I like the approach, just a couple of adjustments:
- Why not move all validations inside the method?
- No need to declare the
public readonly encryptionKey?: kms.IKey;
variable - Watch out for the typo in the function name
Suggestion:
private createArtifactConfig(props: CanaryProps): CfnCanary.ArtifactConfigProperty | undefined {
if (!props.artifactS3EncryptionMode) {
return undefined;
}
const isNodeRuntime = !cdk.Token.isUnresolved(props.runtime) && props.runtime.family === RuntimeFamily.NODEJS;
const isArtifactS3EncryptionModeDefined = !cdk.Token.isUnresolved(props.artifactS3EncryptionMode) && props.artifactS3EncryptionMode;
const isArtifactS3KmsKeyDefined = !cdk.Token.isUnresolved(props.artifactS3KmsKey) && props.artifactS3KmsKey;
if (isArtifactS3EncryptionModeDefined &&
props.artifactS3EncryptionMode !== ArtifactsEncryptionMode.KMS &&
isArtifactS3KmsKeyDefined
) {
throw new Error('A customer-managed KMS key was provided, but the encryption mode is not set to SSE-KMS.');
}
// Only check runtime family is nodejs because versions prior to syn-nodejs-puppeteer-3.3 are deprecated and can no longer be configured.
if (!isNodeRuntime && isArtifactS3EncryptionModeDefined) {
throw new Error(`Artifact encryption is only supported for canaries that use Synthetics runtime version syn-nodejs-puppeteer-3.3 or later, got ${props.runtime.name}.`);
}
let encryptionKey: kms.IKey | undefined;
if (props.artifactS3EncryptionMode === ArtifactsEncryptionMode.KMS) {
// Kms Key is set or generated for using `createArtifactConfig`
encryptionKey = props.artifactS3KmsKey ?? new kms.Key(this, 'Key', { description: `Created by ${this.node.path}` });
}
encryptionKey?.grantEncryptDecrypt(this.role);
return {
s3Encryption: {
encryptionMode: props.artifactS3EncryptionMode,
artifactS3KmsKeyArn: encryptionKey?.keyArn,
},
};
}
6f06849
to
5f26026
Compare
@lpizzinidev |
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 👍
Not sure about the failing build. It seems like an issue with automation scripts:
error /home/runner/work/aws-cdk/aws-cdk/node_modules/@lerna/create/node_modules/nx, /home/runner/work/aws-cdk/aws-cdk/node_modules/@nx/devkit/node_modules/nx, /home/runner/work/aws-cdk/aws-cdk/node_modules/lerna/node_modules/nx: Command failed.
ffa5818
to
4ca916c
Compare
Because of the nature of the encryption key and permission granting changes, I'm adding the security review label to this as well. We'll review the PR internally with security and let you know if there's any extra changes needed. |
4aaf084
to
f914da9
Compare
f914da9
to
fa72ee2
Compare
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 addressing the changes! Just a few more comments about some of the recent changes.
isArtifactS3EncryptionModeDefined && | ||
props.artifactS3EncryptionMode !== ArtifactsEncryptionMode.KMS && | ||
isArtifactS3KmsKeyDefined | ||
props.artifactS3EncryptionMode === ArtifactsEncryptionMode.S3_MANAGED && | ||
props.artifactS3KmsKey |
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.
I can see we're no longer checking if these props are tokens. Is it possible for users to provide them as tokens? I don't think it would change much of the logic here, but if they can be tokens, we ought to have unit tests for them.
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.
As I understand it, these are not expected to become tokens. Therefore, the token check is unnecessary, so I removed it.
Pull request has been modified.
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.
LGTM, thanks for the contribution!
@Mergifyio update |
❌ Mergify doesn't have permission to updateFor security reasons, Mergify can't update this pull request. Try updating locally. |
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). |
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). |
Pull request has been modified.
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. |
Issue # (if applicable)
Closes #30190.
Reason for this change
To select encryption options.
Description of changes
Add
artifactS3Encryption
property to the Canary Construct.Description of how you validated changes
Add unit tests and integ tests.
Checklist
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license