0

currently I am working with AWS DynamoDB and I struggle with user authorization and restricting access to specific items inside of a DynamoDB Table. I have already read the documentation and came across multiple blog posts, but unfortunately I haven't found my use case yet.

Some background information:

Each user of the web app belongs to a company and each company has multiple orders. These orders are inside of the DynamoDB table "Orders". What I want to achieve is that the users can only read order items from the company they belong to.

My Approach

My idea was to create the "Orders" table with a partition key of "companyId" and a sort key of "orderId". During my research I figured out that I can restrict the access through IAM Policy roles, but I couldn't find a way to access the companyId of the user inside of the policy role. Users are authenticating through AWS Cognito.

My Question

How can I restrict the user access specific items inside of a DynamoDB? Taking into account the each user belongs to a company and should only see orders of this company.

Looking forward to some help!

2
  • Are you asking if dynamodb can limit access to a partition of data based on the current user's identity, like Row-Level Security in other database system, or are how to restrict access through code. Commented Sep 20, 2022 at 12:29
  • Hi @RossBush, yes correct, I want to setup something like Row-Level Security in other data base systems. E.g. a user that belongs to company A can only read order from DynamoDB Table "Orders" which have an attribute companyId: "company A". Commented Sep 20, 2022 at 12:40

2 Answers 2

2

AWS has published Isolating SaaS Tenants with Dynamically Generated IAM Policies blog on their website. This blog explains exactly the thing that you want to achieve.

In short, I can explain:

  1. Use CustomerId as PartitionKey

  2. Create an IAM policy with access on Orders table like below

    1 {
    2  "Version": "2012-10-17",
    3  "Statement": [
    4    {
    5      "Action": [
    6        "dynamodb:GetItem",
    7        "dynamodb:BatchGetItem",
    8        "dynamodb:Query",
    9        "dynamodb:DescribeTable"
    10      ],
    11      "Resource": "arn:aws:dynamodb:us-west-2:123456789012:table/Orders",
    12      "Effect": "Allow"
    13    }
    14  ]
    15 }
    
  3. Create a template for Session Policy where you will replace CustomerId with incoming request's customerId on runtime.

    1  {
    2    "Effect": "Allow",
    3    "Action": [
    4         "dynamodb:*"
    5    ],
    6    "Resource": [
    7         "arn:aws:dynamodb:*:*:table/{{table}}"
    8    ],
    9    "Condition": {
    10        "ForAllValues:StringEquals": {
    11            "dynamodb: LeadingKeys": [ "{{customerId}}" ]
    12        }
    13    }
    14 }
    
  4. Now, invoke STS (Security Token Service) with above IAM & Session policy to get temporary credentials that has access limited to a single tenant/customer data.

    Below is the pseudo code, you can use your programming language's SDK to write below code.

    AssumeRoleResponse response = sts.assumeRole (ar -> ar
         .webIdentityToken(openIdToken)
         .policy(scopedPolicy)
         .roleArn(role));
    Credentials tenantCredentials = response.credentials();
    DynamoDbClient dynamoDbClient = DynamoDbClient.builder()
         .credentialsProvider(tenantCredentials)
         .build();
    
  5. Finally, create DynamoDBClient object using these temporary credentials and use it. This object of DynamoDBClient will have access to only current user's customer data.

Hope this should help!

Sign up to request clarification or add additional context in comments.

Comments

1

Using custom attributes, you can create a backend layer that will check these parameters, query DynamoDB with the specified attribute, and return them - https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-settings-attributes.html

The second option is to set up role for each company - https://docs.aws.amazon.com/cognito/latest/developerguide/role-based-access-control.html#using-rules-to-assign-roles-to-users

4 Comments

Thanks for the quick reply! Regarding your first option: Do you have some more information! This is exactly where I struggle. Your approach, that each user will get a custom attribute, in my case companyId, right? Do you mean that I use this attribute inside of IAM User Policy?
@JatinMehrotra Yes I found this post, but it doesn't handle the issue that a user belongs to a group in our case a company and we have to checke for the company instead of the user id!
@ZabielskiGabriel I think I understood your approach for option 1. This would mean that I have to create a user pool for each company with a custom attribute e.g. "companyId", right?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.