diff --git a/cdk/bootstrap/bootstrap-template.yaml b/cdk/bootstrap/bootstrap-template.yaml index 46520daf..0c91e3ca 100644 --- a/cdk/bootstrap/bootstrap-template.yaml +++ b/cdk/bootstrap/bootstrap-template.yaml @@ -1002,6 +1002,8 @@ Resources: - lambda:GetFunctionCodeSigningConfig - lambda:GetFunctionRecursionConfig - lambda:GetProvisionedConcurrencyConfig + - lambda:PutProvisionedConcurrencyConfig + - lambda:DeleteProvisionedConcurrencyConfig - lambda:GetRuntimeManagementConfig - lambda:ListVersionsByFunction - lambda:InvokeFunction diff --git a/cdk/bootstrap/policies/application.json b/cdk/bootstrap/policies/application.json index ecc11dc4..9f5932d8 100644 --- a/cdk/bootstrap/policies/application.json +++ b/cdk/bootstrap/policies/application.json @@ -50,6 +50,8 @@ "lambda:GetFunctionCodeSigningConfig", "lambda:GetFunctionRecursionConfig", "lambda:GetProvisionedConcurrencyConfig", + "lambda:PutProvisionedConcurrencyConfig", + "lambda:DeleteProvisionedConcurrencyConfig", "lambda:GetRuntimeManagementConfig", "lambda:ListVersionsByFunction", "lambda:InvokeFunction", diff --git a/cdk/src/bootstrap/policies/application.ts b/cdk/src/bootstrap/policies/application.ts index d219bd76..88b66862 100644 --- a/cdk/src/bootstrap/policies/application.ts +++ b/cdk/src/bootstrap/policies/application.ts @@ -84,6 +84,8 @@ export function applicationPolicy(): iam.PolicyDocument { 'lambda:GetFunctionCodeSigningConfig', 'lambda:GetFunctionRecursionConfig', 'lambda:GetProvisionedConcurrencyConfig', + 'lambda:PutProvisionedConcurrencyConfig', + 'lambda:DeleteProvisionedConcurrencyConfig', 'lambda:GetRuntimeManagementConfig', 'lambda:ListVersionsByFunction', 'lambda:InvokeFunction', diff --git a/cdk/test/bootstrap/policies.test.ts b/cdk/test/bootstrap/policies.test.ts index d03e75d3..2ee788c3 100644 --- a/cdk/test/bootstrap/policies.test.ts +++ b/cdk/test/bootstrap/policies.test.ts @@ -149,6 +149,20 @@ describe('IaCRole-ABCA-Application', () => { ); }); + it('grants Put/Delete provisioned-concurrency, not just Get (#409)', () => { + // The Slack-events function pins provisioned concurrency on its `live` + // alias, so the exec role needs Put (create/update) and Delete (removal), + // not only the Get verb. Get-without-Put rolled the deploy back with + // AccessDenied on lambda:PutProvisionedConcurrencyConfig. + const resolvedDoc = stack.resolve(doc); + const statements = resolvedDoc.Statement as Array<{ Action: string | string[] }>; + const allActions = statements.flatMap((s) => + Array.isArray(s.Action) ? s.Action : [s.Action], + ); + expect(allActions).toContain('lambda:PutProvisionedConcurrencyConfig'); + expect(allActions).toContain('lambda:DeleteProvisionedConcurrencyConfig'); + }); + it('LambdaEventSourceMappings grants tagging (CDK event-source constructs tag the mapping)', () => { // Regression guard for #407: DynamoDBEventSource (and peers) tag the // created event source mapping, so the exec role needs Tag/UntagResource diff --git a/docs/design/DEPLOYMENT_ROLES.md b/docs/design/DEPLOYMENT_ROLES.md index ad6a6cf3..12efc37c 100644 --- a/docs/design/DEPLOYMENT_ROLES.md +++ b/docs/design/DEPLOYMENT_ROLES.md @@ -319,6 +319,8 @@ DynamoDB tables, Lambda functions, API Gateway, Cognito, WAFv2, EventBridge, SQS "lambda:GetFunctionCodeSigningConfig", "lambda:GetFunctionRecursionConfig", "lambda:GetProvisionedConcurrencyConfig", + "lambda:PutProvisionedConcurrencyConfig", + "lambda:DeleteProvisionedConcurrencyConfig", "lambda:GetRuntimeManagementConfig", "lambda:ListVersionsByFunction", "lambda:InvokeFunction", diff --git a/docs/src/content/docs/architecture/Deployment-roles.md b/docs/src/content/docs/architecture/Deployment-roles.md index 57476da6..b9995ddb 100644 --- a/docs/src/content/docs/architecture/Deployment-roles.md +++ b/docs/src/content/docs/architecture/Deployment-roles.md @@ -323,6 +323,8 @@ DynamoDB tables, Lambda functions, API Gateway, Cognito, WAFv2, EventBridge, SQS "lambda:GetFunctionCodeSigningConfig", "lambda:GetFunctionRecursionConfig", "lambda:GetProvisionedConcurrencyConfig", + "lambda:PutProvisionedConcurrencyConfig", + "lambda:DeleteProvisionedConcurrencyConfig", "lambda:GetRuntimeManagementConfig", "lambda:ListVersionsByFunction", "lambda:InvokeFunction",