TDD in Your Infrastructure Pipeline
In the last two parts of this series, we have described what Test Driven Development (TDD) is, and how it can be applied to infrastructure to validate that security controls are implemented. Generally, a TDD pipeline consists of a number of components:
- A testing framework (such as Chef Inspec, terratest, Sentinel, Open Policy Agent, Mocha, etc.)
- The testing code (which can be in any language depending on the framework used to implement test suites)
- The infrastructure as code (IaC) - such as Terraform, Pulumi, CDK, etc.
- A version control system (such as Git) preferably with methods to lock branches
- A means to run tests (such as a GitHub Actions, GitLab Runner, CircleCI, etc.
The purpose of this article is to put all of these parts together in a pipeline.
Choosing a Framework
Before starting to run (no pun intended) with TDD, choosing a proper framework should be top of mind. There are several drivers when it comes to choosing a TDD framework. The table below outlines these decisions relating to TDD for Infrastructure.
|Chef Inspec||HashiCorp Sentinel||Terraform Validator||Open Policy Agent (OPA)|
|Price||Open Source||Enterprise-only||Open Source||Open Source|
|Cloud(s)||AWS, Azure, GCP||AWS, Azure, GCP||GCP only||AWS, Azure, GCP|
|Language(s)||Ruby||Sentinel||YAML/Rego via Policy Library||Rego|
|Limited to Infrastructure?||Applications and OS-level support||Works with Vault, Consul, and Nomad||Only Infrastructure||Many applications|
A Comparison of Testing Frameworks for Infrastructure as Code
In this article, we will be using Chef Inspec. However, know that the steps to implement these test frameworks are similar.
Setting up the Code
One of the main value propositions for using TDD for IaC is to ensure that security requirements are clearly defined. Tests should be written first, then the infrastructure code should be built to let tests pass. The following diagram outlines the recommended steps to ensure success with setting up testable infrastructure code.
Security and compliance requirements start from business drivers. Meeting requirements highlighted by demonstrating compliance with regimes such as FedRAMP, GDPR, PCI-DSS, and HITRUST help break barriers to market entrance. What this means is that there should be good communication between compliance teams and the engineers that implement infrastructure. Having sessions for engineering teams to translate security requirements into tests (that may not yet pass since the infrastructure hasn’t been created/modified yet) using a selected framework is key to ensuring success.
Implementing Successful Version Control Patterns
Once tests are written, they should be checked into version control. This helps to answer questions regarding auditing, technical decisions, and compliance status of infrastructure components during development. There are numerous ways to achieve proper Git version control for infrastructure tests including: GitFlow, GitHub flow, GitLab flow, OneFlow, and Trunk-based development. The choice on what version control pattern varies depending on organization and project - and is outside of the scope of this article, however having a pattern that can enforce security checks (e.g. blocking merges to main/feature branches before tests pass) is important to success with Test-driven infrastructure.
Running with it!
In order to run tests and provide feedback effectively, some sort of system that can periodically or upon request, execute a test suite is essential. To achieve this, a system is typically implemented using a continuous integration (CI) system due to the vast ecosystem that many of them have as well as community support (and thus, ease of use).
GitHub is an excellent platform for projects that leverage the Git versioning system. Making this platform even better is the ability to perform actions depending on what happens within a particular version control pattern (such as merging branches, opening a pull request, and so on). To perform tests using Chef Inspec within GitHub Actions, the following code snippet can be used.
Code to Run Chef Inspec Tests with GitHub Actions
The Whole Picture
Using a pipeline that is well defined with business objectives in mind can be an effective way to ensure security in any infrastructure project that is defined with infrastructure as code. Using a test-driven approach ensures that security requirements are properly communicated from security/compliance teams to engineering teams for proper implementation in cloud environments. Using TDD is a large upfront investment that requires writing tests and establishing automation to be effective, but ultimately allows teams to move faster and more securely.
The information presented in this article is accurate as of 11/5/2020. Follow the ScaleSec blog for new articles and updates.
ScaleSec is a service-disabled, veteran-owned small business (SDVOSB) for cloud security and compliance that helps innovators meet the requirements of their most scrutinizing customers. We specialize in cloud security engineering and cloud compliance. Our team of experts guides customers through complex cloud security challenges, from foundations to implementation, audit preparation and beyond.