DevSecOps Jenkins CI/CD Pipeline for a Node.js Application

Overview: This project focuses on setting up a Jenkins CI/CD pipeline for a Node.js application, emphasizing DevSecOps practices. The pipeline incorporates stages for code quality analysis using SonarQube, security checks with OWASP tools, and Docker image scanning with Trivy. The objective is to automate the deployment process while upholding high standards of code quality and security.

Launch EC2 Instance

Create an AWS EC2 instance with the necessary permissions. Make note of the public IP address.

Use t2.large as the instance type so that it can support the tools running for this project

Jenkins Setup

  1. Install Java:
sudo apt update
sudo apt install fontconfig openjdk-17-jre
  1. Install Jenkins:
sudo wget -O /usr/share/keyrings/jenkins-keyring.asc \
  https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key
echo "deb [signed-by=/usr/share/keyrings/jenkins-keyring.asc]" \
  https://pkg.jenkins.io/debian-stable binary/ | sudo tee \
  /etc/apt/sources.list.d/jenkins.list > /dev/null
sudo apt-get update
sudo apt-get install jenkins

Setting up Docker and Docker-compose

  1. Install Docker and Docker-compose.
sudo apt-get install docker.io docker-compose
  1. Add Ubuntu/Jenkins user to the Docker group.
sudo usermod -aG docker $USER
sudo usermod -aG docker jenkins

SonarQube Server Setup

SonarQube serves as an autonomous code review tool designed to facilitate the delivery of Clean Code. Seamlessly integrating into your workflow, SonarQube identifies code issues within your projects, enabling continuous code inspections.

Utilize Docker to deploy SonarQube. Docker provides a convenient and consistent environment for running applications, ensuring easy setup and management of SonarQube.

docker run -itd --name sonarqube-server -p 9000:9000 sonarqube:lts-community

Access the SonarQube server via port 9000 and log in with the credentials user: admin, pass: admin.

Next, on the SonarQube Server:

  1. Go to Administration.

  2. Navigate to Security.

  3. Select Users.

  4. Create a new user and generate a token for it: Administration > Security > Users > Token > Create Token.

In Jenkins:

  1. Install the SonarQube Scanner plugin: Manage Jenkins > Plugins > Available Plugin > search for "SonarQube scanner" > install.

  2. Add the token from SonarQube server into Jenkins: Manage Jenkins > Credentials > Add Credentials > Choose "Secret text" as kind, set ID as "sonar".

Additionally, if you need to add Docker Hub Credentials:

  1. Manage Jenkins > Credentials > Add Credentials > Choose "Username and Password" as kind, set ID as "DockerHubCreds".

Following this, we'll establish the connection between the SonarQube server and Jenkins:

  1. Navigate to Manage Jenkins.

  2. Access the system settings.

  3. Locate "SonarQube server".

  4. Add a new SonarQube server configuration.

  5. Save the changes.

We're going to activate the SonarQube Scanner plugin:

  1. Go to Manage Jenkins.

  2. Choose Tools.

  3. Look for "SonarQube Scanner installations".

  4. Save your changes.

Now, we will set up a webhook on the SonarQube Server for Jenkins.

  1. Navigate to Administration.

  2. Select Configuration.

  3. Locate the Webhooks section.

  4. Click on Create to initiate the webhook setup process.

In the next step, we will install Trivy

Trivy is an open-source vulnerability scanner tailored for container images. It operates by utilizing a database containing a catalog of known vulnerabilities, allowing it to meticulously scan container images for potential security flaws.

sudo apt-get install wget apt-transport-https gnupg lsb-release
wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | sudo apt-key add -
echo deb https://aquasecurity.github.io/trivy-repo/deb $(lsb_release -sc) main | sudo tee -a /etc/apt/sources.list.d/trivy.list
sudo apt-get update
sudo apt-get install trivy

Install OWASP which is a tool to check the prevalent risks related to web application security vulnerabilities.

To integrate OWASP into Jenkins:

  1. Add the OWASP dependency checker plugin: Go to Manage Jenkins > Plugins > Available Plugins > search for "OWASP dependency checker" > install.

  2. Enable OWASP: Go to Manage Jenkins > Tools > find "Dependency-Check installations" > save your changes.

In the next step, we will create a pipeline for jenkins

This Jenkins pipeline automates the continuous integration and deployment process for a Node.js application. It comprises several stages:

  1. Code: Clones the source code from a GitHub repository.

  2. SonarQube Analysis: Conducts static code analysis using SonarQube to assess code quality.

  3. SonarQube Quality Gates: Sets quality gates based on SonarQube analysis results.

  4. OWASP: Utilizes OWASP dependency checker to scan for vulnerabilities in dependencies.

  5. Build and Test: Builds a Docker image for the Node.js application.

  6. Trivy: Conducts vulnerability scanning on the Docker image using Trivy.

  7. Push to Private Docker Hub Repo: Pushes the Docker image to a private Docker Hub repository.

  8. Deploy: Deploys the application using Docker Compose.

Here is our Pipeline

 pipeline{
    agent any
    environment{
        SONAR_HOME = tool "Sonar"
    }
    stages{

        stage("code"){
            steps{
                git url:"https://github.com/sanchit1498/cicdnodejsApp" , branch:"master"
                echo "cloned sucess"
            }
        }

        stage("Sonarqube analysis"){
            steps{
              withSonarQubeEnv("Sonar"){
                 sh "$SONAR_HOME/bin/sonar-scanner -Dsonar.projectName=nodetodo -Dsonar.projectKey=nodetodo -X"
              }
            }
        }

        stage("SonarQube Quality Gates"){
            steps{
              timeout(time: 1, unit:"MINUTES"){
                waitForQualityGate abortPipeline: false
              }
            }
        }

        stage("OWASP"){
            steps{
               dependencyCheck additionalArguments: '--scan ./' , odcInstallation: 'OWASP'
               dependencyCheckPublisher pattern: '**/dependency-check-report.xml'
            }
        }

        stage("build and test"){
            steps{
                sh 'docker build -t node-app-batch-6:latest .'
               echo "build sucess"
            }
        }
         stage("Trivy"){
            steps{
              sh "trivy image node-app-batch-6"
            }
        }


        stage("Push to Private Docker Hub Repo"){
            steps{
                withCredentials([usernamePassword(credentialsId:"DockerHubCreds",passwordVariable:"dockerPass",usernameVariable:"dockerUser")]){
                sh "docker login -u ${env.dockerUser} -p ${env.dockerPass}"
                sh "docker tag node-app-batch-6:latest ${env.dockerUser}/node-app-batch-6:latest"
                sh "docker push ${env.dockerUser}/node-app-batch-6:latest"
                }
            }
        }

        stage("deploy"){
            steps{
               sh "docker compose down && docker compose up -d"
                 echo "deployed sucessfully"
            }
        }
    }
}

Now we are ready for build