亚马逊AWS官方博客

基于 Chef InSpec 的基础设施测试

 

1 Chef InSpec介绍

 

任何业务都依赖于基础设施环境。近年来,基础设施领域已发生了巨大的变化。从最初的传统数据中心到数据中心托管服务,而如今,基础设施即服务和云平台在企业中更受欢迎。因此,大多数企业正在将其工作负载从本地数据中心迁移到云平台。

 

为了部署和管理这些复杂的基础设施配置,很多企业使用代码即基础设施(IaC)。当您使用IaC在AWS云平台上创建成百上千个资源时,如何知道代码按预期方式部署了这些资源?这些资源是否遵守合规性和安全性措施?我们并不确定,因此需要基础设施测试程序。

 

Chef InSpec是一个用于测试和审核应用程序和基础设施的开源代码框架。

 

Chef InSpec的工作原理是将系统的实际状态与您编写的Chef InSpec代码表达的期望状态进行比较。Chef InSpec可以检测违规并以报告的形式显示。

 

2 Chef InSpec入门

下面将主要介绍Chef InSpec的安装及环境配置。

 

2.1 Chef InSpec安装

 

Chef InSpec提供了适配多种操作系统环境的安装包,支持的操作系统类型如下:

  • Amazon Linux
  • Debian GNU/Linux
  • Red Hat Enterprise Linux/CentOS
  • macOS
  • SUSE Linux Enterprise Server
  • Ubuntu Linux
  • Windows

软件包的下载地址如下:

https://downloads.chef.io/products/inspec

 

本文以Amazon Linux环境为例进行说明,下载当前最新的Chef InSpec软件包,使用下面的命令进行Chef InSpec安装:

rpm -ivh inspec-<version>.x86_64.rpm

 

安装完成后可以看到inspec命令可以正常运行,并提示inspec命令可以使用的参数帮助信息

2.2 Chef InSpec配置介绍

 

使用Chef InSpec时主要需要弄清楚下面的三部分:

  • Command-line interface
  • Profile
  • Resource

 

InSpec CLI使用local,SSH,WinRM,Docker或AWS等连接方式,可针对不同基础设施目标运行测试和审核。常用命令说明如下:

命令 说明
archive 将配置文件压缩成tar.gz(默认)或zip文件
check 验证指定路径上的所有测试
exec

针对指定目标运行所有测试文件。

加载给定的配置文件,并在需要时获取其依赖项。然后连接到目标并执行配置文件中包含的所有控件。输出测试结果。

help 查看特定命令的帮助信息
shell 打开一个交互式的调试终端
version 打印此工具的版本

 

Chef InSpec支持创建复杂的测试和合规性配置文件,每个profile文件都是独立的结构,具有自己的执行流程。用户可以自己编写profile文件,还可以在社区支持的Chef Supermarket和GitHub上找到别人写的profile。

 

Profile文件通常具有下面的目录结构:

 

examples/profile
├── README.md
├── controls
│   ├── example.rb
├── libraries
│   └── extension.rb
└── inspec.yml

 

其中各个文件和目录的说明如下:

  • md是用于解释profile的适用范围和用法
  • controls是所有测试用例所在的目录
  • libraries是用于存放扩展Chef InSpec资源代码的目录
  • yml包含配置文件的描述

 

Chef InSpec拥有80多种可供使用的资源。如果您需要的资源尚未提供,也可以编写自己的自定义资源。Chef InSpec支持的资源列表如下:

https://docs.chef.io/inspec/resources/

 

2.3 使用Chef InSpec测试AWS资源

 

典型的使用环境如下图所示,在数据中心内使用Chef InSpec对AWS进行基础设施资源测试。

从本地数据中心连接AWS环境需要使用Access Key和Secret Access Key(AKSK)。在企业环境中,通常会将IAM User集中在一个Master账号中进行管理,用户使用IAM User登陆AWS环境,然后再用Assume Role的方式操作其它AWS账户。

 

使用Chef InSpec连接AWS前,首先需要创建IAM用户,并生成AKSK。另外在UseCase账号中,需要创建Assume Role,给予适当的权限并允许Master账号中的IAM User切换到Use Case账号。

 

在本地数据中心连接AWS环境的配置示例如下:

# cat .aws/credentials 
[default]
aws_access_key_id = <Access Key>
aws_secret_access_key = <Secret Access Key>

