英文:
AWS: Unable to use the "dynamodb:LeadingKeys" condition to control access to a GSI in DynamoDB
问题
我一直在参考AWS的这些博客文章,以实现在DynamoDB中实现租户数据隔离。我制定了以下附加到用于访问我在DynamoDB中创建的表的IAM角色的IAM策略。
{
"Version": "2012-10-17",
"Statement": [
{
"Condition": {
"ForAllValues:StringLike": {
"dynamodb:LeadingKeys": [
"tenant/t001/product/*"
]
}
},
"Action": "dynamodb:PutItem",
"Resource": "arn:aws:dynamodb:<REGION>:<ACCOUNT-NUMBER>:table/<TABLE-NAME>",
"Effect": "Allow"
},
{
"Condition": {
"ForAllValues:StringLike": {
"dynamodb:LeadingKeys": [
"tenant/t001/*"
]
}
},
"Action": "dynamodb:PutItem",
"Resource": "arn:aws:dynamodb:<REGION>:<ACCOUNT-NUMBER>:table/<TABLE-NAME>/index/<INDEX-NAME>",
"Effect": "Allow"
}
]
}
使用此策略,当我传递给表的主键(PartKey1)的分区键的值不遵循tenant/t001/product/*
模式时,我被拒绝访问执行PutItem操作。例如,当我如预期地将t002
作为租户ID传递给PartKey1时,我被拒绝访问,而应该是t001
才能成功执行PutItem操作。
但是,在GSI上的情况不同。它简单地接受我传递给GSI的分区键(PartKey2)的任何值。
然后,我在第二个语句中将dynamodb:PutItem
操作更改为仅为dynamodb:Query
。因此,新的内联策略将如下所示。
{
"Version": "2012-10-17",
"Statement": [
{
"Condition": {
"ForAllValues:StringLike": {
"dynamodb:LeadingKeys": [
"tenant/t001/product/*"
]
}
},
"Action": "dynamodb:PutItem",
"Resource": "arn:aws:dynamodb:<REGION>:<ACCOUNT-NUMBER>:table/<TABLE-NAME>",
"Effect": "Allow"
},
{
"Condition": {
"ForAllValues:StringLike": {
"dynamodb:LeadingKeys": [
"tenant/t001/*"
]
}
},
"Action": "dynamodb:Query",
"Resource": "arn:aws:dynamodb:<REGION>:<ACCOUNT-NUMBER>:table/<TABLE-NAME>/index/<INDEX-NAME>",
"Effect": "Allow"
}
]
}
通过这个更改,当我尝试使用不遵循tenant/t001/*
模式的值查询GSI时,我被拒绝访问(如预期)。
我无法想出为什么AWS允许在dynamodb:Query
条件下使用dynamodb:LeadingKeys
(对于GSI),但在dynamodb:PutItem
条件下不允许。因为为什么我们会在插入时无法隔离租户数据的情况下,在查询时去麻烦隔离它们呢?
我有遗漏什么吗?
英文:
I have been referring to these blog articles from AWS to implement tenant data isolation in DynamoDB. I came up with the below IAM policy which is attached to the IAM Role going to be used to access the table I've created in DynamoDB.
{
"Version": "2012-10-17",
"Statement": [
{
"Condition": {
"ForAllValues:StringLike": {
"dynamodb:LeadingKeys": [
"tenant/t001/product/*"
]
}
},
"Action": "dynamodb:PutItem",
"Resource": "arn:aws:dynamodb:<REGION>:<ACCOUNT-NUMBER>:table/<TABLE-NAME>",
"Effect": "Allow"
},
{
"Condition": {
"ForAllValues:StringLike": {
"dynamodb:LeadingKeys": [
"tenant/t001/*"
]
}
},
"Action": "dynamodb:PutItem",
"Resource": "arn:aws:dynamodb:<REGION>:<ACCOUNT-NUMBER>:table/<TABLE-NAME>/index/<INDEX-NAME>",
"Effect": "Allow"
}
]
}
With this, I was denied access to perform PutItem on the table when the value I passed for the Partition Key (PartKey1) of the table's Primary Key is NOT following the pattern tenant/t001/product/*
. For example, I was denied access when I passed tenant/t002/product/p001
to PartKey1 as expected. Because I'm giving t002
as the tenant id, which should have been t001
to successfully perform PutItem.
But, it was not the same with the GSI. It simply accepts any value I pass into the Partition Key of the GSI (PartKey2).
Then I changed the dynamodb:PutItem
action to dynamodb:Query
ONLY in the second statement. So the new inline policy would look like this.
{
"Version": "2012-10-17",
"Statement": [
{
"Condition": {
"ForAllValues:StringLike": {
"dynamodb:LeadingKeys": [
"tenant/t001/product/*"
]
}
},
"Action": "dynamodb:PutItem",
"Resource": "arn:aws:dynamodb:<REGION>:<ACCOUNT-NUMBER>:table/<TABLE-NAME>",
"Effect": "Allow"
},
{
"Condition": {
"ForAllValues:StringLike": {
"dynamodb:LeadingKeys": [
"tenant/t001/*"
]
}
},
"Action": "dynamodb:Query",
"Resource": "arn:aws:dynamodb:<REGION>:<ACCOUNT-NUMBER>:table/<TABLE-NAME>/index/<INDEX-NAME>",
"Effect": "Allow"
}
]
}
With this change, I was denied access (as expected) when I tried to query the GSI with a value that doesn't follow the pattern tenant/t001/*
, for example, tenant/t002/product
.
I couldn't think of any reason why would AWS allow the use of dynamodb:LeadingKeys
(for a GSI) in conditions when it is dynamodb:Query
but not with dynamodb:PutItem
. Because why would we go into trouble of isolating tenant data in Query time, when we cannot isolate them during the insertion?
Am I missing something here?
AWS blog articles, documentations:
- https://aws.amazon.com/blogs/security/how-to-secure-your-saas-tenant-data-in-dynamodb-with-abac-and-client-side-encryption/
- https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/specifying-conditions.html
- https://aws.amazon.com/blogs/apn/partitioning-pooled-multi-tenant-saas-data-with-amazon-dynamodb/
答案1
得分: 1
你不能对 GSI(或 LSI)执行 PutItem
操作...
因此,在你的原始策略中:
"Action": "dynamodb:PutItem",
"Resource": "arn:aws:dynamodb:<REGION>:<ACCOUNT-NUMBER>:table/<TABLE-NAME>/index/<INDEX-NAME>",
"Effect": "Allow"
没有任何效果...
英文:
You can't PutItem
to GSI (or LSI) ...
So in your original policy
"Action": "dynamodb:PutItem",
"Resource": "arn:aws:dynamodb:<REGION>:<ACCOUNT-NUMBER>:table/<TABLE-NAME>/index/<INDEX-NAME>",
"Effect": "Allow"
Has zero effect...
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论