amazon-web-servicesamazon-dynamodbamazon-iam

How to get fine-grained access to DynamoDB working with assumed permissions?


I am trying to get fine-grained DynamoDB access working by assuming an IAM role using a policy to specify which rows my user can query, as per the documentation.

The problem is that the permissions I pass in when I assume the role do not appear to be getting applied.

My table has a single string hash key that is formatted {user-id}:{guid} and a global index on the user-id column.

The permission policy statement I want to apply looks like this:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "dynamodb:*"
      ],
      "Resource": [
        "arn:aws:dynamodb:*:*:table/my-dynamo-table"
      ],
      "Condition": {
        "ForAllValues:StringLike": {
          "dynamodb: LeadingKeys": [
            "leading-key:*"
          ]
        }
      }
    },
    {
      "Effect": "Allow",
      "Action": [
        "dynamodb:Query",
        "dynamodb:GetItem"
      ],
      "Resource": [
        "arn:aws:dynamodb:*:*:table/my-dynamo-table/index/*"
      ],
      "Condition": {
        "ForAllValues:StringEquals": {
          "dynamodb: LeadingKeys": [
            "leading-key"
          ]
        }
      }
    }
  ]
}

From the command line I assume my role like this:

aws sts assume-role 
   --role-arn arn:aws:iam::12345678:role/test-dynamodb-role 
   --role-session-name dynamo-cmd-line-test 
   --policy { \"Version\": \"2012-10-17\",\"Statement\": [{\"Effect\": \"Allow\",\"Action\": [\"dynamodb:*\"],\"Resource\": [\"arn:aws:dynamodb:*:*:table/my-dynamo-table\"],\"Condition\": {\"ForAllValues:StringLike\": {\"dynamodb: LeadingKeys\": [ \"leading-key:*\" ]}}},{\"Effect\": \"Allow\",\"Action\": [\"dynamodb:Query\", \"dynamodb:GetItem\"],\"Resource\": [\"arn:aws:dynamodb:*:*:table/my-dynamo-table/index/*\"],\"Condition\": {\"ForAllValues:StringEquals\": {\"dynamodb: LeadingKeys\": [ \"leading-key\" ]}}}] }

I save the returned credentials into my .aws/credentials file under [temp-sts] then I try to call dynamodb get-item:

aws dynamodb get-item --table-name my-dynamo-table --key "{ \"Id\": { \"S\": \"leading-key:93be7f8b-7c13-4248-1b28-ad2cf92b237f\"}}" --profile temp-sts

As things stand, with the IAM role created but no policies attached to it in the AWS IAM console, I get an error:

An error occurred (AccessDeniedException) when calling the GetItem operation: 
  User: arn:aws:sts::12345678:assumed-role/test-dynamo-role/dynamo-cmd-line-test is not authorized to perform: dynamodb:GetItem 
    on resource: arn:aws:dynamodb:region-1:123454321:table/my-dynamo-table 
    because no identity-based policy allows the dynamodb:GetItem action

In the AWS UI I can add a policy to the IAM role I am assuming to explicitly allow a GetItem action, but then it allows all queries, regardless of whether the leading-key matches at all.

How can I apply the permissions in my sts assume-role request policy to my assumed role?


Solution

  • After struggling with this for a lot longer I found the aws accessanalyzer validate-policy tool (documented here), which finally let me track down the problem: "dynamodb: LeadingKeys" should have been "dynamodb:LeadingKeys". With that resolved and a policy on the role being assumed to allow access to this dynamo database, I am able to assume the role and have queries limited to the correct subset of keys.