Skip to content

Commit f55a547

Browse files
authored
Merge pull request #145 from theburningmonk/feature/restrict_iam
Restrict permissions given to the generated IAM role
2 parents a65c3dc + ced6a5b commit f55a547

File tree

3 files changed

+60
-5
lines changed

3 files changed

+60
-5
lines changed

lib/deploy/stepFunctions/compileIamRole.js

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,36 @@ const path = require('path');
66
module.exports = {
77
compileIamRole() {
88
const customRolesProvided = [];
9+
let functionArns = [];
910
this.getAllStateMachines().forEach((stateMachineName) => {
1011
const stateMachineObj = this.getStateMachine(stateMachineName);
1112
customRolesProvided.push('role' in stateMachineObj);
13+
14+
const stateMachineJson = JSON.stringify(stateMachineObj);
15+
const regex = new RegExp(/"Resource":"([a-z:#{}_\-.]*)"/gi);
16+
let match = regex.exec(stateMachineJson);
17+
while (match !== null) {
18+
functionArns.push(match[1]);
19+
match = regex.exec(stateMachineJson);
20+
}
1221
});
1322
if (_.isEqual(_.uniq(customRolesProvided), [true])) {
1423
return BbPromise.resolve();
1524
}
25+
functionArns = _.uniq(functionArns);
1626

17-
let iamRoleStateMachineExecutionTemplate = JSON.stringify(this.serverless.utils.readFileSync(
27+
let iamRoleStateMachineExecutionTemplate = this.serverless.utils.readFileSync(
1828
path.join(__dirname,
1929
'..',
2030
'..',
21-
'iam-role-statemachine-execution-template.json'))
31+
'iam-role-statemachine-execution-template.txt')
2232
);
33+
2334
iamRoleStateMachineExecutionTemplate =
24-
iamRoleStateMachineExecutionTemplate.replace('[region]', this.options.region)
25-
.replace('[PolicyName]', this.getStateMachinePolicyName());
35+
iamRoleStateMachineExecutionTemplate
36+
.replace('[region]', this.options.region)
37+
.replace('[PolicyName]', this.getStateMachinePolicyName())
38+
.replace('[functions]', JSON.stringify(functionArns));
2639

2740
const iamRoleStateMachineLogicalId = this.getiamRoleStateMachineLogicalId();
2841
const newIamRoleStateMachineExecutionObject = {

lib/deploy/stepFunctions/compileIamRole.test.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,4 +85,46 @@ describe('#compileIamRole', () => {
8585
.provider.compiledCloudFormationTemplate.Resources.IamRoleStateMachineExecution.Type
8686
).to.equal('AWS::IAM::Role');
8787
});
88+
89+
it('should give invokeFunction permission for only functions referenced by state machine', () => {
90+
const helloLambda = 'arn:aws:lambda:#{AWS::Region}:#{AWS::AccountId}:function:hello';
91+
const worldLambda = 'arn:aws:lambda:#{AWS::Region}:#{AWS::AccountId}:function:world';
92+
serverless.service.stepFunctions = {
93+
stateMachines: {
94+
myStateMachine1: {
95+
name: 'stateMachineBeta1',
96+
definition: {
97+
StartAt: 'Hello',
98+
States: {
99+
Hello: {
100+
Type: 'Task',
101+
Resource: helloLambda,
102+
End: true,
103+
},
104+
},
105+
},
106+
},
107+
myStateMachine2: {
108+
name: 'stateMachineBeta2',
109+
definition: {
110+
StartAt: 'World',
111+
States: {
112+
World: {
113+
Type: 'Task',
114+
Resource: worldLambda,
115+
End: true,
116+
},
117+
},
118+
},
119+
},
120+
},
121+
};
122+
123+
serverlessStepFunctions.compileIamRole();
124+
const policy = serverlessStepFunctions.serverless.service
125+
.provider.compiledCloudFormationTemplate.Resources.IamRoleStateMachineExecution
126+
.Properties.Policies[0];
127+
expect(policy.PolicyDocument.Statement[0].Resource)
128+
.to.be.deep.equal([helloLambda, worldLambda]);
129+
});
88130
});

lib/iam-role-statemachine-execution-template.json renamed to lib/iam-role-statemachine-execution-template.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
"Action": [
2525
"lambda:InvokeFunction"
2626
],
27-
"Resource": "*"
27+
"Resource": [functions]
2828
}
2929
]
3030
}

0 commit comments

Comments
 (0)