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

Posted

技术标签:

【中文标题】有没有办法对 AWS Cloudformation 模板进行单元测试【英文标题】:Is there a way to unit test AWS Cloudformation template 【发布时间】:2017-03-11 00:16:54 【问题描述】:

当我们说 cloudformation 是“基础架构即代码”时,下一个立即想到的问题是如何测试此代码。 我们可以对这段代码做一些基本的单元测试吗

我对 cloudformation 验证不屑一顾,因为这只是一种进行语法验证的方式,而且我可以使用任何其他免费的 JSON/YAML 验证器来完成。

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

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

【问题讨论】:

aws cloudformation validate-template 不仅检查您是否使用正确的 JSON/YAML。它还执行其他检查。例如。它会检查您的 Refs。但它不会检查您的属性是否有效。真正知道的唯一方法是创建一个堆栈,然后针对正在运行的堆栈运行一些测试(例如 ssh in、发送 http 请求……) ***.com/questions/11854772/… 有一些可用于单元测试的解决方案 【参考方案1】:

以下是如何将几种测试软件方法应用于 CloudFormation 模板/堆栈的细分:

起绒

对于 linting(检查 CloudFormation 模板代码的语法/语法正确性),您可以使用 ValidateTemplate API 检查基本模板结构,并使用 CreateChangeSet API 更详细地验证您的资源属性。

请注意,ValidateTemplate 比简单的 JSON/YAML 语法检查器执行更彻底的检查 - 它验证 Template Anatomy 的正确性、Intrinsic Functions 的正确语法/用法以及所有 Ref 值的正确解析。 ValidateTemplate 检查基本 CloudFormation 语法,但不会根据特定属性架构验证模板的资源。为了根据 AWS 资源类型检查模板的参数、资源和属性的结构,如果任何参数或资源属性格式不正确,CreateChangeSet 应返回错误。

单元测试

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

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

但是,您自己的 Custom Resources 可以而且应该进行单元测试。这可以使用实施自己的语言中的合适测试框架来完成(例如,对于 Lambda 支持的自定义资源,也许像 lambda-tester 这样的库会是一个很好的起点)。

集成测试

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

使用脚本语言,使用该语言的 AWS 开发工具包执行 CloudFormation 堆栈创建。设计模板以返回 Stack Outputs 反映您要测试的行为。在脚本语言创建堆栈后,将堆栈输出与预期值进行比较(然后在清理过程中选择删除堆栈)。 使用AWS::CloudFormation::WaitCondition 资源表示成功的测试/断言,因此成功的堆栈创建表示成功的集成测试运行,失败的堆栈创建表示失败的集成测试运行。

除了 CloudFormation,在基础设施即代码测试领域值得一提的一个有趣工具是 kitchen-terraform,这是一组用于 Test Kitchen 的插件,可让您为 Terraform 模块编写全自动集成测试套件.最终可能会为 CloudFormation 构建类似的集成测试工具,但目前还不存在。

【讨论】:

如果您想在 Amazon 生态系统之外使用工具,Test-Kitchen 非常适合在服务器上运行并断言服务可用,尽管还有其他更多“黑盒”类型基础设施测试套件也可以在没有代理的情况下执行此操作。 有时资源伴随着引导脚本。如何使用特定 AMI 测试引导脚本? 对于基本的 linting,我想要检查所有 required 属性但 aws cloudformation validate-template 不存在的东西,例如当我验证没有CidrBlockAWS::EC2::VPC 时,它通过了。我是否遗漏了什么或者这是我正在使用的 aws cli 版本(1.14.26)中的错误? @KevinCross ValidateTemplate 仅在本地验证基本 CloudFormation 语法,它不会针对特定资源架构验证您的模板。要实际验证模板的资源和属性,您可以使用CreateChangeSet API(例如,aws cloudformation create-change-set 使用 CLI)。我将更新我的答案以包含这些额外信息。 只是添加到这个答案 - 谢谢@wjordan,对我帮助很大:我最近通过 AWS 快速入门团队了解了 TaskCat:github.com/aws-quickstart/taskcat【参考方案2】:

此工具“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 已开放)

访问日志 查找未为适用资源(例如弹性负载均衡器和 CloudFront 分配)启用的访问日志

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

【讨论】:

【参考方案3】:

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

什么是 taskcat?

taskcat 是一个测试 AWS CloudFormation 模板的工具。它在多个 AWS 区域中部署您的 AWS CloudFormation 模板,并为每个区域生成包含通过/失败等级的报告。您可以指定要包含在测试中的区域和可用区数量,并从您的 AWS CloudFormation 模板传入参数值。 taskcat 以 Python 类的形式实现,您可以导入、实例化和运行。

用法

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

笔记

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

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

【讨论】:

【参考方案4】:

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

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

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

【讨论】:

【参考方案5】:

特别谈到 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 Code 扩展云一致性:https://marketplace.visualstudio.com/items?itemName=raphaelbottino.cc-template-scanner

另外,还有一个 VS Code 扩展 Linter,可以用作pre-commit 进行验证,名称为:CloudFormation Linter

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

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

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

如果您想深入了解在 AWS 上使用验证和资源测试/合规性的情况,我建议您使用配置服务研究“Compliance as code”。

此服务演示文稿的链接:https://www.youtube.com/watch?v=fBewaclMo2s

【讨论】:

【参考方案6】:

我找不到 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。

【讨论】:

【参考方案7】:

有一个 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 是xsh 的库,要使用它,您必须先安装xsh

【讨论】:

以上是关于有没有办法对 AWS Cloudformation 模板进行单元测试的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法使用 cloudformation 创建 aws lambda 执行角色?

将现有 AWS 资源整合到 CloudFormation 堆栈中

CloudFormation 嵌套堆栈名称

AWS Cloudformation的相关概念

AWS > CloudFormation 模板 - 您可以在上传之前对其进行测试吗?

AWS CloudFormation入门实践