Python 为AWS S3中的权限指定IAM角色
我试图将所有AWS Cognito用户限制在S3存储桶中他们自己的子目录中 我不希望他们在我的大存储桶中列出、读取或写入其他人的子目录/文件,我只希望他们在自己的目录中读取和写入对象 我在汲取灵感 我的政策是:Python 为AWS S3中的权限指定IAM角色,python,amazon-web-services,amazon-s3,boto,amazon-cognito,Python,Amazon Web Services,Amazon S3,Boto,Amazon Cognito,我试图将所有AWS Cognito用户限制在S3存储桶中他们自己的子目录中 我不希望他们在我的大存储桶中列出、读取或写入其他人的子目录/文件,我只希望他们在自己的目录中读取和写入对象 我在汲取灵感 我的政策是: { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:ListBucke
{
"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,方法是使用从STS检索的访问/机密/安全令牌三元组,使用Cognito令牌创建一个boto
看起来您的代码使用的是硬编码的访问密钥和密钥,而不是使用Cognito检索凭据。与为所有用户嵌入相同的访问密钥和密钥不同,要利用Cognito,您需要遵循并使用GetId(,)获取标识ID,然后使用GetCredentialsForIdentity()获取当前ID的Cognito颁发的凭据。然后将这些凭据与boto S3连接一起使用
还要确保缓存每个用户的ID,并在调用Cognito时重用它。答案相当愚蠢。显然,S3中的bucket本身有自己的策略(它们相当隐蔽),但我有一个指令:
Principal: "*"
这使得bucket具有全球可读性
第二个启示是,如果您使用s3:ListBucket
和条件限制一个bucket,这并不意味着如果您列出该bucket,您将只得到这些结果—您必须按名称调用它。例如,boto
:
wrong = bucket.list() # will simply 403
right = bucket.list(prefix="base/subdir/<cognito-id>/") # will succeed
error=bucket.list()#只需403
右=bucket.list(prefix=“base/subdir/”)#将成功
换句话说,S3的设计使您必须知道所需文件夹的前缀键,这是一个很好的实践
我必须说,AWS的人们在这里和他们的论坛上对诊断这个问题的帮助给我留下了深刻的印象。总之,现在对S3有了更好的理解。很有趣。关于你的观点的问题:1)我如何测试这一点?我能看到这是否是非空的吗?以及3)我如何从我的角度看到我的开发人员用户ID之间的映射(test@test.com)AWS的问题呢?我已经用讨论过的一些要点更新了这个问题,但仍然不起作用。嗯。我也在3)上找到了你观点的答案。在你向STS索要凭证之前,只要Cognito授予你网络令牌,就会给出这个标识ID。嗯,是的,我知道。我有两个角色,一个用于已验证,另一个用于未经验证。我将此标记为答案,因为它可能是我面临的问题以及试图调试自己问题的人员的最有用的信息。您能否澄清更改后哪些问题不起作用,是否与原始问题相同(您可以访问子文件夹下的任何密钥)还是别的?是的,同样的问题。当我的GetObject
和PutObject
访问权限应限于用户文件夹时,我可以访问任何键。此外,我可以列出整个bucket中的所有对象,而不仅仅是具有指定前缀的对象。您的bucket策略中是否有允许比您的角色更多访问的特殊内容?除了您在此处列出的角色之外,您是否还有其他附加到该角色的策略?如果您在我们的论坛上发表文章或以其他方式向我们获取您的帐户id,我们还可以查看您的帐户详细信息并进行更仔细的调试。@BobKinney:没有其他角色,我知道我的bucket中没有什么特别的内容。不过肯定有什么地方出了问题。不,我只是没有发布整个身份验证流程的代码。我(正如我在帖子中提到的)正在联系Cognito和STS以获得钥匙。此外,您提到的流程效率很低,您可以简单地使用GetOpenIDTokenForDeveloperIdentity
并从那里assumeWitheBidentity
与STS-关联。请参阅我文章的最后一段,其中有相关的403
wrong = bucket.list() # will simply 403
right = bucket.list(prefix="base/subdir/<cognito-id>/") # will succeed