@@ -731,6 +731,58 @@ describe('#compileIamRole', () => {
731
731
. to . be . deep . equal ( [ worldTableArn ] ) ;
732
732
} ) ;
733
733
734
+ it ( 'should give dynamodb permission to index table whenever IndexName is provided' , ( ) => {
735
+ const helloTable = 'hello' ;
736
+
737
+ const genStateMachine = ( id , tableName ) => ( {
738
+ id,
739
+ definition : {
740
+ StartAt : 'A' ,
741
+ States : {
742
+ A : {
743
+ Type : 'Task' ,
744
+ Resource : 'arn:aws:states:::aws-sdk:dynamodb:query' ,
745
+ Parameters : {
746
+ TableName : tableName ,
747
+ } ,
748
+ Next : 'B' ,
749
+ } ,
750
+ B : {
751
+ Type : 'Task' ,
752
+ Resource : 'arn:aws:states:::aws-sdk:dynamodb:query' ,
753
+ Parameters : {
754
+ TableName : tableName ,
755
+ IndexName : 'GSI1' ,
756
+ } ,
757
+ End : true ,
758
+ } ,
759
+ } ,
760
+ } ,
761
+ } ) ;
762
+
763
+ serverless . service . stepFunctions = {
764
+ stateMachines : {
765
+ myStateMachine1 : genStateMachine ( 'StateMachine1' , helloTable ) ,
766
+ } ,
767
+ } ;
768
+
769
+ serverlessStepFunctions . compileIamRole ( ) ;
770
+ const policy = serverlessStepFunctions . serverless . service
771
+ . provider . compiledCloudFormationTemplate . Resources . StateMachine1Role
772
+ . Properties . Policies [ 0 ] ;
773
+
774
+ expect ( policy . PolicyDocument . Statement [ 0 ] . Action )
775
+ . to . be . deep . equal ( [ 'dynamodb:Query' ] ) ;
776
+
777
+ expect ( policy . PolicyDocument . Statement [ 0 ] . Resource [ 0 ] ) . to . be . deep . equal ( {
778
+ 'Fn::Join' : [ ':' , [ 'arn' , { Ref : 'AWS::Partition' } , 'dynamodb' , { Ref : 'AWS::Region' } , { Ref : 'AWS::AccountId' } , 'table/hello' ] ] ,
779
+ } ) ;
780
+
781
+ expect ( policy . PolicyDocument . Statement [ 0 ] . Resource [ 1 ] ) . to . be . deep . equal ( {
782
+ 'Fn::Join' : [ ':' , [ 'arn' , { Ref : 'AWS::Partition' } , 'dynamodb' , { Ref : 'AWS::Region' } , { Ref : 'AWS::AccountId' } , 'table/hello/index/GSI1' ] ] ,
783
+ } ) ;
784
+ } ) ;
785
+
734
786
it ( 'should give dynamodb permission to * whenever TableName.$ is seen' , ( ) => {
735
787
const helloTable = 'hello' ;
736
788
@@ -778,6 +830,84 @@ describe('#compileIamRole', () => {
778
830
expect ( policy . PolicyDocument . Statement [ 0 ] . Resource ) . to . equal ( '*' ) ;
779
831
} ) ;
780
832
833
+ it ( 'should give dynamodb permission to table/TableName/index/* when IndexName.$ is seen' , ( ) => {
834
+ const helloTable = 'hello' ;
835
+
836
+ const genStateMachine = ( id , tableName ) => ( {
837
+ id,
838
+ definition : {
839
+ StartAt : 'A' ,
840
+ States : {
841
+ A : {
842
+ Type : 'Task' ,
843
+ Resource : 'arn:aws:states:::aws-sdk:dynamodb:query' ,
844
+ Parameters : {
845
+ TableName : tableName ,
846
+ 'IndexName.$' : '$.myDynamicIndexName' ,
847
+ } ,
848
+ End : true ,
849
+ } ,
850
+ } ,
851
+ } ,
852
+ } ) ;
853
+
854
+ serverless . service . stepFunctions = {
855
+ stateMachines : {
856
+ myStateMachine1 : genStateMachine ( 'StateMachine1' , helloTable ) ,
857
+ } ,
858
+ } ;
859
+
860
+ serverlessStepFunctions . compileIamRole ( ) ;
861
+ const policy = serverlessStepFunctions . serverless . service
862
+ . provider . compiledCloudFormationTemplate . Resources . StateMachine1Role
863
+ . Properties . Policies [ 0 ] ;
864
+ expect ( policy . PolicyDocument . Statement [ 0 ] . Action )
865
+ . to . be . deep . equal ( [ 'dynamodb:Query' ] ) ;
866
+
867
+ // even though some tasks target specific indices, because IndexName.$ is used we
868
+ // have to give broad permissions to allow execution to talk to whatever index
869
+ // the input specifies
870
+ expect ( policy . PolicyDocument . Statement [ 0 ] . Resource [ 0 ] [ 'Fn::Join' ] [ 1 ] [ 5 ] ) . to . equal ( 'table/hello/index/*' ) ;
871
+ } ) ;
872
+
873
+ it ( 'should give dynamodb permission to table/* whenever TableName.$ and IndexName.$ are seen' , ( ) => {
874
+ const genStateMachine = id => ( {
875
+ id,
876
+ definition : {
877
+ StartAt : 'A' ,
878
+ States : {
879
+ A : {
880
+ Type : 'Task' ,
881
+ Resource : 'arn:aws:states:::aws-sdk:dynamodb:query' ,
882
+ Parameters : {
883
+ 'TableName.$' : '$.myDynamicTableName' ,
884
+ 'IndexName.$' : '$.myDynamicIndexName' ,
885
+ } ,
886
+ End : true ,
887
+ } ,
888
+ } ,
889
+ } ,
890
+ } ) ;
891
+
892
+ serverless . service . stepFunctions = {
893
+ stateMachines : {
894
+ myStateMachine1 : genStateMachine ( 'StateMachine1' ) ,
895
+ } ,
896
+ } ;
897
+
898
+ serverlessStepFunctions . compileIamRole ( ) ;
899
+ const policy = serverlessStepFunctions . serverless . service
900
+ . provider . compiledCloudFormationTemplate . Resources . StateMachine1Role
901
+ . Properties . Policies [ 0 ] ;
902
+ expect ( policy . PolicyDocument . Statement [ 0 ] . Action )
903
+ . to . be . deep . equal ( [ 'dynamodb:Query' ] ) ;
904
+
905
+ // even though some tasks target specific tables, because TableName.$ is used we
906
+ // have to give broad permissions to allow execution to talk to whatever table
907
+ // the input specifies
908
+ expect ( policy . PolicyDocument . Statement [ 0 ] . Resource [ 0 ] ) . to . equal ( '*' ) ;
909
+ } ) ;
910
+
781
911
it ( 'should give Redshift Data permissions to * for safe actions' , ( ) => {
782
912
serverless . service . stepFunctions = {
783
913
stateMachines : {
0 commit comments