有没有办法对 AWS Cloudformation 模板进行单元测试

Is there a way to unit test AWS Cloudformation template

当我们说cloudformation是'Infrastructure as Code'时,下一个立即想到的问题就是如何测试这段代码。 我们可以对这段代码做一些基本的单元测试吗

我不考虑 cloudformation 验证,因为这只是一种进行语法验证的方式,我可以使用任何其他免费的 JSON/YAML 验证器。

我更倾向于某种功能验证,可能是测试我是否定义了所有用作参考的变量。 可能测试我正在使用的任何属性实际上是该组件支持的属性

没想到它应该测试权限是否正确或者我没有用尽我的限制。但至少超出了基本 JSON/YAML 语法验证

您描述的测试(至少在 JSON 解析之外)可以通过用于 generate/read 模板的编程库解析 CloudFormation 模板来部分实现。它们不会显式测试模板,但会在您使用未为资源定义的 属性 的情况下抛出异常或错误。

查看 go-cloudformation:https://github.com/crewjam/go-cloudformation

除此之外,您需要 运行 堆栈才能看到错误。我相信测试 IaaC 是基础设施自动化的主要挑战之一。不仅是单元测试,还有集成测试和持续验证。

这里详细介绍了如何将几种软件测试方法应用于 CloudFormation templates/stacks:

林丁

对于 linting(检查 CloudFormation 模板代码的 syntax/grammar 正确性),您可以使用 ValidateTemplate API to check basic template structure, and the CreateChangeSet API 来更详细地验证您的资源属性。

  • 请注意,ValidateTemplate 执行的检查比简单的 JSON/YAML 语法检查器更彻底 - 它验证正确的 Template Anatomy, correct syntax/usage of Intrinsic Functions, and correct resolution of all Ref 值。
  • ValidateTemplate 检查基本的 CloudFormation 语法,但不会根据特定 属性 模式验证模板的资源。为了根据 AWS 资源类型检查模板的参数、资源和属性的结构,如果任何参数或资源属性格式不正确,CreateChangeSet 应该 return 出错。

单元测试

执行单元测试首先需要回答以下问题:要测试can/should 的最小独立单元 功能是什么?对于 CloudFormation,我认为最小的可测试单元是 Resource.

官方 AWS Resource Types 是 AWS supported/maintained(无论如何都是专有实现),因此不需要最终用户开发人员编写任何额外的单元测试。

但是,您自己的 Custom Resources could and should be unit-tested. This can be done using a suitable testing framework in the implementation's own language (e.g., for Lambda-backed Custom Resources, perhaps a library like lambda-tester 将是一个很好的起点。

集成测试

这是 CloudFormation 堆栈(主要用于将各种资源绑定到一个集成应用程序中)的最重要和最相关的测试类型,也是可以使用更多改进和最佳实践开发的类型。以下是关于如何通过实际 creating/updating 包含真实 AWS 资源的完整堆栈来集成测试 CloudFormation 代码的一些初步想法:

  • 使用脚本语言,使用该语言的 AWS SDK 执行 CloudFormation 堆栈创建。将模板设计为 return Stack Outputs 以反映您要测试的行为。在脚本语言创建堆栈后,将堆栈输出与预期值进行比较(然后可选择在清理过程中删除堆栈)。
  • 使用AWS::CloudFormation::WaitCondition个资源代表成功tests/assertions,这样一个成功的堆栈创建就代表一个成功的集成测试运行,一个失败的堆栈创建代表一个失败的集成测试运行.

除了 CloudFormation 之外,在 space 测试基础架构即代码中值得一提的一个有趣工具是 kitchen-terraform, a set of plugins for Test Kitchen which allow you to write fully-automated integration test suites for Terraform 模块。最终可能会为 CloudFormation 构建类似的集成测试工具,但目前还不存在。

此工具“cfn-nag”解析一组 CloudFormation 模板并应用规则来查找可能导致基础设施不安全的代码模式。该工具的结果包括违反资源的逻辑资源标识符和违反规则的解释。 延伸阅读:https://stelligent.com/2016/04/07/finding-security-problems-early-in-the-development-process-of-a-cloudformation-template-with-cfn-nag/

虽然该工具会尝试匹配很多特定规则,但粗略的类别是:

IAM 和资源策略(S3 存储桶、SQS 等) 匹配在某些方面过于宽松的策略(例如操作或主体中的通配符)

安全组入口和出口规则 匹配过于宽松的规则(例如,入口规则对 0.0.0.0/0 开放,端口范围 1-65535 开放)

访问日志 查找未为适用资源(例如 Elastic Load Balancer 和 CloudFront 分配)启用的访问日志

加密 未对适用资源(例如 EBS 卷或 S3 存储桶上的 PutObject 调用)启用或强制执行的(服务器端)加密

特别说到CloudFormation,AWS推荐使用taskcat,这是一个在所有AWS区域内部署基础设施/模板的工具,在这个过程中它已经执行了代码验证。

