使用 Cognito 的 DynamoDB 细粒度访问

DynamoDB Fine Grain Access with Cognito

我正在开发一项需要访问 DynamoDB table 的服务,该服务必须通过授权用户访问 table 来管理。帐户管理由 Cognito 处理。我目前正在调查对 DynamoDB table 的直接访问,其中 read/write 访问受限,基于具有关联 IAM 策略的用户组。

table 中存在多个组织,多个用户绑定到一个组织。该模型的示例如下。我还以多对一关系存储部门和部门信息。

用户的 Cognito Sub 作为用户 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 变量的 IAM 策略,例如 'organization' 允许我创建一个单一的策略来限制仅访问与该组织相关的行?我无法使用下面的代码进行此操作。

{
    "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 将 custom:org = Acme 作为 Cognito 属性,用户 B 将 custom:org = Globex 作为其自定义 Cognito 属性。

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

经过进一步研究后,我不确定这是否可行,但如果有人有任何尝试此类事情的经验,我很乐意听到。

我认为你很接近,根据 this article 应该是 StringLike 而不是 StringEquals

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

可能还想阅读 Multi-tenant SaaS Storage Strategies 白皮书

编辑 我不相信静态策略可以为所欲为。

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

重点是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()

中tenentId的动态注入
policy = json.dumps(policyTemplate).replace("{TENANTID}", tenantID)

return policy