# cat ~/.aws/config 
[default]
region = cn-north-1
output = json

[profile usecase]
role_arn = <UseCase Account IAM Role Arn>

 

 

 

使用如下命令创建示例profile,该命令会自动生成profile目录结构。

# inspec init profile --platform aws example

 ─────────────────────────── InSpec Code Generator ─────────────────────────── 

Creating new profile at /root/example
 • Creating file README.md
 • Creating file attributes.yml
 • Creating directory controls
 • Creating file controls/example.rb
 • Creating file inspec.yml

 

 

示例代码的测试内容在controls/example.rb文件中

# copyright: 2018, The Authors

title "Sample Section"

aws_vpc_id = attribute("aws_vpc_id", value: "", description: "Optional AWS VPC identifier.")

# You add controls here
control "aws-single-vpc-exists-check" do # A unique ID for this control.
  only_if { aws_vpc_id != "" } # Only run this control if the `aws_vpc_id` attribute is provided.
  impact 1.0                                                                # The criticality, if this control fails.
  title "Check to see if custom VPC exists."                                # A human-readable title.
  describe aws_vpc(aws_vpc_id) do                                           # The test itself.
    it { should exist }
  end
end

# Plural resources can be inspected to check for specific resource details.
control "aws-vpcs-check" do
  impact 1.0
  title "Check in all the VPCs for default sg not allowing 22 inwards"
  aws_vpcs.vpc_ids.each do |vpc_id|
    describe aws_security_group(vpc_id: vpc_id, group_name: "default") do
      it { should allow_in(port: 22) }
    end
  end
end

control "aws-vpcs-multi-region-status-check" do                             # A unique ID for this control.
  impact 1.0                                                                # The criticality, if this control fails.
  title 'Check AWS VPCs in all regions have status "available"'             # A human-readable title.
  aws_regions.region_names.each do |region|                                 # Loop over all available AWS regions
    aws_vpcs(aws_region: region).vpc_ids.each do |vpc|                      # Find all VPCs in a single AWS region
      describe aws_vpc(aws_region: region, vpc_id: vpc) do                  # The test itself.
        it { should exist }                                                 # Confirms AWS VPC exists
        it { should be_available }                                          # Confirms AWS VPC has status "available"
      end
    end
  end
end

 

 

 

该测试的主要内容包含:

  • 如果传入指定的VPC ID,则检查指定的VPC是否存在
  • 检查所有VPC的安全组内是否包含允许22端口访问的策略
  • 检查所有区域内的状态为available的VPC

 

执行如下命令运行该profile对AWS环境进行测试:

# inspec exec example -t aws://cn-north-1/usecase

Profile: AWS InSpec Profile (example)
Version: 0.1.0
Target:  aws://cn-north-1

  ↺  aws-single-vpc-exists-check: Check to see if custom VPC exists.
     ↺  Skipped control due to only_if condition.
  ✔  aws-vpcs-check: Check in all the VPCs for default sg not allowing 22 inwards
     ✔  EC2 Security Group ID: sg-01d67dds39bcffe17 Name: default VPC ID: vpc-032cdd155d561c7bf  is expected to allow in {:port=>22}
  ✔  aws-vpcs-multi-region-status-check: Check AWS VPCs in all regions have status "available"
     ✔  VPC vpc-032cdd155d561c7bf in cn-north-1 is expected to exist
     ✔  VPC vpc-032cdd155d561c7bf in cn-north-1 is expected to be available

Profile: Amazon Web Services  Resource Pack (inspec-aws)
Version: 1.31.0
Target:  aws://cn-north-1

     No tests executed.

Profile Summary: 2 successful controls, 0 control failures, 1 control skipped
Test Summary: 3 successful, 0 failures, 1 skipped

 

3 总结

 

在实际的应用场景中,可以将Chef InSpec用于Terraform等IaC工具进行环境部署之后的测试与审核,另外,还可以将Chef InSpec与Jenkins等CI/CD工具集合使用,以持续测试您部署的基础架构,以确保其符合合规性策略。

 

本篇作者


卢冲 – 亚马逊 AWS 专业服务团队云架构咨询顾问。负责企业级客户的云架构设计和优化、云上运维咨询和技术实施。曾就职于Novell、RedHat等企业,具有多年企业级客户项目实施经验。