Streamlining DevSecOps: Part 1 — Azure DevOps Integration with Jenkins for End-to-End Implementation

DINESH REDDY JETTI
6 min readDec 15, 2023

--

Implementing DevSecOps in Jenkins involves integrating security practices into the software development and delivery pipeline. Jenkins, as a popular continuous integration/continuous deployment (CI/CD) tool, can be extended to incorporate security checks and measures throughout the development lifecycle. Here are steps and considerations for implementing DevSecOps in Jenkins and will deploy the container into the VM by pulling an image from ACR

Static Application Security Testing (SAST)

Integrate SAST tools into your Jenkins pipeline to analyze source code for security vulnerabilities. Tools like SonarQube, Checkmarx, and Fortify can be integrated as build steps to scan the codebase for potential security issues , in this blog we will see SonarQube integration with jenkins pipeline

Dependency Scanning

Use tools like OWASP Dependency-Check or Snyk to scan dependencies for known vulnerabilities. Integrate these tools into your Jenkins pipeline to ensure that your application does not use outdated or insecure libraries, in this blog we will see OWASP Dependency-Check integration with jenkins pipeline

Secrets Management

Implement secure handling of credentials and secrets within Jenkins. Use Jenkins credentials plugin to manage sensitive information securely and avoid hardcoding secrets in scripts or configurations , in this blog we will see Gitleaks integration with jenkins pipeline

Container Security

If you are using containers, implement container security checks. Tools like trivy or Clair can be integrated into your pipeline to scan container images for vulnerabilities , in this blog we will see trivy integration

Installing jenkins into ubuntu

#!/bin/bash
sudo apt update -y
apt install openjdk-17-jdk openjdk-17-jre -y
/usr/bin/java --version
curl -fsSL https://pkg.jenkins.io/debian-stable/jenkins.io.key | sudo tee /usr/share/keyrings/jenkins-keyring.asc > /dev/null
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 -y
sudo apt-get install jenkins -y
sudo systemctl start jenkins
sudo systemctl status jenkins

Access the jenkins on the port 8080 by default & please make sure you opened the inbound port on the NIC , refer the below path on the vm and pass that in the text box

After key in the password , you can install the suggested plugins by one click

Install the docker into ubuntu using the below script

#!/bin/bash

# Update the package index
sudo apt update

# Install packages to allow apt to use a repository over HTTPS
sudo apt install -y apt-transport-https ca-certificates curl software-properties-common

# Add Docker's official GPG key
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

# Set up the stable Docker repository
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# Update the package index again
sudo apt update

# Install the latest version of Docker
sudo apt install -y docker-ce docker-ce-cli containerd.io

# Add your user to the docker group to run Docker without sudo
sudo usermod -aG docker $USER

# Print a message to inform the user to restart their session
echo "Docker has been installed. Please restart your session to apply group changes."

sudo usermod -aG docker $USER #my case is azureuser
newgrp docker
sudo chmod 777 /var/run/docker.sock

Open the port 9090 on the NIC and try to run the container using the below command

docker run -d --name sonar -p 9000:9000 sonarqube:lts-community

launh the url at the VMIP:9000
username admin
password admin

Install trivy into the vm

sudo apt-get install wget apt-transport-https gnupg lsb-release -y

wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | gpg --dearmor | sudo tee /usr/share/keyrings/trivy.gpg > /dev/null

echo "deb [signed-by=/usr/share/keyrings/trivy.gpg] 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 -y

Specifically, search for and install the following plugins

  • JDK Plugin: Provides support for building Java applications -Eclipse Temurin installer
  • SonarQube Scanner Plugin: Integrates Jenkins with SonarQube for continuous inspection of code quality.
  • Maven Integration Plugin: Allows Jenkins to use Maven to build and manage projects.
  • OWASP Dependency-Check Plugin: Integrates OWASP Dependency-Check into the Jenkins build process for identifying project dependencies and checking if there are any known, publicly disclosed, vulnerabilities

Configure Java and Maven in Global Tool Configuration

Goto Manage Jenkins

→ Tools

→ Install JDK(17) and Maven3(3.6.0)

→ Click on Apply and Save

