AWS S3 Transfer Manager ${cognito-identity.amazonaws.com:sub} Policy Variable Access Denied

柔情痞子 提交于 2019-12-01 06:57:07

问题


I am trying to download a file from AWS S3 to my iOS mobile app from a folder that is specific to the user, using Transfer Manager, like so:

@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
    })
}

My IAM role permission policy is the following, gotten from 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}/*"
            ]
        }
    ]
}

Response I get is

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

The user is authenticated via AWS Cognito User Pool & Cognito Federated Identities. I've debugged and extracted the JWT token, and seen that the sub = "631d121f-b294-4318-b3cd-36b3b74ebdff". I've even used Charles to see the Request/Response.

It does work if I replace ${cognito-identity.amazonaws.com:sub} in the last statement S3GetObjects with 631d121f-b294-4318-b3cd-36b3b74ebdff to get arn:aws:s3:::sidestreamx/631d121f-b294-4318-b3cd-36b3b74ebdff/*. The first statement can continue having the policy variable and it'll still work. It'll work if I remove the first statement altogether! It's when I add the policy variable to the last statement where it starts to breakdown.

I've checked out this Stack Overflow question and this one, to no avail. So yea, I don't know. I've been at this for almost over 9 man hours, so any help would sincerely be appreciatd.


回答1:


Problem solved. Turns out, ${cognito-identity.amazonaws.com:sub} doesn't really refer to the sub in the JWT token. It refers to IdentityID from the credentialsProvider:

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

I manually made a folder in my bucket with the name equal to task.result! (which is in the format of us-east-1:XXXXXXXXXXXXXXXXXX fyi), and it worked.



来源:https://stackoverflow.com/questions/42605419/aws-s3-transfer-manager-cognito-identity-amazonaws-comsub-policy-variable-ac

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!