使用Cognito实现DynamoDB的细粒度访问控制

3
我正在开发一个服务,需要访问DynamoDB表,必须通过授权用户访问该表来管理。账户管理由Cognito处理。目前我正在调查直接访问DynamoDB表的方法,基于用户组关联IAM策略来限制读写权限。
表中存在多个组织,多个用户与一个组织相关联。下面是一个模型示例。我还以一对多的方式存储了部门和行业信息。
用户的Cognito子标识存储为他们的用户ID,在USR#下存储在数据库中。
+-------+-------+-----------------+------------+--------+
|  PK   |  SK   |      Name       |   GSI1PK   | GSI2PK |
+-------+-------+-----------------+------------+--------+
| ORG#1 | ORG#1 | Acme Inc        |            |        |
| ORG#1 | USR#1 | John Doe        |            |        |
| ORG#2 | ORG#2 | Globetex        |            |        |
| ORG#2 | USR#2 | Jane Doe        |            |        |
| ORG#1 | SEC#1 | Sector A1       | ORG#1SEC#1 | SEC#1  |
| DEP#1 | DEP#1 | Human Resources | ORG#1SEC#1 | DEP#1  |
+-------+-------+-----------------+------------+--------+

目前我可以针对特定IAM策略中每个组织以硬编码的方式限制访问。 但是,这种方法不具有可扩展性。 如果存在一百个组织,则必须存在一百个用户组,并具有单独的策略。 以下是此策略的示例。

是否有任何方法创建一个利用自定义Cognito变量(例如“organization”)的IAM策略,使我能够创建仅限于以该组织开头的行的单个策略? 我无法使用以下代码使其正常工作。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "dynamodb:GetItem",
                "dynamodb:PutItem",
                "dynamodb:Query"
            ],
            "Resource": [
                "arn:aws:dynamodb:region:id:table/TableName"
            ],
            "Condition": {
                "ForAllValues:StringEquals": {
                    "dynamodb:LeadingKeys": [
                        "${cognito-identity.amazonaws.com:org}"
                    ]
                }
            }
        }
    ]
}

编辑说明:为了更清晰,我的问题是在验证过程中动态地将自定义Cognito变量插入IAM策略。

例如,用户A具有自定义Cognito属性custom:org = Acme,而用户B具有自定义Cognito属性custom:org = Globex。

如上所述的单个策略可以直接将此属性插入到策略中,因此一个策略可以用于多个不同组织的用户。

经过进一步的研究,我不确定是否完全可能,但如果有人尝试过类似的操作,我很乐意听取经验。

1个回答

2

我认为你很接近正确了,根据这篇文章的内容,应该使用StringLike而不是StringEquals

"Condition": {
              "ForAllValues:StringLike": {
                  "dynamodb:LeadingKeys": [
                      "{TENANTID}-*"
                  ]
              }

您可能还想阅读多租户SaaS存储策略白皮书。

编辑:我不认为静态策略能够实现您想要的功能。

然而,链接文章中的代码确实提供了“管理来自任何租户的用户访问权限”的功能。

关键点在于使用role/AccessDynamoWithTenantContext

    tenantPolicy = getPolicy(event['tenantID'])
    
    assumed_role = sts_client.assume_role(
        RoleArn="arn:aws:iam::<account-id>:role/AccessDynamoWithTenantContext",
        RoleSessionName="tenant-aware-product",
        Policy=tenantPolicy,
    )

getPolicy()中动态注入租户ID

policy = json.dumps(policyTemplate).replace("{TENANTID}", tenantID)

return policy

谢谢,你提供的链接非常有用。我还想引用这份文档,其中提供了使用Cognito用户池和IAM策略实现AWS多租户的示例。在AWS云上使用Amazon Cognito进行SaaS身份验证和隔离 - Adam
@Adam 不用谢。如果回答正确,请不要忘记将其标记为已接受的答案。 - Charles
不是贬低您的回答的有用性,但我认为它并没有完全解决我所寻找的问题。当我回头看时,我已经重新表述了我的问题,因为它不太清楚。这是我的错。我的想法是创建一个单一的IAM策略,可以注入存储在自定义Cognito属性中的租户ID,以供任何用户使用。然后,该策略可以管理来自任何租户的用户访问权限。经过更多的研究,我不确定这是否可能。无论如何,您提供的信息在多个方面都对我有所帮助。 - Adam
1
@Adam 我承认我从未实现过它,但是链接的文章似乎可以做到你想要的。请查看编辑。 - Charles
谢谢,我第一次完全误读了文章的那部分。我想补充一点,任何尝试这个的人都应该访问https://www.youtube.com/watch?v=4_csSXc_GNU观看它的实际操作。 - Adam

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接