AWS CLI 实战:使用 `aws accessanalyzer validate-policy` 校验 IAM 策略并解读 Findings
2026/9/13 13:32:08 网站建设 项目流程

AWS CLI 实战:使用aws accessanalyzer validate-policy校验 IAM 策略并解读 Findings

【免费下载链接】aws-cliUniversal Command Line Interface for Amazon Web Services项目地址: https://gitcode.com/GitHub_Trending/aw/aws-cli

aws accessanalyzer validate-policy是 AWS CLI 中用于请求 IAM Access Analyzer 对策略文档进行静态校验的命令,它会基于一套策略检查规则返回一组 findings,帮助你发现策略中的错误、安全告警、警告与可优化建议。本文以仓库中自带的实战示例(validate-policy.rst)为主体,逐条解读一份 Cognito 身份池信任策略暴露出的三类问题,并结合当前仓库中的 AWS 服务模型定义(service-2.json)深入剖析命令的完整参数、findings 结构与定位信息,让你掌握"写策略 → 校验 → 看懂报告 → 修复"的完整闭环。

一、命令概览:validate-policy能做什么

IAM Access Analyzer 的ValidatePolicyAPI 会"请求对策略进行校验,并返回一组 findings。这些 findings 帮助你识别问题并提供可操作的建议,从而让你编写出符合安全最佳实践且可正常工作的策略"。该 API 是只读操作("readonly": true),不会修改任何策略,也不会触发实际授权判断,而是纯静态分析。

从服务模型看,该操作对应的 HTTP 请求为POST /policy/validation(见 service-2.json),可能抛出的异常包括:

  • InternalServerException(服务端内部错误)
  • ValidationException(请求参数不合法)
  • ThrottlingException(请求过于频繁被限流)
  • AccessDeniedException(调用者没有足够权限执行该操作)

也就是说,执行该命令至少需要具备调用accessanalyzer:ValidatePolicy的 IAM 权限。

在 AWS CLI 中,命令对应形态为:

aws accessanalyzer validate-policy \ --policy-document file://myfile.json \ --policy-type RESOURCE_POLICY

