@@ -731,6 +731,58 @@ describe('#compileIamRole', () => {
731731 . to . be . deep . equal ( [ worldTableArn ] ) ;
732732 } ) ;
733733
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+
734786 it ( 'should give dynamodb permission to * whenever TableName.$ is seen' , ( ) => {
735787 const helloTable = 'hello' ;
736788
@@ -778,6 +830,84 @@ describe('#compileIamRole', () => {
778830 expect ( policy . PolicyDocument . Statement [ 0 ] . Resource ) . to . equal ( '*' ) ;
779831 } ) ;
780832
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+
781911 it ( 'should give Redshift Data permissions to * for safe actions' , ( ) => {
782912 serverless . service . stepFunctions = {
783913 stateMachines : {
0 commit comments