为什么我的 Amazon EMR 应用程序失败,并显示 HTTP 403 “Access Denied”(访问被拒绝)AmazonS3Exception 错误?

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

当我提交应用程序到 Amazon EMR 集群时,应用程序遇到 HTTP 403“Access Denied”(访问被拒绝)AmazonS3Exception 错误:

java.io.IOException: com.amazon.ws.emr.hadoop.fs.shaded.com.amazonaws.services.s3.model.AmazonS3Exception: Access Denied (Service: Amazon S3; Status Code: 403; Error Code: AccessDenied; Request ID: 8B28722038047BAA; S3 Extended Request ID: puwS77OKgMrvjd30/EY4CWlC/AuhOOSNsxfI8xQJXMd20c7sCq4ljjVKsX4AwS7iuo92C9m+GWY=), S3 Extended Request ID: puwS77OKgMrvjd30/EY4CWlC/AuhOOSNsxfI8xQJXMd20c7sCq4ljjVKsX4AwS7iuo92C9m+GWY=

解决方法

如果权限配置不正确,则您可能会在 Amazon EMR 或 Amazon Simple Storage Service (Amazon S3) 上收到“Access Denied”(访问被拒绝)错误。

首先,请检查您的应用程序代码中指定的凭证或角色

在 EMR 集群的主节点上运行以下命令。使用您的 Amazon S3 路径替换 s3://doc-example-bucket/abc/

aws s3 ls s3://doc-example-bucket/abc/

如果此命令成功,则说明应用程序代码中指定的凭证或角色导致“Access Denied”(访问被拒绝)错误。确认您的应用程序使用的是预期凭证或者代入的是预期角色,并且它有权访问 Amazon S3 路径。通过使用 AWS CLI 代入 AWS Identity and Access Management (IAM) 角色来验证该角色拥有访问 Amazon S3 路径的权限。然后,对 S3 路径执行示例请求。

