在使用 IAM 角色或用户请求 API 调用时,如何排除显式拒绝错误消息?

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

使用 AWS Identity and Access Management(IAM)角色或用户请求 API 调用时,我收到了显式拒绝错误消息。如何排查和解决显式拒绝错误消息?

简短描述

为使 IAM 实体(角色或用户)成功进行 API 调用,该实体必须满足以下条件:

  • 角色或用户具有请求 API 调用的正确权限。
  • 适用于请求上下文的所有策略中的任何语句都不会拒绝该权限。

如果您的 IAM 实体不符合这些条件,则 API 调用将失败并引发类似于以下内容的(AccessDenied)错误:

  • 遇到问题的 IAM 用户或角色:arn:XXXXXXXX:iam::XXXXXXXX:role/TestReadOnly

    错误:调用 RunInstances 操作时出错(AccessDenied):用户:arn:aws:iam::XXXXXXXX:user/tester 无权在资源:role TestReadOnly 上执行:ec2:RunInstances,带有显式拒绝

注意:本文中的问题排查步骤专门处理显式拒绝错误,而不是隐式拒绝错误。有关隐式拒绝错误的更多信息,请参阅隐式拒绝和显式拒绝之间的区别

解决方法

出现显式拒绝错误的原因是以下一个或多个策略存在问题:

  • 基于身份的策略
  • 基于资源的策略
  • 权限边界
  • 服务控制策略
  • 会话策略

基于身份的策略

基于身份的策略控制实体允许/拒绝的操作。使用以下问题排查步骤确定基于身份的策略存在的问题。

注意:最佳做法是在条件中将 DenyStringNotLike 结合使用以防止意外特权访问。

1.    检查基于身份的策略中是否没有 Deny 语句。此示例包含一个 Deny 语句:

{
  "Effect": "Deny",
  "Action": "iam:DeleteRole"
  "Resource": "*"
}

2.    检查您的策略是否强制实施了多重身份验证(MFA)。如果您的 IAM 实体在强制实施 MFA 时未使用其他身份验证要素进行身份验证,则权限将被拒绝。例如,如果您的实体在不实施 MFA 的情况下使用 AWS CLI 进行身份验证,则您的 API 调用将被拒绝。请参阅这个 MFA 强制实施的例子:

{
  "Sid": "DenyAllExceptListedIfNoMFA",
  "Effect": "Deny",
  "NotAction": [
    "iam:CreateVirtualMFADevice",
    "iam:EnableMFADevice",
    "iam:GetUser",
    "iam:ListMFADevices",
    "iam:ListVirtualMFADevices",
    "iam:ResyncMFADevice",
    "sts:GetSessionToken"
  ],
  "Resource": "*",
  "Condition": {
    "BoolIfExists": {"aws:MultiFactorAuthPresent": "false"}
  }
}

此策略明确拒绝所有 API 调用,但 NotAction 策略元素中提到的调用除外。

3.    确保您的策略符合所有必需条件。如果您的策略有多个条件运算符或多个密钥,则使用 AND 逻辑评估条件。每个 RequestTag 密钥必须在单独的语句中使用才能获得相同的 AND 逻辑。以下是导致 API 调用失败的常见问题的示例:

{
  "Sid": "AllowRunInstancesWithRestrictions2",
  "Effect": "Deny",
  "Action": [
    "ec2:CreateVolume",
    "ec2:RunInstances"
  ],
  "Resource": [
    "arn:aws:ec2:*:*:volume/*",
    "arn:aws:ec2:*:*:instance/*"
  ],
  "Condition": {
    "ForAllValues:StringNotLike": {
      "aws:TagKeys": "Production"
    },
    "StringEquals": {
      "ec2:InstanceType": "t2.micro"
    }
  }
}

为避免这些 API 调用出现显式拒绝访问错误,请确保满足上述条件。

注意aws:TagKeys 条件区分大小写。

基于资源的策略

基于资源的策略允许或拒绝对资源的访问。与统一的基于 IAM 身份的策略不同,基于资源的策略是由服务设计的。以下问题排查步骤以 Amazon Simple Storage Service(Amazon S3)基于资源的策略和 VPC 端点策略为例。

S3 存储桶策略评估

Amazon S3 存储桶策略评估的工作原理如下:

注意:假定存储桶 ACL 设置为默认。

  • 要访问同一账户中的存储桶,IAM 实体需要基于 IAM 身份的策略 OR 存储桶策略中的权限。
  • 要访问其他账户中的存储桶,IAM 实体需要存储桶策略 AND 基于 IAM 身份的策略中的权限才能获得访问权限。

1.    在基于资源的策略中检查 Deny 语句。此示例显示存储桶策略中的 Deny 语句:

