View a markdown version of this page

使用 Guard 验证模板 - Amazon CloudFormation
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)。

使用 Guard 验证模板

Amazon CloudFormation Guard(cfn-guard)是一种策略即代码工具。您可以使用 Guard 语言编写描述必需或禁止配置的规则,然后根据这些规则检查 JSON 或 YAML 数据。例如,您可以要求模板中的每个 Amazon S3 存储桶都使用加密,或者屏蔽向互联网开放端口 22 的安全组规则。

Guard 适用于任何 JSON 或 YAML 数据。除了 CloudFormation 模板外,您还可以查看 CloudFormation 更改集和 Amazon Config 配置项目。本主题侧重于检查模板。

有关发布说明和完整的命令参考,请参阅 GitHub 上的 Guard。有关完整的语言参考,请参阅《Guard 用户指南》。

有关本地验证的限制以及部署前需采取的步骤,请参阅了解验证范围。

安装 Guard

在 macOS 上,使用 Homebrew 安装 Guard:

brew install cloudformation-guard

在 Linux 或 macOS 上,您可以改为运行安装脚本。该脚本将最新版本安装到 ~/.guard/bin。脚本完成后,请将该目录添加到您的 PATH。

curl --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/aws-cloudformation/cloudformation-guard/main/install-guard.sh | sh

如果您有 Rust 工具链,也可以通过 Cargo 安装 Guard:

cargo install cfn-guard

要确认安装,请输出已安装的版本:

cfn-guard --version

有关 Windows 安装、Docker 映像和版本验证的信息,请参阅 Setting up Guard。

了解 Guard 语言

现在 Guard 已安装完毕,您可以开始编写规则了。Guard 规则由以下部分构成:

  • 查询:使用虚线路径从数据中选择值,例如 Resources.MyBucket.Properties.BucketName。使用 * 选择映射中的每个值,使用 [*] 选择列表中的每个项目。在方括号中添加筛选条件以缩小选择范围。例如,Resources.*[ Type == 'AWS::S3::Bucket' ] 选择每个 Amazon S3 存储桶。

  • 子句:做出判定为真或假的断言。子句将查询与运算符(例如 ==、!=、>=、in、exists、empty 或 is_string)组合在一起。位于不同行上的子句必须全部通过。要接受两个子句中的任何一个,请将其与 or 联接。

  • 变量:使用 let 存储查询结果,并在以后使用 % 前缀引用它。变量允许您一次性选择一组资源,并在多条规则中重复使用它。

  • 命名规则:使用名称对 rule 块中的子句进行分组。添加一个 when 条件,以便在规则不适用时将其跳过,例如,当模板没有 Amazon S3 存储桶时。规则可以引用其他规则,因此您可以从小部分构建复杂的策略。

  • 自定义消息:在子句后的 << 和 >> 之间添加文本,以解释输出中的失败。

有关完整语法,请参阅 Writing Guard rules。

编写规则

将规则保存为扩展名为 .guard 的文件。rules.guard 中的以下示例要求模板中的每个 Amazon S3 存储桶都必须指定存储桶加密并屏蔽公共访问权限:

let s3_buckets = Resources.*[ Type == 'AWS::S3::Bucket' ] rule S3_BUCKET_ENCRYPTED when %s3_buckets !empty { %s3_buckets.Properties.BucketEncryption exists << Violation: S3 buckets must specify BucketEncryption. Fix: Add a BucketEncryption property with ServerSideEncryptionConfiguration. >> } rule S3_BUCKET_PUBLIC_ACCESS_BLOCKED when %s3_buckets !empty { %s3_buckets.Properties.PublicAccessBlockConfiguration { BlockPublicAcls == true BlockPublicPolicy == true IgnorePublicAcls == true RestrictPublicBuckets == true } }

第一行将每个 Amazon S3 存储桶存储在 s3_buckets 变量中。仅当模板包含至少一个存储桶时,每条规则才会运行。第一条规则检查 BucketEncryption 属性是否存在,并包含一条在检查失败时由 Guard 输出的消息。第二条规则检查 PublicAccessBlockConfiguration 内部的四个属性。由于子句位于不同的行中,因此所有四个子句均须通过。

您可以将多条规则保存在同一个文件中,也可以按主题将规则拆分到不同的文件中,例如,将存储规则存入一个文件,将网络规则存入另一个文件。当您将目录传递给命令时,Guard 会评估该目录中的每个 .guard 文件。

验证模板

将规则文件传递给 --rules,将模板传递给 --data。添加 --type CFNTemplate 以便 Guard 按资源逻辑 ID 报告调查发现。

cfn-guard validate --rules rules.guard --data template.yaml --type CFNTemplate

