AWS S3 传输管理器 ${cognito-identity.amazonaws.com:sub} 策略变量访问被拒绝

问题描述 投票:0回答:2

我正在尝试使用传输管理器将文件从 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 角色权限策略如下,来自 此 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}/*"
            ]
        }
    ]
}

我得到的回应是

<?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 用户池和 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/*
。第一个语句可以继续使用策略变量,并且它仍然有效。如果我完全删除第一条语句就会起作用!当我将策略变量添加到最后一个语句时,它开始崩溃。

我已经检查了这个Stack Overflow问题和这个,但无济于事。所以是的,我不知道。我已经在这方面花费了近 9 个工时,因此我们将真诚地感谢您的任何帮助。

swift amazon-web-services amazon-s3 amazon-cognito amazon-iam
2个回答
25
投票

问题解决了。事实证明,

${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),并且它有效。


0
投票

虽然@azizj 的答案是正确的:

${cognito-identity.amazonaws.com:sub} 并不真正指 JWT 令牌中的 sub

就我而言,我确实需要在 IAM 策略中引用 JWT 令牌中的

sub
。事实证明这是可行的!转到您的身份池 -> 用户访问 -> 选择身份提供商并编辑访问控制属性。您可以使用默认声明映射或提供自定义标签键。我使用了默认值,现在可以使用 IAM 策略中的
sub
主体标签来引用令牌的
username
声明:

{
    "Effect": "Allow",
    "Action": "s3:ListBucket",
    "Resource": [
        "arn:aws:s3:::mybucket"
    ],
    "Condition": {
        "StringLike": {
            "s3:prefix": [
                "${aws:PrincipalTag/username}/*"
            ]
        }
    }
},

显然,您可以将声明映射到不同的主体标签键,并在策略中相应地引用它。

重要的是,为了使其正常工作,您还需要更新 IAM 角色的信任策略并将

"sts:TagSession"
添加为允许的操作。如果你不这样做,你会得到一个错误:

InvalidIdentityPoolConfigurationException: Invalid identity pool configuration. Check assigned IAM roles for this pool.

AWS 文档涵盖了所有这些,但我花了一段时间才找到正确的信息,所以发布以防对其他人有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.