【问题标题】:Upload to S3 Bucket Giving Access Denied from ECS Instance上传到 S3 存储桶,导致 ECS 实例拒绝访问
【发布时间】:2019-12-04 05:29:42
【问题描述】:

我一直在尝试为我在 ECS 中运行的 web 应用设置简单的 S3 图像上传功能。 ECS 集群是由系统管理员设置的,我不再获得帮助,但每个上传请求都返回此错误:

{ AccessDenied: Access Denied
at Request.extractError (/www/node_modules/aws-sdk/lib/services/s3.js:585:35)
at Request.callListeners (/www/node_modules/aws-sdk/lib/sequential_executor.js:106:20)
at Request.emit (/www/node_modules/aws-sdk/lib/sequential_executor.js:78:10)
at Request.emit (/www/node_modules/aws-sdk/lib/request.js:683:14)
at Request.transition (/www/node_modules/aws-sdk/lib/request.js:22:10)
at AcceptorStateMachine.runTo (/www/node_modules/aws-sdk/lib/state_machine.js:14:12)
at /www/node_modules/aws-sdk/lib/state_machine.js:26:10
at Request.<anonymous> (/www/node_modules/aws-sdk/lib/request.js:38:9)
at Request.<anonymous> (/www/node_modules/aws-sdk/lib/request.js:685:12)
at Request.callListeners (/www/node_modules/aws-sdk/lib/sequential_executor.js:116:18)
at Request.emit (/www/node_modules/aws-sdk/lib/sequential_executor.js:78:10)
at Request.emit (/www/node_modules/aws-sdk/lib/request.js:683:14)
at Request.transition (/www/node_modules/aws-sdk/lib/request.js:22:10)
at AcceptorStateMachine.runTo (/www/node_modules/aws-sdk/lib/state_machine.js:14:12)
at /www/node_modules/aws-sdk/lib/state_machine.js:26:10
at Request.<anonymous> (/www/node_modules/aws-sdk/lib/request.js:38:9)
at Request.<anonymous> (/www/node_modules/aws-sdk/lib/request.js:685:12)
at Request.callListeners (/www/node_modules/aws-sdk/lib/sequential_executor.js:116:18)
at callNextListener (/www/node_modules/aws-sdk/lib/sequential_executor.js:96:12)
at IncomingMessage.onEnd (/www/node_modules/aws-sdk/lib/event_listeners.js:299:13)
at ZoneDelegate.invokeTask (/www/node_modules/zone.js/dist/zone-node.js:423:31)
at Zone.runTask (/www/node_modules/zone.js/dist/zone-node.js:195:47)
message: 'Access Denied',
code: 'AccessDenied',
region: null,
time: 2019-07-25T20:59:24.717Z,
requestId: '5E0BB7DDFAF2013F',
extendedRequestId:
'UAFzo69NlfPqSIXKUUIrpvBqdj97v/xMfOxdbRfFK2rLuO06Sb/zmjTxA5/beimDuEEaq53ntdk=',
cfId: undefined,
statusCode: 403,
retryable: false,
retryDelay: 70.57095033673187 }

发出请求的代码是:

import S3 = require('aws-sdk/clients/s3');

config.update({ region: 'us-west-2' });
const s3 = new S3();
...
private async handleLogoUpload(id: string, dto: UpdateCustomerDto): Promise<string> {
    const filePath = `${TMP_DIR}/${dto.logoUrl[0].name}`;
    const logoFile = await readAsync(filePath);
    const uploadData = await s3.upload({
      Key: id, Bucket: 'sm-logo', Body: logoFile, ACL: 'public-read',
    }).promise();
    return deleteAsync(filePath).then(() => uploadData.Location);
  }

我在这里尝试了本文中的所有内容:https://aws.amazon.com/premiumsupport/knowledge-center/s3-403-upload-bucket/

ECS 实例任务执行角色有这个策略:

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

Bucket 本身具有公共读/写权限。

我将 S3 的端点添加到 VPC。

VPC 允许所有出站流量,并且 VPC 上的另一个容器可以毫无问题地访问 S3。

我已经束手无策了。我在上面尝试的任何方法都没有奏效,我似乎找不到其他有类似问题的人。它在本地工作,所以我认为这是一个网络问题,但我不知所措。

【问题讨论】:

  • 您是否可以登录 ECS 实例并使用 AWS CLI 测试权限?试试aws s3 ls s3://sm-logoaws s3 cp file.txt s3://sm-logo/。这样我们就可以判断是权限、网络还是代码相关。
  • 必须在容器中安装 aws-cli,但这样做之后我能够列出和 cp
  • 不知道是不是public-read出了问题?如果存储桶已配置 Amazon S3 阻止公共访问,则可能会被拒绝。您可以尝试删除 ACL 以查看它是否有效?
  • 抱歉延迟回复。就是这样!它现在可以毫无问题地上传,但该对象不再可公开访问。有什么建议吗?

标签: amazon-web-services amazon-s3 amazon-ecs amazon-vpc aws-sdk-nodejs


【解决方案1】:

默认情况下,Amazon S3 Block Public Access – Another Layer of Protection for Your Accounts and Buckets | AWS News Blog 将阻止存储桶和对象公开访问。

您可以选择性地关闭此功能以允许:

  • 存储桶策略(适用于整个存储桶)
  • 对象 ACL(访问控制列表),仅适用于对象

只有在所有内容(或子目录)都可以公开访问的情况下才使用存储桶策略。

它在 AWS CLI 中起作用的原因是它没有指定 --acl public-read。但是,当代码指定ACL: 'public-read'时,请求被阻塞了。

因此,您应该关闭这些选项

  • 阻止对通过访问控制列表 (ACL) 授予的存储桶和对象的公共访问
  • 阻止对通过任何访问控制列表 (ACL) 授予的存储桶和对象的公共访问

【讨论】:

  • 嗨,约翰,所有这些选项目前都已关闭,但上传的上传内容仍无法公开访问
  • 这次你用ACL: 'public-read'了吗?如果您在 S3 控制台中访问它,是否可以使用“打开”按钮?如果您只是单击链接(没有按钮),它是否有效?如果您在“操作”菜单中手动将其标记为“公开”,是否可以解决问题?
  • 我没有使用ACL: 'public-read'。即使“阻止所有公共访问”设置为关闭,它仍然无法上传。如果我打开并下载文件,它就可以工作,而不是如果我只是单击公共链接。如果我手动将其设置为“公共”,则公共链接开始工作
  • 有两种方法可以将其公开:使用存储桶策略(适用于存储桶中的所有文件或特定子目录),或者使用 ACL: 'public-read'你上面的代码。如果您将其从代码中取出,请将其放回原处。
【解决方案2】:

如果我理解的问题是正确的,那么我认为您必须在任务定义中以适当的 S3 权限传递任务角色,而不是将权限传递给任务执行角色。

因为根据我的理解,从在容器任务角色 [1] 内运行的应用程序进行 api 调用时使用的不是任务执行角色。即使在这样做之后如果它不起作用,我们也可以尝试使用本地机器上的 aws cli 测试相同的角色,以查看它是否具有将对象上传到 s3 的适当权限。

[1] Amazon ECS 任务角色 - https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_IAM_role.html

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-10-09
    • 2017-07-04
    • 2019-02-03
    • 1970-01-01
    • 2021-07-05
    • 2018-01-10
    • 1970-01-01
    • 2017-02-12
    相关资源
    最近更新 更多