TaskCat Github 存储库:https://github.com/aws-quickstart/taskcat

此外,通过Visual Studio代码您可以使用扩展Cloud conformity template scanner或使用趋势科技当前购买的功能进行安全验证,其名称已从云符合性更改为Trend Micro Template scanner.
它将基本上执行模板和架构代码的验证,这些代码链接到来自 AWS 的 Well Architected Framework 的模型和用例。

关于模板扫描器:https://aws.amazon.com/blogs/apn/using-shift-left-to-find-vulnerabilities-before-deployment-with-trend-micro-template-scanner/

VS 代码扩展云整合:https://marketplace.visualstudio.com/items?itemName=raphaelbottino.cc-template-scanner

此外,还有一个 VS Code 扩展 Linter,您可以将其用作 pre-commit 验证,名称为:CloudFormation Linter.

CloudFormation 短绒:https://marketplace.visualstudio.com/items?itemName=kddejong.vscode-cfn-lint

如果您想使用 DevSecOps“SEC”实现基础设施代码管道,您还可以使用更高级的功能,这是 Scout 套件.它有自己的云验证器,可以在构建容器中 运行,它将审核云以验证是否存在安全标准之外的资源。

Scout Suite Github 存储库:https://github.com/nccgroup/ScoutSuite

如果您想更深入地了解在 AWS 上使用验证和资源测试/合规性,我建议您使用配置服务研究“合规性即代码”。

Link 介绍此服务:https://www.youtube.com/watch?v=fBewaclMo2s

我找不到真正的 Cloudformation 模板单元测试解决方案,所以我创建了一个。 https://github.com/DontShaveTheYak/cloud-radar

Cloud-Radar 让你拿一个模板,传入你想设置的参数。然后将该模板呈现为其最终形式。这意味着所有条件和内部函数都已解决。

这允许您采用类似 this 的模板并编写以下测试:

from pathlib import Path
from unittest.mock import mock_open, patch

import pytest

from cloud_radar.cf.unit import Template


@pytest.fixture
def template():
    template_path = Path(__file__).parent / "../../templates/log_bucket/log_bucket.yaml"

    return Template.from_yaml(template_path.resolve(), {})

def test_log_defaults(template):

    result = template.render({"BucketPrefix": "testing"})

    assert "LogsBucket" in result["Resources"]

    bucket_name = result["Resources"]["LogsBucket"]["Properties"]["BucketName"]

    assert "us-east-1" in bucket_name


def test_log_retain(template):

    result = template.render(
        {"BucketPrefix": "testing", "KeepBucket": "TRUE"}, region="us-west-2"
    )

    assert "LogsBucket" not in result["Resources"]

    bucket = result["Resources"]["RetainLogsBucket"]

    assert "DeletionPolicy" in bucket

    assert bucket["DeletionPolicy"] == "Retain"

    bucket_name = bucket["Properties"]["BucketName"]

    assert "us-west-2" in bucket_name

编辑:如果您有兴趣测试 Cloudformation 模板,请查看我的博客系列 Hypermodern Cloudformation

新工具现已上市。测试所有 CloudFormation 东西! (TaskCat

什么是taskcat?

taskcat 是一个测试 AWS CloudFormation 模板的工具。它会在多个 AWS 区域部署您的 AWS CloudFormation 模板,并为每个区域生成一份具有 pass/fail 等级的报告。您可以指定要包含在测试中的区域和可用区数量,并从您的 AWS CloudFormation 模板传入参数值。 taskcat 被实现为一个 Python class ,您可以导入、实例化和 运行.

用法

关注此文档:https://aws.amazon.com/blogs/infrastructure-and-automation/up-your-aws-cloudformation-testing-game-using-taskcat/

笔记

  1. taskcat 无法读取 AWS_PROFILE 环境变量。如果不是默认配置文件,则需要在 general 的一部分中定义配置文件。
general:
  auth:
    default: dev-account

参考:https://github.com/aws-quickstart/taskcat/issues/434

有一个 bash 库 xsh-lib/aws,它的一个工具可以从 CLI 部署 AWS CloudFormation 模板。

可在以下位置找到该工具:https://github.com/xsh-lib/aws/blob/master/functions/cfn/deploy.sh

它处理模板验证和上传、堆栈命名、监管、更新、清理、超时、回滚和状态检查。

除上述之外,它还处理嵌套模板和非内联 Lambda。这节省了上传嵌套模板和非内联 Lambda 函数的工作,如果手动进行测试,这些工作可能会让人们抓狂。

它支持自定义的配置文件,这使得部署更加容易。真实世界的配置文件是 here.

从 CLI 调用该工具的简单示例如下所示:

xsh aws/cfn/deploy -t template.json -s mystack -o OPTIONS=Param1Key=Param1Value

xsh-lib/aws is a library of xsh,要使用它,您必须先安装 xsh