模板通过后,Guard 会输出 PASS 状态并返回退出代码 0。当规则未通过时,Guard 会列出未通过的规则;对于每个不合规的资源,它还会列出未通过的检查、属性路径以及原因。对于存储桶缺失 BucketEncryption 的模板,其输出以如下内容开头:

template.yaml Status = FAIL FAILED rules rules.guard/S3_BUCKET_ENCRYPTED FAIL --- Evaluating data template.yaml against rules rules.guard Number of non-compliant resources 1 Resource = MyBucket { Type = AWS::S3::Bucket Rule = S3_BUCKET_ENCRYPTED { ...

当一条或多条规则未通过时,Guard 会返回退出代码 19;当无法解析规则或数据文件时,则返回退出代码 5。您可以使用这些退出代码来停止自动化构建。

在验证模板时,以下选项非常有用:

  • 多次传递 --rules 或 --data,或传递一个目录,以在一次运行中检查多个规则文件或模板。传递到 --data 的目录必须仅包含数据文件,而传递到 --rules 的目录必须仅包含规则文件。

  • 将 --show-summary 与 pass、fail、skip、all 或 none 配合使用以控制摘要表中显示哪些规则。默认值为 fail。

  • 将 --output-format 与 json、yaml、junit 或 sarif 配合使用,为其他工具生成输出。junit 和 sarif 格式适用于大多数构建系统和代码扫描工具。

  • 使用 --input-parameters 传递包含规则所引用的值的 JSON 或 YAML 文件,例如已批准的安全组 ID 列表。这使得环境特定的值不会出现在您的规则中。

有关所有选项,请参阅《Guard 用户指南》中的 validate。

测试规则

在自动化工作流中使用规则之前,请利用内置的单元测试支持对其进行测试。测试文件列出了示例输入以及针对每条规则所预期的结果:PASS、FAIL 或 SKIP。rules_tests.yaml 中的以下示例测试了上一个示例中的 S3_BUCKET_ENCRYPTED 规则:

--- - input: Resources: {} expectations: rules: S3_BUCKET_ENCRYPTED: SKIP - input: Resources: MyBucket: Type: AWS::S3::Bucket Properties: {} expectations: rules: S3_BUCKET_ENCRYPTED: FAIL - input: Resources: MyBucket: Type: AWS::S3::Bucket Properties: BucketEncryption: ServerSideEncryptionConfiguration: - ServerSideEncryptionByDefault: SSEAlgorithm: aws:kms expectations: rules: S3_BUCKET_ENCRYPTED: PASS

使用 test 命令运行测试:

cfn-guard test --rules-file rules.guard --test-data rules_tests.yaml

Guard 为每个期望值输出 PASS 或 FAIL,并在任何期望失败时返回退出代码 7。有关更多信息,请参阅 Testing Guard rules。

从模板生成规则

若想快速上手,您可以根据已满足您要求的模板生成规则。rulegen 命令会读取模板,并为需要模板中的属性值的每种资源类型编写规则:

cfn-guard rulegen --template template.yaml --output generated.guard

检查生成的文件,只保留代表您策略的检查。生成的规则是一个起点,通常需要源模板中的精确值,这对于其他模板可能过于严苛。

向您的工作流添加 Guard

您可以在以下位置运行 Guard:

  • 在您的编辑器中:CloudFormation 语言服务器会在您编辑模板时运行 Guard 规则包,并以内联方式显示失败。有关设置,请参阅CloudFormation 语言服务器。

  • 在 Git 提交之前:Guard 提供了一个 pre-commit 钩子,可以在更改的模板上运行 validate 或在更改的规则上运行 test。请将以下内容添加到 .pre-commit-config.yaml 文件中,并将路径替换为您自己的路径:

    repos: - repo: https://github.com/aws-cloudformation/cloudformation-guard rev: pre-commit-v0.0.2 hooks: - id: cfn-guard args: - --operation=validate - --rules=rules/ files: ^templates/.*
  • 在自动化构建中:将 cfn-guard validate 作为构建步骤运行,并使用退出代码使构建失败。使用 --output-format junit 或 --output-format sarif 发布结果。此外还提供了一个 GitHub 操作和一个容器映像。请从 public.ecr.aws/aws-cloudformation/cloudformation-guard 提取映像。

  • 使用 cloudformation-validate:cfn-validate 命令和 Amazon CDK 验证插件可以运行支持的 Guard 规则子集及其内置检查。有关更多信息,请参阅 使用 cloudformation-validate 验证模板。

  • 堆栈操作期间:要在 CloudFormation 或 Cloud Control API 创建、更新或删除资源时强制执行规则,请使用 Guard 钩子。有关更多信息,请参阅 Guard Hooks。

有关涵盖常见安全和合规控制的即用型规则,请参阅 GitHub 上的 Amazon Guard Rules Registry。