其中--policy-document传入 JSON 策略文档(可直接给字符串,也可用file://前缀读取本地文件),--policy-type声明策略类型。

二、示例场景:校验一份 Cognito 角色信任策略

仓库中 validate-policy.rst 给出的示例是一份用于 Web 身份联合的 Amazon Cognito 角色信任策略。所谓"信任策略"(trust policy)是一种资源策略,它决定哪些身份可以代入该 IAM 角色,因此这里--policy-type使用RESOURCE_POLICY

示例命令:

aws accessanalyzer validate-policy \ --policy-document file://myfile.json \ --policy-type RESOURCE_POLICY

待校验的myfile.json内容如下:

{ "Version": "2012-10-17", "Statement": [ { "Sid": "", "Effect": "Allow", "Principal": { "Federated": "cognito-identity.amazonaws.com" }, "Action": [ "sts:AssumeRole", "sts:TagSession" ], "Condition": { "StringEquals": { "cognito-identity.amazonaws.com:aud": "us-west-2_EXAMPLE" } } } ] }

这份策略的意图很典型:允许 Cognito 身份池(cognito-identity.amazonaws.com)在满足aud条件(身份池 ID 为us-west-2_EXAMPLE)的情况下代入该角色。但正如输出所示,这份策略存在三处问题,其中两处是会导致策略失效的ERROR

三、逐条解读 Findings 报告

执行上述命令后,返回的 JSON 输出如下(为便于阅读已格式化):

{ "findings": [ { "findingDetails": "Add a value to the empty string in the Sid element.", "findingType": "SUGGESTION", "issueCode": "EMPTY_SID_VALUE", "locations": [ { "path": [ { "value": "Statement" }, { "index": 0 }, { "value": "Sid" } ], "span": { "end": { "column": 21, "line": 5, "offset": 81 }, "start": { "column": 19, "line": 5, "offset": 79 } } } ] }, { "findingDetails": "The sts:AssumeRole action is invalid with the following principal(s): cognito-identity.amazonaws.com. Use a SAML provider principal with the sts:AssumeRoleWithSAML action or use an OIDC provider principal with the sts:AssumeRoleWithWebIdentity action. Ensure the provider is Federated if you use either of the two options.", "findingType": "ERROR", "issueCode": "MISMATCHED_ACTION_FOR_PRINCIPAL", "locations": [ { "path": [ { "value": "Statement" }, { "index": 0 }, { "value": "Action" }, { "index": 0 } ], "span": { "end": { "column": 32, "line": 11, "offset": 274 }, "start": { "column": 16, "line": 11, "offset": 258 } } }, { "path": [ { "value": "Statement" }, { "index": 0 }, { "value": "Principal" }, { "value": "Federated" } ], "span": { "end": { "column": 61, "line": 8, "offset": 202 }, "start": { "column": 29, "line": 8, "offset": 170 } } } ] }, { "findingDetails": "The following actions: sts:TagSession are not supported by the condition key cognito-identity.amazonaws.com:aud. The condition will not be evaluated for these actions. We recommend that you move these actions to a different statement without this condition key.", "findingType": "ERROR", "issueCode": "UNSUPPORTED_ACTION_FOR_CONDITION_KEY", "locations": [ { "path": [ { "value": "Statement" }, { "index": 0 }, { "value": "Action" }, { "index": 1 } ], "span": { "end": { "column": 32, "line": 12, "offset": 308 }, "start": { "column": 16, "line": 12, "offset": 292 } } }, { "path": [ { "value": "Statement" }, { "index": 0 }, { "value": "Condition" }, { "value": "StringEquals" }, { "value": "cognito-identity.amazonaws.com:aud" } ], "span": { "end": { "column": 79, "line": 16, "offset": 464 }, "start": { "column": 58, "line": 16, "offset": 443 } } } ] } ] }

Finding 1:EMPTY_SID_VALUE(类型:SUGGESTION)

第一条 finding 指出:"为Sid元素中的空字符串添加一个值。" 策略中"Sid": ""是一个空值,虽然不会影响访问控制结果,但不属于规范的写法。这是一个风格类建议(SUGGESTION),按官方解释,Suggestions 只是推荐不影响访问控制的风格改进。修复方式就是给Sid一个有意义的标识,例如"CognitoWebIdentityAssumeRole"

Finding 2:MISMATCHED_ACTION_FOR_PRINCIPAL(类型:ERROR)

这是本示例中最关键的问题。finding 指出:sts:AssumeRole动作对于 principalcognito-identity.amazonaws.com是无效的,并给出两条修复路径:

  • 使用 SAML provider principal 配合sts:AssumeRoleWithSAML动作;
  • 使用 OIDC provider principal 配合sts:AssumeRoleWithWebIdentity动作;
  • 同时强调:无论选择哪种方案,都必须确保 provider 是Federated类型。

原因在于:Cognito 身份池属于 OIDC 联合(federated)身份,这类主体只能通过sts:AssumeRoleWithWebIdentity代入角色;而sts:AssumeRole面向的是 IAM 实体或通过sts:AssumeRole显式授权的角色,与Federatedprincipal 不匹配。示例文档明确提示:与 Cognito 配合使用的正确代入动作是sts:AssumeRoleWithWebIdentity。这是一个ERROR级别的发现——意味着策略的这一部分实际上无法正常工作。

注意该 finding 的locations包含两个定位点:一处指向Statement[0].Action[0](即sts:AssumeRole),另一处指向Statement[0].Principal.Federated(即cognito-identity.amazonaws.com)。这体现了 Access Analyzer 会同时标注"问题动作"与"关联主体",帮助你在策略中快速定位问题的两端。

Finding 3:UNSUPPORTED_ACTION_FOR_CONDITION_KEY(类型:ERROR)

第三条 finding 指出:条件键cognito-identity.amazonaws.com:aud不支持sts:TagSession动作,因此该条件对sts:TagSession不会生效("The condition will not be evaluated for these actions")。建议是把这些动作移到不使用该条件键的独立 statement 中。

这也是一个ERROR。结合上下文理解:sts:TagSessionsts:AssumeRoleWithWebIdentity均会返回会话标签相关的授权信息,但cognito-identity.amazonaws.com:aud这一条件键只与"代入"类动作(如AssumeRoleWithWebIdentity)的上下文中可用,并非所有动作都支持该条件键。修复方案通常是:将sts:TagSession拆到单独的 statement,或调整动作集合,使条件键只应用于支持它的动作。该 finding 的两个定位点分别指向Statement[0].Action[1]sts:TagSession)与Statement[0].Condition.StringEquals["cognito-identity.amazonaws.com:aud"](条件键本身)。

