How can I create a policy in DynamoDB, which allows the corresponding IAM users to modify just a subset of the documents in a table?
For example, let's say there is an attribute published,
and I want this IAM user to perform PutItem and UpdateItem
on documents which have published: false.
You can only use DynamoDB Fine-Grained Access Control on the hash key value. You could save an item with "draft" pre-pended to the hash-key value and use the following policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"dynamodb:UpdateItem",
],
"Resource": [
"arn:aws:dynamodb:REGION:ACCOUNT_NUMBER:table/TABLE_NAME"
],
"Condition": {
"ForAllValues:StringLike": {
"dynamodb:LeadingKeys": ["draft*"],
}
}
}
]
}
Adapted from https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/FGAC_DDB.html
Related
Here is the portion of my ARM file about the database:
{
"type": "Microsoft.Sql/servers/databases",
"name": "[concat(variables('SqlServerName'), '/', variables('dbName'))]",
"tags": {
"displayName": "Database"
},
"location": "[resourceGroup().location]",
"apiVersion": "2020-02-02-preview",
"dependsOn": [
"[resourceId('Microsoft.Sql/servers', variables('SqlServerName'))]"
],
"properties": {
"collation": "[parameters('dbCollation')]",
"edition": "[parameters('dbEdition')]",
"maxSizeBytes": "53687091200",
"requestedServiceObjectiveName": "[parameters('dbRequestedServiceObjectiveName')]"
}
}
And here my parameters:
"dbEdition": {
"value": "Standard"
},
"dbRequestedServiceObjectiveName": {
"value": "S2"
}
But these database properties are ignored and the deployed database doesn't respect them.
What's wrong?
UPDATE
As #SwathiDhanwada pointed out in comments, the edition property may not exist as per the doc.
I should use sku defined like:
Yet the powershell script to get a list of available skus for a given location returns something like:
The headers of the table are not the same as the properties of the sku object 🤦♂️
As a CosmosDB (SQL API) user I would like to index all non object or array properties inside of an object.
By default the index in cosmos /* will index every property, our data set is getting extremely large (expensive) and this strategy is no longer optimal. We store our metadata at the root and our customer data wrapped inside of an object property data.
Our platform restricts queries on the data path to be value type properties, this means that for us to index objects and arrays nested under the data path is just slowing down writes and costing RUs to store but never getting used.
I have tried several iterations of index policies but cannot find one that fits. Example:
{
"partitionKey": "f402a704-19bb-4f4d-93e6-801c50280cf6",
"id": "4a7a11e5-00b5-4def-8e80-132a8c083f24",
"data": {
"country": "Belgium",
"employee": 250,
"teammates": [
{ "name": "Jake", "id": 123 ...},
{ "name": "kyle", "id": 3252352 ...}
],
"user": {
"name": "Brian",
"addresses": [{ "city": "Moscow" ...}, { "city": "Moscow" ...}]
}
}
}
In this case I want to only index the root properties as well as /data/employee and /data/country.
Policies like /data/* will not work because it would then index /data/teammates/name ... and so on.
/data/? => assumes data is a value type which it never will be so this doesn't work.
/data/ and /data/*/? and /data/*? are not accepted by cosmos as valid policies.
Additionally I can't simply exclude /data/teammates/ and /data/user/ because what is inside of data is completely dynamic so while that might cover this use case there are several 100k others that it would not.
I have tried many iterations but it seems that options don't work for various reasons, is there a way to support what I am trying to do?
This indexing policy will index the properties you are asking for.
{
"indexingMode": "consistent",
"automatic": true,
"includedPaths": [
{
"path": "/partitionKey/?"
},
{
"path": "/data/country/?"
},
{
"path": "/data/employee/?"
}
],
"excludedPaths": [
{
"path": "/*"
}
]
}
Suppose I've the following data in my container:
{
"id": "1DBF704E-1623-4844-DC86-EFA729A5C048",
"firstName": "Wylie",
"lastName": "Ramsey",
"country": "AZ",
"city": "Tucson"
}
Where I use the field "id" as the item id, and the field "country" as the partition key, when I query on specific partition key:
SELECT * FROM c WHERE c.country = "AZ"
(get all the people in "AZ")
Should I add "country" as an index or I will get it by default, since I declered "country" as my partition key?
Is there a diference when using the SDK (meaning: adding the new PartitionKey("AZ") option and then sending the query as mentioned above)?
I created a collection with 50,000 records and disabled indexing on all properties.
Indexing policy:
{
"indexingMode": "consistent",
"automatic": true,
"includedPaths": [], // Included nothing
"excludedPaths": [
{
"path": "/\"_etag\"/?"
},
{
"path": "/*" // Exclude all paths
}
]
}
Querying by id cost 2.85 RUs.
Querying by PartitionKey cost 580 RUs.
Indexing policy with PartitionKey (country) added:
{
"indexingMode": "consistent",
"automatic": true,
"includedPaths": [
{
"path": "/country/*"
}
],
"excludedPaths": [
{
"path": "/\"_etag\"/?"
},
{
"path": "/*" // Exclude all paths
}
]
}
Adding an index on the PartitionKey brought it down to 2.83 RUs.
So the answer to this is Yes, if you have disabled default indexing policies and need to search by partition key then you should add an index to it.
In my opinion, it's a good practice to query with partition key in cosmosdb sql api, here's the offical doc related to it.
By the way, cosmosdb sql api indexes all the properties by default. If you'd like to cover the default setting and customise the indexing policy, this doc may provide more details.
I am trying to create a DDB policy whereby the Cognito user id (sub) should be equal to the DynamoDB table name. The table name in DDB is the user's id (sub).
So the policy should limit access to the user's table for that user only.
Below is a pseudo policy I have created.
What is unclear to me is how do I specify that the user id ( sub ) should be equal to the DDB table name ?
{
"Version": "2020-11-01",
"Statement": [
{
"Sid": "xxxxxxxxxxxxxx",
"Effect": "Allow",
"Action": [
"dynamodb:Scan",
"dynamodb:Query",
],
"Resource": [ "arn:aws:dynamodb:<REGION>:<ACCOUNT_ID>:table/<${www.amazon.com:user_id}>"]
}
DDB TABLE NAME SHOULD MATCH USER ID HERE ${www.amazon.com:user_id}
]
}
Unfortunately you cannot currently do it with DynamoDB. This is because the table resource for DynamoDB does no support any condition keys (see https://docs.aws.amazon.com/service-authorization/latest/reference/list_amazondynamodb.html#amazondynamodb-resources-for-iam-policies).
The only thing you could possibly do is to limit access per leading keys using the dynamodb:LeadingKeys condition. This again would only work for the Query action. Does not work on Scan (obviously). Your policy would then look something like this:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"dynamodb:GetItem",
"dynamodb:Query"
],
"Resource": ["arn:aws:dynamodb:*:*:table/MyTable"],
"Condition": {
"ForAllValues:StringEquals": {
"dynamodb:LeadingKeys": ["${cognito-identity.amazonaws.com:sub}"]
}
}
}
]
}
Can I apply a policy to an AWS DynamoDB table but restrict it based on the Cognito ID of the user accessing it?
E.g. A Customer table has a primary hash key equal to the Cognito ID. When anyone but the user sharing the same ID tries to get the item they will receive an unauthorised exception.
(Non DynanoDB policies are probably also valid.)
You should be able to do something like this using the same techniques as those for using an ID Provider. You should use the Cognito identifier as the key in the policy:
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": [
"dynamodb:DeleteItem",
"dynamodb:GetItem",
"dynamodb:PutItem",
"dynamodb:Query"
],
"Resource": ["arn:aws:dynamodb:REGION:123456789012:table/UserData"],
"Condition": {
"ForAllValues:StringEquals": {
"dynamodb:LeadingKeys": ["${cognito-identity.amazonaws.com:sub}"]}
}
}]
}