Skip to content

Commit 5acef15

Browse files
author
Farid Nouri Neshat
committed
feat(kms): @aws-cdk/kms:applyImportedAliasPermissionsToPrincipal
1 parent 7ca46d6 commit 5acef15

File tree

5 files changed

+62
-3
lines changed

5 files changed

+62
-3
lines changed

packages/@aws-cdk-testing/framework-integ/test/aws-kms/test/integ.alias-from-alias-name.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@ import { App, Stack } from 'aws-cdk-lib';
22
import { Alias } from 'aws-cdk-lib/aws-kms';
33
import { IntegTest } from '@aws-cdk/integ-tests-alpha';
44
import { AccountRootPrincipal, Role } from 'aws-cdk-lib/aws-iam';
5+
import * as cxapi from 'aws-cdk-lib/cx-api';
56

6-
const app = new App();
7+
const app = new App({
8+
context: { [cxapi.KMS_APPLY_IMPORTED_ALIAS_PERMISSIONS_TO_PRINCIPAL]: true },
9+
});
710
const stack = new Stack(app, 'aws-cdk-kms');
811
const alias = Alias.fromAliasName(stack, 'alias', 'alias/MyKey');
912

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import * as perms from './private/perms';
66
import { FeatureFlags, RemovalPolicy, Resource, Stack, Token, Tokenization, ValidationError } from '../../core';
77
import { addConstructMetadata } from '../../core/lib/metadata-resource';
88
import { propertyInjectable } from '../../core/lib/prop-injectable';
9-
import { KMS_ALIAS_NAME_REF } from '../../cx-api';
9+
import { KMS_ALIAS_NAME_REF, KMS_APPLY_IMPORTED_ALIAS_PERMISSIONS_TO_PRINCIPAL } from '../../cx-api';
1010

1111
const REQUIRED_ALIAS_PREFIX = 'alias/';
1212
const DISALLOWED_PREFIX = REQUIRED_ALIAS_PREFIX + 'aws/';
@@ -206,6 +206,9 @@ export class Alias extends AliasBase {
206206
}
207207

