@@ -908,6 +908,122 @@ describe('#compileIamRole', () => {
908
908
expect ( policy . PolicyDocument . Statement [ 0 ] . Resource [ 0 ] ) . to . equal ( '*' ) ;
909
909
} ) ;
910
910
911
+ it ( 'should give batch dynamodb permission for only tables referenced by state machine' , ( ) => {
912
+ const helloTable = 'hello' ;
913
+ const helloTableArn = {
914
+ 'Fn::Join' : [
915
+ ':' , [ 'arn' , { Ref : 'AWS::Partition' } , 'dynamodb' , { Ref : 'AWS::Region' } , { Ref : 'AWS::AccountId' } , 'table/hello' ] ,
916
+ ] ,
917
+ } ;
918
+ const worldTable = 'world' ;
919
+ const worldTableArn = {
920
+ 'Fn::Join' : [
921
+ ':' , [ 'arn' , { Ref : 'AWS::Partition' } , 'dynamodb' , { Ref : 'AWS::Region' } , { Ref : 'AWS::AccountId' } , 'table/world' ] ,
922
+ ] ,
923
+ } ;
924
+
925
+ const genStateMachine = ( id , tableName ) => ( {
926
+ id,
927
+ definition : {
928
+ StartAt : 'A' ,
929
+ States : {
930
+ A : {
931
+ Type : 'Task' ,
932
+ Resource : 'arn:aws:states:::aws-sdk:dynamodb:batchWriteItem' ,
933
+ Parameters : {
934
+ RequestItems : {
935
+ [ tableName ] : [ ] ,
936
+ } ,
937
+ } ,
938
+ Next : 'B' ,
939
+ } ,
940
+ B : {
941
+ Type : 'Task' ,
942
+ Resource : 'arn:aws:states:::aws-sdk:dynamodb:batchGetItem' ,
943
+ Parameters : {
944
+ RequestItems : {
945
+ [ tableName ] : { } ,
946
+ } ,
947
+ } ,
948
+ End : true ,
949
+ } ,
950
+ } ,
951
+ } ,
952
+ } ) ;
953
+ serverless . service . stepFunctions = {
954
+ stateMachines : {
955
+ myStateMachine1 : genStateMachine ( 'StateMachine1' , helloTable ) ,
956
+ myStateMachine2 : genStateMachine ( 'StateMachine2' , worldTable ) ,
957
+ } ,
958
+ } ;
959
+
960
+ serverlessStepFunctions . compileIamRole ( ) ;
961
+ const resources = serverlessStepFunctions . serverless . service
962
+ . provider . compiledCloudFormationTemplate . Resources ;
963
+ const policy1 = resources . StateMachine1Role . Properties . Policies [ 0 ] ;
964
+ const policy2 = resources . StateMachine2Role . Properties . Policies [ 0 ] ;
965
+
966
+ [ policy1 , policy2 ] . forEach ( ( policy ) => {
967
+ expect ( policy . PolicyDocument . Statement [ 0 ] . Action )
968
+ . to . be . deep . equal ( [
969
+ 'dynamodb:BatchWriteItem' ,
970
+ 'dynamodb:BatchGetItem' ,
971
+ ] ) ;
972
+ } ) ;
973
+
974
+ expect ( policy1 . PolicyDocument . Statement [ 0 ] . Resource )
975
+ . to . be . deep . equal ( [ helloTableArn ] ) ;
976
+ expect ( policy2 . PolicyDocument . Statement [ 0 ] . Resource )
977
+ . to . be . deep . equal ( [ worldTableArn ] ) ;
978
+ } ) ;
979
+
980
+ it ( 'should give batch dynamodb permission to * whenever RequestItems.$ is seen' , ( ) => {
981
+ const genStateMachine = id => ( {
982
+ id,
983
+ definition : {
984
+ StartAt : 'A' ,
985
+ States : {
986
+ A : {
987
+ Type : 'Task' ,
988
+ Resource : 'arn:aws:states:::aws-sdk:dynamodb:batchWriteItem' ,
989
+ Parameters : {
990
+ RequestItems : {
991
+ tableName : [ ] ,
992
+ } ,
993
+ } ,
994
+ Next : 'B' ,
995
+ } ,
996
+ B : {
997
+ Type : 'Task' ,
998
+ Resource : 'arn:aws:states:::aws-sdk:dynamodb:batchWriteItem' ,
999
+ Parameters : {
1000
+ 'RequestItems.$' : '$.requestItems' ,
1001
+ } ,
1002
+ End : true ,
1003
+ } ,
1004
+ } ,
1005
+ } ,
1006
+ } ) ;
1007
+
1008
+ serverless . service . stepFunctions = {
1009
+ stateMachines : {
1010
+ myStateMachine1 : genStateMachine ( 'StateMachine1' ) ,
1011
+ } ,
1012
+ } ;
1013
+
1014
+ serverlessStepFunctions . compileIamRole ( ) ;
1015
+ const policy = serverlessStepFunctions . serverless . service
1016
+ . provider . compiledCloudFormationTemplate . Resources . StateMachine1Role
1017
+ . Properties . Policies [ 0 ] ;
1018
+ expect ( policy . PolicyDocument . Statement [ 0 ] . Action )
1019
+ . to . be . deep . equal ( [ 'dynamodb:BatchWriteItem' ] ) ;
1020
+
1021
+ // even though some tasks target specific tables, because RequestItems.$ is used we
1022
+ // have to give broad permissions to allow execution to talk to whatever table
1023
+ // the input specifies
1024
+ expect ( policy . PolicyDocument . Statement [ 0 ] . Resource ) . to . equal ( '*' ) ;
1025
+ } ) ;
1026
+
911
1027
it ( 'should give Redshift Data permissions to * for safe actions' , ( ) => {
912
1028
serverless . service . stepFunctions = {
913
1029
stateMachines : {
0 commit comments