UNPKG

8.12 kBMarkdownView Raw
1# AWS Key Management Service Construct Library
2<!--BEGIN STABILITY BANNER-->
3
4---
5
6![End-of-Support](https://img.shields.io/badge/End--of--Support-critical.svg?style=for-the-badge)
7
8> AWS CDK v1 has reached End-of-Support on 2023-06-01.
9> This package is no longer being updated, and users should migrate to AWS CDK v2.
10>
11> For more information on how to migrate, see the [_Migrating to AWS CDK v2_ guide][doc].
12>
13> [doc]: https://docs.aws.amazon.com/cdk/v2/guide/migrating-v2.html
14
15---
16
17<!--END STABILITY BANNER-->
18
19Define a KMS key:
20
21```ts
22new kms.Key(this, 'MyKey', {
23 enableKeyRotation: true,
24});
25```
26
27Define a KMS key with waiting period:
28
29Specifies the number of days in the waiting period before AWS KMS deletes a CMK that has been removed from a CloudFormation stack.
30
31```ts
32const key = new kms.Key(this, 'MyKey', {
33 pendingWindow: Duration.days(10), // Default to 30 Days
34});
35```
36
37
38Add a couple of aliases:
39
40```ts
41const key = new kms.Key(this, 'MyKey');
42key.addAlias('alias/foo');
43key.addAlias('alias/bar');
44```
45
46
47Define a key with specific key spec and key usage:
48
49Valid `keySpec` values depends on `keyUsage` value.
50
51```ts
52const key = new kms.Key(this, 'MyKey', {
53 keySpec: kms.KeySpec.ECC_SECG_P256K1, // Default to SYMMETRIC_DEFAULT
54 keyUsage: kms.KeyUsage.SIGN_VERIFY, // and ENCRYPT_DECRYPT
55});
56```
57
58## Sharing keys between stacks
59
60To use a KMS key in a different stack in the same CDK application,
61pass the construct to the other stack:
62
63[sharing key between stacks](test/integ.key-sharing.lit.ts)
64
65
66## Importing existing keys
67
68### Import key by ARN
69
70To use a KMS key that is not defined in this CDK app, but is created through other means, use
71`Key.fromKeyArn(parent, name, ref)`:
72
73```ts
74const myKeyImported = kms.Key.fromKeyArn(this, 'MyImportedKey', 'arn:aws:...');
75
76// you can do stuff with this imported key.
77myKeyImported.addAlias('alias/foo');
78```
79
80Note that a call to `.addToResourcePolicy(statement)` on `myKeyImported` will not have
81an affect on the key's policy because it is not owned by your stack. The call
82will be a no-op.
83
84### Import key by alias
85
86If a Key has an associated Alias, the Alias can be imported by name and used in place
87of the Key as a reference. A common scenario for this is in referencing AWS managed keys.
88
89```ts
90import * as cloudtrail from '@aws-cdk/aws-cloudtrail';
91
92const myKeyAlias = kms.Alias.fromAliasName(this, 'myKey', 'alias/aws/s3');
93const trail = new cloudtrail.Trail(this, 'myCloudTrail', {
94 sendToCloudWatchLogs: true,
95 kmsKey: myKeyAlias,
96});
97```
98
99Note that calls to `addToResourcePolicy` and `grant*` methods on `myKeyAlias` will be
100no-ops, and `addAlias` and `aliasTargetKey` will fail, as the imported alias does not
101have a reference to the underlying KMS Key.
102
103### Lookup key by alias
104
105If you can't use a KMS key imported by alias (e.g. because you need access to the key id), you can lookup the key with `Key.fromLookup()`.
106
107In general, the preferred method would be to use `Alias.fromAliasName()` which returns an `IAlias` object which extends `IKey`. However, some services need to have access to the underlying key id. In this case, `Key.fromLookup()` allows to lookup the key id.
108
109The result of the `Key.fromLookup()` operation will be written to a file
110called `cdk.context.json`. You must commit this file to source control so
111that the lookup values are available in non-privileged environments such
112as CI build steps, and to ensure your template builds are repeatable.
113
114Here's how `Key.fromLookup()` can be used:
115
116```ts
117const myKeyLookup = kms.Key.fromLookup(this, 'MyKeyLookup', {
118 aliasName: 'alias/KeyAlias',
119});
120
121const role = new iam.Role(this, 'MyRole', {
122 assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),
123});
124myKeyLookup.grantEncryptDecrypt(role);
125```
126
127Note that a call to `.addToResourcePolicy(statement)` on `myKeyLookup` will not have
128an affect on the key's policy because it is not owned by your stack. The call
129will be a no-op.
130
131## Key Policies
132
133Controlling access and usage of KMS Keys requires the use of key policies (resource-based policies attached to the key);
134this is in contrast to most other AWS resources where access can be entirely controlled with IAM policies,
135and optionally complemented with resource policies. For more in-depth understanding of KMS key access and policies, see
136
137* https://docs.aws.amazon.com/kms/latest/developerguide/control-access-overview.html
138* https://docs.aws.amazon.com/kms/latest/developerguide/key-policies.html
139
140KMS keys can be created to trust IAM policies. This is the default behavior for both the KMS APIs and in
141the console. This behavior is enabled by the '@aws-cdk/aws-kms:defaultKeyPolicies' feature flag,
142which is set for all new projects; for existing projects, this same behavior can be enabled by
143passing the `trustAccountIdentities` property as `true` when creating the key:
144
145```ts
146new kms.Key(this, 'MyKey', { trustAccountIdentities: true });
147```
148
149With either the `@aws-cdk/aws-kms:defaultKeyPolicies` feature flag set,
150or the `trustAccountIdentities` prop set, the Key will be given the following default key policy:
151
152```json
153{
154 "Effect": "Allow",
155 "Principal": {"AWS": "arn:aws:iam::111122223333:root"},
156 "Action": "kms:*",
157 "Resource": "*"
158}
159```
160
161This policy grants full access to the key to the root account user.
162This enables the root account user -- via IAM policies -- to grant access to other IAM principals.
163With the above default policy, future permissions can be added to either the key policy or IAM principal policy.
164
165```ts
166const key = new kms.Key(this, 'MyKey');
167const user = new iam.User(this, 'MyUser');
168key.grantEncrypt(user); // Adds encrypt permissions to user policy; key policy is unmodified.
169```
170
171Adopting the default KMS key policy (and so trusting account identities)
172solves many issues around cyclic dependencies between stacks.
173Without this default key policy, future permissions must be added to both the key policy and IAM principal policy,
174which can cause cyclic dependencies if the permissions cross stack boundaries.
175(For example, an encrypted bucket in one stack, and Lambda function that accesses it in another.)
176
177### Appending to or replacing the default key policy
178
179The default key policy can be amended or replaced entirely, depending on your use case and requirements.
180A common addition to the key policy would be to add other key admins that are allowed to administer the key
181(e.g., change permissions, revoke, delete). Additional key admins can be specified at key creation or after
182via the `grantAdmin` method.
183
184```ts
185const myTrustedAdminRole = iam.Role.fromRoleArn(this, 'TrustedRole', 'arn:aws:iam:....');
186const key = new kms.Key(this, 'MyKey', {
187 admins: [myTrustedAdminRole],
188});
189
190const secondKey = new kms.Key(this, 'MyKey2');
191secondKey.grantAdmin(myTrustedAdminRole);
192```
193
194Alternatively, a custom key policy can be specified, which will replace the default key policy.
195
196> **Note**: In applications without the '@aws-cdk/aws-kms:defaultKeyPolicies' feature flag set
197and with `trustedAccountIdentities` set to false (the default), specifying a policy at key creation _appends_ the
198provided policy to the default key policy, rather than _replacing_ the default policy.
199
200```ts
201const myTrustedAdminRole = iam.Role.fromRoleArn(this, 'TrustedRole', 'arn:aws:iam:....');
202// Creates a limited admin policy and assigns to the account root.
203const myCustomPolicy = new iam.PolicyDocument({
204 statements: [new iam.PolicyStatement({
205 actions: [
206 'kms:Create*',
207 'kms:Describe*',
208 'kms:Enable*',
209 'kms:List*',
210 'kms:Put*',
211 ],
212 principals: [new iam.AccountRootPrincipal()],
213 resources: ['*'],
214 })],
215});
216const key = new kms.Key(this, 'MyKey', {
217 policy: myCustomPolicy,
218});
219```
220
221> **Warning:** Replacing the default key policy with one that only grants access to a specific user or role
222runs the risk of the key becoming unmanageable if that user or role is deleted.
223It is highly recommended that the key policy grants access to the account root, rather than specific principals.
224See https://docs.aws.amazon.com/kms/latest/developerguide/key-policies.html for more information.