如何使用 IAM 策略排查访问被拒绝或未经授权操作错误?

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

我正在尝试对 AWS 资源执行操作,但收到“access denied(访问被拒绝)”或“unauthorized operation(未经授权操作)”错误。如何排查此类权限问题?

简短描述

要排查 AWS Identity and Access Management(IAM)策略的问题,请执行以下操作:

解决方法

确定 API 调用方并理解错误消息

重要提示:

请务必在查看 IAM 策略前代表正确的 IAM 实体进行 API 调用。如果错误消息不包含调用方信息,请按照以下步骤确定 API 调用方:

  1. 打开 AWS 管理控制台
  2. 在页面右上角选择账户信息旁边的箭头。
  3. 如果您以 IAM 角色的身份登录,“当前活跃身份”表示代入角色的名称,“账户 ID”表示账户 ID。
  4. 如果您以联合身份用户的身份登录,“联合身份用户”表示联合身份角色的名称和角色会话的名称。

-或者-

使用 AWS CLI 命令 get-caller-identity 来确定 API 调用方。您也可以使用带 --debug 标记的 AWS CLI 命令通过与下面的内容相似的输出确定凭证来源:

2018-03-13 16:23:57,570 - MainThread - botocore.credentials - INFO - Found credentials in shared credentials file: ~/.aws/credentials

检查 IAM 策略权限

通过检查附上的 IAM 策略来验证是否已授予 API 调用方必要的权限。有关更多信息,请参阅确定在账户内是否允许或拒绝请求

评估 AWS Organizations SCP

如果 AWS 账户是 AWS Organizations 的一部分,则可以在分层级别应用 SCP 以允许或拒绝操作。SCP 权限由 AWS 账户中的所有 IAM 实体继承。确保 SCP 中未明确拒绝 API 调用方。

确保被调用的 API 在影响调用方的组织 SCP 策略中没有被明确拒绝

查看基于身份的策略和基于资源的策略

确保 IAM 实体基于身份的策略中有针对 API 调用方的明确允许语句。然后,确保 API 支持资源级权限。如果 API 调用方不支持资源级权限,请确保在 IAM 策略语句的资源元素中指定了通配符“*”

您可以将基于资源的策略附加到 AWS 服务中的资源以提供访问权限。有关更多信息,请参阅基于身份的策略和基于资源的策略

要查看 IAM 策略摘要,请执行以下操作:

  1. 打开 IAM 控制台
  2. 在导航窗格中,选择 Policies(策略)。
  3. 选择策略名称旁边的箭头来展开策略详细信息视图。

在以下示例中,策略不起作用,因为并非所有 Amazon Elastic Compute Cloud(Amazon EC2)API 操作都支持资源级权限:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "SorryThisIsNotGoingToWorkAsExpected",
            "Effect": "Allow",
            "Action": ["ec2:*"],
            "Resource": "arn:aws:ec2:us-east-1:accountid:instance/*"
        }
    ]
}

尝试使用 run-instances AWS CLI 命令在 us-east-1 区域启动 Amazon EC2 实例的 IAM 用户会收到类似以下内容的错误消息:

"An error occurred (UnauthorizedOperation) when calling the RunInstances operation: You are not authorized to perform this operation. Encoded authorization failure message:…"

要解决此问题,请将资源更改为通配符“*”。这是因为 Amazon EC2 仅支持部分资源级权限

要解码授权失败消息以获取有关此失败原因的更多详细信息,请使用类似于以下内容的 DecodeAuthorizationMessage API 操作:

$ aws sts decode-authorization-message --encoded-message <encoded-message-from-the-error>

检查权限边界

如果 IAM 实体附加了权限边界,则边界将设置该实体拥有的最大权限。有关更多信息,请参阅如何使用权限边界限制 IAM 用户和角色的范围,同时防止权限升级?

评估会话策略

如果 API 调用方是 IAM 角色或联合身份用户,则会在会话持续时间内传递会话策略。会话的权限是如下策略的交集:用于创建会话的 IAM 实体的基于身份的策略和会话策略。确保 IAM 策略和实体中存在该 API 调用。

确保策略中的条件键受 API 支持

AWS 条件键可用于将向 AWS 发出的 API 请求中的元素与 IAM 策略中指定的键值进行比较。条件键可以是全局条件键,也可以由 AWS 服务定义。AWS 服务特定的条件键只能在该服务中使用(例如 EC2 API 操作中的 EC2 条件)。有关更多信息,请参阅 AWS 服务的操作、资源和条件上下文键

一个条件元素可以包含多个条件,并且在每个条件块中可以包含多个键值对。有关更多信息,请参阅创建具有多个键或值的条件

在此策略示例中,如果 IAM API 请求由 IAM 用户 admin 调用且源 IP 地址为 1.1.1.0/24 或 2.2.2.0/24,则条件元素相匹配。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "iam:*",
      "Resource": "*",
      "Condition": {
        "StringEquals": {
          "aws:username": "admin"
        },
        "IpAddress": {
          "aws:SourceIp": [
            "1.1.1.0/24",
            "2.2.2.0/24"
          ]
        }
      }
    }
  ]
}

