为什么无法加载其他 AWS 账户上传到我的 Amazon S3 存储桶的网站内容?

上次更新日期:2021 年 1 月 27 日

我使用 Amazon Simple Storage Service (Amazon S3) 存储桶来存储我的网站内容。其他 AWS 账户的用户向我的存储桶上传了一个网站对象。我的存储桶策略是正确的,但无法在网站上加载该对象。如何修复此问题?

简短描述

如果另一个 AWS 账户将对象上传到您的存储桶,则默认情况下,您不会拥有该对象。因此,您可能无法读取该对象。上传账户必须明确授予您(即存储桶拥有者)该对象的权限。

此外,存储桶策略不适用于存储桶中归其他账户所有的对象。因此,向您网站的用户授予读取访问权限的存储桶策略不会自动应用到由其他账户上传的对象。

要修复此加载问题,请使用以下任一方法更改对象的访问控制列表 (ACL):

  • 对象拥有者授予对象的公共读取访问权限。
  • 对象拥有者授予存储桶拥有者完全控制对象的权限。

请注意有关向其他账户授予存储桶访问权限的以下注意事项:

  • 默认情况下,存储桶的账户无法读取由其他账户上传到该存储桶的对象。上传对象的账户必须明确更新 ACL 才能授予读取权限。
  • 由其他账户上传到存储桶的对象不会自动继承在存储桶策略中定义的权限。存储桶拥有者必须获取对象的所有权才能应用存储桶策略。
  • 如果您想允许其他账户访问您的存储桶,最佳做法是使用存储桶策略。存储桶策略是管理权限的一种更集中、更全面的方法。
  • 如果您想允许其他账户将对象上传到您的存储桶,请创建一个 AWS Identity and Access Management (IAM) 角色。IAM 角色必须从您的 AWS 账户中创建,并进行配置,以便另一个 AWS 账户可以代入该角色。当其他账户使用该 IAM 角色上传对象后,您的账户便具有该对象的所有权,因为该角色属于您的账户。有关使用 IAM 角色进行跨账户配置的示例,请参阅存储桶拥有者针对不属于自己的对象授予跨账户权限

解决方法

对象拥有者授予对象公共读取访问权限

上传该对象的账户可通过运行以下 AWS 命令行界面 (AWS CLI) 命令,授予对象公共读取访问权限:

aws s3api put-object-acl --bucket docexamplebucket --key example.jpg --acl public read

对于 --bucket 的值,请输入用于存储您网站内容的存储桶的名称。

注意:如果在运行 AWS CLI 命令时收到错误,请确保您使用的是最新的 AWS CLI 版本

要限制对象的流量,存储桶拥有者可以使用存储桶策略,该策略仅允许来自特定 IP 地址或 VPC 的请求。

例如,此存储桶策略可以拒绝访问 awsexamplebucket 中的对象,除非访问请求来自列为“aws:SourceIp”的 IP 地址。或者,请求必须来自指定为“aws:sourceVpc”的 VPC:

{
    "Version": "2012-10-17",
    "Id": "Policy1415115909152",
    "Statement": [
        {
            "Sid": "Deny-Access-Except-For-Trusted-IPs-and-VPC",
            "Effect": "Deny",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::docexamplebucket/*",
            "Condition": {
                "NotIpAddress": {
                    "aws:SourceIp": [
                        "1.1.1.1/32",
                        "2.2.2.2/32",
                        "3.3.3.3/32"
                    ]
                },
                "StringNotEquals": {
                    "aws:sourceVpc": "vpc-12345abc"
                }
            }
        }
    ]
}

对象拥有者授予存储桶拥有者完全控制对象的权限

对象拥有者可以通过在目标存储桶上启用 S3 对象拥有权来自动授予存储桶拥有者完全控制对象的权限。此功能在对象拥有者上传对象时授予存储桶拥有者控制器,并包含 bucket-owner-full-control 预装 ACL。

当存储桶拥有者将其 S3 对象所有权配置为“首选存储桶拥有者”后,存储桶拥有者可以添加另一个存储桶策略。此附加存储桶策略必须要求所有 Amazon S3 PUT 操作包含 bucket-owner-full-control 预装 ACL。此 ACL 授予存储桶拥有者完全控制新对象的权限。有关更多信息,请参阅使用 S3 对象所有权控制已上传对象的所有权

要授予存储桶拥有者完全控制对象的权限,请在上传对象时使用以下 CLI 语法:

aws s3api put-object --bucket docexamplebucket --key example.jpg --acl bucket-owner-full-control

存储桶拥有者现在拥有该对象,且该对象会继承在存储桶策略中设置的权限。

对于在启用 S3 对象所有权之前已上传的现有对象,对象拥有者必须授予存储桶拥有者对该对象的权限。然后,存储桶拥有者必须复制对象本身。

要授予存储桶拥有者完全控制对象的权限,请将以下 CLI 语法用于上传对象的账户:

aws s3api put-object-acl --bucket docexamplebucket --key example.jpg --acl bucket-owner-full-control

要继承对象的对象所有权,存储桶拥有者必须像下面这样复制对象本身:

aws s3 cp s3://docexamplebucket/example.jpg s3://docexamplebucket/example.jpg --acl bucket-owner-full-control

存储桶拥有者现在拥有该对象,且该对象会继承在存储桶策略中设置的权限。

要求跨账户上传向存储桶拥有者授予完全控制对象的权限

如需要求来自其他账户的所有上传 (s3:PutObject) 授予存储桶拥有者完全控制对象的权限,您可以使用类似于以下的存储桶策略:

{
    "Id": "Policy1541018284691",
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "RequireBucketOwnerFullControlOnPuts",
            "Principal": {
                "AWS": [
                    "arn:aws:iam::111122223333:user/iam_user"                ]
            },
            "Action": [
                "s3:PutObject"
            ],
            "Effect": "Allow",
            "Resource": "arn:aws:s3:::docexamplebucket/*",
            "Condition": {
                "StringEquals": {
                    "s3:x-amz-acl": "bucket-owner-full-control"
                }
            }
        }
    ]
}

使用此存储桶策略时,其他账户 (111122223333) 中的用户只有在指定了对象的 ACL 时才能上传到存储桶。对象的 ACL 必须授予存储桶拥有者完全控制权。然后,用户必须像下面这样上传对象:

aws s3 cp path/to/local/file s3://docexamplebucket --acl bucket-owner-full-control