skip to Main Content

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

Answers


  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

    Login or Signup to reply.
  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!

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search