修复后的策略示例

综合三条 finding,可以给出修正版本(Sid补齐、动作换成sts:AssumeRoleWithWebIdentitysts:TagSession单独成句以避开不受支持的条件键):

{ "Version": "2012-10-17", "Statement": [ { "Sid": "CognitoWebIdentityAssumeRole", "Effect": "Allow", "Principal": { "Federated": "cognito-identity.amazonaws.com" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "cognito-identity.amazonaws.com:aud": "us-west-2_EXAMPLE" } } }, { "Sid": "TagSession", "Effect": "Allow", "Principal": { "Federated": "cognito-identity.amazonaws.com" }, "Action": "sts:TagSession" } ] }

将修改后的文档再次执行validate-policy,若返回"findings": []即为通过校验。

四、从服务模型理解完整参数

validate-policy命令的每个参数都直接对应ValidatePolicyRequest结构体(见 service-2.json)。其中policyDocumentpolicyType必填参数,其余为可选:

参数必填说明
--policy-documentJSON 策略文档,支持字符串或file://文件路径
--policy-type要校验的策略类型(见下方枚举)
--locale用于本地化 findings 的语言区域(见下方枚举)
--max-results响应中返回的最大结果数(走 query string)
--next-token分页游标,用于获取后续结果(走 query string)
--validate-policy-resource-type资源策略要附加的资源类型,仅在policy-typeRESOURCE_POLICY时指定

--policy-type的合法取值

按服务模型中的PolicyType枚举(service-2.json),共四种:

  • IDENTITY_POLICY:身份策略,为 IAM principal 授予权限,包括 IAM 角色、用户、组的托管策略与内联策略;
  • RESOURCE_POLICY:资源策略,为 AWS 资源授予权限,包括 IAM 角色的信任策略、Amazon S3 桶策略等;
  • SERVICE_CONTROL_POLICY:服务控制策略(SCP),挂载到 AWS 组织、组织单元(OU)或账号的组织策略;
  • RESOURCE_CONTROL_POLICY:资源控制策略(RCP)。

模型文档还特别说明:RESOURCE_POLICY既接受"身份策略 / 资源策略"这类通用输入,也接受"托管策略 / S3 桶策略"这类具体输入。

--validate-policy-resource-type的合法取值

当策略类型为RESOURCE_POLICY时,可通过该参数声明策略将挂载到哪类资源,从而让检查更精准。服务模型中ValidatePolicyResourceType的枚举(service-2.json)包括:

  • AWS::S3::Bucket
  • AWS::S3::AccessPoint
  • AWS::S3::MultiRegionAccessPoint
  • AWS::S3ObjectLambda::AccessPoint
  • AWS::IAM::AssumeRolePolicyDocument
  • AWS::DynamoDB::Table

例如校验一份要挂到 S3 桶的资源策略,可写--validate-policy-resource-type AWS::S3::Bucket。文档同时说明:对于不在该枚举中的资源类型(例如 KMS 密钥),可以不指定该参数,此时 Access Analyzer 会运行适用于所有资源策略的通用检查。

--locale的合法取值

服务模型中Locale枚举(service-2.json)支持:DE(德语)、EN(英语)、ES(西班牙语)、FR(法语)、IT(意大利语)、JA(日语)、KO(韩语)、PT_BR(巴西葡萄牙语)、ZH_CN(简体中文)、ZH_TW(繁体中文)。未指定时默认返回英文。