Configure SonarQube Integration

Dashboard > Manage Jenkins > System

Configure Owasp in Global Tool Configuration

Configure Docker in Global Tool Configuration

Define all the required creds as below

we can invoke these creds while setting up our original pipeline as below

//Git checkout 

stage('Git Checkout') {
steps {
git branch: 'main', credentialsId: 'azure-repo-id', url: 'https://rkrvritN45PSP@dev.azure.com/rkrvritN45PSP/RVRIT/_git/Mainproject-Repo'

}
}
 steps {
script{
withDockerRegistry(credentialsId: 'acr-docker', toolName: 'docker3', url: 'http://project231.azurecr.io') {
sh "docker build -t shopping-cart ."
sh "docker tag shopping-cart project231.azurecr.io/samples/sprinb:latest"
sh "docker push project231.azurecr.io/samples/shopping-cart:latest"
}
}

Configure Docker credentials and specify Service Principal (SP) and Azure Container Registry (ACR) details in the environment block. Then, define the build and push stages using these variables.

// Define service principal creds as below  
Ensure that the credential kind is Username with password and enter the following items:

Username - The appId of the service principal
Password - The password of the service principal
ID - Credential identifier


environment{
AZURE_SUBSCRIPTION_ID='491e1121-********'
AZURE_CLIENT_SECRET='S6p8Q~R3ZtNjJ********'
AZURE_CLIENT_ID='b7d9f0a4-47f9-**********'
AZURE_TENANT_ID='2047b1bd-99*******'
CONTAINER_REGISTRY='project231.azurecr.io'
RESOURCE_GROUP='AZ-NEW-22'
REPO="services"
IMAGE_NAME="springboot-app"
TAG="latest"
}


stage('Docker Build & Push') {
steps {
withCredentials([usernamePassword(credentialsId: 'myAzureCredential', passwordVariable: 'AZURE_CLIENT_SECRET', usernameVariable: 'AZURE_CLIENT_ID')]) {
sh 'az login --service-principal -u $AZURE_CLIENT_ID -p $AZURE_CLIENT_SECRET -t $AZURE_TENANT_ID'
sh 'az account set -s $AZURE_SUBSCRIPTION_ID'
sh 'az acr login --name $CONTAINER_REGISTRY --resource-group $RESOURCE_GROUP'
sh 'az acr build --image $REPO/$IMAGE_NAME:$TAG --registry $CONTAINER_REGISTRY --file Dockerfile . '
}
}
}

Scan the image and publish results to the json file as below

 stage("TRIVY"){
steps{
sh " trivy --format json --output ${TRIVY_REPORT_FILE} image $CONTAINER_REGISTRY/$REPO/$IMAGE_NAME:$TAG"
}
}

Define the pull and run stages using these variables.

  stage('Docker Image Pull & Deploy') {
steps {
withCredentials([usernamePassword(credentialsId: 'myAzureCredential', passwordVariable: 'AZURE_CLIENT_SECRET', usernameVariable: 'AZURE_CLIENT_ID')]) {
sh 'az login --service-principal -u $AZURE_CLIENT_ID -p $AZURE_CLIENT_SECRET -t $AZURE_TENANT_ID'
sh 'az account set -s $AZURE_SUBSCRIPTION_ID'
sh 'az acr login --name $CONTAINER_REGISTRY --resource-group $RESOURCE_GROUP'
sh 'docker pull $CONTAINER_REGISTRY/$REPO/$IMAGE_NAME:$TAG'
sh "docker run -d -p 8081:8081 $CONTAINER_REGISTRY/$REPO/$IMAGE_NAME:$TAG"
}
}
}

You can refer the complete E2E pipeline in the below repo , you can simply reuse this for your usecase

https://github.com/regspweek41/jenkins-DevSecOps-Azure.git

By incorporating these practices into your Jenkins pipeline, you can create a robust DevSecOps environment that ensures security is an integral part of the software development and delivery process. Regularly update and adapt your security measures to address emerging threats and vulnerabilities.

--

--

DINESH REDDY JETTI

Cloud Infra Devops. Lead @ Zuellig Pharma | DevOps, Security , Automation, Azure, AWS, GCP