IAM 策略错误和问题排查示例

查看以下示例以确定错误消息、API 调用方、API 和正在被调用的资源:

示例错误消息 API 调用方 API 资源 何时
A:“在调用 DescribeInstances 操作时出现错误(UnauthorizedOperation):未授权您执行此操作。” 未知 DescribeInstances 未知 出错时间
B:“在调用 AssumeRole 操作时出现错误 (AccessDenied):用户 arn:aws:iam::123456789012:user/test 无权对资源 arn:aws:iam::123456789012:role/EC2-FullAccess 执行 sts:AssumeRole” arn:aws:iam::123456789012:user/test AssumeRole arn:aws:iam::123456789012:role/EC2-FullAccess 出错时间
C:“在调用 GetSessionToken 操作时出现错误 (AccessDenied):无法调用带会话凭证的 GetSessionToken” 未知 GetSessionToken 未知 出错时间
D:“在调用 AssociateIamInstanceProfile 操作时出现错误(UnauthorizedOperation):未授权您执行此操作。已编码授权失败消息:....” 未知 AssociateIamInstanceProfile 未知 出错时间

通过使用此评估方法,您可以确定针对不同 AWS 服务的权限问题收到的错误消息的原因。有关更多详细信息,请参阅以下错误消息和问题排查步骤:

示例错误消息 A:

此错误消息指示您无权调用 DescribeInstances API。

要解决此错误,请执行以下步骤:

  1. 请确定 API 调用方。
  2. 请确认 ec2:DescribeInstances API 操作未包含在任何拒绝语句中。
  3. 请确认 ec2:DescribeInstances API 操作包含在允许语句中。
  4. 请确认未针对此 API 操作指定资源。注意:此 API 操作不支持资源级权限
  5. 请确认允许语句中指定的所有 IAM 条件受 DescribeInstances 操作支持,并且条件相匹配。

有关更多信息,请参阅 DescribeInstanceStatus

示例错误消息 B:

此错误消息包含 API 名称、API 调用方和目标资源。请确保调用 API 的 IAM 身份拥有正确的资源访问权限。使用之前的评估方法查看 IAM 策略。

要解决此错误,请按照以下步骤确认 IAM 角色的信任策略:EC2-FullAccess:

  1. 请确认 arn:aws:iam::123456789012:user/test 或 arn:aws:iam::123456789012:root 未包含在信任策略的任何拒绝语句中。
  2. 请确认 arn:aws:iam::123456789012:user/test 或 arn:aws:iam::123456789012:root 包含在信任策略的允许语句中。
  3. 请确认允许语句中指定的所有 IAM 条件均受 sts:AssumeRole API 操作支持并且相匹配。

请按照以下步骤确认附加到 API 调用方的 IAM 策略(arn:aws:iam::123456789012:user/test):

  1. 请确认 arn:aws:iam::123456789012:role/EC2-FullAccess 未包含在任何含有 sts:AssumeRole API 操作的拒绝语句中。
  2. 如果 arn:aws:iam::123456789012:root 包含在信任策略的允许语句中,请确认 arn:aws:iam::123456789012:role/EC2-FullAccess 包含在含有 sts:AssumeRole API 操作的 IAM 策略的允许语句中。
  3. 请确认允许语句中指定的所有 IAM 条件均受 sts:AssumeRole API 操作支持并且相匹配。

示例错误消息 C:

此错误消息指示 get-session-token 不受临时凭证支持。有关更多信息,请参阅比较 AWS STS API 操作

示例错误消息 D:

此错误消息返回一则可以提供授权失败详细信息的编码消息。要对错误消息进行解码并获得授权失败的详细信息,请参阅 DecodeAuthorizationMessage。在对错误消息进行解码之后,请确定 API 调用方并查看资源级权限和条件。

要解决此错误,请按照以下步骤查看 IAM 策略权限:

  1. 如果错误消息指示 API 被明确拒绝,请从匹配的语句中删除 ec2:AssociateIamInstanceProfile 或 iam:PassRole API 操作。
  2. 请确认 ec2:AssociateIamInstanceProfile 和 iam:PassRole 位于含有受支持和正确的资源目标的允许语句中。例如,请确认 ec2:AssociateIamInstanceProfile API 操作的资源目标是 EC2 实例并且 iam:PassRole 的资源目标是 IAM 角色。
  3. 如果 ec2:AssociateIamInstanceProfile 和 iam:PassRole API 操作位于同一个允许语句中,请确认所有条件均受 ec2:AssociateIamInstanceProfile 和 iam:PassRole API 操作的支持,并且相关条件相匹配。
  4. 如果 ec2:AssociateIamInstanceProfile 和 iam:PassRole API 操作位于不同的允许语句中,请确认各允许语句中的所有条件均受操作支持,并且相关条件相匹配。

有关更多信息,请参阅策略评估逻辑确定在账户内是否允许或拒绝请求