Skip to content

Commit cdafcc5

Browse files
authored
feat(secretsmanager): add support for rotateImmediatelyOnUpdate for secret rotation schedule (#25652)
When adding a rotation schedule to a secret, you can specify whether or not the secret should be rotated immediately. This is optional, and by default, the secret will be rotated immediately if rotateImmediatelyOnUpdate is undefined. This PR exposes the rotateImmediatelyOnUpdate property enabling the user to configure this as false if they do not want the secret to be rotated immediately. Configuring this property as being explicitly true will result in the secret being rotated immediately, which is the default behavior. Closes #25365 ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent e724385 commit cdafcc5

File tree

10 files changed

+93
-36
lines changed

10 files changed

+93
-36
lines changed

packages/@aws-cdk-testing/framework-integ/test/aws-secretsmanager/test/integ.hosted-rotation.js.snapshot/cdk-integ-secret-hosted-rotation.assets.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
{
2-
"version": "20.0.0",
2+
"version": "31.0.0",
33
"files": {
4-
"80e7147ae17e29a7810c1890b8caa90a140f0089dcb2dce470bd13d88e5acc41": {
4+
"68111103cf6a45cb34025acaab5488606270170cf3e4bccee5883433fe58e704": {
55
"source": {
66
"path": "cdk-integ-secret-hosted-rotation.template.json",
77
"packaging": "file"
88
},
99
"destinations": {
1010
"current_account-current_region": {
1111
"bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}",
12-
"objectKey": "80e7147ae17e29a7810c1890b8caa90a140f0089dcb2dce470bd13d88e5acc41.json",
12+
"objectKey": "68111103cf6a45cb34025acaab5488606270170cf3e4bccee5883433fe58e704.json",
1313
"assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}"
1414
}
1515
}

packages/@aws-cdk-testing/framework-integ/test/aws-secretsmanager/test/integ.hosted-rotation.js.snapshot/cdk-integ-secret-hosted-rotation.template.json

+1
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@
8282
"ExcludeCharacters": "&@/",
8383
"RotationType": "MySQLSingleUser"
8484
},
85+
"RotateImmediatelyOnUpdate": false,
8586
"RotationRules": {
8687
"AutomaticallyAfterDays": 30
8788
}
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"version":"20.0.0"}
1+
{"version":"31.0.0"}

packages/@aws-cdk-testing/framework-integ/test/aws-secretsmanager/test/integ.hosted-rotation.js.snapshot/integ.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"version": "20.0.0",
2+
"version": "31.0.0",
33
"testCases": {
44
"integ.hosted-rotation": {
55
"stacks": [

packages/@aws-cdk-testing/framework-integ/test/aws-secretsmanager/test/integ.hosted-rotation.js.snapshot/manifest.json

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,6 @@
11
{
2-
"version": "20.0.0",
2+
"version": "31.0.0",
33
"artifacts": {
4-
"Tree": {
5-
"type": "cdk:tree",
6-
"properties": {
7-
"file": "tree.json"
8-
}
9-
},
104
"cdk-integ-secret-hosted-rotation.assets": {
115
"type": "cdk:asset-manifest",
126
"properties": {
@@ -23,7 +17,7 @@
2317
"validateOnSynth": false,
2418
"assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}",
2519
"cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}",
26-
"stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/80e7147ae17e29a7810c1890b8caa90a140f0089dcb2dce470bd13d88e5acc41.json",
20+
"stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/68111103cf6a45cb34025acaab5488606270170cf3e4bccee5883433fe58e704.json",
2721
"requiresBootstrapStackVersion": 6,
2822
"bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version",
2923
"additionalDependencies": [
@@ -89,6 +83,12 @@
8983
]
9084
},
9185
"displayName": "cdk-integ-secret-hosted-rotation"
86+
},
87+
"Tree": {
88+
"type": "cdk:tree",
89+
"properties": {
90+
"file": "tree.json"
91+
}
9292
}
9393
}
9494
}

packages/@aws-cdk-testing/framework-integ/test/aws-secretsmanager/test/integ.hosted-rotation.js.snapshot/tree.json

+40-23
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,6 @@
44
"id": "App",
55
"path": "",
66
"children": {
7-
"Tree": {
8-
"id": "Tree",
9-
"path": "Tree",
10-
"constructInfo": {
11-
"fqn": "constructs.Construct",
12-
"version": "10.1.85"
13-
}
14-
},
157
"cdk-integ-secret-hosted-rotation": {
168
"id": "cdk-integ-secret-hosted-rotation",
179
"path": "cdk-integ-secret-hosted-rotation",
@@ -30,7 +22,7 @@
3022
}
3123
},
3224
"constructInfo": {
33-
"fqn": "@aws-cdk/aws-secretsmanager.CfnSecret",
25+
"fqn": "aws-cdk-lib.aws_secretsmanager.CfnSecret",
3426
"version": "0.0.0"
3527
}
3628
},
@@ -57,13 +49,13 @@
5749
}
5850
},
5951
"constructInfo": {
60-
"fqn": "@aws-cdk/aws-secretsmanager.CfnRotationSchedule",
52+
"fqn": "aws-cdk-lib.aws_secretsmanager.CfnRotationSchedule",
6153
"version": "0.0.0"
6254
}
6355
}
6456
},
6557
"constructInfo": {
66-
"fqn": "@aws-cdk/aws-secretsmanager.RotationSchedule",
58+
"fqn": "aws-cdk-lib.aws_secretsmanager.RotationSchedule",
6759
"version": "0.0.0"
6860
}
6961
},
@@ -111,19 +103,19 @@
111103
}
112104
},
113105
"constructInfo": {
114-
"fqn": "@aws-cdk/aws-secretsmanager.CfnResourcePolicy",
106+
"fqn": "aws-cdk-lib.aws_secretsmanager.CfnResourcePolicy",
115107
"version": "0.0.0"
116108
}
117109
}
118110
},
119111
"constructInfo": {
120-
"fqn": "@aws-cdk/aws-secretsmanager.ResourcePolicy",
112+
"fqn": "aws-cdk-lib.aws_secretsmanager.ResourcePolicy",
121113
"version": "0.0.0"
122114
}
123115
}
124116
},
125117
"constructInfo": {
126-
"fqn": "@aws-cdk/aws-secretsmanager.Secret",
118+
"fqn": "aws-cdk-lib.aws_secretsmanager.Secret",
127119
"version": "0.0.0"
128120
}
129121
},
@@ -143,7 +135,7 @@
143135
}
144136
},
145137
"constructInfo": {
146-
"fqn": "@aws-cdk/aws-secretsmanager.CfnSecret",
138+
"fqn": "aws-cdk-lib.aws_secretsmanager.CfnSecret",
147139
"version": "0.0.0"
148140
}
149141
},
@@ -164,19 +156,20 @@
164156
"rotationType": "MySQLSingleUser",
165157
"excludeCharacters": "&@/"
166158
},
159+
"rotateImmediatelyOnUpdate": false,
167160
"rotationRules": {
168161
"automaticallyAfterDays": 30
169162
}
170163
}
171164
},
172165
"constructInfo": {
173-
"fqn": "@aws-cdk/aws-secretsmanager.CfnRotationSchedule",
166+
"fqn": "aws-cdk-lib.aws_secretsmanager.CfnRotationSchedule",
174167
"version": "0.0.0"
175168
}
176169
}
177170
},
178171
"constructInfo": {
179-
"fqn": "@aws-cdk/aws-secretsmanager.RotationSchedule",
172+
"fqn": "aws-cdk-lib.aws_secretsmanager.RotationSchedule",
180173
"version": "0.0.0"
181174
}
182175
},
@@ -224,32 +217,56 @@
224217
}
225218
},
226219
"constructInfo": {
227-
"fqn": "@aws-cdk/aws-secretsmanager.CfnResourcePolicy",
220+
"fqn": "aws-cdk-lib.aws_secretsmanager.CfnResourcePolicy",
228221
"version": "0.0.0"
229222
}
230223
}
231224
},
232225
"constructInfo": {
233-
"fqn": "@aws-cdk/aws-secretsmanager.ResourcePolicy",
226+
"fqn": "aws-cdk-lib.aws_secretsmanager.ResourcePolicy",
234227
"version": "0.0.0"
235228
}
236229
}
237230
},
238231
"constructInfo": {
239-
"fqn": "@aws-cdk/aws-secretsmanager.Secret",
232+
"fqn": "aws-cdk-lib.aws_secretsmanager.Secret",
233+
"version": "0.0.0"
234+
}
235+
},
236+
"BootstrapVersion": {
237+
"id": "BootstrapVersion",
238+
"path": "cdk-integ-secret-hosted-rotation/BootstrapVersion",
239+
"constructInfo": {
240+
"fqn": "aws-cdk-lib.CfnParameter",
241+
"version": "0.0.0"
242+
}
243+
},
244+
"CheckBootstrapVersion": {
245+
"id": "CheckBootstrapVersion",
246+
"path": "cdk-integ-secret-hosted-rotation/CheckBootstrapVersion",
247+
"constructInfo": {
248+
"fqn": "aws-cdk-lib.CfnRule",
240249
"version": "0.0.0"
241250
}
242251
}
243252
},
253+
"constructInfo": {
254+
"fqn": "aws-cdk-lib.Stack",
255+
"version": "0.0.0"
256+
}
257+
},
258+
"Tree": {
259+
"id": "Tree",
260+
"path": "Tree",
244261
"constructInfo": {
245262
"fqn": "constructs.Construct",
246-
"version": "10.1.85"
263+
"version": "10.2.26"
247264
}
248265
}
249266
},
250267
"constructInfo": {
251-
"fqn": "constructs.Construct",
252-
"version": "10.1.85"
268+
"fqn": "aws-cdk-lib.App",
269+
"version": "0.0.0"
253270
}
254271
}
255272
}

