Skip to content
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

fix(standardize encryption props) Standardize how encryption properties are used for SNS/SQS constructs. #846

Merged
merged 2 commits into from
Nov 21, 2022
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
11 changes: 7 additions & 4 deletions DESIGN_GUIDELINES.md
Original file line number Diff line number Diff line change
Expand Up @@ -309,9 +309,9 @@ Existing Inconsistencies would not be published, that’s for our internal use
| --- | --- | --- |--- |
| existingTopicObj? | [`sns.Topic`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_sns.Topic.html)|An optional, existing SNS topic to be used instead of the default topic. Providing both this and `topicProps` will cause an error|
| topicProps? | [`sns.TopicProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_sns.TopicProps.html)|Optional user provided properties to override the default properties for the SNS topic.
| enableEncryptionWithCustomerManagedKey? | `boolean`|Use a KMS Key, either managed by this CDK app, or imported. If importing an encryption key, it must be specified in the encryptionKey property for this construct.| Sending messages from an AWS service to an encrypted Topic [requires a Customer Master key](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-key-management.html#compatibility-with-aws-services). Those constructs require these properties. |
| encryptionKey? | [`kms.Key`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_kms.Key.html)|An optional, imported encryption key to encrypt the SQS queue, and SNS Topic.|
| encryptionKeyProps? | [`kms.KeyProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_kms.KeyProps.html)|An optional, user provided properties to override the default properties for the KMS encryption key |
| enableEncryptionWithCustomerManagedKey? | `boolean`|If no key is provided, this flag determines whether the SNS Topic is encrypted with a new CMK or an AWS managed key.|This flag is ignored if any of the following are defined: topicProps.masterKey, encryptionKey or encryptionKeyProps.| Sending messages from an AWS service to an encrypted Topic [requires a Customer Master key](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-key-management.html#compatibility-with-aws-services). Those constructs require these properties. |
| encryptionKey? | [`kms.Key`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_kms.Key.html)|An optional, imported encryption key to encrypt the SNS Topic with.|
| encryptionKeyProps? | [`kms.KeyProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_kms.KeyProps.html)|Optional user provided properties to override the default properties for the KMS encryption key used to encrypt the SNS Topic with. |

**Required Construct Properties**

Expand All @@ -331,7 +331,10 @@ Existing Inconsistencies would not be published, that’s for our internal use
| deadLetterQueueProps? | [`sqs.QueueProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_sqs.QueueProps.html)|Optional user provided props to override the default props for the SQS queue.|
| maxReceiveCount | `int` | The number of times a message can be unsuccessfully dequeued before being moved to the dead letter queue. Defaults to `15`. |
| enableQueuePurging | `boolean` | Whether to grant additional permissions to the Lambda function enabling it to purge the SQS queue. Defaults to `false`. | This is only on 2 constructs, docs talk about a Lambda function role.|
| encryptionKey? | [`kms.Key`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_kms.Key.html)|Optional imported encryption key to encrypt the SQS queue. | Sending messages from an AWS service to an encrypted queue [requires a Customer Master key](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-key-management.html#compatibility-with-aws-services). Those constructs require these properties. |
|enableEncryptionWithCustomerManagedKey?|`boolean`|If no key is provided, this flag determines whether the queue is encrypted with a new CMK or an AWS managed key. |This flag is ignored if any of the following are defined: queueProps.encryptionMasterKey, encryptionKey or encryptionKeyProps.|
|encryptionKey?|[`kms.Key`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_kms.Key.html)|An optional, imported encryption key to encrypt the SQS Queue with.|Sending messages from an AWS service to an encrypted queue [requires a Customer Master key](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-key-management.html#compatibility-with-aws-services). Those constructs require these properties. |
|encryptionKeyProps?|[`kms.KeyProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_kms.Key.html#construct-props)|Optional user provided properties to override the default properties for the KMS encryption key used to encrypt the SQS queue with.|


**Required Construct Properties**

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ new ApiGatewayToSqs(this, "ApiGatewayToSqsPattern", new ApiGatewayToSqsProps.Bui
|allowDeleteOperation?|`boolean`|Whether to deploy an API Gateway Method for Delete operations on the queue (i.e. sqs:DeleteMessage).|
|deleteRequestTemplate?|`string`|Override the default API Gateway Request template for Delete method, if allowDeleteOperation set to true.|
|logGroupProps?|[`logs.LogGroupProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_logs.LogGroupProps.html)|User provided props to override the default props for for the CloudWatchLogs LogGroup.|
|enableEncryptionWithCustomerManagedKey?|`boolean`|If no key is provided, this flag determines whether the queue is encrypted with a new CMK or an AWS managed key. This flag is ignored if any of the following are defined: queueProps.encryptionMasterKey, encryptionKey or encryptionKeyProps.|
|encryptionKey?|[`kms.Key`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_kms.Key.html)|An optional, imported encryption key to encrypt the SQS Queue with.|
|encryptionKeyProps?|[`kms.KeyProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_kms.Key.html#construct-props)|Optional user provided properties to override the default properties for the KMS encryption key used to encrypt the SQS queue with.|

## Pattern Properties

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

// Imports
import * as api from 'aws-cdk-lib/aws-apigateway';
import * as kms from 'aws-cdk-lib/aws-kms';
import * as sqs from 'aws-cdk-lib/aws-sqs';
import * as iam from 'aws-cdk-lib/aws-iam';
import * as defaults from '@aws-solutions-constructs/core';
Expand All @@ -30,79 +31,98 @@ export interface ApiGatewayToSqsProps {
*
* @default - Default properties are used.
*/
readonly apiGatewayProps?: api.RestApiProps | any
readonly apiGatewayProps?: api.RestApiProps | any;
/**
* Existing instance of SQS queue object, providing both this and queueProps will cause an error
*
* @default - None
*/
readonly existingQueueObj?: sqs.Queue,
readonly existingQueueObj?: sqs.Queue;
/**
* User provided props to override the default props for the SQS queue.
*
* @default - Default props are used
*/
readonly queueProps?: sqs.QueueProps,
readonly queueProps?: sqs.QueueProps;
/**
* Whether to deploy a secondary queue to be used as a dead letter queue.
*
* @default - required field.
*/
readonly deployDeadLetterQueue?: boolean,
readonly deployDeadLetterQueue?: boolean;
/**
* Optional user provided properties for the dead letter queue
*
* @default - Default props are used
*/
readonly deadLetterQueueProps?: sqs.QueueProps,
readonly deadLetterQueueProps?: sqs.QueueProps;
/**
* The number of times a message can be unsuccessfully dequeued before being moved to the dead-letter queue.
*
* @default - required only if deployDeadLetterQueue = true.
*/
readonly maxReceiveCount?: number,
readonly maxReceiveCount?: number;
/**
* Whether to deploy an API Gateway Method for Create operations on the queue (i.e. sqs:SendMessage).
*
* @default - false
*/
readonly allowCreateOperation?: boolean,
readonly allowCreateOperation?: boolean;
/**
* API Gateway Request template for Create method, if allowCreateOperation set to true
*
* @default - None
*/
readonly createRequestTemplate?: string,
readonly createRequestTemplate?: string;
/**
* Whether to deploy an API Gateway Method for Read operations on the queue (i.e. sqs:ReceiveMessage).
*
* @default - "Action=SendMessage&MessageBody=$util.urlEncode(\"$input.body\")"
*/
readonly allowReadOperation?: boolean,
readonly allowReadOperation?: boolean;
/**
* API Gateway Request template for Get method, if allowReadOperation set to true
*
* @default - "Action=ReceiveMessage"
*/
readonly readRequestTemplate?: string,
readonly readRequestTemplate?: string;
/**
* Whether to deploy an API Gateway Method for Delete operations on the queue (i.e. sqs:DeleteMessage).
*
* @default - false
*/
readonly allowDeleteOperation?: boolean
readonly allowDeleteOperation?: boolean;
/**
* API Gateway Request template for Delete method, if allowDeleteOperation set to true
*
* @default - "Action=DeleteMessage&ReceiptHandle=$util.urlEncode($input.params('receiptHandle'))"
*/
readonly deleteRequestTemplate?: string,
readonly deleteRequestTemplate?: string;
/**
* User provided props to override the default props for the CloudWatchLogs LogGroup.
*
* @default - Default props are used
*/
readonly logGroupProps?: logs.LogGroupProps
readonly logGroupProps?: logs.LogGroupProps;
/**
* If no key is provided, this flag determines whether the queue is encrypted with a new CMK or an AWS managed key.
* This flag is ignored if any of the following are defined: queueProps.encryptionMasterKey, encryptionKey or encryptionKeyProps.
*
* @default - False if queueProps.encryptionMasterKey, encryptionKey, and encryptionKeyProps are all undefined.
*/
readonly enableEncryptionWithCustomerManagedKey?: boolean;
/**
* An optional, imported encryption key to encrypt the SQS Queue with.
*
* @default - None
*/
readonly encryptionKey?: kms.Key;
/**
* Optional user provided properties to override the default properties for the KMS encryption key used to encrypt the SQS queue with.
*
* @default - None
*/
readonly encryptionKeyProps?: kms.KeyProps;
}

/**
Expand Down Expand Up @@ -140,7 +160,10 @@ export class ApiGatewayToSqs extends Construct {
[this.sqsQueue] = defaults.buildQueue(this, 'queue', {
existingQueueObj: props.existingQueueObj,
queueProps: props.queueProps,
deadLetterQueue: this.deadLetterQueue
deadLetterQueue: this.deadLetterQueue,
enableEncryptionWithCustomerManagedKey: props.enableEncryptionWithCustomerManagedKey,
encryptionKey: props.encryptionKey,
encryptionKeyProps: props.encryptionKeyProps
});

// Setup the API Gateway
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { Stack } from "aws-cdk-lib";
import { ApiGatewayToSqs } from '../lib';
import '@aws-cdk/assert/jest';
import * as api from "aws-cdk-lib/aws-apigateway";
import * as kms from 'aws-cdk-lib/aws-kms';
import * as sqs from "aws-cdk-lib/aws-sqs";

test('Test deployment w/o DLQ', () => {
Expand Down Expand Up @@ -171,4 +172,93 @@ test('Test deployment with existing queue object', () => {
});

expect(stack).toCountResources("AWS::SQS::Queue", 1);
});

test('Queue is encrypted with imported CMK when set on encryptionKey prop', () => {
const stack = new Stack();
const cmk = new kms.Key(stack, 'cmk');
new ApiGatewayToSqs(stack, 'api-gateway-sqs', {
encryptionKey: cmk
});

expect(stack).toHaveResource("AWS::SQS::Queue", {
KmsMasterKeyId: {
"Fn::GetAtt": [
"cmk01DE03DA",
"Arn"
]
}
});
});

test('Queue is encrypted with imported CMK when set on queueProps.encryptionKeyProps prop', () => {
const stack = new Stack();
const cmk = new kms.Key(stack, 'cmk');
new ApiGatewayToSqs(stack, 'api-gateway-sqs', {
queueProps: {
encryptionMasterKey: cmk
}
});

expect(stack).toHaveResource("AWS::SQS::Queue", {
KmsMasterKeyId: {
"Fn::GetAtt": [
"cmk01DE03DA",
"Arn"
]
}
});
});

test('Queue is encrypted with provided encrytionKeyProps', () => {
const stack = new Stack();
new ApiGatewayToSqs(stack, 'api-gateway-sqs', {
encryptionKeyProps: {
alias: 'new-key-alias-from-props'
}
});

expect(stack).toHaveResource("AWS::SQS::Queue", {
KmsMasterKeyId: {
"Fn::GetAtt": [
"apigatewaysqsEncryptionKey4A698F7C",
"Arn"
]
}
});

expect(stack).toHaveResource('AWS::KMS::Alias', {
AliasName: 'alias/new-key-alias-from-props',
TargetKeyId: {
'Fn::GetAtt': [
'apigatewaysqsEncryptionKey4A698F7C',
'Arn'
]
}
});
});

test('Queue is encrypted by default with AWS-managed KMS key when no other encryption properties are set', () => {
const stack = new Stack();
new ApiGatewayToSqs(stack, 'api-gateway-sqs', {});

expect(stack).toHaveResource('AWS::SQS::Queue', {
KmsMasterKeyId: "alias/aws/sqs"
});
});

test('Queue is encrypted with customer managed KMS Key when enable encryption flag is true', () => {
const stack = new Stack();
new ApiGatewayToSqs(stack, 'api-gateway-sqs', {
enableEncryptionWithCustomerManagedKey: true
});

expect(stack).toHaveResource("AWS::SQS::Queue", {
KmsMasterKeyId: {
"Fn::GetAtt": [
"apigatewaysqsEncryptionKey4A698F7C",
"Arn"
]
}
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,9 @@ constructStack.getEncryptionKey().addToResourcePolicy(policyStatement);
|topicProps?|[`sns.TopicProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_sns.TopicProps.html)|User provided props to override the default props for the SNS Topic. |
|existingEventBusInterface?|[`events.IEventBus`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_events.IEventBus.html)| Optional user-provided custom EventBus for construct to use. Providing both this and `eventBusProps` results an error.|
|eventBusProps?|[`events.EventBusProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_events.EventBusProps.html)|Optional user-provided properties to override the default properties when creating a custom EventBus. Setting this value to `{}` will create a custom EventBus using all default properties. If neither this nor `existingEventBusInterface` is provided the construct will use the `default` EventBus. Providing both this and `existingEventBusInterface` results an error.|
|enableEncryptionWithCustomerManagedKey?|`boolean`|Use a KMS Key, either managed by this CDK app, or imported. If importing an encryption key, it must be specified in the encryptionKey property for this construct.|
|encryptionKey?|[`kms.Key`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_kms.Key.html)|An optional, imported encryption key to encrypt the SNS Topic.|
|encryptionKeyProps?|[`kms.KeyProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_kms.KeyProps.html)|An optional, user provided properties to override the default properties for the KMS encryption key.|
|enableEncryptionWithCustomerManagedKey?|`boolean`|If no key is provided, this flag determines whether the SNS Topic is encrypted with a new CMK or an AWS managed key. This flag is ignored if any of the following are defined: topicProps.masterKey, encryptionKey or encryptionKeyProps.|
|encryptionKey?|[`kms.Key`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_kms.Key.html)|An optional, imported encryption key to encrypt the SNS Topic with.|
|encryptionKeyProps?|[`kms.KeyProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_kms.Key.html#construct-props)|Optional user provided properties to override the default properties for the KMS encryption key used to encrypt the SNS Topic with.|

## Pattern Properties

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,22 +52,22 @@ export interface EventbridgeToSnsProps {
*/
readonly existingTopicObj?: sns.Topic;
/**
* Use a KMS Key, either managed by this CDK app, or imported. If importing an encryption key, it must be specified in
* the encryptionKey property for this construct.
* If no key is provided, this flag determines whether the topic is encrypted with a new CMK or an AWS managed key.
* This flag is ignored if any of the following are defined: topicProps.masterKey, encryptionKey or encryptionKeyProps.
*
* @default - true (encryption enabled, managed by this CDK app).
* @default - True if topicProps.masterKey, encryptionKey, and encryptionKeyProps are all undefined.
*/
readonly enableEncryptionWithCustomerManagedKey?: boolean;
/**
* An optional, imported encryption key to encrypt the SQS queue, and SNS Topic.
* An optional, imported encryption key to encrypt the SNS topic with.
*
* @default - not specified.
* @default - None.
*/
readonly encryptionKey?: kms.Key;
/**
* Optional user-provided props to override the default props for the encryption key.
* Optional user provided properties to override the default properties for the KMS encryption key used to encrypt the SNS topic with.
*
* @default - Default props are used.
* @default - None
*/
readonly encryptionKeyProps?: kms.KeyProps;
}
Expand Down
Loading