Skip to content

Commit

Permalink
feat: allow additive IAM role statements
Browse files Browse the repository at this point in the history
  • Loading branch information
taschmidt committed Aug 2, 2022
1 parent 20263c3 commit f985240
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 5 deletions.
14 changes: 10 additions & 4 deletions lib/deploy/stepFunctions/compileIamRole.js
Original file line number Diff line number Diff line change
Expand Up @@ -500,23 +500,29 @@ function getIamPermissions(taskStates) {
});
}

function getIamStatements(iamPermissions) {
function getIamStatements(iamPermissions, stateMachineObj) {
// when the state machine doesn't define any Task states, and therefore doesn't need ANY
// permission, then we should follow the behaviour of the AWS console and return a policy
// that denies access to EVERYTHING
if (_.isEmpty(iamPermissions)) {
if (_.isEmpty(iamPermissions) && _.isEmpty(stateMachineObj.iamRoleStatements)) {
return [{
Effect: 'Deny',
Action: '*',
Resource: '*',
}];
}

return iamPermissions.map(p => ({
const iamStatements = iamPermissions.map(p => ({
Effect: 'Allow',
Action: p.action.split(','),
Resource: p.resource,
}));

if (!_.isEmpty(stateMachineObj.iamRoleStatements)) {
iamStatements.push(...stateMachineObj.iamRoleStatements);
}

return iamStatements;
}

module.exports = {
Expand Down Expand Up @@ -551,7 +557,7 @@ module.exports = {

iamPermissions = consolidatePermissionsByAction(iamPermissions);
iamPermissions = consolidatePermissionsByResource(iamPermissions);
const iamStatements = getIamStatements(iamPermissions);
const iamStatements = getIamStatements(iamPermissions, stateMachineObj);

const iamRoleStateMachineExecutionTemplate = this.serverless.utils.readFileSync(
path.join(__dirname,
Expand Down
38 changes: 38 additions & 0 deletions lib/deploy/stepFunctions/compileIamRole.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,44 @@ describe('#compileIamRole', () => {
expectation(policy2, [fooLambda, barLambda]);
});

it('should add discrete iam role permissions', () => {
const iamRoleStatement = {
Effect: 'Allow',
Action: ['service:Action'],
Resource: ['arn:aws:item'],
};
const lambdaArn = 'arn:aws:lambda:123:*:function:hello';
serverless.service.stepFunctions = {
stateMachines: {
myStateMachine1: {
id: 'StateMachine1',
name: 'stateMachine1',
iamRoleStatements: [iamRoleStatement],
definition: {
StartAt: 'A',
States: {
A: {
Type: 'Task',
Resource: lambdaArn,
End: true,
},
},
},
},
},
};
serverlessStepFunctions.compileIamRole();
const policies = serverlessStepFunctions.serverless
.service.provider.compiledCloudFormationTemplate.Resources
.StateMachine1Role.Properties.Policies;
expect(policies).to.have.length(1);
const statements = policies[0].PolicyDocument.Statement;
expect(statements).to.have.length(2);
const [statement1, statement2] = statements;
expect(statement1.Action[0]).to.equal('lambda:InvokeFunction');
expect(statement2).to.be.deep.equal(iamRoleStatement);
});

it('should give sns:Publish permission for only SNS topics referenced by state machine', () => {
const helloTopic = 'arn:aws:sns:#{AWS::Region}:#{AWS::AccountId}:hello';
const worldTopic = 'arn:aws:sns:us-east-1:#{AWS::AccountId}:world';
Expand Down
11 changes: 10 additions & 1 deletion lib/deploy/stepFunctions/compileStateMachines.schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,14 @@ const tracingConfig = Joi.object().keys({
enabled: Joi.boolean().default(false),
});

const iamRoleStatements = Joi.array().items(
Joi.object({
Effect: Joi.string().valid('Allow', 'Deny'),
Action: [Joi.string(), Joi.array().items(Joi.string())],
Resource: [Joi.string(), Joi.array()],
}),
);

const id = Joi.string();
const tags = Joi.object();
const name = Joi.string();
Expand All @@ -75,6 +83,7 @@ const schema = Joi.object().keys({
loggingConfig,
tracingConfig,
inheritGlobalTags,
});
iamRoleStatements,
}).oxor('role', 'iamRoleStatements');

module.exports = schema;
15 changes: 15 additions & 0 deletions lib/deploy/stepFunctions/compileStateMachines.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1632,4 +1632,19 @@ describe('#compileStateMachines', () => {
.provider.compiledCloudFormationTemplate.Resources
.StateMachineBeta1.DeletionPolicy).to.equal('Retain');
});

it('should not allow both role and iamRoleStatements', () => {
serverless.service.stepFunctions = {
stateMachines: {
myStateMachine1: {
role: 'arn:aws:role',
iamRoleStatements: [],
definition: 'definition1',
},
},
validate: true,
};
// Definition is invalid and validate=true, should throw
expect(() => serverlessStepFunctions.compileStateMachines()).to.throw(Error);
});
});

0 comments on commit f985240

Please sign in to comment.