From a640e061b0f34c7b810265a897bd93c02a055de3 Mon Sep 17 00:00:00 2001 From: yamatatsu Date: Tue, 19 Nov 2019 21:35:21 +0900 Subject: [PATCH] feat(sns): support KMS masterKey on SNS Add Support KMS masterKey on SNS. It is allowed to set `masterKey` as `Kms::Key` to `TopicProps`. Fixes #1729 --- packages/@aws-cdk/aws-sns/lib/topic.ts | 9 ++++ packages/@aws-cdk/aws-sns/package.json | 4 +- .../aws-sns/test/integ.sns.expected.json | 52 ++++++++++++++++++- packages/@aws-cdk/aws-sns/test/integ.sns.ts | 6 ++- packages/@aws-cdk/aws-sns/test/test.sns.ts | 16 ++++++ 5 files changed, 84 insertions(+), 3 deletions(-) diff --git a/packages/@aws-cdk/aws-sns/lib/topic.ts b/packages/@aws-cdk/aws-sns/lib/topic.ts index 1f9c1d38fee3c..e62c2c1468b28 100644 --- a/packages/@aws-cdk/aws-sns/lib/topic.ts +++ b/packages/@aws-cdk/aws-sns/lib/topic.ts @@ -1,3 +1,4 @@ +import { IKey } from '@aws-cdk/aws-kms'; import { Construct, Stack } from '@aws-cdk/core'; import { CfnTopic } from './sns.generated'; import { ITopic, TopicBase } from './topic-base'; @@ -23,6 +24,13 @@ export interface TopicProps { * @default Generated name */ readonly topicName?: string; + + /** + * A KMS Key, either managed by this CDK app, or imported. + * + * @default None + */ + readonly masterKey?: IKey; } /** @@ -53,6 +61,7 @@ export class Topic extends TopicBase { const resource = new CfnTopic(this, 'Resource', { displayName: props.displayName, topicName: this.physicalName, + kmsMasterKeyId: props.masterKey && props.masterKey.keyId, }); this.topicArn = this.getResourceArnAttribute(resource.ref, { diff --git a/packages/@aws-cdk/aws-sns/package.json b/packages/@aws-cdk/aws-sns/package.json index c95e2dfa054e7..33c1a52fde053 100644 --- a/packages/@aws-cdk/aws-sns/package.json +++ b/packages/@aws-cdk/aws-sns/package.json @@ -78,6 +78,7 @@ "@aws-cdk/aws-cloudwatch": "1.16.1", "@aws-cdk/aws-events": "1.16.1", "@aws-cdk/aws-iam": "1.16.1", + "@aws-cdk/aws-kms": "1.16.1", "@aws-cdk/core": "1.16.1" }, "homepage": "https://github.com/aws/aws-cdk", @@ -85,6 +86,7 @@ "@aws-cdk/aws-cloudwatch": "1.16.1", "@aws-cdk/aws-events": "1.16.1", "@aws-cdk/aws-iam": "1.16.1", + "@aws-cdk/aws-kms": "1.16.1", "@aws-cdk/core": "1.16.1" }, "engines": { @@ -119,4 +121,4 @@ ] }, "stability": "stable" -} \ No newline at end of file +} diff --git a/packages/@aws-cdk/aws-sns/test/integ.sns.expected.json b/packages/@aws-cdk/aws-sns/test/integ.sns.expected.json index 8e5512e49281d..ae421268bf6c2 100644 --- a/packages/@aws-cdk/aws-sns/test/integ.sns.expected.json +++ b/packages/@aws-cdk/aws-sns/test/integ.sns.expected.json @@ -4,8 +4,58 @@ "Type": "AWS::SNS::Topic", "Properties": { "DisplayName": "fooDisplayName", - "TopicName": "fooTopic" + "TopicName": "fooTopic", + "KmsMasterKeyId": { "Ref":"CustomKey1E6D0D07" } } + }, + "CustomKey1E6D0D07": { + "Type": "AWS::KMS::Key", + "Properties": { + "KeyPolicy": { + "Statement": [ + { + "Action": [ + "kms:Create*", + "kms:Describe*", + "kms:Enable*", + "kms:List*", + "kms:Put*", + "kms:Update*", + "kms:Revoke*", + "kms:Disable*", + "kms:Get*", + "kms:Delete*", + "kms:ScheduleKeyDeletion", + "kms:CancelKeyDeletion", + "kms:GenerateDataKey" + ], + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":root" + ] + ] + } + }, + "Resource": "*" + } + ], + "Version": "2012-10-17" + } + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" } } } diff --git a/packages/@aws-cdk/aws-sns/test/integ.sns.ts b/packages/@aws-cdk/aws-sns/test/integ.sns.ts index c5bb1e5e991c4..7c744df2e3357 100644 --- a/packages/@aws-cdk/aws-sns/test/integ.sns.ts +++ b/packages/@aws-cdk/aws-sns/test/integ.sns.ts @@ -1,3 +1,4 @@ +import { Key } from '@aws-cdk/aws-kms'; import { App, Stack, StackProps } from '@aws-cdk/core'; import { Topic } from '../lib'; @@ -5,9 +6,12 @@ class SNSInteg extends Stack { constructor(scope: App, id: string, props?: StackProps) { super(scope, id, props); + const key = new Key(this, "CustomKey"); + new Topic(this, 'MyTopic', { topicName: 'fooTopic', - displayName: 'fooDisplayName' + displayName: 'fooDisplayName', + masterKey: key, }); } } diff --git a/packages/@aws-cdk/aws-sns/test/test.sns.ts b/packages/@aws-cdk/aws-sns/test/test.sns.ts index 099a2b2e472da..54beeb6d4be7b 100644 --- a/packages/@aws-cdk/aws-sns/test/test.sns.ts +++ b/packages/@aws-cdk/aws-sns/test/test.sns.ts @@ -1,5 +1,6 @@ import { expect, haveResource } from '@aws-cdk/assert'; import iam = require('@aws-cdk/aws-iam'); +import kms = require('@aws-cdk/aws-kms'); import cdk = require('@aws-cdk/core'); import { App, Stack } from '@aws-cdk/core'; import { Test } from 'nodeunit'; @@ -67,6 +68,21 @@ export = { test.done(); }, + 'specify kmsMasterKey'(test: Test) { + const stack = new cdk.Stack(); + const key = new kms.Key(stack, "CustomKey"); + + new sns.Topic(stack, 'MyTopic', { + masterKey: key, + }); + + expect(stack).to(haveResource("AWS::SNS::Topic", { + "KmsMasterKeyId": { "Ref": "CustomKey1E6D0D07" }, + })); + + test.done(); + }, + 'specify both'(test: Test) { const stack = new cdk.Stack();