【问题标题】:Cannot 'getObject' from S3 bucket - policy not working无法从 S3 存储桶中“获取对象” - 策略不起作用
【发布时间】:2019-01-01 03:50:50
【问题描述】:

我在这上面花了 10 多个小时(我知道哈哈),但根本无法深入了解它。


更新 - 见 QN 底部


场景

我有一个应用程序,允许用户将对象上传到 S3,然后在以后随时下载。

使用以下策略,上传工作正常,但 getObject 调用却不行。

IAM 用户政策

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "*",
            "Resource": "*"
        }
    ]
}

我也尝试了上面的一堆其他更细粒度的策略,但都没有奏效,因此,为了让它工作,我试图设置一个用户策略,授予对 AWS 的根级别访问权限旨在从那里对其进行微调。

存储桶政策

我认为这不需要任何存储桶策略,但是,对于它的价值,我没有尝试任何策略以及以下策略:

{
    "Version": "2012-10-17",
    "Id": "AWSGeneratedPolicyId",
    "Statement": [
        {
            "Sid": "RandomSidGeneratedHere",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::305492142848:user/username-this-line-copy-pasted-from-AWS-IAM-console"
            },
            "Action": "s3:*",
            "Resource": [
                "arn:aws:s3:::bucketname",
                "arn:aws:s3:::bucketname/*"
            ]
        }
    ]
}

函数调用getObject:

const params = {
        Bucket: 'bucketname',
        Key: 'objectkey',
    };
    s3.getObject(params, function(err, data) {
        if (err) {
            console.log(err.message);
        } else {
            console.log(data);
        }
    });

结果和错误信息

<Error>
  <Code>AccessDenied</Code>
  <Message>Access Denied</Message>
  <RequestId>FC1698B03B31AF06</RequestId>
  <HostId>
    ZDDPr+WHCAnoAY/FyGTZA3iv8+L9R0r5CYGI5Owf/DOsItmsU5BSEtD8qXAZc4UHSgSqv2zneH4=
  </HostId>
</Error>

疑难解答:

我知道凭据是正确的,因为上传工作正常 我知道上面的“测试”硬编码函数是正确的(就存储桶名称和密钥而言),因为如果我将存储桶更改为“公共”以供读取,那么对 getObject 的函数调用就可以正常工作

以上内容暗示相关 IAM 用户没有getObject 的权限 - 但根据应用的用户策略,还需要哪些权限??

非常感谢任何建议(注意 - 我浏览了论坛并看到了类似的问题,但似乎没有一个答案对我有用)

更新

一时兴起,我改变了功能来做到这一点:

s3.listBuckets({}, function(err, data) {
    if (err) console.log(err, err.stack);
    console.log(data);
}

并且我没有列出所有预期的存储桶,而是从不同的帐户获取存储桶列表。尽管下面是顶部的代码,但仍在发生这种情况:

const AWS = require('aws-sdk');

AWS.config = new AWS.Config();
AWS.config.accessKeyId = process.env.AWS_KEY;
AWS.config.secretAccessKey = process.env.AWS_SECRET;
AWS.config.region = 'ap-southeast-2';

const s3 = new AWS.S3();

现在这种奇怪现象是有道理的 - 列出的存储桶完全是不同 AWS 账户上的存储桶(我在试验 serverless.com 框架时创建的一个)。

假设

本地服务器的配置以某种方式固定,并且在代码中设置的配置属性没有影响。

我可以通过将完全相同的代码部署到它按预期工作的实际服务器来确认这种情况(即 getObject 调用工作正常)

修改后的问题:

如何清除“缓存”或终端中保留这些值的任何内容?这是 iTerm/serverless.com 的错误吗(如果是这样,我可以采取必要的步骤...)。如果它不是错误而是预期的行为,那么将来应该如何避免这种情况?

【问题讨论】:

  • 如果您通过 Amazon S3 控制台上传对象,您的代码能否成功下载?你能告诉我们你上传对象的代码吗?具体来说,看看你为ACL 设置了什么会很有趣,通常应该是bucket-owner-full-control
  • @JohnRotenstein 通过控制台上传也有同样的问题(访问被拒绝消息)。如果我通过控制台上传并提供公共读取访问权限(如预期的那样),它就可以工作。用于上传的代码 - 它基本上是使用 React 和 EvaporateJS (github.com/TTLabs/EvaporateJS)。我想这里需要注意的重点是访问密钥 ID 和秘密访问密钥是在上传和下载功能中重复使用的环境变量(所以那里没有不匹配)。

标签: amazon-web-services amazon-s3 aws-sdk


【解决方案1】:

我已经尝试过这项政策并奏效了。

尝试在我的存储桶策略下使用 *(只是为了丢弃)访问所有 AWS IAM 账户,另一件事,你为什么使用 expire 属性?无论如何尝试删除该行。

{
    "Version": "2012-10-17",
    "Id": "AWSGeneratedPolicyId",
    "Statement": [
        {
            "Sid": "RandomSidGeneratedHere",
            "Effect": "Allow",
            "Principal": {
                "AWS": "*"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::bucketname/*"
        }
    ]
}

另外,当您上传图片时,请检查您是否分配了 ACL 属性:

S3.putObject({
            Bucket: process.env.bucket,
            Body: imageContent.body,
            Key: `${key}`,
            ACL:'public-read'
        })

编码愉快!

【讨论】:

  • 为答案干杯!但是提供“公共读取”虽然会起作用,但会使存储桶内容不安全。这些对象只需要对我的服务器可用。原谅 expire 属性 - 它用于 getSignedUrl 函数(具有相同的问题) - 与“getObject”无关。我忘了从问题中删除它,并将更新。
  • 好的,那么您必须通过 EC2 实例授予对照片存储桶的访问权限。查看此链接:Read More
  • 否,服务器未在 EC2 上运行。无论服务器在哪里运行,问题都存在。
  • 您是否在服务器上设置环境变量(aws 凭据)?
【解决方案2】:

好的,根据更新后的问题 - 以及来自 listObjects 函数调用的线索,我发现在服务器运行时,AWS 配置忽略了我的凭据,而支持存储在路径中的凭据:~/.aws/credentials

解决方案:

删除提到的credentials 文件,一切正常...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-11-25
    • 2018-11-20
    • 2011-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-26
    相关资源
    最近更新 更多