packages/@aws-cdk-testing/framework-integ/test/aws-secretsmanager/test/integ.hosted-rotation.ts

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ class TestStack extends cdk.Stack {
1717
});
1818
customSecret.addRotationSchedule('Schedule', {
1919
hostedRotation: secretsmanager.HostedRotation.mysqlSingleUser(),
20+
rotateImmediatelyOnUpdate: false,
2021
});
2122
}
2223
}

packages/aws-cdk-lib/aws-secretsmanager/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ const secret = new secretsmanager.Secret(this, 'Secret');
124124

125125
secret.addRotationSchedule('RotationSchedule', {
126126
hostedRotation: secretsmanager.HostedRotation.mysqlSingleUser(),
127+
rotateImmediatelyOnUpdate: false, // by default, Secrets Manager rotates the secret immediately
127128
});
128129
```
129130

packages/aws-cdk-lib/aws-secretsmanager/lib/rotation-schedule.ts

+9
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,14 @@ export interface RotationScheduleOptions {
4242
* @default Duration.days(30)
4343
*/
4444
readonly automaticallyAfter?: Duration;
45+
46+
/**
47+
* Specifies whether to rotate the secret immediately or wait until the next
48+
* scheduled rotation window.
49+
*
50+
* @default - secret is rotated immediately
51+
*/
52+
readonly rotateImmediatelyOnUpdate?: boolean;
4553
}
4654

4755
/**
@@ -132,6 +140,7 @@ export class RotationSchedule extends Resource {
132140
rotationLambdaArn: props.rotationLambda?.functionArn,
133141
hostedRotationLambda: props.hostedRotation?.bind(props.secret, this),
134142
rotationRules,
143+
rotateImmediatelyOnUpdate: props.rotateImmediatelyOnUpdate,
135144
});
136145

137146
// Prevent secrets deletions when rotation is in place

packages/aws-cdk-lib/aws-secretsmanager/test/rotation-schedule.test.ts

+28
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,34 @@ test('create a rotation schedule with a rotation Lambda', () => {
4343
});
4444
});
4545

46+
test('create a rotation schedule without immediate rotation', () => {
47+
// GIVEN
48+
const secret = new secretsmanager.Secret(stack, 'Secret');
49+
const rotationLambda = new lambda.Function(stack, 'Lambda', {
50+
runtime: lambda.Runtime.NODEJS_14_X,
51+
code: lambda.Code.fromInline('export.handler = event => event;'),
52+
handler: 'index.handler',
53+
});
54+
55+
// WHEN
56+
new secretsmanager.RotationSchedule(stack, 'RotationSchedule', {
57+
secret,
58+
rotationLambda,
59+
rotateImmediatelyOnUpdate: false,
60+
});
61+
62+
// THEN
63+
Template.fromStack(stack).hasResourceProperties('AWS::SecretsManager::RotationSchedule', {
64+
SecretId: {
65+
Ref: 'SecretA720EF05',
66+
},
67+
RotationRules: {
68+
AutomaticallyAfterDays: 30,
69+
},
70+
RotateImmediatelyOnUpdate: false,
71+
});
72+
});
73+
4674
test('assign permissions for rotation schedule with a rotation Lambda', () => {
4775
// GIVEN
4876
const secret = new secretsmanager.Secret(stack, 'Secret');

0 commit comments

Comments
 (0)