根据Cognito ID的IAM策略,用于S3文件夹访问

12

我已经创建了一个IAM策略,允许Cognito用户写入我的S3存储桶,但是我希望根据他们的Cognito ID限制他们只能写入特定的文件夹。我遵循了亚马逊的说明(这里),创建了一个看起来像这样的策略:

{
    "Effect": "Allow",
    "Action": ["s3:PutObject","s3:GetObject"],
    "Resource": [
        "arn:aws:s3:::mybucket/myappfolder/${cognito-identity.amazonaws.com:sub}*"
    ]
}

但是当我尝试使用AWS iOS SDK的v2进行上传时,我收到了一个访问被拒绝的错误。

如果我修改资源的最后一个路径组件,用SDK的AWSCognitoCredentialsProvider提供的明确的identityId值替换${cognito-identity.amazonaws.com:sub},那么它就可以正常工作。

{
    "Effect": "Allow",
    "Action": ["s3:PutObject","s3:GetObject"],
    "Resource": [
        "arn:aws:s3:::mybucket/myappfolder/us-east-1:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx*"
    ]
}

我理解这两者应该是相同的,我在我的策略中漏掉了什么吗?还是我应该在上传请求中使用不同的路径?

** 更新 **

我最初在iOS中遇到了这个问题,所以今晚我尝试在node.js中做同样的事情,结果是相同的。这是我在node中使用的简单代码:

var s3 = new AWS.S3();

AWS.config.region = 'us-east-1';

AWS.config.credentials = new AWS.CognitoIdentityCredentials(AWSParams);

AWS.config.credentials.get(function (err) {

    if (!err) {

        console.log("Cognito Identity Id: " + AWS.config.credentials.identityId);

        var bucketName = 'ch123_test_bucket';

        var keyName = AWS.config.credentials.identityId + '.txt';

        var params = {Bucket: bucketName, Key: keyName, Body: 'Hello World!'};

        s3.putObject(params, function (err, data) {
            if (err)
                console.log(err)
            else
                console.log("Successfully uploaded data to " + bucketName + "/" + keyName);
        });
}

我使用iOS时得到了相同的结果:除非我在IAM策略中提供显式的cognito ID,否则API将响应403。

我已经将我的IAM策略精简到最少。但这并不奏效:

{
  "Statement": [
   {
     "Effect": "Allow",
     "Action": ["s3:PutObject","s3:GetObject"],
     "Resource": [
         "arn:aws:s3:::ch123_test_bucket/${cognito-identity.amazonaws.com:sub}*"
      ]
  }
 ]
}

这个操作会:

{
"Statement": [
  {
    "Effect": "Allow",
    "Action": ["s3:PutObject","s3:GetObject"],
    "Resource": [
        "arn:aws:s3:::ch123_test_bucket/us-east-1:68a5dc49-6cc7-4289-8257-d3d5636f7034*"
    ]
  }
 ]
}

我不明白我错了什么……我能找到的唯一文档总是展示着我一直在使用的同一个Resource值的例子。


只是为了明确,您包含的第一个策略与第二个不匹配。您确定它们是相同的吗?您能否在应用程序中包含您正在使用的代码?您是否正在使用传输管理器? - Bob Kinney
@BobKinney 我已经更新了我的问题,展示了一个简单的node.js示例来说明问题。 - ChrisH
@ChrisH,感谢您的详细问题。我有一条评论和一个问题。我的评论是:这一行 var s3 = new AWS.S3(); 应该在设置凭据之后(第三行),否则会出现错误。而且,问题是:您所写的是针对未经身份验证的用户,那么如何针对已经身份验证的用户执行相同操作呢?谢谢! - securecurve
1
你是怎么查看 ${cognito-identity.amazonaws.com:sub} IAM 变量的?我正在使用联合身份,并需要查看传递到该变量中的内容。我有一种感觉,当与 S3 和联合身份一起使用时,冒号 (:)会被转换为 %3A,并破坏来自网关 API 传递的 URL 编码字符串与策略资源中的 IAM 变量的匹配。 - Aaron
2个回答

10

很抱歉,目前使用Cognito控制台生成的角色与策略变量存在问题。请更新您的角色访问策略,确保正确评估策略变量的值包括以下内容:

"Version": "2012-10-17"

2014-09-16更新:我们已经更新了Amazon Cognito控制台,通过身份池创建向导创建的角色已修正此问题。现有角色仍需要进行上述修改。


1
那真是太关键了,我花了3个小时才找到它...非常感谢!你应该真的纠正一下DynamoDB在Android上的指南,因为这就是我遵循的指南,但它确实没有这个版本字段! - David Ferrand
@Dadou 对于出现的问题我们深表歉意。它没有版本的部分原因是因为该策略不需要使用策略变量,所以该政策中没有要求。 - Bob Kinney

0

你缺少最后的斜杠。

{
    "Effect": "Allow",
    "Action": ["s3:PutObject","s3:GetObject"],
    "Resource": [
        "arn:aws:s3:::mybucket/cognito/myappfolder/${cognito-identity.amazonaws.com:sub}/*"
    ]
}

另外也请考虑一下这篇文章


1
谢谢,但是尾随的 '/' 没有任何区别。你链接的 SO 问题确认了我已经想到的...并且建议我的 IAM 策略应该是有效的。 - ChrisH

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接