CLOUGH
CLOUGH

Reputation: 741

AWS: Unable to use the "dynamodb:LeadingKeys" condition to control access to a GSI in DynamoDB

I have been referring to these blog articles from AWS to implement tenant data isolation in DynamoDB. I came up with the below IAM policy which is attached to the IAM Role going to be used to access the table I've created in DynamoDB.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Condition": {
                "ForAllValues:StringLike": {
                    "dynamodb:LeadingKeys": [
                        "tenant/t001/product/*"
                    ]
                }
            },
            "Action": "dynamodb:PutItem",
            "Resource": "arn:aws:dynamodb:<REGION>:<ACCOUNT-NUMBER>:table/<TABLE-NAME>",
            "Effect": "Allow"
        },
        {
            "Condition": {
                "ForAllValues:StringLike": {
                    "dynamodb:LeadingKeys": [
                        "tenant/t001/*"
                    ]
                }
            },
            "Action": "dynamodb:PutItem",
            "Resource": "arn:aws:dynamodb:<REGION>:<ACCOUNT-NUMBER>:table/<TABLE-NAME>/index/<INDEX-NAME>",
            "Effect": "Allow"
        }
    ]
}

With this, I was denied access to perform PutItem on the table when the value I passed for the Partition Key (PartKey1) of the table's Primary Key is NOT following the pattern tenant/t001/product/*. For example, I was denied access when I passed tenant/t002/product/p001 to PartKey1 as expected. Because I'm giving t002 as the tenant id, which should have been t001 to successfully perform PutItem.

But, it was not the same with the GSI. It simply accepts any value I pass into the Partition Key of the GSI (PartKey2).

Then I changed the dynamodb:PutItem action to dynamodb:Query ONLY in the second statement. So the new inline policy would look like this.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Condition": {
                "ForAllValues:StringLike": {
                    "dynamodb:LeadingKeys": [
                        "tenant/t001/product/*"
                    ]
                }
            },
            "Action": "dynamodb:PutItem",
            "Resource": "arn:aws:dynamodb:<REGION>:<ACCOUNT-NUMBER>:table/<TABLE-NAME>",
            "Effect": "Allow"
        },
        {
            "Condition": {
                "ForAllValues:StringLike": {
                    "dynamodb:LeadingKeys": [
                        "tenant/t001/*"
                    ]
                }
            },
            "Action": "dynamodb:Query",
            "Resource": "arn:aws:dynamodb:<REGION>:<ACCOUNT-NUMBER>:table/<TABLE-NAME>/index/<INDEX-NAME>",
            "Effect": "Allow"
        }
    ]
}

With this change, I was denied access (as expected) when I tried to query the GSI with a value that doesn't follow the pattern tenant/t001/*, for example, tenant/t002/product.

I couldn't think of any reason why would AWS allow the use of dynamodb:LeadingKeys (for a GSI) in conditions when it is dynamodb:Query but not with dynamodb:PutItem. Because why would we go into trouble of isolating tenant data in Query time, when we cannot isolate them during the insertion?

Am I missing something here?

AWS blog articles, documentations:

Upvotes: 1

Views: 679

Answers (1)

Charles
Charles

Reputation: 23793

You can't PutItem to GSI (or LSI) ...

So in your original policy

"Action": "dynamodb:PutItem",
"Resource": "arn:aws:dynamodb:<REGION>:<ACCOUNT-NUMBER>:table/<TABLE-NAME>/index/<INDEX-NAME>",
"Effect": "Allow"

Has zero effect...

Upvotes: 1

Related Questions