From bdd4b635253379e8c8f165f9cadd13470437c220 Mon Sep 17 00:00:00 2001 From: Perry Son <13183804+perrylson@users.noreply.github.com> Date: Thu, 22 Aug 2024 01:09:45 -0700 Subject: [PATCH 1/3] feat: add clientToken prop for AccessPoint --- .../test/aws-efs/test/integ.efs.js.snapshot/cdk.out | 2 +- .../aws-efs/test/integ.efs.js.snapshot/integ.json | 2 +- .../test/integ.efs.js.snapshot/manifest.json | 11 ++++++++--- .../test-efs-integ.assets.json | 6 +++--- .../test-efs-integ.template.json | 1 + ...gtestDefaultTestDeployAssert7E1529D5.assets.json | 2 +- .../aws-efs/test/integ.efs.js.snapshot/tree.json | 5 +++-- .../framework-integ/test/aws-efs/test/integ.efs.ts | 1 + packages/aws-cdk-lib/aws-efs/README.md | 3 ++- packages/aws-cdk-lib/aws-efs/lib/access-point.ts | 10 ++++++++++ .../aws-cdk-lib/aws-efs/test/access-point.test.ts | 13 +++++++++++++ 11 files changed, 44 insertions(+), 12 deletions(-) diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-efs/test/integ.efs.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-efs/test/integ.efs.js.snapshot/cdk.out index 560dae10d018f..bd5311dc372de 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-efs/test/integ.efs.js.snapshot/cdk.out +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-efs/test/integ.efs.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"33.0.0"} \ No newline at end of file +{"version":"36.0.5"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-efs/test/integ.efs.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-efs/test/integ.efs.js.snapshot/integ.json index 4e919fb88d5ba..8ed7e1cb009cd 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-efs/test/integ.efs.js.snapshot/integ.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-efs/test/integ.efs.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "33.0.0", + "version": "36.0.5", "testCases": { "test-efs-integ-test/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-efs/test/integ.efs.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-efs/test/integ.efs.js.snapshot/manifest.json index a11e326711d33..c6dbaf807913c 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-efs/test/integ.efs.js.snapshot/manifest.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-efs/test/integ.efs.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "33.0.0", + "version": "36.0.5", "artifacts": { "test-efs-integ.assets": { "type": "cdk:asset-manifest", @@ -14,10 +14,11 @@ "environment": "aws://unknown-account/unknown-region", "properties": { "templateFile": "test-efs-integ.template.json", + "terminationProtection": false, "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/a5b1ebc6006a2ce28112fae5df0ca689544d5dbbbbdd004fc794310ce2d08695.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/f38d63f13d470d5b3ddbf40c819538dea6aefd66655c0fdbfc1d5bc3edf24d17.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -186,7 +187,10 @@ "/test-efs-integ/FileSystem/AccessPoint/Resource": [ { "type": "aws:cdk:logicalId", - "data": "FileSystemAccessPointF8178182" + "data": "FileSystemAccessPointF8178182", + "trace": [ + "!!DESTRUCTIVE_CHANGES: WILL_REPLACE" + ] } ], "/test-efs-integ/BootstrapVersion": [ @@ -217,6 +221,7 @@ "environment": "aws://unknown-account/unknown-region", "properties": { "templateFile": "testefsintegtestDefaultTestDeployAssert7E1529D5.template.json", + "terminationProtection": false, "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-efs/test/integ.efs.js.snapshot/test-efs-integ.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-efs/test/integ.efs.js.snapshot/test-efs-integ.assets.json index 77423251f9e2e..fc5074dea778b 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-efs/test/integ.efs.js.snapshot/test-efs-integ.assets.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-efs/test/integ.efs.js.snapshot/test-efs-integ.assets.json @@ -1,7 +1,7 @@ { - "version": "33.0.0", + "version": "36.0.5", "files": { - "a5b1ebc6006a2ce28112fae5df0ca689544d5dbbbbdd004fc794310ce2d08695": { + "f38d63f13d470d5b3ddbf40c819538dea6aefd66655c0fdbfc1d5bc3edf24d17": { "source": { "path": "test-efs-integ.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "a5b1ebc6006a2ce28112fae5df0ca689544d5dbbbbdd004fc794310ce2d08695.json", + "objectKey": "f38d63f13d470d5b3ddbf40c819538dea6aefd66655c0fdbfc1d5bc3edf24d17.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-efs/test/integ.efs.js.snapshot/test-efs-integ.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-efs/test/integ.efs.js.snapshot/test-efs-integ.template.json index f13f94be56bcd..4e6af142e86ce 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-efs/test/integ.efs.js.snapshot/test-efs-integ.template.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-efs/test/integ.efs.js.snapshot/test-efs-integ.template.json @@ -458,6 +458,7 @@ "Value": "test-efs-integ/FileSystem/AccessPoint" } ], + "ClientToken": "client-token", "FileSystemId": { "Ref": "FileSystem8A8E25C0" }, diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-efs/test/integ.efs.js.snapshot/testefsintegtestDefaultTestDeployAssert7E1529D5.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-efs/test/integ.efs.js.snapshot/testefsintegtestDefaultTestDeployAssert7E1529D5.assets.json index dd7c253a12bbe..32c92a250f37d 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-efs/test/integ.efs.js.snapshot/testefsintegtestDefaultTestDeployAssert7E1529D5.assets.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-efs/test/integ.efs.js.snapshot/testefsintegtestDefaultTestDeployAssert7E1529D5.assets.json @@ -1,5 +1,5 @@ { - "version": "33.0.0", + "version": "36.0.5", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-efs/test/integ.efs.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-efs/test/integ.efs.js.snapshot/tree.json index 08d186b424150..a690d5ea9de34 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-efs/test/integ.efs.js.snapshot/tree.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-efs/test/integ.efs.js.snapshot/tree.json @@ -751,6 +751,7 @@ "attributes": { "aws:cdk:cloudformation:type": "AWS::EFS::AccessPoint", "aws:cdk:cloudformation:props": { + "clientToken": "client-token", "fileSystemId": { "Ref": "FileSystem8A8E25C0" }, @@ -826,7 +827,7 @@ "path": "test-efs-integ-test/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.2.69" + "version": "10.3.0" } }, "DeployAssert": { @@ -872,7 +873,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.2.69" + "version": "10.3.0" } } }, diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-efs/test/integ.efs.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-efs/test/integ.efs.ts index b1f3e8f92604c..9f0ba846ac17a 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-efs/test/integ.efs.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-efs/test/integ.efs.ts @@ -24,6 +24,7 @@ fileSystem.addAccessPoint('AccessPoint', { gid: '1000', uid: '1000', }, + clientToken: 'client-token', }); new integ.IntegTest(app, 'test-efs-integ-test', { diff --git a/packages/aws-cdk-lib/aws-efs/README.md b/packages/aws-cdk-lib/aws-efs/README.md index 1a4419dcb0f24..09a2a46cfc046 100644 --- a/packages/aws-cdk-lib/aws-efs/README.md +++ b/packages/aws-cdk-lib/aws-efs/README.md @@ -217,7 +217,8 @@ the access point can only access data in its own directory and below. To learn m Use the `addAccessPoint` API to create an access point from a fileSystem. ```ts fixture=with-filesystem-instance -fileSystem.addAccessPoint('AccessPoint'); +fileSystem.addAccessPoint('MyAccessPoint', {clientToken: 'client-token', +}); ``` By default, when you create an access point, the root(`/`) directory is exposed to the client diff --git a/packages/aws-cdk-lib/aws-efs/lib/access-point.ts b/packages/aws-cdk-lib/aws-efs/lib/access-point.ts index dcdea87857de9..033e5d44e55c6 100644 --- a/packages/aws-cdk-lib/aws-efs/lib/access-point.ts +++ b/packages/aws-cdk-lib/aws-efs/lib/access-point.ts @@ -102,6 +102,15 @@ export interface AccessPointOptions { * @default - user identity not enforced */ readonly posixUser?: PosixUser; + + /** + * The opaque string specified in the request to ensure idempotent creation. + * + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-efs-accesspoint.html#cfn-efs-accesspoint-clienttoken + * + * @default - No client token. + */ + readonly clientToken?: string; } /** @@ -216,6 +225,7 @@ export class AccessPoint extends AccessPointBase { gid: props.posixUser.gid, secondaryGids: props.posixUser.secondaryGids, } : undefined, + clientToken: props.clientToken, }); Tags.of(this).add('Name', this.node.path); diff --git a/packages/aws-cdk-lib/aws-efs/test/access-point.test.ts b/packages/aws-cdk-lib/aws-efs/test/access-point.test.ts index 2a9b0387594dd..47e0dc36d837d 100644 --- a/packages/aws-cdk-lib/aws-efs/test/access-point.test.ts +++ b/packages/aws-cdk-lib/aws-efs/test/access-point.test.ts @@ -50,6 +50,19 @@ test('support tags for AccessPoint', () => { }); }); +test('allow client token to be set for AccessPoint', () => { + // WHEN + new AccessPoint(stack, 'MyAccessPoint', { + fileSystem, + clientToken: 'client-token', + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::EFS::AccessPoint', { + ClientToken: 'client-token', + }); +}); + test('import an AccessPoint using fromAccessPointId', () => { // WHEN const ap = new AccessPoint(stack, 'MyAccessPoint', { From 19b3884b86f2b31bef18ba33f0adf4e821ffd71e Mon Sep 17 00:00:00 2001 From: Perry Son <13183804+perrylson@users.noreply.github.com> Date: Wed, 2 Oct 2024 21:00:21 -0700 Subject: [PATCH 2/3] feat: add client token length validation and corresponding unit tests --- packages/aws-cdk-lib/aws-efs/README.md | 4 +++- packages/aws-cdk-lib/aws-efs/lib/access-point.ts | 13 +++++++++---- .../aws-efs/test/access-point.test.ts | 16 ++++++++++++++++ 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/packages/aws-cdk-lib/aws-efs/README.md b/packages/aws-cdk-lib/aws-efs/README.md index 09a2a46cfc046..07731d4b26785 100644 --- a/packages/aws-cdk-lib/aws-efs/README.md +++ b/packages/aws-cdk-lib/aws-efs/README.md @@ -217,7 +217,9 @@ the access point can only access data in its own directory and below. To learn m Use the `addAccessPoint` API to create an access point from a fileSystem. ```ts fixture=with-filesystem-instance -fileSystem.addAccessPoint('MyAccessPoint', {clientToken: 'client-token', +fileSystem.addAccessPoint('MyAccessPoint', { + // create a unique access point via an optional client token + clientToken: 'client-token', }); ``` diff --git a/packages/aws-cdk-lib/aws-efs/lib/access-point.ts b/packages/aws-cdk-lib/aws-efs/lib/access-point.ts index 033e5d44e55c6..d6bb8a59d5f5a 100644 --- a/packages/aws-cdk-lib/aws-efs/lib/access-point.ts +++ b/packages/aws-cdk-lib/aws-efs/lib/access-point.ts @@ -1,7 +1,7 @@ import { Construct } from 'constructs'; import { IFileSystem } from './efs-file-system'; import { CfnAccessPoint } from './efs.generated'; -import { ArnFormat, IResource, Resource, Stack, Tags } from '../../core'; +import { ArnFormat, IResource, Resource, Stack, Tags, Token } from '../../core'; /** * Represents an EFS AccessPoint @@ -106,9 +106,9 @@ export interface AccessPointOptions { /** * The opaque string specified in the request to ensure idempotent creation. * - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-efs-accesspoint.html#cfn-efs-accesspoint-clienttoken + * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-efs-accesspoint.html#cfn-efs-accesspoint-clienttoken * - * @default - No client token. + * @default - No client token */ readonly clientToken?: string; } @@ -210,6 +210,11 @@ export class AccessPoint extends AccessPointBase { constructor(scope: Construct, id: string, props: AccessPointProps) { super(scope, id); + const clientToken = props.clientToken; + if ((clientToken?.length === 0 || (clientToken && clientToken.length > 64)) && !Token.isUnresolved(clientToken)) { + throw new Error(`The length of \'clientToken\' must range from 1 to 64 characters, got: ${clientToken.length} characters`); + } + const resource = new CfnAccessPoint(this, 'Resource', { fileSystemId: props.fileSystem.fileSystemId, rootDirectory: { @@ -225,7 +230,7 @@ export class AccessPoint extends AccessPointBase { gid: props.posixUser.gid, secondaryGids: props.posixUser.secondaryGids, } : undefined, - clientToken: props.clientToken, + clientToken, }); Tags.of(this).add('Name', this.node.path); diff --git a/packages/aws-cdk-lib/aws-efs/test/access-point.test.ts b/packages/aws-cdk-lib/aws-efs/test/access-point.test.ts index 47e0dc36d837d..084a6eb2b2f7a 100644 --- a/packages/aws-cdk-lib/aws-efs/test/access-point.test.ts +++ b/packages/aws-cdk-lib/aws-efs/test/access-point.test.ts @@ -63,6 +63,22 @@ test('allow client token to be set for AccessPoint', () => { }); }); +test('throw when client token has a length that is less than 1', () => { + expect(() => new AccessPoint(stack, 'MyAccessPoint', { + fileSystem, + clientToken: '', + }, + )).toThrow(/The length of \'clientToken\' must range from 1 to 64 characters, got: 0 characters/); +}); + +test('throw when client token has a length that is greater than 64', () => { + expect(() => new AccessPoint(stack, 'MyAccessPoint', { + fileSystem, + clientToken: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', + }, + )).toThrow(/The length of \'clientToken\' must range from 1 to 64 characters, got: 65 characters/); +}); + test('import an AccessPoint using fromAccessPointId', () => { // WHEN const ap = new AccessPoint(stack, 'MyAccessPoint', { From 98f2519432b7d1e9476debd6877d7b6b4371e16f Mon Sep 17 00:00:00 2001 From: Perry Son <13183804+perrylson@users.noreply.github.com> Date: Thu, 3 Oct 2024 07:12:59 -0700 Subject: [PATCH 3/3] feat: refactor unit test --- packages/aws-cdk-lib/aws-efs/test/access-point.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/aws-cdk-lib/aws-efs/test/access-point.test.ts b/packages/aws-cdk-lib/aws-efs/test/access-point.test.ts index 084a6eb2b2f7a..8f867d939fb04 100644 --- a/packages/aws-cdk-lib/aws-efs/test/access-point.test.ts +++ b/packages/aws-cdk-lib/aws-efs/test/access-point.test.ts @@ -74,7 +74,7 @@ test('throw when client token has a length that is less than 1', () => { test('throw when client token has a length that is greater than 64', () => { expect(() => new AccessPoint(stack, 'MyAccessPoint', { fileSystem, - clientToken: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', + clientToken: 'a'.repeat(65), }, )).toThrow(/The length of \'clientToken\' must range from 1 to 64 characters, got: 65 characters/); });