Skip to content

Commit 2e5c77b

Browse files
authored
Merge pull request #545 from akshaydk/master
feat: generate IAM policy for S3 when ItemReader is used
2 parents 6347598 + 907bda4 commit 2e5c77b

File tree

2 files changed

+72
-2
lines changed

2 files changed

+72
-2
lines changed

lib/deploy/stepFunctions/compileIamRole.js

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@ function getTaskStates(states) {
2020
}
2121
case 'Map': {
2222
const mapStates = state.ItemProcessor ? state.ItemProcessor.States : state.Iterator.States;
23-
return getTaskStates(mapStates);
23+
const taskStates = getTaskStates(mapStates);
24+
if (state.ItemReader) {
25+
taskStates.push(state.ItemReader);
26+
}
27+
return taskStates;
2428
}
2529
default: {
2630
return [];
@@ -395,10 +399,21 @@ function getEventBridgePermissions(state) {
395399
}
396400

397401
function getS3GetObjectPermissions(state) {
402+
const bucket = state.Parameters['Bucket.$'] ? state.Parameters['Bucket.$'] : state.Parameters.Bucket;
403+
const key = state.Parameters['Key.$'] ? state.Parameters['Key.$'] : state.Parameters.Key;
404+
405+
if (bucket.startsWith('$') && key.startsWith('$')) {
406+
return [{
407+
action: 's3:GetObject',
408+
resource: [
409+
'*',
410+
],
411+
}];
412+
}
398413
return [{
399414
action: 's3:GetObject',
400415
resource: [
401-
`arn:aws:s3:::${state.Parameters.Bucket}/${state.Parameters.Key}`,
416+
`arn:aws:s3:::${bucket}/${key}`,
402417
],
403418
}];
404419
}
@@ -514,6 +529,7 @@ function getIamPermissions(taskStates) {
514529
case 'arn:aws:states:::events:putEvents.waitForTaskToken':
515530
return getEventBridgePermissions(state);
516531

532+
case 'arn:aws:states:::s3:getObject':
517533
case 'arn:aws:states:::aws-sdk:s3:getObject':
518534
return getS3GetObjectPermissions(state);
519535

lib/deploy/stepFunctions/compileIamRole.test.js

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1363,6 +1363,60 @@ describe('#compileIamRole', () => {
13631363
.to.be.deep.equal([`arn:aws:s3:::${testBucket}/${world}`]);
13641364
});
13651365

1366+
it('should give s3:GetObject permission for only objects referenced by state machine with ItemReader', () => {
1367+
const testBucket = 'test-bucket';
1368+
const testKey = 'test-key';
1369+
1370+
const genStateMachine = (id, lambdaArn, bucket, key) => ({
1371+
id,
1372+
definition: {
1373+
StartAt: 'A',
1374+
States: {
1375+
A: {
1376+
Type: 'Map',
1377+
ItemProcessor: {
1378+
StartAt: 'B',
1379+
States: {
1380+
B: {
1381+
Type: 'Task',
1382+
Resource: lambdaArn,
1383+
End: true,
1384+
},
1385+
},
1386+
},
1387+
ItemReader: {
1388+
Resource: 'arn:aws:states:::s3:getObject',
1389+
Parameters: {
1390+
'Bucket.$': bucket,
1391+
'Key.$': key,
1392+
},
1393+
},
1394+
End: true,
1395+
},
1396+
},
1397+
},
1398+
});
1399+
1400+
serverless.service.stepFunctions = {
1401+
stateMachines: {
1402+
myStateMachine1: genStateMachine('StateMachine1',
1403+
'arn:aws:lambda:us-west-2:1234567890:function:foo', '$.testBucket', '$.testKey'),
1404+
myStateMachine2: genStateMachine('StateMachine2',
1405+
'arn:aws:lambda:us-west-2:1234567890:function:foo', testBucket, testKey),
1406+
},
1407+
};
1408+
1409+
serverlessStepFunctions.compileIamRole();
1410+
const resources = serverlessStepFunctions.serverless.service
1411+
.provider.compiledCloudFormationTemplate.Resources;
1412+
const policy1 = resources.StateMachine1Role.Properties.Policies[0];
1413+
const policy2 = resources.StateMachine2Role.Properties.Policies[0];
1414+
expect(policy1.PolicyDocument.Statement[1].Resource)
1415+
.to.be.deep.equal('*');
1416+
expect(policy2.PolicyDocument.Statement[1].Resource)
1417+
.to.be.deep.equal([`arn:aws:s3:::${testBucket}/${testKey}`]);
1418+
});
1419+
13661420
it('should not generate any permissions for Task states not yet supported', () => {
13671421
const genStateMachine = id => ({
13681422
id,

0 commit comments

Comments
 (0)