Skip to content

Commit da8e1d5

Browse files
authored
refactor(kms): Rename EncryptionKeyAlias to Alias (#2769)
BREAKING CHANGE: The `EncryptionKeyAlias` class was renamed to `Alias`. Associated types (such as `EncryptionKeyAliasProps`) were renamed in the same way.
1 parent da94d8b commit da8e1d5

File tree

5 files changed

+128
-52
lines changed

5 files changed

+128
-52
lines changed

packages/@aws-cdk/aws-kms/README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,15 @@
1515
Defines a KMS key:
1616

1717
```js
18-
new EncryptionKey(this, 'MyKey', {
18+
new Key(this, 'MyKey', {
1919
enableKeyRotation: true
2020
});
2121
```
2222

2323
Add a couple of aliases:
2424

2525
```js
26-
const key = new EncryptionKey(this, 'MyKey');
26+
const key = new Key(this, 'MyKey');
2727
key.addAlias('alias/foo');
2828
key.addAlias('alias/bar');
2929
```
@@ -39,10 +39,10 @@ pass the construct to the other stack:
3939
### Importing existing keys
4040

4141
To use a KMS key that is not defined in this CDK app, but is created through other means, use
42-
`EncryptionKey.import(parent, name, ref)`:
42+
`Key.import(parent, name, ref)`:
4343

4444
```ts
45-
const myKeyImported = EncryptionKey.import(this, 'MyImportedKey', {
45+
const myKeyImported = Key.import(this, 'MyImportedKey', {
4646
keyArn: 'arn:aws:...'
4747
});
4848

packages/@aws-cdk/aws-kms/lib/alias.ts

Lines changed: 69 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,57 @@
1-
import { Construct } from '@aws-cdk/cdk';
1+
import { Construct, IResource, Resource, Token } from '@aws-cdk/cdk';
22
import { IKey } from './key';
33
import { CfnAlias } from './kms.generated';
44

55
const REQUIRED_ALIAS_PREFIX = 'alias/';
6-
const DISALLOWED_PREFIX = REQUIRED_ALIAS_PREFIX + 'AWS';
6+
const DISALLOWED_PREFIX = REQUIRED_ALIAS_PREFIX + 'aws/';
77

8-
export interface EncryptionKeyAliasProps {
8+
/**
9+
* A KMS Key alias.
10+
*/
11+
export interface IAlias extends IResource {
12+
/**
13+
* The name of the alias.
14+
*
15+
* @attribute AliasName
16+
*/
17+
readonly aliasName: string;
18+
19+
/**
20+
* The Key to which the Alias refers.
21+
*
22+
* @attribute TargetKeyId
23+
*/
24+
readonly aliasTargetKey: IKey;
25+
}
26+
27+
/**
28+
* Construction properties for a KMS Key Alias object.
29+
*/
30+
export interface AliasProps {
931
/**
1032
* The name of the alias. The name must start with alias followed by a
1133
* forward slash, such as alias/. You can't specify aliases that begin with
1234
* alias/AWS. These aliases are reserved.
1335
*/
14-
readonly alias: string;
36+
readonly name: string;
1537

1638
/**
1739
* The ID of the key for which you are creating the alias. Specify the key's
1840
* globally unique identifier or Amazon Resource Name (ARN). You can't
1941
* specify another alias.
2042
*/
21-
readonly key: IKey;
43+
readonly targetKey: IKey;
44+
}
45+
46+
abstract class AliasBase extends Resource implements IAlias {
47+
public abstract readonly aliasName: string;
48+
49+
public abstract readonly aliasTargetKey: IKey;
50+
}
51+
52+
export interface AliasAttributes {
53+
readonly aliasName: string;
54+
readonly aliasTargetKey: IKey;
2255
}
2356

2457
/**
@@ -29,31 +62,46 @@ export interface EncryptionKeyAliasProps {
2962
* Working with Aliases in the AWS Key Management Service Developer Guide.
3063
*
3164
* You can also add an alias for a key by calling `key.addAlias(alias)`.
65+
*
66+
* @resource AWS::KMS::Alias
3267
*/
33-
export class EncryptionKeyAlias extends Construct {
34-
/**
35-
* The name of the alias.
36-
*/
37-
public aliasName: string;
68+
export class Alias extends AliasBase {
69+
public static fromAliasAttributes(scope: Construct, id: string, attrs: AliasAttributes): IAlias {
70+
// tslint:disable-next-line: class-name
71+
class _Alias extends AliasBase {
72+
public get aliasName() { return attrs.aliasName; }
73+
public get aliasTargetKey() { return attrs.aliasTargetKey; }
74+
}
75+
return new _Alias(scope, id);
76+
}
77+
78+
public readonly aliasName: string;
79+
public readonly aliasTargetKey: IKey;
3880

39-
constructor(scope: Construct, id: string, props: EncryptionKeyAliasProps) {
81+
constructor(scope: Construct, id: string, props: AliasProps) {
4082
super(scope, id);
4183

42-
if (!props.alias.startsWith(REQUIRED_ALIAS_PREFIX)) {
43-
throw new Error(`Alias must start with the prefix "${REQUIRED_ALIAS_PREFIX}": ${props.alias}`);
44-
}
84+
if (!Token.unresolved(props.name)) {
85+
if (!props.name.startsWith(REQUIRED_ALIAS_PREFIX)) {
86+
throw new Error(`Alias must start with the prefix "${REQUIRED_ALIAS_PREFIX}": ${props.name}`);
87+
}
4588

46-
if (props.alias === REQUIRED_ALIAS_PREFIX) {
47-
throw new Error(`Alias must include a value after "${REQUIRED_ALIAS_PREFIX}": ${props.alias}`);
48-
}
89+
if (props.name === REQUIRED_ALIAS_PREFIX) {
90+
throw new Error(`Alias must include a value after "${REQUIRED_ALIAS_PREFIX}": ${props.name}`);
91+
}
92+
93+
if (props.name.startsWith(DISALLOWED_PREFIX)) {
94+
throw new Error(`Alias cannot start with ${DISALLOWED_PREFIX}: ${props.name}`);
95+
}
4996

50-
if (props.alias.startsWith(DISALLOWED_PREFIX)) {
51-
throw new Error(`Alias cannot start with ${DISALLOWED_PREFIX}: ${props.alias}`);
97+
if (!props.name.match(/^[a-zA-Z0-9:/_-]{1,256}$/)) {
98+
throw new Error(`Alias name must be between 1 and 256 characters in a-zA-Z0-9:/_-`);
99+
}
52100
}
53101

54102
const resource = new CfnAlias(this, 'Resource', {
55-
aliasName: props.alias,
56-
targetKeyId: props.key.keyArn
103+
aliasName: props.name,
104+
targetKeyId: props.targetKey.keyArn
57105
});
58106

59107
this.aliasName = resource.aliasName;

packages/@aws-cdk/aws-kms/lib/key.ts

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
import iam = require('@aws-cdk/aws-iam');
22
import { PolicyDocument, PolicyStatement } from '@aws-cdk/aws-iam';
3-
import { Construct, DeletionPolicy, IResource } from '@aws-cdk/cdk';
4-
import { EncryptionKeyAlias } from './alias';
3+
import { Construct, DeletionPolicy, IResource, Resource } from '@aws-cdk/cdk';
4+
import { Alias } from './alias';
55
import { CfnKey } from './kms.generated';
66

7+
/**
8+
* A KMS Key, either managed by this CDK app, or imported.
9+
*/
710
export interface IKey extends IResource {
811
/**
912
* The ARN of the key.
@@ -15,7 +18,7 @@ export interface IKey extends IResource {
1518
/**
1619
* Defines a new alias for the key.
1720
*/
18-
addAlias(alias: string): EncryptionKeyAlias;
21+
addAlias(alias: string): Alias;
1922

2023
/**
2124
* Adds a statement to the KMS key resource policy.
@@ -47,7 +50,7 @@ export interface IKey extends IResource {
4750
grantEncryptDecrypt(grantee: iam.IGrantable): iam.Grant;
4851
}
4952

50-
abstract class KeyBase extends Construct implements IKey {
53+
abstract class KeyBase extends Resource implements IKey {
5154
/**
5255
* The ARN of the key.
5356
*/
@@ -64,8 +67,8 @@ abstract class KeyBase extends Construct implements IKey {
6467
/**
6568
* Defines a new alias for the key.
6669
*/
67-
public addAlias(alias: string): EncryptionKeyAlias {
68-
return new EncryptionKeyAlias(this, 'Alias', { alias, key: this });
70+
public addAlias(alias: string): Alias {
71+
return new Alias(this, 'Alias', { name: alias, targetKey: this });
6972
}
7073

7174
/**
@@ -179,9 +182,17 @@ export interface KeyProps {
179182

180183
/**
181184
* Defines a KMS key.
185+
*
186+
* @resource AWS::KMS::Key
182187
*/
183188
export class Key extends KeyBase {
184-
189+
/**
190+
* Import an externally defined KMS Key using its ARN.
191+
*
192+
* @param scope the construct that will "own" the imported key.
193+
* @param id the id of the imported key in the construct tree.
194+
* @param keyArn the ARN of an existing KMS key.
195+
*/
185196
public static fromKeyArn(scope: Construct, id: string, keyArn: string): IKey {
186197
class Import extends KeyBase {
187198
public keyArn = keyArn;

packages/@aws-cdk/aws-kms/test/integ.key-sharing.lit.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class KeyStack extends cdk.Stack {
1919
}
2020

2121
interface UseStackProps extends cdk.StackProps {
22-
key: kms.IKey; // Use IEncryptionKey here
22+
key: kms.IKey; // Use IKey here
2323
}
2424

2525
/**
@@ -29,7 +29,7 @@ class UseStack extends cdk.Stack {
2929
constructor(scope: cdk.App, id: string, props: UseStackProps) {
3030
super(scope, id, props);
3131

32-
// Use the IEncryptionKey object here.
32+
// Use the IKey object here.
3333
props.key.addAlias('alias/foo');
3434
}
3535
}

packages/@aws-cdk/aws-kms/test/test.alias.ts

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@ import { expect, haveResource } from '@aws-cdk/assert';
22
import { App, Stack } from '@aws-cdk/cdk';
33
import { Test } from 'nodeunit';
44
import { Key } from '../lib';
5-
import { EncryptionKeyAlias } from '../lib/alias';
5+
import { Alias } from '../lib/alias';
66

77
export = {
88
'default alias'(test: Test) {
99
const app = new App();
1010
const stack = new Stack(app, 'Test');
1111
const key = new Key(stack, 'Key');
1212

13-
new EncryptionKeyAlias(stack, 'Alias', { key, alias: 'alias/foo' });
13+
new Alias(stack, 'Alias', { targetKey: key, name: 'alias/foo' });
1414

1515
expect(stack).to(haveResource('AWS::KMS::Alias', {
1616
AliasName: 'alias/foo',
@@ -29,9 +29,9 @@ export = {
2929
enabled: false
3030
});
3131

32-
test.throws(() => new EncryptionKeyAlias(stack, 'Alias', {
33-
alias: 'foo',
34-
key
32+
test.throws(() => new Alias(stack, 'Alias', {
33+
name: 'foo',
34+
targetKey: key
3535
}));
3636

3737
test.done();
@@ -46,15 +46,15 @@ export = {
4646
enabled: false
4747
});
4848

49-
test.throws(() => new EncryptionKeyAlias(stack, 'Alias', {
50-
alias: 'alias/',
51-
key
49+
test.throws(() => new Alias(stack, 'Alias', {
50+
name: 'alias/',
51+
targetKey: key
5252
}));
5353

5454
test.done();
5555
},
5656

57-
'fails if alias starts with "alias/AWS"'(test: Test) {
57+
'fails if alias contains illegal characters'(test: Test) {
5858
const app = new App();
5959
const stack = new Stack(app, 'Test');
6060

@@ -63,19 +63,36 @@ export = {
6363
enabled: false
6464
});
6565

66-
test.throws(() => new EncryptionKeyAlias(stack, 'Alias', {
67-
alias: 'alias/AWS',
68-
key
66+
test.throws(() => new Alias(stack, 'Alias', {
67+
name: 'alias/@Nope',
68+
targetKey: key
69+
}), 'a-zA-Z0-9:/_-');
70+
71+
test.done();
72+
},
73+
74+
'fails if alias starts with "alias/aws/"'(test: Test) {
75+
const app = new App();
76+
const stack = new Stack(app, 'Test');
77+
78+
const key = new Key(stack, 'MyKey', {
79+
enableKeyRotation: true,
80+
enabled: false
81+
});
82+
83+
test.throws(() => new Alias(stack, 'Alias', {
84+
name: 'alias/aws/',
85+
targetKey: key
6986
}));
7087

71-
test.throws(() => new EncryptionKeyAlias(stack, 'Alias', {
72-
alias: 'alias/AWSAwesome',
73-
key
88+
test.throws(() => new Alias(stack, 'Alias', {
89+
name: 'alias/aws/Awesome',
90+
targetKey: key
7491
}));
7592

76-
test.throws(() => new EncryptionKeyAlias(stack, 'Alias', {
77-
alias: 'alias/AWS/awesome',
78-
key
93+
test.throws(() => new Alias(stack, 'Alias', {
94+
name: 'alias/AWS/awesome',
95+
targetKey: key
7996
}));
8097

8198
test.done();

0 commit comments

Comments
 (0)