排查 AWS CLI 中的 'Access Denied' 和身份验证问题
系统性地排查使用 AWS CLI 时遇到的 'Access Denied' 和身份验证错误。本指南涵盖关键诊断步骤,从使用 `aws sts get-caller-identity` 验证凭证开始,检查复杂的 IAM 策略评估层次结构,并解决由临时凭证或基于资源的策略(如 S3 存储桶策略)引起的问题。学习使用关键命令和 IAM 策略模拟器,快速识别并修复 AWS 环境中的授权失败。
排查 AWS CLI 中的 'Access Denied' 和身份验证问题
AWS CLI 中的 Access Denied 令人沮丧,因为消息通常会指出失败的 API 调用,但不会指出导致问题的策略行。这些问题几乎总是源于配置错误的身份和访问管理 (IAM) 策略、过期的临时凭证或 CLI 环境设置不正确。
一个有用的习惯是将问题分解为两个问题:CLI 以谁的身份调用,以及哪个策略边界阻止该身份执行操作?
1. 初步诊断:识别调用者和凭证
在深入进行复杂的策略分析之前,第一步是明确确认 AWS CLI 正在使用哪个 IAM 身份,以及这些凭证是否仍然有效。
检查当前身份:sts get-caller-identity
这是最关键的诊断命令。它确切地告诉您是哪个用户 ARN、角色 ARN 或假设角色会话正在执行后续的 AWS 命令。
aws sts get-caller-identity
预期输出:
{
"UserId": "AIDAIAMUSERID",
"Account": "123456789012",
"Arn": "arn:aws:iam::123456789012:user/DevUser"
}
如果返回的 ARN 与您期望的用户或角色不匹配,则说明您正在使用错误的 AWS 配置文件或环境变量。
验证配置文件配置和区域
确保使用了正确的 AWS 配置文件,可以通过 --profile 标志指定,也可以通过 AWS_PROFILE 环境变量设置。
# 检查默认配置文件的设置
aws configure list
# 或检查特定配置文件
aws configure list --profile prod-admin
如果输出显示没有区域或区域不正确,则对全局资源或特定区域服务(如 S3 存储桶或 EC2 实例)的操作可能会失败,有时如果 CLI 查找的位置找不到资源,则会导致 Access Denied。
提示: 如果
sts get-caller-identity命令本身因身份验证错误而失败,则表明访问密钥存在根本性问题(可能已被删除、撤销或不正确)。
处理临时凭证
如果您使用 IAM 角色(通过 STS AssumeRole),则 CLI 使用包含 SessionToken 的临时凭证。这些凭证在会话配置的持续时间后过期,在默认设置中通常为一小时。虽然 AWS CLI 在从标准凭证提供程序链获取时通常会自动刷新它们,但手动配置可能会失败。
症状: 命令最初有效,但在设定时间段(例如 60 分钟)后失败,并出现身份验证错误。
解决方案: 如果使用自定义脚本或手动加载的环境,请确保您的角色代入方法包含在凭证过期时刷新凭证的机制。
2. 深入探讨 IAM 策略和授权
一旦确认了所使用的身份,下一步就是确定该身份为何缺乏必要的权限。AWS 授权失败很复杂,因为多个策略会同时进行评估。
IAM 策略评估层次结构
授权错误通常是由以下策略组件之一引起的:
- 显式拒绝: 任何适用策略(身份、资源或边界)中的显式
Deny语句始终会覆盖Allow语句。 - 缺少允许: 适用于身份或资源的策略均未授予特定操作。
A. 基于身份的策略(用户和角色)
检查直接附加到用户或正在承担的角色的 IAM 策略。查找:
- 缺少操作: 策略是否明确列出了必要的 API 操作(例如
s3:ListBucket、ec2:DescribeInstances)? - 资源约束: 策略是否使用
Resource元素将操作限制为特定资源?一个常见错误是在操作需要特定 ARN 时设置Resource: "*",反之亦然。 - 条件: 是否存在未满足的条件(例如源 IP 地址、时间、需要 MFA)?
B. 基于资源的策略(S3、SQS、KMS)
对于 S3 或 KMS 等服务,资源本身有一个策略来规定谁可以访问它。对于跨账户访问以及许多特定于资源的设计,资源策略还必须允许主体。在同一账户中,确切的交互取决于主体类型和服务,因此不要假设身份策略单独就能解释所有结果。
示例: 尝试访问一个 S3 存储桶(资源策略),该策略对所有来自特定 VPC 端点之外的用户具有显式 Deny,无论用户的 IAM 策略如何,都将导致 Access Denied。
C. 权限边界和 SCP
如果您的组织使用 AWS Organizations,则服务控制策略 (SCP) 定义了账户内允许的最大权限。类似地,权限边界限制了 IAM 实体可能拥有的最大权限。
如果 SCP 或边界拒绝了所需的操作,则 CLI 操作将失败,即使身份策略授予了权限。
实用工具:IAM 策略模拟器
在排查复杂的故障时,AWS 管理控制台中的 IAM 策略模拟器非常有用。您可以针对特定资源(例如 arn:aws:s3:::my-bucket/key)测试特定操作(例如 s3:GetObject),并指定 IAM 实体,帮助您精确定位导致拒绝的策略语句。
3. 常见的 'Access Denied' 场景和解决方案
场景 1:S3 访问被拒绝(资源与身份)
S3 Access Denied 是出了名的,因为它可能源于用户策略或存储桶策略。
| 原因 | 诊断 | 解决方案 |
|---|---|---|
| 缺少存储桶策略允许 | sts get-caller-identity 有效,但 aws s3 ls 失败。 |
修改存储桶策略以明确允许调用 ARN 执行必要的操作(s3:ListBucket、s3:GetObject)。 |
| 缺少 KMS 解密权限 | 访问加密对象失败(即使 S3 策略允许)。 | 确保 IAM 实体有权使用加密对象的基础 KMS 密钥(kms:Decrypt)。 |
| 请求者付费 | 尝试下载大文件失败。 | 如果存储桶要求请求者付费,则 CLI 命令必须包含 --request-payer requester 标志。 |
场景 2:由于条件失败导致的隐式拒绝
许多策略使用条件来强制执行安全最佳实践,例如要求多因素身份验证 (MFA)。
如果您的策略包含如下条件:
"Condition": {
"Bool": {
"aws:MultiFactorAuthPresent": "true"
}
}
并且您尝试在未通过身份验证的 MFA 的情况下运行命令,则该操作将被隐式拒绝。
解决方案: 对于需要 MFA 的命令,您必须首先创建一个使用您的 MFA 设备进行身份验证的 STS 会话:
# 1. 使用您的 MFA 令牌获取临时凭证
aws sts get-session-token --serial-number arn:aws:iam::123456:mfa/user --token-code 123456
# 2. 将生成的 AccessKeyId、SecretAccessKey 和 SessionToken 导出为 CLI 会话的环境变量。
场景 3:区域缺失或不正确
虽然不总是 Access Denied 错误,但尝试对资源执行操作而未指定正确的区域通常会导致授权或资源未找到失败,尤其是在处理区域服务(如 EC2、DynamoDB 或 EKS)时。
解决方案: 在命令中明确定义区域,或确保您的配置文件配置正确。
aws ec2 describe-instances --region us-west-2
节省时间的特定服务检查
当您不再将 AWS 视为一个权限系统时,IAM 错误更容易调试。每个服务都添加了自己的资源模型和条件键。
对于 S3,将存储桶级操作与对象级操作分开。s3:ListBucket 使用存储桶 ARN,而 s3:GetObject 和 s3:PutObject 使用存储桶下的对象 ARN。授予 arn:aws:s3:::my-bucket 上 s3:GetObject 的策略形状错误;对象访问需要 arn:aws:s3:::my-bucket/*。相反的错误对于列出操作同样常见。
对于 KMS,请同时检查密钥策略和 IAM 策略。一个角色可能看起来拥有 kms:Decrypt,但如果密钥策略不允许该角色路径,则解密仍然会失败。这在下载加密的 S3 对象、拉取加密的 EBS 快照或读取使用客户管理密钥的密钥时会出现。
对于 ECR,Docker 登录和镜像拉取需要多个服务对齐。CLI 身份可能需要 ecr:GetAuthorizationToken,并且如果存储库跨账户共享,则存储库策略可能需要允许拉取操作。如果集群节点角色正在拉取镜像,则使用您的个人管理员配置文件进行调试几乎无法证明什么;请以节点角色或任务执行角色进行测试。
对于 STS 代入角色工作流,请查看信任关系的双方。调用者需要调用 sts:AssumeRole 的权限,并且目标角色信任策略必须信任调用者。如果信任策略中存在外部 ID 或 MFA 条件,则代入角色命令必须满足它。
环境优先级可能会迷惑经验丰富的用户
AWS CLI 不仅读取 ~/.aws/credentials。它会遍历一个凭证提供程序链,其中可能包括命令行标志、环境变量、命名配置文件、SSO 缓存条目、Web 身份令牌、EC2 或 ECS 元数据以及配置文件中配置的角色代入。这就是为什么 aws configure list 比打开一个文件更有用。
一个常见的本地故障如下:您运行 export AWS_PROFILE=dev,然后稍后将临时生产凭证粘贴到 AWS_ACCESS_KEY_ID、AWS_SECRET_ACCESS_KEY 和 AWS_SESSION_TOKEN 中。环境密钥可能会接管,因此看起来使用 dev 的命令实际上正在使用导出的会话。在已打开一天的终端中,运行:
env | sort | grep '^AWS_'
如果您经常切换账户,请使用单独的终端选项卡、凭证助手或在破坏性命令之前打印调用者身份的包装脚本。输出中的额外一行比从错误账户中删除要便宜。
4. 诊断命令总结
使用此命令检查表快速诊断授权失败链:
| 目标 | 命令 | 目的 |
|---|---|---|
| 验证身份 | aws sts get-caller-identity |
确认执行命令的 ARN。 |
| 验证配置 | aws configure list |
检查配置文件设置、区域和输出格式。 |
| 测试策略有效性 | (使用 IAM 策略模拟器) | 检查 IAM 身份是否可以对资源执行特定的 API 操作。 |
| 识别策略拒绝 | aws cloudtrail lookup-events ... |
使用 CloudTrail 查看策略评估失败的确切事件记录。 |
一个真实的调试路径
一个好的第一遍看起来像这样。即使您认为您的 shell 已经设置好,也要使用显式编写的配置文件和区域再次运行失败的命令:
AWS_PROFILE=prod-readonly aws s3 ls s3://example-audit-logs --region us-east-1
aws sts get-caller-identity --profile prod-readonly
aws configure list --profile prod-readonly
如果身份错误,请停在那里。检查环境中的 AWS_ACCESS_KEY_ID、AWS_SECRET_ACCESS_KEY、AWS_SESSION_TOKEN、AWS_PROFILE 和 AWS_REGION。环境凭证可以优先于配置文件,并使 CLI 充当您忘记之前导出的角色。在 CI 中,在失败的步骤附近打印 aws sts get-caller-identity,以便构建日志证明运行时使用的角色。
如果身份正确,请记下确切的 API 操作。高级命令可能会隐藏这一点。aws s3 cp 可能需要 s3:GetObject、s3:PutObject、s3:ListBucket、kms:Decrypt 或 kms:GenerateDataKey,具体取决于方向、加密以及 CLI 是否必须检查存储桶。当错误消息包含 AccessDenied 但不包含操作时,CloudTrail 通常会为您提供事件名称和资源。
对于 S3,请检查存储桶策略、对象所有权、阻止公共访问设置、VPC 端点策略和 KMS 密钥策略。对于 KMS 加密的对象,S3 允许是不够的;调用者还需要相关的 KMS 权限,并且密钥策略必须允许主体路径。对于组织,在编辑身份策略之前检查 SCP。SCP 不能授予访问权限,但它可以限制账户中任何主体可以执行的操作。
预防主要是枯燥的卫生习惯:短期角色凭证、名称清晰的配置文件、针对真实 ARN 测试的最小权限策略,以及启用 CloudTrail 以便工程师可以实际查询它。最好的修复不是更广泛的 Action: "*";而是找到缺少的一个操作或与请求匹配的一个拒绝条件。