Blog Detail

DevSecOps CICD for Terraform Deployment using Github Action

Left Image
Siddharth Lakhani
June 30, 2023

Introduction:

The utilization of Cloud Infrastructure deployment has significantly increased due to its compelling features such as Scalability, Reliability, Cost-Effectiveness (pay-as-you-go model), and simplified implementation of Disaster Recovery and Backup Strategies, among others.

To expedite service deployment and upgrades, organizations leverage Infrastructure as Code (IaaC) technologies like Terraform or CloudFormation (for AWS) and employ CI/CD tools for automation. When writing code to deploy resources, it is crucial to consider security measures and adhere to best practices to ensure the product's security remains uncompromised. This is the reason the implementation of DevSecOps CI/CD is essential.


Problem Statement:

Recently, a client with a fintech application required us to manage their cloud infrastructure using Terraform code. The client's top priority was to ensure robust security measures within their infrastructure, seeking to identify and rectify potential security gaps even before creating the infrastructure itself. They were using GitHub Actions to automate the process.

Our primary objective was to design and implement a DevSecOps pipeline using Terraform, integrating security best practices seamlessly into the pipeline. By doing so, we aimed to address their security concerns proactively, allowing the client to deploy a secure and reliable infrastructure while also achieving a highly streamlined and automated development process.

Implementing DevSecOps Methodology to scan terraform code vulnerabilities:

Left Image

By implementing DevSecOps Methodology, we can ensure that security is considered from the very beginning of the development process. This helps to prevent security vulnerabilities from being introduced into the code and makes it easier to fix any vulnerabilities that are found. It also can help to improve the reliability and performance of cloud infrastructure deployments. This is because it automates the process of deploying and upgrading services, which reduces the risk of human error.

Steps we followed to implement DevSecOps Pipeline:

There are several third-party tools available to scan terraform code which supported in github action:

  • Checkov
  • Tfsec
  • Tflint
  • Terrascan

In this project we used checkov to scan security measures and also use tflint to implement rules to follow best practices.

Checkov:

Checkov is the static code analysis tool. It is used to scan missconfiguration present under the Infrastructure as a Code (IaaC) such as terraform.

It contains more than 750 predefined policies to check the missconfiguration issues.It also supports the custom policies.

Below are the few samples of policies:

  • CKV_AWS_88: "EC2 instance should not have public IP."
  • CKV_AWS_46: "Ensure no hard-coded secrets exist in EC2 user data"
  • CKV_AWS_260: "Ensure no security groups allow ingress from 0.0.0.0:0 to port 80"
  • CKV_AWS_126: "Ensure that detailed monitoring is enabled for EC2 instances"
Check: CKV_AWS_126: "Ensure that detailed monitoring is enabled for EC2 instances"
  FAILED for resource: aws_instance.my_ec2_instance
Error: File: /ec2.tf:1-14
  Guide: https://docs.paloaltonetworks.com/content/techdocs/en_US/prisma/prisma-cloud/prisma-cloud-code-security-policy-reference/aws-policies/aws-logging-policies/ensure-that-detailed-monitoring-is-enabled-for-ec2-instances.html
1 | resource "aws_instance" "my_ec2_instance" {
2 | ami = "ami-022e1a32d3f742bd8"
3 | availability_zone = "us-east-1e"
4 | instance_type = "t2.micro"
5 | key_name = "sid-terraform"
6 | security_groups = [aws_security_group.my-sg.id]
7 | subnet_id = "subnet-05ce424831aef41aa"
8 | tags = {
9 | "Name" = "ec2_dev"
 10 | }
 11 | tags_all = {
 12 | "Name" = "ec2_dev"
 13 | }
 14 | }

This is the sample output of Passed and Failed Policies in Github Action.

We can integrate checkov in Github Action by using its available template of code below jobs section.

name: 'Checkov'
runs-on: ubuntu-latest

steps:
 - name: Checkout
   uses: actions/checkout@v3

 - name: Run Checkov action
   id: checkov
   uses: bridgecrewio/checkov-action@master
   with:
    directory: .
    output_format: sarif
    output_file_path: reports/checkov-results.sarif

Tflint:

TFLint is a Terraform linter that analyzes Terraform configurations and provides suggestions for improvements, best practices, and potential errors.

It helps catch issues and maintain consistency in your Terraform code.

