diff --git a/lib/deploy/stepFunctions/compileIamRole.js b/lib/deploy/stepFunctions/compileIamRole.js index 47b1e2e..6eae6e7 100644 --- a/lib/deploy/stepFunctions/compileIamRole.js +++ b/lib/deploy/stepFunctions/compileIamRole.js @@ -561,6 +561,22 @@ function getEventBridgePermissions(state) { ]; } +function getEventBridgeSchedulerPermissions(state) { + const scheduleGroupName = state.Parameters.GroupName; + + return [ + { + action: 'scheduler:CreateSchedule', + resource: { + 'Fn::Sub': [ + 'arn:${AWS::Partition}:scheduler:${AWS::Region}:${AWS::AccountId}:schedule/${scheduleGroupName}/*', + { scheduleGroupName }, + ], + }, + }, + ]; +} + function getS3ObjectPermissions(action, state) { const bucket = state.Parameters.Bucket || '*'; const key = state.Parameters.Key || '*'; @@ -707,6 +723,9 @@ function getIamPermissions(taskStates) { case 'arn:aws:states:::events:putEvents.waitForTaskToken': return getEventBridgePermissions(state); + case 'arn:aws:states:::aws-sdk:scheduler:createSchedule': + return getEventBridgeSchedulerPermissions(state); + case 'arn:aws:states:::s3:getObject': case 'arn:aws:states:::aws-sdk:s3:getObject': return getS3ObjectPermissions('s3:GetObject', state); diff --git a/lib/deploy/stepFunctions/compileIamRole.test.js b/lib/deploy/stepFunctions/compileIamRole.test.js index c79d9da..8b97f59 100644 --- a/lib/deploy/stepFunctions/compileIamRole.test.js +++ b/lib/deploy/stepFunctions/compileIamRole.test.js @@ -3721,6 +3721,60 @@ describe('#compileIamRole', () => { }, ]); }); + + it('should give event bridge scheduler createSchedule permissions', () => { + const genStateMachine = id => ({ + id, + definition: { + StartAt: 'A', + States: { + A: { + Type: 'Task', + Resource: 'arn:aws:states:::aws-sdk:scheduler:createSchedule', + Parameters: { + ActionAfterCompletion: 'DELETE', + FlexibleTimeWindow: { + Mode: 'FLEXIBLE', + MaximumWindowInMinutes: 5, + }, + 'Name.$': '$$.Execution.Name', + GroupName: 'MyScheduleGroup', + ScheduleExpression: 'at("2024-03-04T00:00:00")', + Target: { + Arn: 'arn:aws:states:${AWS::Region}:${AWS::AccountId}:stateMachine:MyStateMachine', + RoleArn: 'arn:aws:iam::${AWS::AccountId}:role/MyIAMRole', + Input: { + foo: 'bar', + }, + }, + }, + End: true, + }, + }, + }, + }); + + serverless.service.stepFunctions = { + stateMachines: { + myStateMachine1: genStateMachine('StateMachine1'), + }, + }; + + serverlessStepFunctions.compileIamRole(); + const statements = serverlessStepFunctions.serverless.service + .provider.compiledCloudFormationTemplate.Resources.StateMachine1Role + .Properties.Policies[0].PolicyDocument.Statement; + + const eventPermissions = statements.filter(s => _.isEqual(s.Action, ['scheduler:CreateSchedule'])); + expect(eventPermissions[0].Resource).to.has.lengthOf(1); + expect(eventPermissions[0].Resource).to.deep.eq([{ + 'Fn::Sub': [ + 'arn:${AWS::Partition}:scheduler:${AWS::Region}:${AWS::AccountId}:schedule/${scheduleGroupName}/*', + { scheduleGroupName: 'MyScheduleGroup' }, + ], + }]); + }); + it('should handle permissionsBoundary', () => { serverless.service.stepFunctions = { stateMachines: {