Home > OS >  AWS DynamoDB user authorization
AWS DynamoDB user authorization

Time:09-21

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!

CodePudding user response:

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

CodePudding user response:

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!

  • Related