使用 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
我正在开发一项需要访问 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()
policy = json.dumps(policyTemplate).replace("{TENANTID}", tenantID)
return policy