Cognito身份池-使用";动态";属性进行基于属性的访问控制 [英] Cognito Identity Pools - Attribute-based access control with "dynamic" attributes
问题描述
我在Cognito用户池中有数百个S3存储桶和几十个用户。我希望能够选择哪个用户可以访问哪个S3存储桶,例如:
user_a
可以访问bucket_1
、bucket_2
、bucket_3
user_b
可以访问bucket_2
user_c
可以访问bucket_1
、bucket_4
以此类推。
我希望能够做到这一点,而无需创建创建动态策略的专用API。我考虑过使用Cognito身份池和基于属性的访问控制。
有is a cool example,其中用户获得一个属性"department": "legal"
,然后被分配一个角色,该角色仅允许查询带有-legal
后缀的存储桶,这要归功于${aws:PrincipalTag/department}
魔术。
如果我的用户只访问一个存储桶,那将是一个解决方案。但是,在我的情况下,一个用户可能会被分配到几十个或数百个存储桶(在AWS文档的示例中考虑多个部门)。
我想对每个用户使用多个自定义属性:
bucket_1: true
bucket_2: false
bucket_3: false
- ..等等
并创建允许您访问给定bucket_n
的策略,当且仅当您具有属性bucket_n: true
时。
如果我最多有50个存储桶(Cognito中的自定义属性的硬限制),则可以这样做。
在我的例子中,这个值稍高一些(几百)。我可以让用户访问200多个存储区,也可以只允许用户访问一个存储区。
是否有使用Cognito标识池和IAM策略实现我的目标的方法?
推荐答案
好的,我发现了一个可能对您中的某些人有用的解决办法(&Q;)。
首先,转到Cognito用户池并创建一个您选择的自定义属性,该属性将保存您的所有值。请记住,Cognito的属性值限制为2048个字符。让我们将该属性称为attribute_groups
。将所有值作为字符串放入其中,并使用您选择的分隔符。在我的例子中,具有custom:attribute_groups = "123o789"
属性user1
将意味着user1
在逻辑上属于123
和789
。
映射这些属性in Cognito Identity Pools。按照主体的标记键:groups
将从属性名称:custom:attribute_groups
中选择。
最后,设置用户池中经过身份验证的用户所采用的IAM策略,如下所示。在我的例子中,我希望允许组123
列出s3://my_bucket/123
,456
列出s3://my_bucket/456
,依此类推。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "1",
"Effect": "Allow",
"Action": [
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::my_bucket"
],
"Condition": {
"StringLike": {
"s3:prefix": [
"123/*"
],
"aws:PrincipalTag/groups": [
"*123*"
]
}
}
},
{
"Sid": "2",
"Effect": "Allow",
"Action": [
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::my_bucket"
],
"Condition": {
"StringLike": {
"s3:prefix": [
"456/*"
],
"aws:PrincipalTag/groups": [
"*456*"
]
}
}
},
{
"Sid": "3",
"Effect": "Allow",
"Action": [
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::my_bucket"
],
"Condition": {
"StringLike": {
"s3:prefix": [
"789/*"
],
"aws:PrincipalTag/groups": [
"*789*"
]
}
}
}
]
}
完成我的示例-当user1
获得他们的凭据时(您可以通过创建用户,设置其属性,然后执行aws cognito-idp initiate-auth
以获得ID token
,然后aws cognito-identity get-id
以获得identity
,最后aws cognito-identity get-credentials-for-identity
以获得访问密钥ID/秘密访问密钥/会话令牌),他们可以执行aws s3 ls s3://my_bucket/123
和aws s3 ls s3://my_bucket/789
。
遗憾的是,这仍然受到以下因素的严重限制:
- IAM策略字符限制(10240)
- Cognito自定义属性长度限制(2048)
使用这种细化的IAM策略,您最多可以拥有15-20个组和组。
您可以通过创建多个策略和多个Cognito User Pool组,将每个用户附加到每个组,然后使用ID token
中的cognito:roles
属性迭代这些组,并使用允许您设置CustomRoleArn
的GetCredentialForIdentity来承担这些角色。它可以工作(我已经检查过了),但真的很麻烦。
然而,有一个技巧可以将Cognito功能扩展到您中的一些人,并摆脱这一限制。要求是目录的结构是可预测的,并且您不需要访问子目录。我们将利用${s3:prefix}
也是变量这一事实。
如果是这样,您的策略可能如下所示:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "1",
"Effect": "Allow",
"Action": [
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::my_bucket"
],
"Condition": {
"StringLike": {
"aws:PrincipalTag/groups": [
"*${s3:prefix}*"
]
}
}
},
{
"Sid": "2",
"Effect": "Allow",
"Action": [
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::my_bucket/${s3:prefix}/*"
],
"Condition": {
"StringLike": {
"aws:PrincipalTag/groups": [
"*${s3:prefix}*"
]
}
}
}
]
}
,然后在custom:attribute_groups
中,您必须指定给定用户有权访问的所有前缀(即所有目录)。请注意,将不允许他们访问这些目录的子目录,因为${s3:prefix}
将有所不同。
例如,用户:
custom:attribute_groups = directoryA####directoryA/subdirectoryAA####directoryC/subdirectoryCA/subsubdirectoryCAA
将被允许访问以下位置的文件:
my_bucket/directoryA
my_bucket/directoryA/subdirectoryAA
my_bucket/directoryC/subdirectoryCA/subsubdirectoryCAA
和没有其他(子)目录!directoryA/subdirectoryAB
是无法访问的,即使directoryA
是无法访问的。
这篇关于Cognito身份池-使用";动态";属性进行基于属性的访问控制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!