Streamlining DevSecOps: Part 1 — Azure DevOps Integration with Jenkins for End-to-End Implementation
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.