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

Azi*_*ved 3 amazon-s3 amazon-web-services amazon-iam swift amazon-cognito

我正在尝试使用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
    })
}
Run Code Online (Sandbox Code Playgroud)

我的IAM角色权限策略如下,来自此AWS文档:

{
    "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}/*"
            ]
        }
    ]
}
Run Code Online (Sandbox Code Playgroud)

我得到的回应是

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

用户通过AWS Cognito用户池和Cognito联合身份验证进行身份验证.我调试并提取了JWT令牌,并看到了sub = "631d121f-b294-4318-b3cd-36b3b74ebdff".我甚至用Charles查看了请求/响应.

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

我已经检查了这个Stack Overflow问题和这一个,但无济于事.所以,是的,我不知道.我已经在这里待了将近9个小时,所以任何帮助都会真诚地受到赞赏.

Azi*_*ved 7

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

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

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

  • 对困惑感到抱歉.是的,策略变量是指Cognito Federated Identity的身份ID,而不是用户池字段,尽管术语重叠令人困惑. (2认同)
  • 谢谢!那花了半天的时间才意识到我的认知用户属性中的“ sub”与“ sub”不匹配。这与GitHub问题中的一篇文章相反。 (2认同)