dynamodb:UpdateItem Vertical Access Control: Things to keep in mind

Priyank Rupareliya
2 min readMay 22, 2024

--

As simple as you may think it’d be, I came across a lot of “gotchas” when trying to provide a simple column-level access control for my dynamo db table.

Let’s take a simple example.

Let’s say you’ve a table called products with 4 columns:

  1. product_id (Partition Key)
  2. product_name (String)
  3. product_store_id (String)
  4. product_metadata (map)

The JSON representation should look like this:

{
"product_id": "123",
"product_name": "tomatoes",
"product_store_id": "walmart_44556",
"product_metadata":{
"price_history": {
"2002": 100,
"2003": 110
}
}
}

Now, you want people with Role A to only perform dynamodb:UpdateItem on product_name column.

Here’s the policy you’d attach to your Role A to achieve this:

{
"Version":"2012-10-17",
"Statement":[
{
"Sid":"PolicySid1",
"Effect":"Allow",
"Action":[
"dynamodb:UpdateItem"
],
"Resource":[
"arn:aws:dynamodb:us-east-1:123456789012:table/products"
],
"Condition":{
"ForAllValues:StringEquals":{
"dynamodb:Attributes":[
"product_id",
"product_name"
]
}
}
}
]
}

Your update expression should look something like this (using aws-sdk for javascript):

// Load the AWS SDK for Node.js
const AWS = require('aws-sdk');

// Set the region
AWS.config.update({ region: 'us-east-1' });

// Create DynamoDB document client
const docClient = new AWS.DynamoDB.DocumentClient();

// Define the parameters for the update operation
const params = {
TableName: 'products',
Key: {
'product_id': '123' // Replace with the primary key of the item you want to update
},
UpdateExpression: 'set product_name = :newName',
ExpressionAttributeValues: {
':newName': 'Apples' // Replace with the new product name
},
ReturnValues: 'UPDATED_NEW'
};

// Perform the update operation
docClient.update(params, (err, data) => {
if (err) {
console.error("Unable to update item. Error JSON:", JSON.stringify(err, null, 2));
} else {
console.log("Update succeeded:", JSON.stringify(data, null, 2));
}
});

Here are some gotchas that you need to keep in mind:

  1. You always need your partition-key to be present in the dynamodb:Attributes for the policy to work. I did not have it initially, neither was it specified anywhere in the docs which made me go crazy.
  2. Policy will not work with level 1+ updates. Eg. If ,you want your policy to allow a user to update only product_metadata.price_history, AWS does not support it. You will only be able to implement access control on parent properties of the table.

Priyank Rupareliya is a Senior Software Engineer focused on architecting solutions revolving around Cloud, DevOps, Containerization, Backend and Frontend.

--

--

Priyank Rupareliya
Priyank Rupareliya

Written by Priyank Rupareliya

AWS certified, senior engineer @AT&T. Building reliable, secure and scalable web applications. https://www.linkedin.com/in/priyank-rupareliya-9a562b157/

No responses yet