It will suggest some best practices to write code such as, the module should include main.tf, variables.tf and output.tf file must created etc.

Below is the sample output after running tflint.

Warning: Module should include a main.tf file as the primary entrypoint (terraform_standard_module_structure)
  on main.tf line 1:
   (source code not available)
Reference: https://github.com/terraform-linters/tflint-ruleset-terraform/blob/v0.4.0/docs/rules/terraform_standard_module_structure.md
Warning: Warning: Module should include an empty outputs.tf file (terraform_standard_module_structure)
  on main.tf line 1:
   (source code not available)
Reference: https://github.com/terraform-linters/tflint-ruleset-terraform/blob/v0.4.0/docs/rules/terraform_standard_module_structure.md
Notice: resource name `my-sg` must match the following format: snake_case (terraform_naming_convention)
  on sg.tf line 1:
   1: resource "aws_security_group" "my-sg" {
Reference: https://github.com/terraform-linters/tflint-ruleset-terraform/blob/v0.4.0/docs/rules/terraform_standard_module_structure.md
Warning: Module should include an empty variables.tf file (terraform_standard_module_structure)
  on main.tf line 1:
   (source code not available)
Reference: https://github.com/terraform-linters/tflint-ruleset-terraform/blob/v0.4.0/docs/rules/terraform_standard_module_structure.md
Error: Process completed with exit code 2.

Pre-requisites:

To run tflint commands first we need to install plugin by create .tflint.hcl file and execute tflint --init.

Steps to Integrate Tflint in Github Action:

Create .tflint.hcl file in local machine using below code:

plugin "terraform" {
  enabled = true
  version = "0.4.0"
  source = "github.com/terraform-linters/tflint-ruleset-terraform"
}

Commit and Push into Project Repository:

git add .tflint.hcl
git commit -m "Added .tflint.hcl"
git push origin BRANCH_NAME

Integrate tflint below template of code under jobs section:

name: 'Tflint'
runs-on: ubuntu-latest

steps:
 - name: Checkout
   uses: actions/checkout@v2
 - name: Setup TFLint
   run: curl -s https://raw.githubusercontent.com/terraform-linters/tflint/master/install_linux.sh | bash
 - name: Install Terraform plugins
   run: tflint --init
 - name: Lint Terraform files
   run: tflint

Terraform-docs:

In this project we have used terraform-docs command to create README.md by exporting resources of all modules and input/outputs of terraform apply.

Steps to Configure Terraform-docs command:

First we need to create .terraform-docs.yml file with below context.

formatter: "markdown table"
content: |-
 {{ .Requirements }}
 {{ .Providers }}
 {{ .Modules }}

Steps

  • create
    1. terraform init
    2. terraform plan
    3. terraform apply -auto-approve -no-color | tee tfapply.txt
    4. terraform output --json | tee output_values.json
  • destroy
    1. terraform destroy -auto-approve
    2.  {{ .Resources }}
    3.  {{ .Inputs }}
    4.  {{ .Outputs }}
  • apply output
    1. {{ include "tfapply.txt" }}

Output Values:

enabled: true
from: "output_values.json"
output:
 file: README.md
  mode: replace
template: |-
# DevSecOps CICD for Terraform Deployment using Github Action.
DevSecOps CICD for Terraform Deployment using Github Action to scan vulnerabilities of Terraform code.
 {{ .Content }}

Then we need to run below commands:

  • terraform init
  • terraform plan
  • terraform apply -auto-approve -no-color | tee tfapply.txt
  • terraform output --json | tee output_values.json

terraform-docs -c .terraform-docs.yml . #In this command if .terraform-docs.yml is in same dir where .tf files available then use . otherwise give folder name where file is available.

After executing above commands README.md file will be updated and the same can be committed in the repository.

Complete Execution plan of DevSecOps CI/CD in Github Action:

In the execution plan we have configured four different Jobs:

    1. Checkov
    2. Tflint
    3. Plan
    4. Apply

Checkov and Tflint jobs will execute Parallely and once both jobs will succeed then only Plan Job will execute.

We have applied prompt to review and approve the Plan manually before execute Apply Job.

Complete YAML configuration file of Github Action Pipeline:

Below is the link of YAML configuration file of GIthub Action Pipeline.

terraform.yml

Github Respository link of complete DevSecOps CI/CD Pipeline.

GitHub reference