Skip to content

Commit 5ba6f2c

Browse files
authored
Merge pull request #165 from theburningmonk/feature/fix_empty_perms
fix generated IAM role when there are no Task states
2 parents a32a49d + 4ca4a5c commit 5ba6f2c

File tree

2 files changed

+64
-13
lines changed

2 files changed

+64
-13
lines changed

lib/deploy/stepFunctions/compileIamRole.js

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,25 @@ function getIamPermissions(serverless, taskStates) {
198198
});
199199
}
200200

201+
function getIamStatements(iamPermissions) {
202+
// when the state machine doesn't define any Task states, and therefore doesn't need ANY
203+
// permission, then we should follow the behaviour of the AWS console and return a policy
204+
// that denies access to EVERYTHING
205+
if (_.isEmpty(iamPermissions)) {
206+
return [{
207+
Effect: 'Deny',
208+
Action: '*',
209+
Resource: '*',
210+
}];
211+
}
212+
213+
return iamPermissions.map(p => ({
214+
Effect: 'Allow',
215+
Action: p.action.split(','),
216+
Resource: p.resource,
217+
}));
218+
}
219+
201220
module.exports = {
202221
compileIamRole() {
203222
const customRolesProvided = [];
@@ -223,11 +242,7 @@ module.exports = {
223242
iamPermissions = consolidatePermissionsByAction(iamPermissions);
224243
iamPermissions = consolidatePermissionsByResource(iamPermissions);
225244

226-
const iamStatements = iamPermissions.map(p => ({
227-
Effect: 'Allow',
228-
Action: p.action.split(','),
229-
Resource: p.resource,
230-
}));
245+
const iamStatements = getIamStatements(iamPermissions);
231246

232247
const iamRoleJson =
233248
iamRoleStateMachineExecutionTemplate

lib/deploy/stepFunctions/compileIamRole.test.js

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,14 @@ describe('#compileIamRole', () => {
2424
serverlessStepFunctions = new ServerlessStepFunctions(serverless, options);
2525
});
2626

27+
const expectDenyAllPolicy = (policy) => {
28+
const statements = policy.PolicyDocument.Statement;
29+
expect(statements).to.have.lengthOf(1);
30+
expect(statements[0].Effect).to.equal('Deny');
31+
expect(statements[0].Action).to.equal('*');
32+
expect(statements[0].Resource).to.equal('*');
33+
};
34+
2735
it('should do nothing when role property exists in all statmachine properties', () => {
2836
serverless.service.stepFunctions = {
2937
stateMachines: {
@@ -243,7 +251,7 @@ describe('#compileIamRole', () => {
243251
const policy = serverlessStepFunctions.serverless.service
244252
.provider.compiledCloudFormationTemplate.Resources.IamRoleStateMachineExecution
245253
.Properties.Policies[0];
246-
expect(policy.PolicyDocument.Statement).to.have.lengthOf(0);
254+
expectDenyAllPolicy(policy);
247255
});
248256

249257
it('should give sqs:SendMessage permission for only SQS referenced by state machine', () => {
@@ -362,7 +370,7 @@ describe('#compileIamRole', () => {
362370
const policy = serverlessStepFunctions.serverless.service
363371
.provider.compiledCloudFormationTemplate.Resources.IamRoleStateMachineExecution
364372
.Properties.Policies[0];
365-
expect(policy.PolicyDocument.Statement).to.have.lengthOf(0);
373+
expectDenyAllPolicy(policy);
366374
});
367375

368376
it('should not give sqs:SendMessage permission if QueueUrl is invalid', () => {
@@ -789,10 +797,10 @@ describe('#compileIamRole', () => {
789797
};
790798

791799
serverlessStepFunctions.compileIamRole();
792-
const statements = serverlessStepFunctions.serverless.service
800+
const policy = serverlessStepFunctions.serverless.service
793801
.provider.compiledCloudFormationTemplate.Resources.IamRoleStateMachineExecution
794-
.Properties.Policies[0].PolicyDocument.Statement;
795-
expect(statements).to.have.lengthOf(0);
802+
.Properties.Policies[0];
803+
expectDenyAllPolicy(policy);
796804
});
797805

798806
it('should not generate any permissions for Task states not yet supported', () => {
@@ -818,9 +826,37 @@ describe('#compileIamRole', () => {
818826
};
819827

820828
serverlessStepFunctions.compileIamRole();
821-
const statements = serverlessStepFunctions.serverless.service
829+
const policy = serverlessStepFunctions.serverless.service
822830
.provider.compiledCloudFormationTemplate.Resources.IamRoleStateMachineExecution
823-
.Properties.Policies[0].PolicyDocument.Statement;
824-
expect(statements).to.have.lengthOf(0);
831+
.Properties.Policies[0];
832+
expectDenyAllPolicy(policy);
833+
});
834+
835+
it('should generate a Deny all statement if state machine has no tasks', () => {
836+
const genStateMachine = (name) => ({
837+
name,
838+
definition: {
839+
StartAt: 'A',
840+
States: {
841+
A: {
842+
Type: 'Pass',
843+
End: true,
844+
},
845+
},
846+
},
847+
});
848+
849+
serverless.service.stepFunctions = {
850+
stateMachines: {
851+
myStateMachine1: genStateMachine('stateMachineBeta1'),
852+
myStateMachine2: genStateMachine('stateMachineBeta2'),
853+
},
854+
};
855+
856+
serverlessStepFunctions.compileIamRole();
857+
const policy = serverlessStepFunctions.serverless.service
858+
.provider.compiledCloudFormationTemplate.Resources.IamRoleStateMachineExecution
859+
.Properties.Policies[0];
860+
expectDenyAllPolicy(policy);
825861
});
826862
});

0 commit comments

Comments
 (0)