如果此命令失败,请确认您使用的是最新版本的 AWS Command Line Interface (AWS CLI)。然后,请检查以下各项以解决“访问被拒绝”错误:

    检查 Amazon EC2 实例配置文件角色的策略

    如果 Amazon Elastic Compute Cloud (Amazon EC2) 实例配置文件在 S3 存储桶上没有所需的读取和写入权限,则可能会收到“Access Denied”(访问被拒绝)错误。

    注意:默认情况下,应用程序将会从 Amazon EC2 实例配置文件的 IAM 角色继承 Amazon S3 访问权限。请确保附加于此角色的 IAM 策略允许对源和目标存储桶执行所需的 S3 操作。

    要排查此问题,请运行以下命令以检查您是否具有所需的读取权限:

    $ aws s3 ls s3://doc-example-bucket/myfolder/

    输出可能类似于以下内容:

    An error occurred (AccessDenied) when calling the ListObjectsV2 operation: Access Denied

    – 或者 –

    运行以下命令:

    $ hdfs dfs -ls s3://doc-example-bucket/myfolder

    输出可能类似于以下内容:

    ls: com.amazon.ws.emr.hadoop.fs.shaded.com.amazonaws.services.s3.model.AmazonS3Exception: Access Denied (Service: Amazon S3; Status Code: 403; Error Code: AccessDenied; Request ID: RBT41F8SVAZ9F90B; S3 Extended Request ID: ih/UlagUkUxe/ty7iq508hYVfRVqo+pB6/xEVr5WHuvcIlfQnFf33zGTAaoP2i7cAb1ZPIWQ6Cc=; Proxy: null), S3 Extended Request ID: ih/UlagUkUxe/ty7iq508hYVfRVqo+pB6/xEVr5WHuvcIlfQnFf33zGTAaoP2i7cAb1ZPIWQ6Cc=

    请确保实例配置文件角色对 S3 存储桶具有所需的读写权限。例如,以下 IAM 策略中的 S3 操作提供了对 S3 存储桶 doc-example-bucket 所需的读写访问权限:

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Sid": "ListObjectsInBucket",
          "Effect": "Allow",
          "Action": [
            "s3:ListBucket"
          ],
          "Resource": [
            "arn:aws:s3:::doc-example-bucket"
          ]
        },
        {
          "Sid": "AllObjectActions",
          "Effect": "Allow",
          "Action": "s3:*Object*",
          "Resource": [
            "arn:aws:s3:::doc-example-bucket/*"
          ]
        }
      ]
    }

    检查用于 EMRFS 角色映射的 IAM 角色

    当您使用安全配置为 EMRFS 指定 IAM 角色时,则您正在使用角色映射。您的应用程序将根据角色映射配置从 IAM 角色继承 S3 权限。

    附加到这些角色的 IAM 策略必须对源和目标存储桶具有所需的 S3 权限。要为至 Amazon S3 的 EMRFS 请求指定 IAM 角色,请参阅使用 IAM 角色为 EMRFS 设置安全配置

    检查 Amazon S3 VPC 终端节点策略

    如果 EMR 集群的子网路由表有指向 Amazon S3 VPC 终端节点的路由,则确认终端节点策略允许所需的 Amazon S3 操作。

    要使用 CLI 检查和修改端点策略,请执行以下操作:

    运行以下命令以检查终端节点策略。将 vpce-xxxxxxxx 替换为您的 VPC ID。

    aws ec2 describe-vpc-endpoints --vpc-endpoint-ids "vpce-xxxxxxxx"

    如有必要,运行以下命令来上传修改后的终端节点策略。替换 VPC ID 和 JSON 文件路径。

    aws ec2 modify-vpc-endpoint --vpc-endpoint-id "vpce-xxxxxxxx" --policy-document file://policy.json

    要使用 Amazon VPC 控制台检查和修改端点策略,请执行以下操作:

    1. 打开 Amazon VPC 控制台
    2. 在导航窗格中,选择 Endpoints(端点)。
    3. 选择 Amazon S3 终端节点(EMR 集群的子网路由表中的终端节点)。然后,选择 Policy(策略)选项卡以查看终端节点策略。
    4. 要添加所需的 Amazon S3 操作,选择 Edit Policy(编辑策略)。

    检查 S3 源和目标存储桶策略

    存储桶策略指定委托人允许或拒绝的操作。源和目标存储桶策略必须允许 EC2 实例配置文件角色或映射的 IAM 角色执行所需的 Amazon S3 操作。

    要使用 CLI 检查和修改存储桶策略,请执行以下操作:

    运行以下命令来检查存储桶策略。使用源或目标存储桶的名称替换 doc-example-bucket

    aws s3api get-bucket-policy --bucket doc-example-bucket

    如有必要,运行以下命令来上传修改后的存储桶策略。替换存储桶名称和 JSON 文件路径。

    aws s3api put-bucket-policy --bucket doc-example-bucket --policy file://policy.json

    要使用 Amazon S3 控制台检查和修改存储桶策略,请执行以下操作:

    1. 打开 Amazon S3 控制台
    2. 选择存储桶。
    3. 选择权限选项卡。
    4. 选择 Bucket Policy(存储桶策略)以检查并修改存储桶策略。

    访问另一个账户中的 S3 存储桶

    重要提示:如果您的应用程序访问另一个 AWS 账户的 S3 存储桶,则账户拥有者必须允许您在存储桶策略上的 IAM 角色。

    例如,以下存储桶策略将为 emr-account 中的所有 IAM 角色和用户提供 s3://doc-example-bucket/myfolder/ 的全部访问权限。

    {
      "Id": "MyCustomPolicy",
      "Version": "2012-10-17",
      "Statement": [
        {
          "Sid": "AllowRootAndHomeListingOfCompanyBucket",
          "Principal": {
            "AWS": [
              "arn:aws:iam::emr-account:root"
            ]
          },
          "Action": [
            "s3:ListBucket"
          ],
          "Effect": "Allow",
          "Resource": [
            "arn:aws:s3:::doc-example-bucket"
          ],
          "Condition": {
            "StringEquals": {
              "s3:prefix": [
                "",
                "myfolder/"
              ],
              "s3:delimiter": [
                "/"
              ]
            }
          }
        },
        {
          "Sid": "AllowListingOfUserFolder",
          "Principal": {
            "AWS": [
              "arn:aws:iam::emr-account:root"
            ]
          },
          "Action": [
            "s3:ListBucket"
          ],
          "Effect": "Allow",
          "Resource": [
            "arn:aws:s3:::doc-example-bucket"
          ],
          "Condition": {
            "StringLike": {
              "s3:prefix": [
                "myfolder/*"
              ]
            }
          }
        },
        {
          "Sid": "AllowAllS3ActionsInUserFolder",
          "Principal": {
            "AWS": [
              "arn:aws:iam::emr-account:root"
            ]
          },
          "Effect": "Allow",
          "Action": [
            "s3:*"
          ],
          "Resource": [
            "arn:aws:s3:::doc-example-bucket/myfolder/*",
            "arn:aws:s3:::doc-example-bucket/myfolder*"
          ]
        }
      ]
    }