如何提供对 Amazon S3 存储桶中的对象的跨账户访问权限?

上次更新日期:2022 年 8 月 3 日

我想授权其他 AWS 账户访问 Amazon Simple Storage Service(Amazon S3)存储桶中存储的对象。如何提供对 Amazon S3 存储桶的跨账户访问权限?

简短描述

在 Simple Storage Service (Amazon S3) 中,您可以授予其他 AWS 账户(账户 B)中的用户粒度跨账户访问权限,作用于您的账户(账户 A)拥有的对象。

根据您要提供的访问类型,使用以下解决方案之一授予对对象的跨账户访问权限:

  • AWS Identity and Access Management (IAM) 策略和基于资源的存储桶策略,仅适用于以编程方式访问 S3 存储桶对象
  • IAM 策略和基于资源的访问控制列表,仅适用于以编程方式访问 S3 存储桶对象
    注意:启用存储桶拥有者强制设置后,所有存储桶和对象 ACL 都将被禁用。因此,您无法使用 ACL 授予跨账户访问权限。原定设置下,任何新创建的存储桶都启用了存储桶拥有者强制设置。使用 IAM 策略和存储桶策略(而不是 ACL)来管理对存储桶和对象的跨账户访问也是一种最佳实践。如需了解详情,请参阅控制对象的所有权并禁用存储桶的 ACL
  • 使用跨账户 IAM 角色,以编程方式和通过控制台访问 S3 存储桶对象

如果请求者是 IAM 主体,则拥有主体的 AWS 账户必须通过 IAM 策略授予 S3 权限。根据您的具体使用案例,存储桶拥有者还必须通过存储桶策略或 ACL 授予权限。授予访问权限后,对跨账户存储桶的编程访问将与访问相同账户存储桶相同。

解决方法

IAM 策略和基于资源的存储桶策略

注意:如果您在运行 AWS Command Line Interface (AWS CLI) 命令时遇到错误,请确保您使用的是最新版的 AWS CLI

使用基于资源的存储桶策略来管理跨账户访问控制并审计 S3 对象的权限。如果您在存储桶级别应用存储桶策略,则可以定义以下内容:

  • 谁可以访问存储桶内的对象(使用 Principal 元素)
  • 他们可以访问哪些对象(使用 Resource 元素)
  • 他们如何访问存储桶内的对象(使用 Action 元素)

如果您在存储桶级别应用存储桶策略,将可以为存储桶中的不同对象定义精细访问权限。您还可以检查存储桶策略,以了解谁有权访问 S3 存储桶中的对象。

要使用存储桶策略来管理 S3 存储桶访问权限,请按照以下步骤操作:

注意:请用您的账户替换 Account 变量。

1.    在账户 A 中创建一个 Amazon S3 存储桶

2.    在账户 B 中创建一个 IAM 角色或用户

3.    授予账户 B 中的 IAM 角色权限,以使其可以从特定存储桶下载(GET Object)和上载PUT Object)对象。使用以下 IAM 策略还可以向账户 B 中的 IAM 角色授予调用 PutObjectAcl 的权限,从而向存储桶拥有者授予对象权限:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:PutObject",
                "s3:PutObjectAcl"
            ],
            "Resource": "arn:aws:s3:::AccountABucketName/*"

        }
    ]
}

