Search code examples
amazon-web-servicesdictionaryamazon-dynamodbaccess-controlamazon-iam

DynamoDB Fine Grained Access to Map Items


I know there is the functionality to allow users to only Update certain fields of a record in DynamoDb in a policy, but is there a way to limit access to a field within a field containing a map? For example, I have a table similar to the following:

UserID [string] | Name [string] | Attributes [Map] |

Within the "attributes" map, I want to limit a user to be able to update only a certain column of the map, lets say "value" (if it were a map of just "hash" and "value" self-named columns). Similar to the following if it were a link for permissions:

arn:.../tables/TestTable/Attributes/Value

Is this possible?


Solution

  • From what I can tell of the documentation, no you cannot target specific keys within the map. So either you split those out into their own "fields" or you allow the user to modify the entire map.

    It is worth noting that in DynamoDB jargon Tables are collections of Items. Items are collections of Attributes. So to name an Attribute "Attributes" may lead to confusion.

    Anywho... I would recommend a model similar to the following where characteristics ;) are separate Item attributes:

    UserID [string]
    Name [string]
    Height [string]
    Weight [Float]
    Race [String]
    

    (I'm guessing at the user's characteristics)

    Here is a policy that would allow them to update only Height and Weight, and only on their own record based on UserID. Of course "users" in this regard would need to be federated in some way. For our purposes here I'm assuming you might use Web Identity Federation.

    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Sid": "AllowAccessToOnlyItemsMatchingUserID",
                "Effect": "Allow",
                "Action": [
                    "dynamodb:GetItem",
                    "dynamodb:BatchGetItem",
                    "dynamodb:Query",
                    "dynamodb:PutItem",
                    "dynamodb:UpdateItem",
                    "dynamodb:DeleteItem",
                    "dynamodb:BatchWriteItem"
                ],
                "Resource": [
                    "arn:aws:dynamodb:us-west-2:123456789012:table/Users"
                ],
                "Condition": {
                    "ForAllValues:StringEquals": {
                        "dynamodb:LeadingKeys": [
                            "${www.amazon.com:user_id}"
                        ],
                        "dynamodb:Attributes": [
                            "UserID",
                            "Height",
                            "Weight",
                            ...
                            <list other allowed to edit attributes here>
                        ]
                    },
                    "StringEqualsIfExists": {
                        "dynamodb:Select": "SPECIFIC_ATTRIBUTES"
                    }
                }
            }
        ]
    }
    

    Yes the user_id in ${www.amazon.com:user_id} is correct. It is part of a substitution variable

    From the documentation:

    • dynamodb:LeadingKeys – This condition key allows users to access only the items where the partition key value matches their user ID. This ID, ${www.amazon.com:user_id}, is a substitution variable. For more information about substitution variables, see Using Web Identity Federation.
    • dynamodb:Attributes – This condition key limits access to the specified attributes so that only the actions listed in the permissions policy can return values for these attributes. In addition, the StringEqualsIfExists clause ensures that the app must always provide a list of specific attributes to act upon and that the app can't request all attributes.