From f9dcef27b90c6730a01498bd3fe294e765771219 Mon Sep 17 00:00:00 2001 From: go-to-k <24818752+go-to-k@users.noreply.github.com> Date: Thu, 12 Oct 2023 00:46:21 +0900 Subject: [PATCH] fix(secretsmanager): automaticallyAfter is not disabling the automatic rotation of secrets --- ...k-integ-secret-lambda-rotation.assets.json | 4 +- ...integ-secret-lambda-rotation.template.json | 132 +++++++- .../manifest.json | 22 +- .../tree.json | 289 +++++++++++++++--- .../test/integ.lambda-rotation.ts | 16 +- .../lib/rotation-schedule.ts | 4 + .../test/rotation-schedule.test.ts | 10 +- 7 files changed, 410 insertions(+), 67 deletions(-) diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-secretsmanager/test/integ.lambda-rotation.js.snapshot/cdk-integ-secret-lambda-rotation.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-secretsmanager/test/integ.lambda-rotation.js.snapshot/cdk-integ-secret-lambda-rotation.assets.json index 1ff07329c759a..e5c00458a4bf4 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-secretsmanager/test/integ.lambda-rotation.js.snapshot/cdk-integ-secret-lambda-rotation.assets.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-secretsmanager/test/integ.lambda-rotation.js.snapshot/cdk-integ-secret-lambda-rotation.assets.json @@ -1,7 +1,7 @@ { "version": "34.0.0", "files": { - "dc90d37690ac7b3f65298669ac91e7fd063d66752c781aab7febf755ae8694bf": { + "4e81755b5ba8cd19fd697a14075c9c8dba43c651e234a8bff4b4f4218c21018d": { "source": { "path": "cdk-integ-secret-lambda-rotation.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "dc90d37690ac7b3f65298669ac91e7fd063d66752c781aab7febf755ae8694bf.json", + "objectKey": "4e81755b5ba8cd19fd697a14075c9c8dba43c651e234a8bff4b4f4218c21018d.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-secretsmanager/test/integ.lambda-rotation.js.snapshot/cdk-integ-secret-lambda-rotation.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-secretsmanager/test/integ.lambda-rotation.js.snapshot/cdk-integ-secret-lambda-rotation.template.json index 58263e2820f90..0ba85b744198e 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-secretsmanager/test/integ.lambda-rotation.js.snapshot/cdk-integ-secret-lambda-rotation.template.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-secretsmanager/test/integ.lambda-rotation.js.snapshot/cdk-integ-secret-lambda-rotation.template.json @@ -98,11 +98,71 @@ } }, "Effect": "Allow", + "Principal": { + "AWS": [ + { + "Fn::GetAtt": [ + "LambdaServiceRoleA8ED4D3B", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":root" + ] + ] + } + ] + }, + "Resource": "*" + }, + { + "Action": [ + "kms:CreateGrant", + "kms:DescribeKey" + ], + "Condition": { + "StringEquals": { + "kms:ViaService": { + "Fn::Join": [ + "", + [ + "secretsmanager.", + { + "Ref": "AWS::Region" + }, + ".amazonaws.com" + ] + ] + } + } + }, + "Effect": "Allow", "Principal": { "AWS": { - "Fn::GetAtt": [ - "LambdaServiceRoleA8ED4D3B", - "Arn" + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":root" + ] ] } }, @@ -253,7 +313,7 @@ "Type": "AWS::Lambda::Function", "Properties": { "Code": { - "ZipFile": "NOOP" + "ZipFile": "// dummy func" }, "Handler": "index.handler", "Role": { @@ -281,6 +341,70 @@ }, "Principal": "secretsmanager.amazonaws.com" } + }, + "SecretForRotationDisabledD3CC9741": { + "Type": "AWS::SecretsManager::Secret", + "Properties": { + "GenerateSecretString": {}, + "KmsKeyId": { + "Fn::GetAtt": [ + "Key961B73FD", + "Arn" + ] + } + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "LambdaForRotationDisabledServiceRole9FA05754": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + } + }, + "LambdaForRotationDisabled3F8DC7F6": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "// dummy func" + }, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "LambdaForRotationDisabledServiceRole9FA05754", + "Arn" + ] + }, + "Runtime": "nodejs18.x" + }, + "DependsOn": [ + "LambdaForRotationDisabledServiceRole9FA05754" + ] } }, "Parameters": { diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-secretsmanager/test/integ.lambda-rotation.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-secretsmanager/test/integ.lambda-rotation.js.snapshot/manifest.json index f257469dc3319..4ea1b24fa99f2 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-secretsmanager/test/integ.lambda-rotation.js.snapshot/manifest.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-secretsmanager/test/integ.lambda-rotation.js.snapshot/manifest.json @@ -14,10 +14,11 @@ "environment": "aws://unknown-account/unknown-region", "properties": { "templateFile": "cdk-integ-secret-lambda-rotation.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}/dc90d37690ac7b3f65298669ac91e7fd063d66752c781aab7febf755ae8694bf.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/4e81755b5ba8cd19fd697a14075c9c8dba43c651e234a8bff4b4f4218c21018d.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -81,6 +82,24 @@ "data": "LambdaInvokeN0a2GKfZP0JmDqDEVhhu6A0TUv3NyNbk4YMFKNc69846677" } ], + "/cdk-integ-secret-lambda-rotation/SecretForRotationDisabled/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "SecretForRotationDisabledD3CC9741" + } + ], + "/cdk-integ-secret-lambda-rotation/LambdaForRotationDisabled/ServiceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "LambdaForRotationDisabledServiceRole9FA05754" + } + ], + "/cdk-integ-secret-lambda-rotation/LambdaForRotationDisabled/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "LambdaForRotationDisabled3F8DC7F6" + } + ], "/cdk-integ-secret-lambda-rotation/BootstrapVersion": [ { "type": "aws:cdk:logicalId", @@ -109,6 +128,7 @@ "environment": "aws://unknown-account/unknown-region", "properties": { "templateFile": "cdkintegsecretlambdarotationtestDefaultTestDeployAssert65AE5426.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-secretsmanager/test/integ.lambda-rotation.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-secretsmanager/test/integ.lambda-rotation.js.snapshot/tree.json index 207294c8edffe..4f4fc8fd0357c 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-secretsmanager/test/integ.lambda-rotation.js.snapshot/tree.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-secretsmanager/test/integ.lambda-rotation.js.snapshot/tree.json @@ -113,11 +113,71 @@ } }, "Effect": "Allow", + "Principal": { + "AWS": [ + { + "Fn::GetAtt": [ + "LambdaServiceRoleA8ED4D3B", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":root" + ] + ] + } + ] + }, + "Resource": "*" + }, + { + "Action": [ + "kms:CreateGrant", + "kms:DescribeKey" + ], + "Condition": { + "StringEquals": { + "kms:ViaService": { + "Fn::Join": [ + "", + [ + "secretsmanager.", + { + "Ref": "AWS::Region" + }, + ".amazonaws.com" + ] + ] + } + } + }, + "Effect": "Allow", "Principal": { "AWS": { - "Fn::GetAtt": [ - "LambdaServiceRoleA8ED4D3B", - "Arn" + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":root" + ] ] } }, @@ -129,14 +189,14 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_kms.CfnKey", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.2.70" } } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_kms.Key", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.2.70" } }, "Secret": { @@ -159,8 +219,8 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_secretsmanager.CfnSecret", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.2.70" } }, "Schedule": { @@ -188,14 +248,14 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_secretsmanager.CfnRotationSchedule", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.2.70" } } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_secretsmanager.RotationSchedule", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.2.70" } }, "Policy": { @@ -242,20 +302,20 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_secretsmanager.CfnResourcePolicy", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.2.70" } } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_secretsmanager.ResourcePolicy", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.2.70" } } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_secretsmanager.Secret", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.2.70" } }, "Lambda": { @@ -270,8 +330,8 @@ "id": "ImportServiceRole", "path": "cdk-integ-secret-lambda-rotation/Lambda/ServiceRole/ImportServiceRole", "constructInfo": { - "fqn": "aws-cdk-lib.Resource", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.2.70" } }, "Resource": { @@ -309,8 +369,8 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.CfnRole", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.2.70" } }, "DefaultPolicy": { @@ -354,20 +414,20 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.CfnPolicy", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.2.70" } } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.Policy", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.2.70" } } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.Role", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.2.70" } }, "Resource": { @@ -377,7 +437,7 @@ "aws:cdk:cloudformation:type": "AWS::Lambda::Function", "aws:cdk:cloudformation:props": { "code": { - "zipFile": "NOOP" + "zipFile": "// dummy func" }, "handler": "index.handler", "role": { @@ -390,8 +450,8 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_lambda.CfnFunction", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.2.70" } }, "InvokeN0--a2GKfZP0JmDqDE--Vhhu6+A0TUv3NyNbk4YM+FKNc=": { @@ -411,36 +471,165 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_lambda.CfnPermission", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.2.70" } } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_lambda.Function", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.2.70" + } + }, + "SecretForRotationDisabled": { + "id": "SecretForRotationDisabled", + "path": "cdk-integ-secret-lambda-rotation/SecretForRotationDisabled", + "children": { + "Resource": { + "id": "Resource", + "path": "cdk-integ-secret-lambda-rotation/SecretForRotationDisabled/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::SecretsManager::Secret", + "aws:cdk:cloudformation:props": { + "generateSecretString": {}, + "kmsKeyId": { + "Fn::GetAtt": [ + "Key961B73FD", + "Arn" + ] + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.2.70" + } + }, + "ScheduleForRotationDisabled": { + "id": "ScheduleForRotationDisabled", + "path": "cdk-integ-secret-lambda-rotation/SecretForRotationDisabled/ScheduleForRotationDisabled", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.2.70" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.2.70" + } + }, + "LambdaForRotationDisabled": { + "id": "LambdaForRotationDisabled", + "path": "cdk-integ-secret-lambda-rotation/LambdaForRotationDisabled", + "children": { + "ServiceRole": { + "id": "ServiceRole", + "path": "cdk-integ-secret-lambda-rotation/LambdaForRotationDisabled/ServiceRole", + "children": { + "ImportServiceRole": { + "id": "ImportServiceRole", + "path": "cdk-integ-secret-lambda-rotation/LambdaForRotationDisabled/ServiceRole/ImportServiceRole", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.2.70" + } + }, + "Resource": { + "id": "Resource", + "path": "cdk-integ-secret-lambda-rotation/LambdaForRotationDisabled/ServiceRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "managedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.2.70" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.2.70" + } + }, + "Resource": { + "id": "Resource", + "path": "cdk-integ-secret-lambda-rotation/LambdaForRotationDisabled/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::Function", + "aws:cdk:cloudformation:props": { + "code": { + "zipFile": "// dummy func" + }, + "handler": "index.handler", + "role": { + "Fn::GetAtt": [ + "LambdaForRotationDisabledServiceRole9FA05754", + "Arn" + ] + }, + "runtime": "nodejs18.x" + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.2.70" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.2.70" } }, "BootstrapVersion": { "id": "BootstrapVersion", "path": "cdk-integ-secret-lambda-rotation/BootstrapVersion", "constructInfo": { - "fqn": "aws-cdk-lib.CfnParameter", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.2.70" } }, "CheckBootstrapVersion": { "id": "CheckBootstrapVersion", "path": "cdk-integ-secret-lambda-rotation/CheckBootstrapVersion", "constructInfo": { - "fqn": "aws-cdk-lib.CfnRule", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.2.70" } } }, "constructInfo": { - "fqn": "aws-cdk-lib.Stack", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.2.70" } }, "cdk-integ-secret-lambda-rotation-test": { @@ -467,22 +656,22 @@ "id": "BootstrapVersion", "path": "cdk-integ-secret-lambda-rotation-test/DefaultTest/DeployAssert/BootstrapVersion", "constructInfo": { - "fqn": "aws-cdk-lib.CfnParameter", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.2.70" } }, "CheckBootstrapVersion": { "id": "CheckBootstrapVersion", "path": "cdk-integ-secret-lambda-rotation-test/DefaultTest/DeployAssert/CheckBootstrapVersion", "constructInfo": { - "fqn": "aws-cdk-lib.CfnRule", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.2.70" } } }, "constructInfo": { - "fqn": "aws-cdk-lib.Stack", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.2.70" } } }, @@ -507,8 +696,8 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.App", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.2.70" } } } \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-secretsmanager/test/integ.lambda-rotation.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-secretsmanager/test/integ.lambda-rotation.ts index 4382ab413362b..1078b5be541d3 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-secretsmanager/test/integ.lambda-rotation.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-secretsmanager/test/integ.lambda-rotation.ts @@ -19,9 +19,23 @@ class TestStack extends cdk.Stack { rotationLambda: new lambda.Function(this, 'Lambda', { runtime: STANDARD_NODEJS_RUNTIME, handler: 'index.handler', - code: lambda.Code.fromInline('NOOP'), + code: lambda.Code.fromInline('// dummy func'), }), }); + + const secretForRotationDisabled = new secretsmanager.Secret(this, 'SecretForRotationDisabled', { + encryptionKey: key, + }); + + secretForRotationDisabled.addRotationSchedule('ScheduleForRotationDisabled', { + rotationLambda: new lambda.Function(this, 'LambdaForRotationDisabled', { + runtime: STANDARD_NODEJS_RUNTIME, + handler: 'index.handler', + code: lambda.Code.fromInline('// dummy func'), + }), + automaticallyAfter: cdk.Duration.days(0), + rotateImmediatelyOnUpdate: false, + }); } } diff --git a/packages/aws-cdk-lib/aws-secretsmanager/lib/rotation-schedule.ts b/packages/aws-cdk-lib/aws-secretsmanager/lib/rotation-schedule.ts index b2460667599f1..c2afed47ad0a1 100644 --- a/packages/aws-cdk-lib/aws-secretsmanager/lib/rotation-schedule.ts +++ b/packages/aws-cdk-lib/aws-secretsmanager/lib/rotation-schedule.ts @@ -86,6 +86,10 @@ export class RotationSchedule extends Resource { constructor(scope: Construct, id: string, props: RotationScheduleProps) { super(scope, id); + if (props.automaticallyAfter && props.automaticallyAfter.toMilliseconds() === 0) { + return; + } + if ((!props.rotationLambda && !props.hostedRotation) || (props.rotationLambda && props.hostedRotation)) { throw new Error('One of `rotationLambda` or `hostedRotation` must be specified.'); } diff --git a/packages/aws-cdk-lib/aws-secretsmanager/test/rotation-schedule.test.ts b/packages/aws-cdk-lib/aws-secretsmanager/test/rotation-schedule.test.ts index d406b8830dda1..1294608ed4751 100644 --- a/packages/aws-cdk-lib/aws-secretsmanager/test/rotation-schedule.test.ts +++ b/packages/aws-cdk-lib/aws-secretsmanager/test/rotation-schedule.test.ts @@ -611,15 +611,7 @@ describe('manual rotations', () => { }); // THEN - Template.fromStack(localStack).hasResourceProperties('AWS::SecretsManager::RotationSchedule', Match.objectEquals({ - SecretId: { Ref: 'SecretA720EF05' }, - RotationLambdaARN: { - 'Fn::GetAtt': [ - 'LambdaD247545B', - 'Arn', - ], - }, - })); + Template.fromStack(localStack).resourceCountIs('AWS::SecretsManager::RotationSchedule', 0); }; checkRotationNotSet(Duration.days(0));