Skip to content

Commit 94e48c6

Browse files
authored
fix(secretsmanager): rotation resource creation can fail due to race condition (#26512)
Setting up a `RotationSchedule` with `rotationLambda` could cause failures due to the lambda invoking permission and the`RotationSchedule` being created concurrently. This fix adds a dependency to ensure the policy is created first and to prevent race conditions. Closes #26481. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent 3305d4f commit 94e48c6

File tree

4 files changed

+36
-3
lines changed

4 files changed

+36
-3
lines changed

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

+4-1
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,10 @@
144144
"RotationRules": {
145145
"AutomaticallyAfterDays": 30
146146
}
147-
}
147+
},
148+
"DependsOn": [
149+
"LambdaInvokeN0a2GKfZP0JmDqDEVhhu6A0TUv3NyNbk4YMFKNc69846677"
150+
]
148151
},
149152
"SecretPolicy06C9821C": {
150153
"Type": "AWS::SecretsManager::ResourcePolicy",

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

+8-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import * as kms from 'aws-cdk-lib/aws-kms';
22
import * as lambda from 'aws-cdk-lib/aws-lambda';
33
import * as cdk from 'aws-cdk-lib';
44
import * as secretsmanager from 'aws-cdk-lib/aws-secretsmanager';
5+
import * as integ from '@aws-cdk/integ-tests-alpha';
56

67
class TestStack extends cdk.Stack {
78
constructor(scope: cdk.App, id: string) {
@@ -24,5 +25,11 @@ class TestStack extends cdk.Stack {
2425
}
2526

2627
const app = new cdk.App();
27-
new TestStack(app, 'cdk-integ-secret-lambda-rotation');
28+
29+
const stack = new TestStack(app, 'cdk-integ-secret-lambda-rotation');
30+
31+
new integ.IntegTest(app, 'cdk-integ-secret-lambda-rotation-test', {
32+
testCases: [stack],
33+
});
34+
2835
app.synth();

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,8 @@ export class RotationSchedule extends Resource {
100100
);
101101
}
102102

103-
props.rotationLambda.grantInvoke(new iam.ServicePrincipal('secretsmanager.amazonaws.com'));
103+
const grant = props.rotationLambda.grantInvoke(new iam.ServicePrincipal('secretsmanager.amazonaws.com'));
104+
grant.applyBefore(this);
104105

105106
props.rotationLambda.addToRolePolicy(
106107
new iam.PolicyStatement({

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

+22
Original file line numberDiff line numberDiff line change
@@ -629,3 +629,25 @@ describe('manual rotations', () => {
629629
checkRotationNotSet(Duration.millis(0));
630630
});
631631
});
632+
633+
test('rotation schedule should have a dependency on lambda permissions', () => {
634+
// GIVEN
635+
const secret = new secretsmanager.Secret(stack, 'Secret');
636+
const rotationLambda = new lambda.Function(stack, 'Lambda', {
637+
runtime: lambda.Runtime.NODEJS_14_X,
638+
code: lambda.Code.fromInline('export.handler = event => event;'),
639+
handler: 'index.handler',
640+
});
641+
642+
// WHEN
643+
secret.addRotationSchedule('RotationSchedule', {
644+
rotationLambda,
645+
});
646+
647+
// THEN
648+
Template.fromStack(stack).hasResource('AWS::SecretsManager::RotationSchedule', {
649+
DependsOn: [
650+
'LambdaInvokeN0a2GKfZP0JmDqDEVhhu6A0TUv3NyNbk4YMFKNc69846677',
651+
],
652+
});
653+
});

0 commit comments

Comments
 (0)