Skip to content

Commit

Permalink
feat(aws-kms): support waiting period (aws#12224)
Browse files Browse the repository at this point in the history
Closes [aws#12218](aws#12218)

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
hassanazharkhan authored and flochaz committed Jan 5, 2021
1 parent a17eda5 commit a80c10c
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 1 deletion.
11 changes: 11 additions & 0 deletions packages/@aws-cdk/aws-kms/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,17 @@ new kms.Key(this, 'MyKey', {
});
```

Define a KMS key with waiting period:

Specifies the number of days in the waiting period before AWS KMS deletes a CMK that has been removed from a CloudFormation stack.

```ts
const key = new kms.Key(this, 'MyKey', {
pendingWindow: 10 // Default to 30 Days
});
```


Add a couple of aliases:

```ts
Expand Down
27 changes: 26 additions & 1 deletion packages/@aws-cdk/aws-kms/lib/key.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as iam from '@aws-cdk/aws-iam';
import { FeatureFlags, IResource, RemovalPolicy, Resource, Stack } from '@aws-cdk/core';
import { FeatureFlags, IResource, RemovalPolicy, Resource, Stack, Duration } from '@aws-cdk/core';
import * as cxapi from '@aws-cdk/cx-api';
import { IConstruct, Construct } from 'constructs';
import { Alias } from './alias';
Expand Down Expand Up @@ -330,6 +330,22 @@ export interface KeyProps {
* @deprecated redundant with the '@aws-cdk/aws-kms:defaultKeyPolicies' feature flag
*/
readonly trustAccountIdentities?: boolean;

/**
* Specifies the number of days in the waiting period before
* AWS KMS deletes a CMK that has been removed from a CloudFormation stack.
*
* When you remove a customer master key (CMK) from a CloudFormation stack, AWS KMS schedules the CMK for deletion
* and starts the mandatory waiting period. The PendingWindowInDays property determines the length of waiting period.
* During the waiting period, the key state of CMK is Pending Deletion, which prevents the CMK from being used in
* cryptographic operations. When the waiting period expires, AWS KMS permanently deletes the CMK.
*
* Enter a value between 7 and 30 days.
*
* @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-kms-key.html#cfn-kms-key-pendingwindowindays
* @default - 30 days
*/
readonly pendingWindow?: Duration;
}

/**
Expand Down Expand Up @@ -400,11 +416,20 @@ export class Key extends KeyBase {
}
}

let pendingWindowInDays;
if (props.pendingWindow) {
pendingWindowInDays = props.pendingWindow.toDays();
if (pendingWindowInDays < 7 || pendingWindowInDays > 30) {
throw new Error(`'pendingWindow' value must between 7 and 30 days. Received: ${pendingWindowInDays}`);
}
}

const resource = new CfnKey(this, 'Resource', {
description: props.description,
enableKeyRotation: props.enableKeyRotation,
enabled: props.enabled,
keyPolicy: this.policy,
pendingWindowInDays: pendingWindowInDays,
});

this.keyArn = resource.attrArn;
Expand Down
8 changes: 8 additions & 0 deletions packages/@aws-cdk/aws-kms/test/key.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ test('key with some options', () => {
const key = new kms.Key(stack, 'MyKey', {
enableKeyRotation: true,
enabled: false,
pendingWindow: cdk.Duration.days(7),
});

cdk.Tags.of(key).add('tag1', 'value1');
Expand All @@ -292,6 +293,7 @@ test('key with some options', () => {
expect(stack).toHaveResourceLike('AWS::KMS::Key', {
Enabled: false,
EnableKeyRotation: true,
PendingWindowInDays: 7,
Tags: [
{
Key: 'tag1',
Expand All @@ -309,6 +311,11 @@ test('key with some options', () => {
});
});

test('setting pendingWindow value to not in allowed range will throw', () => {
expect(() => new kms.Key(stack, 'MyKey', { enableKeyRotation: true, pendingWindow: cdk.Duration.days(6) }))
.toThrow('\'pendingWindow\' value must between 7 and 30 days. Received: 6');
});

test('setting trustAccountIdentities to false will throw (when the defaultKeyPolicies feature flag is enabled)', () => {
expect(() => new kms.Key(stack, 'MyKey', { trustAccountIdentities: false }))
.toThrow('`trustAccountIdentities` cannot be false if the @aws-cdk/aws-kms:defaultKeyPolicies feature flag is set');
Expand Down Expand Up @@ -435,6 +442,7 @@ describe('imported keys', () => {
});

describe('addToResourcePolicy allowNoOp and there is no policy', () => {
// eslint-disable-next-line jest/expect-expect
test('succeed if set to true (default)', () => {
const key = kms.Key.fromKeyArn(stack, 'Imported',
'arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012');
Expand Down

0 comments on commit a80c10c

Please sign in to comment.