{
  "Effect": "deny",
  "Principal": {
    "AWS": "arn:aws:iam::111111111111:role/ROLENAME"
  },
  "Action": "s3:ListBucket",
  "Resource": "arn:aws:s3:::MyExampleBucket"
}

2.    检查您的策略中描述的 ARN 是否正确。

3.    如果当前用户的 aws:userid 不等于策略中定义的值,则存储桶策略将拒绝访问。请参阅这个例子:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Deny",
      "Principal": "*",
      "Action": "s3:*",
      "Resource": [
        "arn:aws:s3:::MyExampleBucket",
        "arn:aws:s3:::MyExampleBucket/*"
      ],
      "Condition": {
        "StringNotLike": {
          "aws:userId": [
            "AROAEXAMPLEID:*",
            "AIDAEXAMPLEID",
            "111111111111"
          ]
        }
      }
    }
  ]
}

VPC 端点

VPC 端点策略是附加到端点的 IAM 资源策略。此策略不会覆盖或替换 IAM 用户策略或特定于服务的策略(例如 S3 存储桶策略)。

在使用接口端点连接到 Amazon S3 时,有两种方法可以控制对 Amazon S3 数据的访问:

  • 您可以控制可以使用 VPC 端点访问端点服务的 AWS 主体(AWS 账户、IAM 用户和 IAM 角色)。
  • 您可以使用 Amazon S3 存储桶策略控制有权访问存储桶的 VPC 或 VPC 端点。

以下是 Amazon S3 存储桶策略的一个例子。该策略限制从 ID 为 vpce-11111 的 VPC 端点访问名为 examplebucket 的特定存储桶。如果未使用指定的端点,该策略将拒绝对该存储桶的所有访问。aws:SourceVpce 条件用于指定端点。

{
   "Version": "2012-10-17",
   "Id": "Policy123456789”,
   "Statement": [
     {
       "Sid": "AccessSpecificVPCEOnly",
       "Principal": "*",
       "Action": "s3:*",
       "Effect": "Deny",
       "Resource": ["arn:aws:s3:::examplebucket",
                    "arn:aws:s3:::examplebucket/*"],
       "Condition": {
         "StringNotEqualsIfExists": {
           "aws:SourceVpce": "vpce-11111”
         }
       }
     }
   ]
}

请务必检查 VPC 端点是否明确拒绝对资源的访问。

权限边界

权限边界是一种托管策略,该策略设置基于身份的策略可向 IAM 实体授予的最高权限。此托管策略可以限制对实体的权限,这可能会导致显式拒绝错误消息。

此示例显示了一个在 IAM policy 中允许但在权限边界中被明确拒绝的操作。请参阅下面的权限边界:

{
  "Version": "2012-10-17",

  "Statement": [

    {
      "Effect": "Deny",
      "Action": "ec2:*"

      "Resource": "*"
    }
  ]
}

用户拥有以下权限:

{
  "Version": "2012-10-17",
  
  "Statement": {
    "Effect": "Allow",
    "Action": "ec2:RunInstances",
    
    "Resource": "*"
  }
}

尽管用户拥有 RunInstances 权限,但他们在请求权限时会收到一条显式拒绝消息。要解决此错误,请确保您的权限边界和 IAM 都明确允许此操作。

服务控制策略

服务控制策略(SCP)允许您管理组织中的权限。以下示例显示了 SCP 中的一条 Deny 语句。在本示例中,SCP 附加到成员账户或特定组织单元(OU)。它明确拒绝对 RunInstances 操作的访问:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Deny",
      "Action": "ec2:RunInstances"

      "Resource": "*"
    }
  ]
}

要解决显式拒绝错误,请执行以下其中一项操作:

  • 将 SCP 与账户分离。
  • 通过添加排除某些使用案例的条件来修改 Deny 语句。例如,如果 IAM 主体使用角色 CloudOps,则此示例中的此 SCP 不会拒绝 ec2:RunInstances:
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Deny",
      "Action": "ec2:RunInstances"     
      "Resource": "*",
      "Condition": {
        "ArnNotLike": {
          "aws:PrincipalARN": "arn:aws:iam::*:role/CloudOps"
        }
      }
    }
  ]
}

会话策略

会话策略是在以编程方式为角色或用户创建临时会话时作为参数传递的高级策略。您可以使用 AssumeRole、AssumeRoleWithSAML 或 AssumeRoleWithWebIdentity API 操作创建角色会话并传递会话策略。

例如,当用户尝试进行 RunInstances API 调用时,此策略会生成显式拒绝错误。务必检查会话策略中是否存在 Deny 语句:

{
  "Version": "2012-10-17",
  
  "Statement": {
    "Effect": "Deny",
    "Action": "ec2:RunInstances",
    
    "Resource": "*"
  }
}