我试图将所有AWS Cognito用户限制在我的S3存储桶中他们自己的子目录中。
我不希望他们在我的大桶中列出,阅读或写下其他人的子目录/文件,我只希望他们阅读和阅读。在自己的目录中写入对象。
我吸取灵感from this AWS documentation snippet。
这是我的政策:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::my-bucket"
],
"Condition": {
"StringLike": {
"s3:prefix": [
"subfolder/"
]
}
}
},
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::my-bucket/subfolder/${cognito-identity.amazonaws.com:sub}",
"arn:aws:s3:::my-bucket/subfolder/${cognito-identity.amazonaws.com:sub}/*"
]
}
]
}
我的代码用user_id = test@test.com
检索某个用户的文件,但实际上允许我检索受限制的文件:
import boto
# These keys are *not* hardcoded, I'm just leaving out
# the auth flow to get them from Cognito/STS as described
# here: https://mobile.awsblog.com/post/Tx2FL1QAPDE0UAH/Understanding-Amazon-Cognito-Authentication-Part-2-Developer-Authenticated-Ident
conn = boto.s3.connect_to_region('us-east-1',
aws_access_key_id=ACCESS_KEY_FROM_COGNITO,
aws_secret_access_key=SECRET_KEY_FROM_COGNITO,
security_token=SECURITY_KEY_FROM_COGNITO)
# get the bucket
b = conn.get_bucket('my-bucket', validate=False)
# try to get an object we SHOULD be able to get
k = Key(b)
k.key = 'subfolder/us-east-1:xxxx-xxxx-xxxx-xxxxxxxxx/foobar'
print "Contents:", k.get_contents_as_string() # success!
# try to get and object we SHOUDN'T be able to get
k2 = Key(b)
k2.key = 'subfolder/BLAH_BLAH/restricted'
print "Contents:", k2.get_contents_as_string() # should fail, but doesn't
不幸的是,我可以访问和阅读这两个文件的内容,但我在AWS博客文档文章中遵循完全相同的模式。我也不确定为什么我需要boto连接中的validate=False
,但它似乎运行得很好。
我错过了什么?
编辑:在回答下面的答案时,我已尝试将我的角色更新为以下内容,但它没有任何区别:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::my-bucket"
],
"Condition": {
"StringLike": {
"s3:prefix": [
"subfolder/${cognito-identity.amazonaws.com:sub}/*"
]
}
}
},
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::my-bucket/subfolder/${cognito-identity.amazonaws.com:sub}/*"
]
}
]
}
我还确认我使用的访问凭据来自Cognito,使用从使用Cognito令牌创建boto
{{1对象和查询我的角色名称对应于我的身份池的身份验证用户。在这样做时,我在尝试阅读此角色时遇到以下异常(这正是因为我没有授予访问权限所应该发生的事情):
IAMConnection
所以仍然不清楚为什么这不起作用。
答案 0 :(得分:2)
5件事:
答案 1 :(得分:1)
看起来您的代码使用的是硬编码的访问密钥和密钥,并且不使用Cognito来检索凭据。不是为所有用户嵌入相同的访问密钥和密钥,而是利用Cognito,您需要关注Authentication Flow并使用GetId(boto reference,AWS reference)来获取身份ID然后使用GetCredentialsForIdentity(boto reference AWS reference)获取Cognito颁发的当前ID凭据。然后将这些凭据与boto S3连接一起使用。
还要确保为每个用户缓存ID,并在对Cognito进行额外调用时重复使用。
答案 2 :(得分:1)
答案很愚蠢。显然S3中的桶本身有自己的策略(它们相当隐蔽),但我有指令:
Principal: "*"
导致存储桶具有全局可读性。
第二个启示是,如果您使用s3:ListBucket
Condition
限制一个存储桶,这并不意味着如果您列出存储桶只会获得这些结果 - 您必须将其调用按名字。作为boto
中的示例:
wrong = bucket.list() # will simply 403
right = bucket.list(prefix="base/subdir/<cognito-id>/") # will succeed
换句话说,S3的设计使得您必须知道所需文件夹的前缀键,这无论如何都是很好的做法。
我不得不说,我对AWS的人们在这里和他们的论坛上诊断这个问题的帮助印象深刻。无论如何,现在对S3有了更好的理解。