Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DynamoDB multi-tenant IAM policy (sharing documents with other users)

I’m attempting to create a multi-tenant application with DynamoDB and Cognito. The documentation is pretty clear on how to implement fine-grained authorisation so that users can access only their own records, by adding a condition to the IAM access policy like so:

"Condition": {
                "ForAllValues:StringEquals": {
                    "dynamodb:LeadingKeys": [
                        "${cognito-identity.amazonaws.com:sub}"
                    ]
                 }
             }

This is great for allowing users to read & write their own records, when the Cognito user id is the hash key of the row, but I’m struggling with how to allow other users to have read only access to some records.

Take as an example my model for a student who has has multiple courses:

{
    “student_id”: “ABC-1234567”,
    “course_name”: “Statistics 101”,
    “tutors”: [“Cognito-sub-1”, “Cognito-sub-2”],
    “seminar_reviews”: [ 
        {
            “seminar_id”: “XXXYYY-12345”
            “date”: “2018-01-12”,
            “score”: “8”,
            “comments”: “Nice class!”  
        },
        {
            “seminar_id”: “ABCDEF-98765”
            “date”: “2018-01-25”,
            “score”: “3”,
            “comments”: “Boring.”  
        }
    ]
}

(Cognito-sub-1 is the Cognito id of a tutor)

With the policy conditions above applied to the user’s IAM role, the user could read & write this document since the hash key (student_id) is the Cognito id of the user.

I’d also like the tutors listed in the document to have read-only access to certain attributes, but I can’t find any examples of how this can be done. I know that I can’t use the dynamodb:LeadingKeys condition since tutors is not the hash key of the table. Can this be done if I set up a Global Secondary Index (GSI) that uses the list of tutors as the hash key?

If this can be done with an index, I assume that this would only allow read access to that index (since an index can’t allow write operations). Is there any alternative method to allow write access based on an attribute that is not the hash key?

Alternatively, can I use a longer string as the hash key, concatenating attributes like ”owner”: and ”read-only”: that contain lists of Cognito IDs and consume this within my policy to create a more fine-grained permissions model based only on the hash key? This assumes a policy can decode lists from a string, since DynamoDB does not allow a hash key to be a list, JSON object or similar.

I haven’t been able to find any resources that consider fine-grained access control beyond allowing users to read/write only their own records, so if anyone can direct me to some, that would be a great start.

like image 802
Harry Avatar asked May 23 '18 11:05

Harry


1 Answers

You can restrict access to specific attributes easily (just the attributes).

However, in order to achieve more fine-grained access patterns you'd have to either:

  • offload access control task to your code (e.g. Lambda)
  • or you could evaluate your access patterns (which is generally a good thing, however, it might be a little trickier) and model your data accordingly

Generally speaking, when designing NoSQL applications, you should always evaluate how you consume your data. They are usually tailored for specific use-case - unlike RDBMS, which allow very general queries regardless.

There's a nice example regarding modeling relational data in terms of DynamoDB available here

like image 143
mewa Avatar answered Nov 05 '22 03:11

mewa