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/*"
...