DynamoDB w/ Serverless, using Fn::GetRef to reference global secondary index

I found a better answer than was posted by jake.lang. EDIT: I didn't see his second comment in which he suggested the following.

As he noted, his was incorrect since the ARN can change for valid reasons. However, the solution arose because the ARN for a Global Secondary Index is to append "/INDEXNAME" to the ARN for the table. This means the policy statement can be:

iamRoleStatements:
  - Effect: Allow
    Action:
      - dynamodb:Query
      - dynamodb:Scan
      - dynamodb:GetItem
      - dynamodb:PutItem
      - dynamodb:UpdateItem
      - dynamodb:DeleteItem
    Resource:
      - { "Fn::GetAtt": ["MessagesDynamoDBTable", "Arn" ] }
      - { "Fn::Join": [ "/", [ 
          { "Fn::GetAtt": ["MessagesDynamoDBTable", "Arn" ] }, "index", "roomIndex" 
        ]]}
      - { "Fn::Join": [ "/", [
          { "Fn::GetAtt": ["MessagesDynamoDBTable", "Arn" ] }, "index", "userIndex" 
        ]]}

The "Fn::Join" bit is from CloudFormation, and is a "join" operation. It takes an array of strings, concatenating them using the first argument. Hence it is a rather convoluted and overly complex method to calculate the ARN's required in this policy statement.

For documentation, see: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-join.html


Instead of Fn::Join you can use !Sub "${MessagesDynamoDBTable.Arn}", it's simpler. Moreover if you want to access all indexes (that's usually my case), then /index/* is all you need.

Example:

...
      Policies:
        - Version: "2012-10-17"
          Statement:
            - Effect: Allow
              Action:
                - dynamodb:Query
              Resource:
                - !Sub "${MessagesDynamoDBTable.Arn}"
                - !Sub "${MessagesDynamoDBTable.Arn}/index/*"
...