Skip to content

Commit f2f379d

Browse files
authored
Merge pull request #598 from vcarity/master
feat: add support for step func sdk sync execution
2 parents 9a78db4 + 0dfa798 commit f2f379d

File tree

2 files changed

+121
-0
lines changed

2 files changed

+121
-0
lines changed

lib/deploy/stepFunctions/compileIamRole.js

+36
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,39 @@ function getStepFunctionsPermissions(state) {
440440
}];
441441
}
442442

443+
function getStepFunctionsSDKPermissions(state) {
444+
let stateMachineArn = state.Mode === 'DISTRIBUTED' ? {
445+
'Fn::Sub': [
446+
`arn:aws:states:\${AWS::Region}:\${AWS::AccountId}:stateMachine:${state.StateMachineName}`,
447+
{},
448+
],
449+
} : null;
450+
451+
if (!stateMachineArn) {
452+
stateMachineArn = state.Parameters['StateMachineArn.$'] ? '*'
453+
: state.Parameters.StateMachineArn;
454+
}
455+
456+
return [{
457+
action: 'states:StartSyncExecution',
458+
resource: stateMachineArn,
459+
}, {
460+
action: 'states:DescribeExecution,states:StopExecution',
461+
// this is excessive but mirrors behaviour in the console
462+
// also, DescribeExecution supports executions as resources but StopExecution
463+
// doesn't support resources
464+
resource: '*',
465+
}, {
466+
action: 'events:PutTargets,events:PutRule,events:DescribeRule',
467+
resource: {
468+
'Fn::Sub': [
469+
'arn:${AWS::Partition}:events:${AWS::Region}:${AWS::AccountId}:rule/StepFunctionsGetEventsForStepFunctionsExecutionRule',
470+
{},
471+
],
472+
},
473+
}];
474+
}
475+
443476
function getCodeBuildPermissions(state) {
444477
const projectName = state.Parameters.ProjectName;
445478

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

676+
case 'arn:aws:states:::aws-sdk:sfn:startSyncExecution':
677+
return getStepFunctionsSDKPermissions(state);
678+
643679
case 'arn:aws:states:::codebuild:startBuild':
644680
case 'arn:aws:states:::codebuild:startBuild.sync':
645681
return getCodeBuildPermissions(state);

lib/deploy/stepFunctions/compileIamRole.test.js

+85
Original file line numberDiff line numberDiff line change
@@ -2950,6 +2950,55 @@ describe('#compileIamRole', () => {
29502950
}]);
29512951
});
29522952

2953+
it('should give step functions using sdk permissions (too permissive, but mirrors console behavior)', () => {
2954+
const stateMachineArn = 'arn:aws:states:us-east-1:123456789:stateMachine:HelloStateMachine';
2955+
const genStateMachine = id => ({
2956+
id,
2957+
definition: {
2958+
StartAt: 'A',
2959+
States: {
2960+
A: {
2961+
Type: 'Task',
2962+
Resource: 'arn:aws:states:::aws-sdk:sfn:startSyncExecution',
2963+
Parameters: {
2964+
StateMachineArn: stateMachineArn,
2965+
Input: {},
2966+
},
2967+
End: true,
2968+
},
2969+
},
2970+
},
2971+
});
2972+
2973+
serverless.service.stepFunctions = {
2974+
stateMachines: {
2975+
myStateMachine1: genStateMachine('StateMachine1'),
2976+
},
2977+
};
2978+
2979+
serverlessStepFunctions.compileIamRole();
2980+
const statements = serverlessStepFunctions.serverless.service
2981+
.provider.compiledCloudFormationTemplate.Resources.StateMachine1Role
2982+
.Properties.Policies[0].PolicyDocument.Statement;
2983+
2984+
const stateMachinePermissions = statements.filter(s => _.isEqual(s.Action, ['states:StartSyncExecution']));
2985+
expect(stateMachinePermissions).to.have.lengthOf(1);
2986+
expect(stateMachinePermissions[0].Resource).to.deep.eq([stateMachineArn]);
2987+
2988+
const executionPermissions = statements.filter(s => _.isEqual(s.Action, ['states:DescribeExecution', 'states:StopExecution']));
2989+
expect(executionPermissions).to.have.lengthOf(1);
2990+
expect(executionPermissions[0].Resource).to.equal('*');
2991+
2992+
const eventPermissions = statements.filter(s => _.isEqual(s.Action, ['events:PutTargets', 'events:PutRule', 'events:DescribeRule']));
2993+
expect(eventPermissions).to.have.lengthOf(1);
2994+
expect(eventPermissions[0].Resource).to.deep.eq([{
2995+
'Fn::Sub': [
2996+
'arn:${AWS::Partition}:events:${AWS::Region}:${AWS::AccountId}:rule/StepFunctionsGetEventsForStepFunctionsExecutionRule',
2997+
{},
2998+
],
2999+
}]);
3000+
});
3001+
29533002
it('should give step functions permission to * whenever StateMachineArn.$ is seen', () => {
29543003
const stateMachineArn = 'arn:aws:states:us-east-1:123456789:stateMachine:HelloStateMachine';
29553004
const genStateMachine = id => ({
@@ -3004,6 +3053,42 @@ describe('#compileIamRole', () => {
30043053
expect(stateMachinePermissions[0].Resource).to.equal('*');
30053054
});
30063055

3056+
it('should give step functions using sdk permission to * whenever StateMachineArn.$ is seen', () => {
3057+
const genStateMachine = id => ({
3058+
id,
3059+
definition: {
3060+
StartAt: 'A',
3061+
States: {
3062+
A: {
3063+
Type: 'Task',
3064+
Resource: 'arn:aws:states:::aws-sdk:sfn:startSyncExecution',
3065+
Parameters: {
3066+
'StateMachineArn.$': '$.arn',
3067+
Input: {},
3068+
},
3069+
End: true,
3070+
},
3071+
},
3072+
},
3073+
});
3074+
3075+
serverless.service.stepFunctions = {
3076+
stateMachines: {
3077+
myStateMachine1: genStateMachine('StateMachine1'),
3078+
},
3079+
};
3080+
3081+
serverlessStepFunctions.compileIamRole();
3082+
const statements = serverlessStepFunctions.serverless.service
3083+
.provider.compiledCloudFormationTemplate.Resources.StateMachine1Role
3084+
.Properties.Policies[0].PolicyDocument.Statement;
3085+
3086+
const stateMachinePermissions = statements.filter(s => _.includes(s.Action, 'states:StartSyncExecution'));
3087+
3088+
expect(stateMachinePermissions).to.have.lengthOf(1);
3089+
expect(stateMachinePermissions[0].Resource).to.equal('*');
3090+
});
3091+
30073092
it('should support Map state type', () => {
30083093
const getStateMachine = (id, lambdaArn) => ({
30093094
id,

0 commit comments

Comments
 (0)