注意:请务必更新策略以包含您的用户变量(例如账户 ID、存储桶名称和 ARN)。此外,您可以限制对账户 A 中特定存储桶文件夹的访问。要限制对特定存储桶文件夹的访问,请在资源元素中定义文件夹名称,例如“arn:aws:s3:::AccountABucketName/FolderName/*”。如需了解详情,请参阅如何使用 IAM 策略向特定用户授予对特定文件夹的访问权限?

还可以使用 AWS CLI 命令示例 create-policy 创建基于 IAM 身份的策略。

4.    配置账户 A 的存储桶策略以向您在账户 B 中创建的 IAM 角色或用户授予权限。使用此存储桶策略向用户授予对账户 A 所拥有存储桶中的对象的 GetObject 和 PutObject 权限:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::AccountB:user/AccountBUserName"
            },
            "Action": [
                "s3:GetObject",
                "s3:PutObject",
                "s3:PutObjectAcl"
            ],
            "Resource": [
                "arn:aws:s3:::AccountABucketName/*"
            ]
        }
    ]
}

您还可以使用 AWS CLI 命令示例 put-bucket-policy 创建 Simple Storage Service (Amazon S3) 存储桶策略。

注意:您可以通过定义资源元素中的特定 S3 存储桶文件夹来提供更限的访问权限,例如“arn:aws:s3:::AccountABucketName/FolderName/*”。通过使用附条件的 s3:PutObject 权限,存储桶拥有者将能够完全控制其他账户上载的对象。然后执行 ACL,从而在 PutObject API 调用中传递特定的标头。如需了解详情,请参阅授予 s3:PutObject 权限,并指定一个条件以要求存储桶拥有者获得完全控制权

IAM 策略和基于资源的 ACL

如果 ACL 比 IAM 和 S3 存储桶策略更能满足您的需求,则使用对象 ACL 来管理特定场景的权限。如需了解详情,请参阅何时使用基于 ACL 的访问策略(存储桶和对象 ACL)。Amazon S3 ACL 仅允许用户定义以下权限集:READ、WRITE、READ_ACP、WRITE_ACP 和 FULL_CONTROL。您仅可以将 AWS 账户或某个预定义的 Amazon S3 组作为 Amazon S3 ACL 的被授权者。在为 AWS 账户指定电子邮件地址或规范用户 ID 时,ACL 适用于被授权者 AWS 账户中的所有实体。例如,您不能使用 ACL 将访问权限限定为个别 IAM 用户或角色。您也不能将 ACL 应用到具有相同前缀的不同对象。

注意:存储桶拥有者可能不会拥有 ACL 被授权者上载的对象的完全控制权限。这是因为 ACL 不支持 ACL 授权的 S3 操作的条件。

要使用存储桶和对象 ACL 来管理对 S3 存储桶的访问,请遵循以下步骤:

1.    在账户 B 中创建一个 IAM 角色或用户。然后向该该角色或用户授予执行所需 Amazon S3 操作的权限。调用 PutObject 和 GetObject 的用户需要具有基于资源的策略和 IAM 策略部分中列出的权限。

2.    配置存储桶 ACL 以至少包含账户 B 的 WRITE 权限。这可确保账户 B 的 IAM 角色或用户可以将对象上传(调用 PutObject API)到账户 A 拥有的存储桶:

...
<AccessControlPolicy>
  <Owner>
    <ID> AccountACanonicalUserID </ID>
    <DisplayName> AccountADisplayName </DisplayName>
  </Owner>
  <AccessControlList>
...
    <Grant>
      <Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CanonicalUser">
        <ID> AccountBCanonicalUserID </ID>
        <DisplayName> AccountBDisplayName </DisplayName>
      </Grantee>
      <Permission> WRITE </Permission>
    </Grant>
    ...
  </AccessControlList>
</AccessControlPolicy>

注意:要查找您的 CanonicalUserID,请参阅查找 AWS 账户规范用户 ID。​

3.    配置对象 ACL 以至少包含账户 B 的 READ 权限。这将确保账户 B 中的 IAM 角色或用户能够从账户 A 拥有的存储桶下载对象(调用 GetObject API):

...
<AccessControlPolicy>
  <Owner>
    <ID> AccountACanonicalUserID </ID>
    <DisplayName> AccountADisplayName </DisplayName>
  </Owner>
  <AccessControlList>
...
    <Grant>
      <Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CanonicalUser">
        <ID> AccountBCanonicalUserID </ID>
        <DisplayName> AccountBDisplayName </DisplayName>
      </Grantee>
      <Permission> READ </Permission>
    </Grant>
    ...
  </AccessControlList>
</AccessControlPolicy>

ACL 权限因将应用 ACL 的 S3 资源、存储桶或对象而异。有关更多信息,请参阅访问控制列表 (ACL) 概述。您可以在创建存储桶时配置存储桶和对象 ACL,也可以在向现有存储桶上传对象时进行配置。要了解更多信息,请参阅管理 ACL

跨账户 IAM 角色

并非所有 AWS 服务都支持基于资源的策略。这意味着您可以在向多个服务提供跨账户访问权限时,使用跨账户 IAM 角色来集中管理权限。使用跨账户 IAM 角色简化了对存储在多个 S3 存储桶中的 S3 对象的跨账户访问权限的调配。因此,您无需为 S3 存储桶管理多个策略。此方法允许跨账户访问其他 AWS 账户或 AWS 服务拥有或上载的对象。如果您不使用跨账户 IAM 角色,则必须修改对象 ACL。如需了解详情,请参阅 Amazon S3 如何授权对象操作的请求​。

要使用跨账户 IAM 角色来管理 S3 存储桶访问权限,请按照以下步骤操作:

1.    在账户 A 中创建一个 IAM 角色。然后,向该角色授予执行所需 S3 操作的权限。在角色的信任策略中,向账户 B 中的某个角色或用户授予代入账户 A 中角色的权限:

注意:IAM 角色需要信任策略,用于定义哪些委托人可以在哪些条件下担任该角色。IAM 角色可以有多个权限策略(内联和附加策略),用于定义担任该角色的委托人能够执行的权限以及对哪些资源执行权限。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::AccountB:user/AccountBUserName"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

您还可以使用 AWS CLI 命令示例 create-role 创建具有信任的角色策略。

下面的访问策略允许代入该角色的用户通过编程方式以及 Simple Storage Service (Amazon S3) 控制台下载和上载对象。如需了解详情,请参阅如何使用 IAM 策略向特定用户授予对特定文件夹的访问权限?

注意:如果只需要编程访问,可以移除上述策略中的前两个语句:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "s3:ListAllMyBuckets"
            ],
            "Effect": "Allow",
            "Resource": [
                "arn:aws:s3:::*"
            ]
        },
        {
            "Action": [
                "s3:ListBucket",
                "s3:GetBucketLocation"
            ],
            "Effect": "Allow",
            "Resource": "arn:aws:s3:::AccountABucketName"
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:PutObject"
            ],
            "Resource": "arn:aws:s3:::AccountABucketName/*"
        }
    ]
}

还可以使用 AWS CLI 命令示例 create-policy 创建基于 IAM 身份的策略。

2.    向账户 B 中的 IAM 角色或用户授予代入您在账户 A 中创建的 IAM 角色的权限。

注意:必须添加以下示例策略作为 IAM 用户或角色的权限策略。

{
  "Version": "2012-10-17",
  "Statement": {
    "Effect": "Allow",
    "Action": "sts:AssumeRole",
    "Resource": "arn:aws:iam::AccountA:role/AccountARole"
  }
}

还可以使用 AWS CLI 命令示例 create-policy 创建基于 IAM 身份的策略。

3.    从账户 B 中的角色代入账户 A 中的角色,以便账户 B 中的 IAM 实体可以执行所需的 S3 操作。如需了解详情,请参阅切换到角色(控制台)

注意:通过代入账户 A 中的 IAM 角色,访问策略将会确定 Amazon S3 操作。该 IAM 角色将被视为账户 A 中的本地 IAM 实体发起的一次 API 调用。跨账户访问无需存储桶策略或 ACL。有关更多信息,请参阅 Amazon S3 操作