AWS S3 Transfer Manager $ {cognito-identity.amazonaws.com:sub}拒绝了策略变量访问

时间:2017-03-05 06:52:36

标签: swift amazon-web-services amazon-s3 amazon-cognito amazon-iam

我正在尝试使用Transfer Manager从AWS S3将文件从特定于用户的文件夹下载到我的iOS移动应用程序,如下所示:

@IBAction func download() {
    let transferManager = AWSS3TransferManager.default()!
    let downloadingFileURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("disney1.jpg")
    let downloadRequest = AWSS3TransferManagerDownloadRequest()!
    downloadRequest.bucket = "sidestreamx"
    // user's UUID/disney1
    downloadRequest.key = "631d121f-b294-4318-b3cd-36b3b74ebdff/disney1"
    downloadRequest.downloadingFileURL = downloadingFileURL

    transferManager.download(downloadRequest).continue(with: AWSExecutor.mainThread(), with: {
        (task: AWSTask<AnyObject>) -> Any? in
        if let error = task.error as? NSError {
            // handle error
            return nil
        }
        self.imageView.image = UIImage(contentsOfFile: downloadingFileURL.path)
        return nil
    })
}

我的IAM角色权限政策如下,来自this AWS doc

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "GetBucketListIfRequestIsForUser",
            "Action": [
                "s3:ListBucket"
            ],
            "Effect": "Allow",
            "Resource": [
                "arn:aws:s3:::sidestreamx"
            ],
            "Condition": {
                "StringLike": {
                    "s3:prefix": [
                        "${cognito-identity.amazonaws.com:sub}/*"
                    ]
                }
            }
        },
        {
            "Sid": "S3GetObjects",
            "Action": [
                "s3:GetObject",
                "s3:PutObject"
            ],
            "Effect": "Allow",
            "Resource": [
                "arn:aws:s3:::sidestreamx/${cognito-identity.amazonaws.com:sub}/*"
            ]
        }
    ]
}

我得到的回应是

<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>AccessDenied</Code>
   <Message>Access Denied</Message>    
   <RequestId>E1F205B58EF4A670</RequestId>
   <HostId>dUWI8PfVZL3mJmykjhXRqvFd1yt/CqDFNlwgwD3kmLk2vrMBP6JvVgezMYSROt3KyE3dx0+3eDE=</HostId>
</Error>

用户通过AWS Cognito User Pool&amp; Cognito联合身份。我调试并解压缩了JWT令牌,并看到了sub = "631d121f-b294-4318-b3cd-36b3b74ebdff"。我甚至使用Charles来查看请求/响应。

确实有效我将${cognito-identity.amazonaws.com:sub}替换为S3GetObjects 631d121f-b294-4318-b3cd-36b3b74ebdff arn:aws:s3:::sidestreamx/631d121f-b294-4318-b3cd-36b3b74ebdff/*以获取 bullet[i][1] -= 10; 。第一个语句可以继续使用策略变量,它仍然有效。如果我完全删除第一个语句,它就会起作用!当我将策略变量添加到它开始崩溃的最后一个语句时。

我已查看此Stack Overflow个问题和this one,但无济于事。所以,是的,我不知道。我已经花了将近9个工时,所以任何帮助都会真诚地受到赞赏。

1 个答案:

答案 0 :(得分:6)

问题解决了。事实证明,${cognito-identity.amazonaws.com:sub}并未真正引用JWT令牌中的sub。它引用credentialsProvider中的IdentityID:

    (AWSServiceManager.default().defaultServiceConfiguration.credentialsProvider
        as! AWSCognitoCredentialsProvider).getIdentityId()
        .continue({task -> Any? in
        print("Credentials ID is \(task.result!)")
        return nil
    })

我手动在我的存储桶中创建了一个文件夹,其名称等于task.result!(格式为us-east-1:XXXXXXXXXXXXXXXXXX fyi),并且有效。