Skip to content

Commit

Permalink
Merge pull request #598 from vcarity/master
Browse files Browse the repository at this point in the history
feat: add support for step func sdk sync execution
  • Loading branch information
horike37 authored Dec 4, 2023
2 parents 9a78db4 + 0dfa798 commit f2f379d
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 0 deletions.
36 changes: 36 additions & 0 deletions lib/deploy/stepFunctions/compileIamRole.js
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,39 @@ function getStepFunctionsPermissions(state) {
}];
}

function getStepFunctionsSDKPermissions(state) {
let stateMachineArn = state.Mode === 'DISTRIBUTED' ? {
'Fn::Sub': [
`arn:aws:states:\${AWS::Region}:\${AWS::AccountId}:stateMachine:${state.StateMachineName}`,
{},
],
} : null;

if (!stateMachineArn) {
stateMachineArn = state.Parameters['StateMachineArn.$'] ? '*'
: state.Parameters.StateMachineArn;
}

return [{
action: 'states:StartSyncExecution',
resource: stateMachineArn,
}, {
action: 'states:DescribeExecution,states:StopExecution',
// this is excessive but mirrors behaviour in the console
// also, DescribeExecution supports executions as resources but StopExecution
// doesn't support resources
resource: '*',
}, {
action: 'events:PutTargets,events:PutRule,events:DescribeRule',
resource: {
'Fn::Sub': [
'arn:${AWS::Partition}:events:${AWS::Region}:${AWS::AccountId}:rule/StepFunctionsGetEventsForStepFunctionsExecutionRule',
{},
],
},
}];
}

function getCodeBuildPermissions(state) {
const projectName = state.Parameters.ProjectName;

Expand Down Expand Up @@ -640,6 +673,9 @@ function getIamPermissions(taskStates) {
case 'arn:aws:states:::states:startExecution.waitForTaskToken':
return getStepFunctionsPermissions(state);

case 'arn:aws:states:::aws-sdk:sfn:startSyncExecution':
return getStepFunctionsSDKPermissions(state);

case 'arn:aws:states:::codebuild:startBuild':
case 'arn:aws:states:::codebuild:startBuild.sync':
return getCodeBuildPermissions(state);
Expand Down
85 changes: 85 additions & 0 deletions lib/deploy/stepFunctions/compileIamRole.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2950,6 +2950,55 @@ describe('#compileIamRole', () => {
}]);
});

it('should give step functions using sdk permissions (too permissive, but mirrors console behavior)', () => {
const stateMachineArn = 'arn:aws:states:us-east-1:123456789:stateMachine:HelloStateMachine';
const genStateMachine = id => ({
id,
definition: {
StartAt: 'A',
States: {
A: {
Type: 'Task',
Resource: 'arn:aws:states:::aws-sdk:sfn:startSyncExecution',
Parameters: {
StateMachineArn: stateMachineArn,
Input: {},
},
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 stateMachinePermissions = statements.filter(s => _.isEqual(s.Action, ['states:StartSyncExecution']));
expect(stateMachinePermissions).to.have.lengthOf(1);
expect(stateMachinePermissions[0].Resource).to.deep.eq([stateMachineArn]);

const executionPermissions = statements.filter(s => _.isEqual(s.Action, ['states:DescribeExecution', 'states:StopExecution']));
expect(executionPermissions).to.have.lengthOf(1);
expect(executionPermissions[0].Resource).to.equal('*');

const eventPermissions = statements.filter(s => _.isEqual(s.Action, ['events:PutTargets', 'events:PutRule', 'events:DescribeRule']));
expect(eventPermissions).to.have.lengthOf(1);
expect(eventPermissions[0].Resource).to.deep.eq([{
'Fn::Sub': [
'arn:${AWS::Partition}:events:${AWS::Region}:${AWS::AccountId}:rule/StepFunctionsGetEventsForStepFunctionsExecutionRule',
{},
],
}]);
});

it('should give step functions permission to * whenever StateMachineArn.$ is seen', () => {
const stateMachineArn = 'arn:aws:states:us-east-1:123456789:stateMachine:HelloStateMachine';
const genStateMachine = id => ({
Expand Down Expand Up @@ -3004,6 +3053,42 @@ describe('#compileIamRole', () => {
expect(stateMachinePermissions[0].Resource).to.equal('*');
});

it('should give step functions using sdk permission to * whenever StateMachineArn.$ is seen', () => {
const genStateMachine = id => ({
id,
definition: {
StartAt: 'A',
States: {
A: {
Type: 'Task',
Resource: 'arn:aws:states:::aws-sdk:sfn:startSyncExecution',
Parameters: {
'StateMachineArn.$': '$.arn',
Input: {},
},
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 stateMachinePermissions = statements.filter(s => _.includes(s.Action, 'states:StartSyncExecution'));

expect(stateMachinePermissions).to.have.lengthOf(1);
expect(stateMachinePermissions[0].Resource).to.equal('*');
});

it('should support Map state type', () => {
const getStateMachine = (id, lambdaArn) => ({
id,
Expand Down

0 comments on commit f2f379d

Please sign in to comment.