3

My users have Cognito accounts.

According to this article we can restrict access to the DynamoDB API with policy like that:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "dynamodb:GetItem",
                "dynamodb:PutItem",
                "dynamodb:Query"
            ],
            "Resource": [
                "arn:aws:dynamodb: <REGION>:<AWS_ACCOUNT_ID>:table/<TABLE>"
            ],
            "Condition": {
                "ForAllValues:StringEquals": {
                    "dynamodb:LeadingKeys": [
                        "${cognito-identity.amazonaws.com:sub}"
                    ]
                }
            }
        }
    ]
}

Looks pretty straightforward for my case when index key is email (and primary sort key is utc), so I adjusted example above to this one:

    {
        "Effect": "Allow",
        "Action": "dynamodb:UpdateItem",
        "Resource": "arn:aws:dynamodb:us-east-1:123456789123:table/history",
        "Condition": {
            "ForAllValues:StringEquals": {
                "dynamodb:LeadingKeys": [
                    "${cognito-identity.amazonaws.com:email}"
                ],
                "dynamodb:Attributes": [
                    "email",
                    "utc",
                    "updated",
                    "isNew"
                ]
            }
        }

But I keep getting the error AccessDeniedException: User: arn:aws:sts::9876543210:assumed-role/policyname/CognitoIdentityCredentials is not authorized to perform: dynamodb:UpdateItem on resource: arn:aws:dynamodb:us-east-1:123456789123:table/history.

I tried my js http call with * permissions and it works, so pitfall only with this policy.

Vitaly Zdanevich
  • 13,032
  • 8
  • 47
  • 81

2 Answers2

2

In this thread I found that I can use
${cognito-idp.us-east-1.amazonaws.com:sub}
This is not email but in future I can list users with this sub.

Vitaly Zdanevich
  • 13,032
  • 8
  • 47
  • 81
  • Did you make anything special to get the ${cognito-idp.us-east-1.amazonaws.com:sub} working? I have an IdToken from a Cognito User Pool that is send to an ApiGateway with Cognito Authorizer. The mapping template works for setting the user sub as part of the message that is send to dynamodb, but the policy which checks if the user is allowed to write to the row using the ${cognito-idp.us-east-1.amazonaws.com:sub} is not working. If a hardcore it to the sub of the user everything works. So it must be this expression does not return anything or something wrong... – TheCutter Jun 27 '19 at 19:44
  • I have the same issue where I'm getting denied writing with the UserPool Id to Dynamodb with the IAM leading keys policy being either ${cognito-idp.us-east-1.amazonaws.com:sub} or ${cognito-idp.us-east-1.amazonaws.com/us-east-1_XXXX:sub} – Jonathan Dunlap Oct 11 '19 at 18:38
  • I've got an answer from an AWS Dev Member regarding this topic. Have a look here: https://forums.aws.amazon.com/thread.jspa?threadID=305485 – TheCutter Nov 04 '19 at 07:25
1

${cognito-identity.amazonaws.com:email} is not a valid policy variable. It's not resolving to your users' email addresses.

It is a shame as most developers, like yourself, would find the users email address more intuitive than using cognito-identity.amazonaws.com:sub or cognito-identity.amazonaws.com:aud.

Reza Owliaei
  • 3,293
  • 7
  • 35
  • 55
F_SO_K
  • 13,640
  • 5
  • 54
  • 83
  • I thought that email address is a good unique identity of a user. Hmm, now I need to create a new table with another hash key or use API Gateway with Lambda :( – Vitaly Zdanevich Jan 15 '18 at 12:17
  • Exactly. Maybe raise this in AWS support too. Maybe they will add the feature one day. – F_SO_K Jan 15 '18 at 13:24