208208
public grant(grantee: iam.IGrantable, ...actions: string[]): iam.Grant {
209+
if (!FeatureFlags.of(this).isEnabled(KMS_APPLY_IMPORTED_ALIAS_PERMISSIONS_TO_PRINCIPAL)) {
210+
return iam.Grant.drop(grantee, '');
211+
}
209212
return iam.Grant.addToPrincipal({
210213
grantee,
211214
actions,

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

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { Template } from '../../assertions';
33
import * as iam from '../../aws-iam';
44
import { ArnPrincipal, PolicyStatement } from '../../aws-iam';
55
import { App, Arn, Aws, CfnOutput, Stack } from '../../core';
6-
import { KMS_ALIAS_NAME_REF } from '../../cx-api';
6+
import { KMS_ALIAS_NAME_REF, KMS_APPLY_IMPORTED_ALIAS_PERMISSIONS_TO_PRINCIPAL } from '../../cx-api';
77
import { Alias } from '../lib/alias';
88
import { IKey, Key } from '../lib/key';
99

@@ -215,6 +215,7 @@ test('imported alias by name - will throw an error when accessing the key', () =
215215

216216
test('imported alias by name - grantDecrypt applies kms:ResourceAliases condition', () => {
217217
const stack = new Stack();
218+
stack.node.setContext(KMS_APPLY_IMPORTED_ALIAS_PERMISSIONS_TO_PRINCIPAL, true);
218219
const aliasName = 'alias/myAlias';
219220
const myAlias = Alias.fromAliasName(stack, 'MyAlias', aliasName);
220221
const user = new iam.User(stack, 'User');
@@ -252,6 +253,7 @@ test('imported alias by name - grantDecrypt applies kms:ResourceAliases conditio
252253

253254
test('imported alias by name - grantEncrypt applies kms:ResourceAliases condition', () => {
254255
const stack = new Stack();
256+
stack.node.setContext(KMS_APPLY_IMPORTED_ALIAS_PERMISSIONS_TO_PRINCIPAL, true);
255257
const aliasName = 'alias/myAlias';
256258
const myAlias = Alias.fromAliasName(stack, 'MyAlias', aliasName);
257259
const user = new iam.User(stack, 'User');
@@ -289,6 +291,7 @@ test('imported alias by name - grantEncrypt applies kms:ResourceAliases conditio
289291

290292
test('imported alias by name - grantEncryptDecrypt applies kms:ResourceAliases condition', () => {
291293
const stack = new Stack();
294+
stack.node.setContext(KMS_APPLY_IMPORTED_ALIAS_PERMISSIONS_TO_PRINCIPAL, true);
292295
const aliasName = 'alias/myAlias';
293296
const myAlias = Alias.fromAliasName(stack, 'MyAlias', aliasName);
294297
const user = new iam.User(stack, 'User');
@@ -326,6 +329,7 @@ test('imported alias by name - grantEncryptDecrypt applies kms:ResourceAliases c
326329

327330
test('imported alias by name - grantSign applies kms:ResourceAliases condition', () => {
328331
const stack = new Stack();
332+
stack.node.setContext(KMS_APPLY_IMPORTED_ALIAS_PERMISSIONS_TO_PRINCIPAL, true);
329333
const aliasName = 'alias/myAlias';
330334
const myAlias = Alias.fromAliasName(stack, 'MyAlias', aliasName);
331335
const user = new iam.User(stack, 'User');
@@ -363,6 +367,7 @@ test('imported alias by name - grantSign applies kms:ResourceAliases condition',
363367

364368
test('imported alias by name - grantVerify applies kms:ResourceAliases condition', () => {
365369
const stack = new Stack();
370+
stack.node.setContext(KMS_APPLY_IMPORTED_ALIAS_PERMISSIONS_TO_PRINCIPAL, true);
366371
const aliasName = 'alias/myAlias';
367372
const myAlias = Alias.fromAliasName(stack, 'MyAlias', aliasName);
368373
const user = new iam.User(stack, 'User');
@@ -400,6 +405,7 @@ test('imported alias by name - grantVerify applies kms:ResourceAliases condition
400405

401406
test('imported alias by name - grantSignVerify applies kms:ResourceAliases condition', () => {
402407
const stack = new Stack();
408+
stack.node.setContext(KMS_APPLY_IMPORTED_ALIAS_PERMISSIONS_TO_PRINCIPAL, true);
403409
const aliasName = 'alias/myAlias';
404410
const myAlias = Alias.fromAliasName(stack, 'MyAlias', aliasName);
405411
const user = new iam.User(stack, 'User');
@@ -437,6 +443,7 @@ test('imported alias by name - grantSignVerify applies kms:ResourceAliases condi
437443

438444
test('imported alias by name - grantGenerateMac applies kms:ResourceAliases condition', () => {
439445
const stack = new Stack();
446+
stack.node.setContext(KMS_APPLY_IMPORTED_ALIAS_PERMISSIONS_TO_PRINCIPAL, true);
440447
const aliasName = 'alias/myAlias';
441448
const myAlias = Alias.fromAliasName(stack, 'MyAlias', aliasName);
442449
const user = new iam.User(stack, 'User');
@@ -474,6 +481,7 @@ test('imported alias by name - grantGenerateMac applies kms:ResourceAliases cond
474481

475482
test('imported alias by name - grantVerifyMac applies kms:ResourceAliases condition', () => {
476483
const stack = new Stack();
484+
stack.node.setContext(KMS_APPLY_IMPORTED_ALIAS_PERMISSIONS_TO_PRINCIPAL, true);
477485
const aliasName = 'alias/myAlias';
478486
const myAlias = Alias.fromAliasName(stack, 'MyAlias', aliasName);
479487
const user = new iam.User(stack, 'User');
@@ -511,6 +519,7 @@ test('imported alias by name - grantVerifyMac applies kms:ResourceAliases condit
511519

512520
test('imported alias by name - grant method applies kms:ResourceAliases condition', () => {
513521
const stack = new Stack();
522+
stack.node.setContext(KMS_APPLY_IMPORTED_ALIAS_PERMISSIONS_TO_PRINCIPAL, true);
514523
const aliasName = 'alias/myAlias';
515524
const myAlias = Alias.fromAliasName(stack, 'MyAlias', aliasName);
516525
const user = new iam.User(stack, 'User');
@@ -546,6 +555,22 @@ test('imported alias by name - grant method applies kms:ResourceAliases conditio
546555
});
547556
});
548557

558+
test('imported alias by name - grant methods are no-op when feature flag disabled', () => {
559+
const stack = new Stack();
560+
stack.node.setContext(KMS_APPLY_IMPORTED_ALIAS_PERMISSIONS_TO_PRINCIPAL, false);
561+
const aliasName = 'alias/myAlias';
562+
const myAlias = Alias.fromAliasName(stack, 'MyAlias', aliasName);
563+
const user = new iam.User(stack, 'User');
564+
565+
myAlias.grantDecrypt(user);
566+
myAlias.grantEncrypt(user);
567+
myAlias.grantSign(user);
568+
myAlias.grant(user, 'kms:CreateGrant');
569+
570+
// should not create any IAM policy statements
571+
Template.fromStack(stack).resourceCountIs('AWS::IAM::Policy', 0);
572+
});
573+
549574
test('fails if alias policy is invalid', () => {
550575
const app = new App();
551576
const stack = new Stack(app, 'my-stack');

packages/aws-cdk-lib/cx-api/README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,20 @@ _cdk.json_
310310
}
311311
```
312312

313+
* `@aws-cdk/aws-kms:applyImportedAliasPermissionsToPrincipal`
314+
315+
Enable grant methods on imported KMS Aliases to apply permissions scoped by the alias using the `kms:ResourceAliases` condition key. When this flag is disabled, grant* methods on `Alias.fromAliasName` remain no-ops to preserve existing behavior.
316+
317+
_cdk.json_
318+
319+
```json
320+
{
321+
"context": {
322+
"@aws-cdk/aws-kms:applyImportedAliasPermissionsToPrincipal": true
323+
}
324+
}
325+
```
326+
313327
* `@aws-cdk/aws-eks:nodegroupNameAttribute`
314328

315329
When enabled, nodegroupName attribute of the provisioned EKS NodeGroup will not have the cluster name prefix.

packages/aws-cdk-lib/cx-api/lib/features.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ export const EC2_RESTRICT_DEFAULT_SECURITY_GROUP = '@aws-cdk/aws-ec2:restrictDef
9191
export const APIGATEWAY_REQUEST_VALIDATOR_UNIQUE_ID = '@aws-cdk/aws-apigateway:requestValidatorUniqueId';
9292
export const INCLUDE_PREFIX_IN_UNIQUE_NAME_GENERATION = '@aws-cdk/core:includePrefixInUniqueNameGeneration';
9393
export const KMS_ALIAS_NAME_REF = '@aws-cdk/aws-kms:aliasNameRef';
94+
export const KMS_APPLY_IMPORTED_ALIAS_PERMISSIONS_TO_PRINCIPAL = '@aws-cdk/aws-kms:applyImportedAliasPermissionsToPrincipal';
9495
export const EFS_DENY_ANONYMOUS_ACCESS = '@aws-cdk/aws-efs:denyAnonymousAccess';
9596
export const EFS_MOUNTTARGET_ORDERINSENSITIVE_LOGICAL_ID = '@aws-cdk/aws-efs:mountTargetOrderInsensitiveLogicalId';
9697
export const AUTOSCALING_GENERATE_LAUNCH_TEMPLATE = '@aws-cdk/aws-autoscaling:generateLaunchTemplateInsteadOfLaunchConfig';
@@ -844,6 +845,19 @@ export const FLAGS: Record<string, FlagInfo> = {
844845
recommendedValue: true,
845846
},
846847

848+
//////////////////////////////////////////////////////////////////////
849+
[KMS_APPLY_IMPORTED_ALIAS_PERMISSIONS_TO_PRINCIPAL]: {
850+
type: FlagType.BugFix,
851+
summary: 'Enable grant methods on Aliases imported by name to use kms:ResourceAliases condition',
852+
detailsMd: `
853+
This flag enables the grant methods (grant, grantDecrypt, grantEncrypt, etc.) on Aliases imported
854+
by name to grant permissions based on the 'kms:ResourceAliases' condition rather than no-op grants.
855+
When disabled, grant calls on imported aliases will be dropped (no-op) to maintain compatibility.
856+
`,
857+
introducedIn: { v2: 'V2NEXT' },
858+
recommendedValue: true,
859+
},
860+
847861
//////////////////////////////////////////////////////////////////////
848862
[AUTOSCALING_GENERATE_LAUNCH_TEMPLATE]: {
849863
type: FlagType.BugFix,

0 commit comments

Comments
 (0)