Secure GitOps with GitLab CI/CD, Terraform & TFSec End-to-End IaC Security

Oshaba SamsonOshaba Samson
3 min read

Typically, after writing a Terraform script, you would manually run terraform apply in the terminal to deploy your resources. However, GitOps simplifies this process. By integrating your version control system ike GitHub, GitLab, or Bitbucket. now you can automate deployments with a simple git push. This triggers your Terraform pipeline to provision infrastructure automatically. In this project, we'll be using GitLab to demonstrate the GitOps workflow.

Objectives

  • Automate Infrastructure Deployment with GitLab and Terraform

Requirements

  • Gitlab Account

  • Terraform

  • AWS Account

For this tutorial we have already prepared a terraform script that provisions AWS ec2 instance and install some applications like jenkins and sonarqube. You can clone it from here.

To create resources in AWS using terraform we need to configure access and secret key with admin full access. If you have not configured this before ๐Ÿ‘‰ Check out my detailed guide: Mastering IAM in AWS.

After cloning this repo https://gitlab.com/devsecops-projects2/gitops-with-terraform.then we need cd into the folder

cd gitops-with-terraform
  • Open terraform.tvars and change the private_key to an already existing key in your aws account.

  • Create a file and name it gitlab-ci.ymal

  • The next step is to define stages inside the gitlab-ci.yml
stages:
    - init
    - test
    - build
    - deploy
  • Pull terraform hashicorp images

image:
  name: hashicorp/terraform:latest
  entrypoint: [""]
  • Define variables (You need to setup the variables inside github variables)

variables:
  AWS_DEFAULT_REGION: "us-east-1"
  AWS_ACCESS_KEY_ID: $AWS_ACCESS_KEY_ID
  AWS_SECRET_ACCESS_KEY: $AWS_SECRET_ACCESS_KEY

  TF_VAR_env_prefix: "dev"
  TF_VAR_runner_registration_token: $RUNNER_TOKEN
  • initialize terraform

init:
  stage: init
  script:
    - echo "Initializing Terraform..."
    - terraform init
  artifacts:
    paths:
      - .terraform
      - .terraform.lock.hcl
  • Validate your terraform script

validate:
  stage: test
  script:
    - echo "Validating Terraform..."
    - terraform validate  
  allow_failure: true
  • implement tfsec

tfsec:
  stage: test
  image:
    name: aquasec/tfsec
    entrypoint: [""]
  script:
    - tfsec . 
  allow_failure: true
  artifacts:
    when: always
    paths:
      - tfsec-report.json
    reports:
      codequality: tfsec-report.json
  • Review resources to be deployed

build:
  stage: build
  script:
    - echo "Terraform plan..."
    - terraform plan -out "planfile"
  artifacts:
    paths:
      - planfile
  • Deploy application

deploy:
  stage: deploy
  script:
    - echo "Terraform deploy..."
    - terraform apply input=false "planfile"
  • Putting everything together
stages:
    - init
    - test
    - build
    - deploy


image:
  name: hashicorp/terraform:latest
  entrypoint: [""]


variables:
  AWS_DEFAULT_REGION: "us-east-1"
  AWS_ACCESS_KEY_ID: $AWS_ACCESS_KEY_ID
  AWS_SECRET_ACCESS_KEY: $AWS_SECRET_ACCESS_KEY

  TF_VAR_env_prefix: "dev"
  TF_VAR_runner_registration_token: $RUNNER_TOKEN


init:
  stage: init
  script:
    - echo "Initializing Terraform..."
    - terraform init
  artifacts:
    paths:
      - .terraform
      - .terraform.lock.hcl


validate:
  stage: test
  script:
    - echo "Validating Terraform..."
    - terraform validate  
  allow_failure: true


tfsec:
  stage: test
  image:
    name: aquasec/tfsec
    entrypoint: [""]
  script:
    - tfsec . 
  allow_failure: true
  artifacts:
    when: always
    paths:
      - tfsec-report.json
    reports:
      codequality: tfsec-report.json


build:
  stage: build
  script:
    - echo "Terraform plan..."
    - terraform plan -out "planfile"
  artifacts:
    paths:
      - planfile


deploy:
  stage: deploy
  script:
    - echo "Terraform deploy..."
    - terraform apply input=false "planfile"
  • then do git add, git commit and git push

  • You pipeline suppose look like this if everything is successful

if we click on tfsec. We will see something like this

You can see the state of the terraform script. critical issues is 13. and other issues as well.

If we click on build. We will see something like this

In other to deploy the resources. you need to click on the play button of the deploy panel.

After deployment is complete and you click on deploy you should see something like this

You can copy the public ip address and paste with port number 8080 and you will see jenkins like this

  • To destroy or delete the instance click on play beside the destroy

0
Subscribe to my newsletter

Read articles from Oshaba Samson directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Oshaba Samson
Oshaba Samson

I am a software developer with 5 years + experience. I have working on web apps ecommerce, e-learning, hrm web applications and many others