五、Findings 的数据结构:机器可读的定位与分级

每个 finding 都对应服务模型中的ValidatePolicyFinding结构体(service-2.json),其五个字段全部为必填:

字段含义
findingDetails本地化的发现描述,说明问题并给出处理建议
findingType发现的影响级别
issueCode问题的标识码(如EMPTY_SID_VALUEMISMATCHED_ACTION_FOR_PRINCIPAL
learnMoreLink指向该类型 finding 详细说明文档的链接
locations策略文档中与该 finding 相关的位置列表

findingType 的四个级别

服务模型ValidatePolicyFindingType枚举(service-2.json)定义了四类:

  • ERROR:策略中的某部分无法正常工作(本示例中的两个问题即属此类);
  • SECURITY_WARNING:策略允许的访问过于宽松,存在安全风险;
  • WARNING:策略不符合策略编写最佳实践(非安全问题);
  • SUGGESTION:对策略的风格改进建议,不影响访问控制(本示例中的EMPTY_SID_VALUE即属此类)。

locations:精确定位到行列

locations数组中的每个元素是Location结构体(service-2.json),包含两部分:

  • path:策略中的路径,由一系列路径元素组成。value表示对象键名(如StatementSidPrincipal),index表示数组下标(如Statement的第 0 个元素、Action的第 0 项)。因此[{"value":"Statement"},{"index":0},{"value":"Action"},{"index":0}]精确指向"第一个 statement 中第一个 action";
  • span:一段跨度的起止位置。每个位置(Position,见 service-2.json)由line(行号,从 1 开始)、column(列号,从 1 开始)与offset(字符偏移)共同刻画。

这种结构化定位非常适合自动化工具:CI/CD 管道可以根据issueCode直接拦截ERROR级别问题,并把locations映射回源码文件的行列,实现策略即代码(Policy as Code)的静态检查环节。

六、延伸使用与最佳实践

  • 结合其他 Access Analyzer 示例使用validate-policy属于 Access Analyzer 命令家族中的"策略校验"能力,同仓库 awscli/examples/accessanalyzer 目录下还有check-no-public-access.rstcheck-access-not-granted.rstcheck-no-new-access.rst(访问权限验证)、create-access-preview.rstget-access-preview.rst(访问预览)等示例,可组合出"策略校验 + 权限验证"的完整安全评估流程。
  • 写入 CI 校验策略:把--policy-document file://...指向仓库中的策略文件,用--policy-type区分身份策略与资源策略,将命令输出中的findings交给 CI 判断:任何ERROR/SECURITY_WARNING都应在合并前修复。
  • 利用--locale本地化报告:团队使用非英语环境时,可传--locale ZH_CN获得本地化的findingDetails,便于非英语成员直接阅读问题描述。
  • 精准指定资源类型:校验 S3 桶策略、DynamoDB 表策略或角色信任策略时,尽量传入--validate-policy-resource-type,让检查覆盖该资源类型专属的规则,而不是退回到通用检查。
  • 留意分页:当策略包含多个问题时,findings 可能超过单页上限(--max-results),此时响应中的nextToken可用于继续取回剩余结果。

七、小结

通过aws accessanalyzer validate-policy,开发者可以在部署前完成策略的静态自检。本示例展示了 Access Analyzer 的三类典型发现:风格建议(EMPTY_SID_VALUE)、主体与动作不匹配的功能性错误(MISMATCHED_ACTION_FOR_PRINCIPAL)、条件键与动作不兼容的功能性错误(UNSUPPORTED_ACTION_FOR_CONDITION_KEY)。结合服务模型中的参数枚举与 finding 结构定义,你可以把这条命令无缝接入日常开发与 CI 流程,让每一次策略变更都经过"写策略 → 校验 → 看懂报告 → 修复"的标准化闭环。

【免费下载链接】aws-cliUniversal Command Line Interface for Amazon Web Services项目地址: https://gitcode.com/GitHub_Trending/aw/aws-cli

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询