Building a Secure DevSecOps CI/CD Pipeline for a Spring Boot Application Using Jenkins, Snyk, SonarQube, Docker, Trivy, and AWS EKS

1. Overview
In today’s fast-paced software development world, speed alone is not enough. Applications must be secure, reliable, and production-ready before they ever reach users. This is where DevSecOps comes into the picture integrating security directly into the CI/CD pipeline instead of treating it as a separate, last-minute activity.
In this blog, we walk through a real-time, industry-style Jenkins pipeline that demonstrates how DevSecOps is implemented in practice. This pipeline does not stop at just building and deploying an application; it continuously scans source code, third-party dependencies, Docker images, and even the Kubernetes cluster itself.
The objective of this pipeline is simple and solid:
Detect security issues as early as possible
Automate quality and security checks
Ensure only secure artifacts reach production
This setup reflects how modern organizations use GitHub, Jenkins, Snyk, Docker, Trivy, SonarQube, and Kubernetes (EKS) together to build a secure CI/CD ecosystem.
2. What is DevSecOps?
DevSecOps is the next evolution of DevOps that integrates security practices directly into every stage of the software development lifecycle. Rather than addressing security only after deployment, DevSecOps ensures that security is built-in from the very first code commit to production.
Modern DevSecOps pipelines combine various types of security testing, including:
SAST (Static Application Security Testing): White-box testing that analyzes the source code or binaries for vulnerabilities without running the application. Tools like SonarQube are typically used for SAST.
DAST (Dynamic Application Security Testing): Black-box testing that tests the running application for security issues, simulating real-world attacks.
SCA (Software Composition Analysis): Scans third-party libraries and dependencies for known vulnerabilities (CVEs) and license issues. Tools like Snyk handle SCA.
Key Benefits of DevSecOps:
Early detection of vulnerabilities: Identify security risks before they reach production.
Automated and faster secure deployments: Security checks are part of the CI/CD process, not a separate step.
Improved collaboration among Dev, Sec, and Ops teams: Everyone shares responsibility for security.
Continuous monitoring and compliance: Security and compliance checks run automatically, even after deployment.
3.Launch Ubuntu Server (t2.large)
I started by launching a t2.large EC2 instance with the Ubuntu Server image from AWS. This instance will serve as our CI server.

- Instance Type: t2.large or t3.large (2 vCPU, 8 GB RAM)

Storage:
15 GB (gp3)Storage below 15 GB may struggle under tool load.

4. Installing Jenkins on Ubuntu
Started with an Ubuntu EC2 instance (t2.large or t3.large).
Connect to your console and install Jenkins.
Run this script in root user
vi jenkins.sh # Run this script in root user (sudo su -)
#!/bin/bash
sudo apt update -y
#sudo apt upgrade -y
wget -O - https://packages.adoptium.net/artifactory/api/gpg/key/public | tee /etc/apt/keyrings/adoptium.asc
echo "deb [signed-by=/etc/apt/keyrings/adoptium.asc] https://packages.adoptium.net/artifactory/deb $(awk -F= '/^VERSION_CODENAME/{print$2}' /etc/os-release) main" | tee /etc/apt/sources.list.d/adoptium.list
sudo apt update -y
sudo apt install temurin-17-jdk -y
/usr/bin/java --version
curl -fsSL https://pkg.jenkins.io/debian-stable/jenkins.io-2023.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

- Run this script in root user (sudo su -)


- Once Jenkins is installed, you’ll need to allow traffic on port 8080 the default port Jenkins uses for its web interface.
sudo cat /var/lib/jenkins/secrets/initialAdminPassword

5. Install Docker & Configure Permissions
sudo apt-get update
sudo apt-get install docker.io -y
sudo usermod -aG docker $USER # ubuntu or ec2-user
newgrp docker
sudo chmod 777 /var/run/docker.sock

- Check the Docker info after this to ensure it is working fine.

- Give Docker permissions to the Jenkins users.
sudo usermod -aG docker jenkins
sudo systemctl restart jenkins
groups jenkins This command checks which groups the Jenkins user belongs to.
At first, it will show: This means Jenkins is only in its own group not in the docker group yet. So Jenkins cannot run Docker commands for now.

sudo usermod -aG docker jenkins
This command adds the Jenkins user into the Docker group.
-aGmeans: add to the group without removing existing ones.
Now Jenkins will have permission to run Docker.getent group docker
This checks who is inside the Docker group.
If you see output like this:That means Jenkins is now successfully added to the Docker group. Good job!
sudo systemctl restart jenkins
Restart Jenkins service so it can apply the new group changes.
Now Jenkins is ready to use Docker in your pipeline.
6. Run SonarQube Container
docker run -d --name sonar -p 9000:9000 sonarqube:lts-community

- After running the container, verify that it is running:
docker ps
Now, enable port 9000 in your AWS Security Group (Inbound rules → Add Rule → Port 9000 → Allow).
Once the port is enabled, open SonarQube in your browser:

- Now you can see that SonarQube is opened successfully.

7. Create Jenkins Pipeline Job
Go to your Jenkins dashboard.
Click “New Item”, give your job a name (e.g.,
DevOps).

7.1 Required Jenkins Plugins

- Docker: Docker, Docker Pipeline, Docker Build Step

- SonarQube: SonarQube Scanner, Quality Gates Plugin

7.2 Configure Maven
Go to Manage Jenkins > Global Tool Configuration.
Under Maven, click Add Maven.

Name it something like
maven-3.9.9.Select Install automatically and choose version
3.9.9.Save your configuration.
8. Snyk Integration (Security Scanning)
8.1 Overview
Snyk is a developer-first security tool used in DevSecOps pipelines to identify and fix vulnerabilities early in the software development lifecycle.
Snyk performs
white-box security testing, meaning it analyzes the actual source code and dependencies rather than testing a running application from outside.By integrating Snyk into Jenkins, we ensure that security scanning happens automatically during CI, not after deployment.
8.2 Key Purposes of Using Snyk
Detect security issues before production
Scan both custom code and open-source dependencies
Automate security checks inside Jenkins pipelines
Enforce security as code
8.3 Step-by-Step Snyk Integration in Jenkins
- Before integrating Snyk with Jenkins, we must create a Snyk account and generate an API token. Jenkins uses this token to authenticate and perform security scans.
8.4 Create a Snyk Account
Snyk is a cloud-based security platform.
To scan projects and fetch vulnerability data, Jenkins must authenticate with Snyk using an API token, which is generated only after creating an account.
How to Create a Snyk Account
Go to https://snyk.io
Click Sign Up

- Choose a sign-up method: GitHub ,Google ,Bitbucket

- In this setup, the account is created using a Google account.

- Complete the login and reach the Snyk dashboard.

8.5 Generate Snyk API Token for CI/CD Pipelines
- In Snyk dashboard, go to: Account Settings

On this page, you will see an Auth Token with the message:
“Use this token to authenticate the Snyk CLI and in CI/CD pipelines.”
This token is automatically generated by Snyk when you create and log in to your account (using Google, GitHub, etc.).
What You Need to Do
Copy the generated Snyk API Token shown on this page keep this token secure.
This token will be used by Jenkins / CI/CD pipelines to authenticate with Snyk
Do not hardcode this token in pipeline scripts.

8.6 Install Snyk Plugin in Jenkins
The Snyk Jenkins plugin enables Jenkins pipelines to communicate securely with Snyk services.
Go to Jenkins Dashboard
Navigate to: Manage Jenkins → Plugin

Search for Snyk Security Plugin
Install the plugin
The plugin acts as a bridge between Jenkins and Snyk.
8.7 Add Snyk Token to Jenkins Credentials
Prevents exposing tokens in pipeline scripts
Ensures secure authentication
Allows token reuse across multiple jobs
Go to Manage Jenkins → Credentials

- System → Global → Add Credentials Fill the details:

Fill the details
Kind: Secret Text
Secret: Paste your Snyk API Token
ID:
SNYK_TOKENDescription:
SNYK_TOKEN

Click Create
This allows Jenkins pipelines to access Snyk securely without hardcoding secrets.
8.8 Install Node.js, NPM, and Snyk CLI (Required for Snyk CLI)
Why Node.js Is Required
The Snyk CLI is built on Node.js, so the Jenkins server must have the following installed:
Node.js – Runtime environment for Snyk CLI
NPM (Node Package Manager) – Used to install Snyk CLI
Snyk CLI – Executes security scans in CI/CD pipelines
Without Node.js and NPM, Snyk CLI cannot run install Node.js and NPM Snyk CLI
sudo apt update
sudo apt install -y nodejs npm
sudo npm install -g snyk

The Snyk CLI performs automated security scans during the CI pipeline, including:
SAST (Static Application Security Testing)
Scans application source code to identify security vulnerabilities.SCA (Software Composition Analysis)
Scans open-source dependencies for known vulnerabilities and license issues.
Verify Installation
node -v
snyk -v
npm -v

If versions are displayed, installation is successful
8.9 Writing the Initial Jenkins Pipeline Script
Let's first verify that Jenkins can successfully clone your code and build it using Maven. This is a basic test to ensure everything is set up correctly.
Goal: To check if the build process works without errors.
Clone your code from GitHub
Build the project using Maven
No credentials requiredSince we are using a public GitHub repository, there’s no need to configure any credentials for Git access but git must be installledImportant Requirement Although no credentials are needed, Git must be installed on the Jenkins server to allow repository cloning.
sudo apt install git -y

pipeline {
agent any
tools {
maven 'maven3.9.9'
}
stages {
stage('Checkout') {
steps {
echo "Cloning Repository..."
git branch: 'feature',
url: 'https://github.com/KandlaguntaVenkataSivaNiranjanReddy/spring-boot-mongo-docker-kkfunda.git'
}
}
stage('Maven Build') {
steps {
echo "Building the Maven Project..."
sh 'mvn clean package -DskipTests'
}
}
}
}
This confirms that your pipeline is running correctly. Next, you can proceed to the following stages.
So far: Code is cloned , Build is successful
But build success ≠ security.
Even if the application works perfectly, it can still have:
Vulnerable third-party libraries
Outdated dependencies
Known CVEs (security issues)
That’s why the next step is Snyk.
8.10 Adding Snyk to the Jenkins Pipeline
Snyk is introduced to scan: Project dependencies ,Third-party libraries.
Jenkins authenticates using the Snyk API token.
Vulnerabilities are identified and reported.
Outcome:
Security risks are detected early in the CI pipeline.

pipeline {
agent any
tools {
maven 'maven3.9.9'
}
environment {
SNYK_TOKEN = credentials('SNYK_TOKEN') // Snyk API token
}
stages {
stage('Checkout') {
steps {
echo "Cloning Repository..."
git branch: 'feature',
url: 'https://github.com/KandlaguntaVenkataSivaNiranjanReddy/spring-boot-mongo-docker-kkfunda.git'
}
}
stage('Maven Build') {
steps {
echo "Building the Maven Project..."
sh 'mvn clean package -DskipTests'
}
}
stage('Snyk Repo Scan') {
steps {
echo "Running Snyk scan for dependency vulnerabilities..."
sh '''
echo "Authenticating with Snyk..."
snyk auth $SNYK_TOKEN
echo "Running Snyk Test..."
snyk test --all-projects || true
snyk monitor --all-projects || true
'''
}
}
}
8.11 Key Snyk Commands Used in the Jenkins Pipeline
Snyk plays a critical role in our DevSecOps pipeline by providing dependency-level security visibility without blocking the CI/CD flow. The following commands are intentionally designed to detect, report, and monitor vulnerabilities while allowing the pipeline to continue.
1. Understanding snyk test --all-projects || true
This command is used for pre-deployment security analysis of application dependencies.
What snyk test --all-projects Does
Scans all supported project types in the Jenkins workspace
Automatically detects dependency manifests such as:
pom.xml(Maven)package.json(Node.js)requirements.txt(Python)Other supported files
Analyzes:
Direct project dependencies
Transitive (indirect) dependencies
Third-party libraries
Output Provided
Total number of dependencies tested
Total vulnerabilities found
Severity breakdown: CRITICAL ,HIGH ,MEDIUM ,LOW
CVE IDs with vulnerability descriptions
This scan helps identify security issues before containerization or deployment.
Why || true Is Used
snyk test --all-projects || true
Prevents the Jenkins build from failing
Ensures:
Vulnerabilities are reported, not blocked
The pipeline continues to Docker build, image scanning, and deployment
Ideal when security findings are required for visibility and analysis, not for stopping delivery
2. Understanding snyk monitor --all-projects || true (Important)
- Without this command, the project will NOT appear in the Snyk Dashboard and cannot be monitored.
snyk testonly scans locally, butsnyk monitoris mandatory for dashboard visibility and continuous monitoring.
This command goes beyond scanning.
What
snyk monitorDoesTakes a snapshot of the project’s current dependency state
Uploads:
Project metadata
Dependency graph
Vulnerability context
to the Snyk Dashboard
Enables continuous monitoring of the application
Why This Matters
Even after the pipeline finishes, Snyk continues to:
Monitor for newly discovered vulnerabilities
Alert when dependencies become insecure in the future
Converts one-time scans into ongoing security visibility
8.12 Jenkins Job Execution
- The Jenkins job runs successfully

What We See in Jenkins Console Output
From the console output:
Jenkins authenticates with Snyk using the token
Snyk scans the Jenkins workspace

Output shows:
Number of dependencies tested
Number of vulnerabilities found
Severity levels (Critical, High, Medium, Low)
Example meaning: “Tested 78 dependencies, found 168 issues”
This does NOT fail the build it only reports security findings
Purpose: To detect security issues in third-party libraries used by the application
8.13 Results in Snyk Dashboard
After the scan:
The project is automatically sent to the Snyk Dashboard

You can log in to Snyk and see:
The project is automatically sent to the Snyk Dashboard
In the Snyk UI, we can see:
Project name
Vulnerable libraries
CVE details
Severity levels
Fix and upgrade recommendations
Which dependency introduced the issue

Benefits to the Development Team
This helps developers to:
Decide which dependencies need upgrades
Avoid insecure libraries
Keep safe and stable dependencies
Fix vulnerabilities early (Shift Left Security)
Prevent insecure components from reaching production

This proves that security is enforced during the CI stage, not after deployment.
Overall, Snyk revealed high-risk CVEs in third-party dependencies, allowing us to quickly decide what to upgrade and secure before production deployment.
9. Steps to Create SonarQube Token and Configure It in Jenkins
Integrating SonarQube with Jenkins is a critical step in implementing code quality and static code analysis inside a CI/CD pipeline.
For Jenkins to communicate securely with SonarQube, two configurations are mandatory:
Creating an Authentication Token in SonarQube
Configuring the SonarQube Server and Token in Jenkins
This setup allows Jenkins to trigger SonarQube scans automatically during pipeline execution.
9.1 Generate SonarQube Token
Log in to your SonarQube dashboard.
Click on your profile → My Account > Security.

Generate a new token:
Give it a name like
jenkins

- Copy the generated token immediately you won’t be able to see it again later
9.2 Add SonarQube Token in Jenkins Credentials
Go to Jenkins Dashboard
Navigate to: Manage Jenkins → Credentials → (Global) → Add Credentials

Fill the details:
Kind: Secret Text
Secret: Paste the SonarQube token you generated

Description:
sonartokenClick Save

Now the token is securely stored in Jenkins.
Adding credentials alone is not sufficient. Jenkins also needs to know the SonarQube server address (IP + Port).
9.3 Configure SonarQube Server in Jenkins
- Go to: Manage Jenkins → Configure System

Scroll down to SonarQube Servers section
Click on Add SonarQube
Fill the details:
Name:
sonarServer URL:
http://<sonarqube-server-ip>:9000Authentication Token: Select the credential sonartoken from the dropdown

- Click Save
9.4 Configure Sonar Scanner in Jenkins
Go to Manage Jenkins > Global Tool Configuration.
Under SonarQube Scanner, click Add SonarQube Scanner.
Name:
SonarScannerSelect Install automatically

9.5 Running Jenkins Build with SonarQube Integration
Once you’ve configured your SonarQube server and added the authentication token in Jenkins, you can now run your Jenkins builds and trigger code analysis with SonarQube.
Update Pipeline with Sonar Stage:

The name
'sonar'used here must match the name you defined under:
Manage Jenkins → Configure System → SonarQube ServersJenkins will automatically use the SonarQube URL and authentication token from this configuration.
You do not need to manually pass the token or URL in the pipeline.
After configuration is complete, trigger the Jenkins pipeline.
Check the Build Status: The build should complete successfully
pipeline {
agent any
tools {
maven 'maven3.9.9'
}
environment {
SNYK_TOKEN = credentials('SNYK_TOKEN') // Snyk API token
}
stages {
stage('Checkout') {
steps {
echo "Cloning Repository..."
git branch: 'feature',
url: 'https://github.com/KandlaguntaVenkataSivaNiranjanReddy/spring-boot-mongo-docker-kkfunda.git'
}
}
stage('Maven Build') {
steps {
echo "Building the Maven Project..."
sh 'mvn clean package -DskipTests'
}
}
stage('SonarQube Analysis') {
steps {
withSonarQubeEnv('sonar') {
echo "Running SonarQube analysis..."
sh '''
mvn sonar:sonar \
-Dsonar.projectKey=spring-boot-mongo \
-Dsonar.projectName="Spring Boot Mongo Project"
'''
}
}
}
stage('Snyk Repo Scan') {
steps {
echo "Running Snyk scan for dependency vulnerabilities..."
sh '''
echo "Authenticating with Snyk..."
snyk auth $SNYK_TOKEN
echo "Running Snyk Test..."
snyk test --all-projects || true
echo "Sending results to Snyk dashboard..."
snyk monitor --all-projects || true
'''
}
}
}

- Open your SonarQube dashboard (e.g.,
http://<your-ip>:9000) and log in.
You’ll see the projectSpring Boot Mongo Projectlisted, confirming that the analysis was successful.

- You’ll see the project
Spring Boot Mongo Projectlisted, confirming that the analysis was successful.
10. Docker Authentication and Image Security Scanning in Jenkins
- After completing code build, code quality checks, and dependency security scanning, the next critical phase in the DevSecOps pipeline is containerization.
In this stage:
Jenkins builds a Docker image
Scans the image for vulnerabilities using Trivy
Pushes the verified image to Docker Hub
This step ensures that only scanned and verified container images move forward for deployment.
10.1 Why Docker Authentication Is Required in Jenkins
In our pipeline, Jenkins builds a Docker image and pushes it to Docker Hub.
Docker Hub does not allow image push operations without authentication.
Therefore, Jenkins must log in to Docker Hub automatically and securely.Important Security Note: We do NOT use Docker Hub passwords
We use Docker Hub Personal Access Tokens
Tokens are: More secure , Recommended for CI/CD pipelines
10.2 Generate Docker Hub Personal Access Token
- Click on your profile (top-right) → Account Settings

- Select Personal Access Token

- Give it Read, Write, Delete permissions

- Click to generate the token.

- Copy the token immediately it will not be shown again
10.3 Add Docker Hub Credentials to Jenkins
Navigate to: Jenkins Dashboard → Manage Jenkins → Credentials

- Under the appropriate domain (usually global), click:
Add Credentials

In the Kind dropdown, select: Username and password
Fill in the form:
Username: Your Docker Hub username
Password: Paste your Docker authentication token

ID: eg:
dockerDescription: e.g:
docker-credClick OK to save the credentials.
10.4 Installing Trivy on Jenkins Server
Why install Trivy on Jenkins?
Jenkins executes pipeline steps
Trivy command must be available on Jenkins machine
Jenkins will scan locally built Docker images
You created a script:
vi trivy.sh

Then pasted:

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
Then executed:
sh trivy.sh

10.5 Prerequisites Recap Before Docker Build
Before building and pushing Docker images, ensure:
Jenkins is installed and running
Docker is installed on Jenkins server
Jenkins user is added to Docker group
Jenkins user must be added to the Docker group. (
sudo usermod -aG docker jenkins)Docker Hub credentials (username + token) added to Jenkins as Username & Password
GitHub repo has a valid
Dockerfile
10.6 Using Jenkins Snippet Generator for Docker Authentication
To safely authenticate Docker commands (like docker push) from a Jenkins pipeline, you can use the built-in snippet generator:
Navigate to your Jenkins job → Click on Pipeline Syntax (usually bottom left or under job configuration)
From the dropdown, select:
withDockerRegistry: Set up Docker registry endpointDocker registry URL: ( Leave this empty) Docker Hub is a public registry, so no URL is required
Credentials: Choose the one you just added (
docker-cred)

Click
Generate Pipeline Script.Jenkins will provide you with a block like this, which you can use in your pipeline script.
10.7 Pipeline Script for Building and Pushing Docker Image and trivy stages
After completing GitHub → Jenkins → Maven Build → Sonarqube→Snyk Scan, the next stage in the DevSecOps pipeline is containerization and image security scanning.
This step converts the application into a Docker image, scans it for vulnerabilities, and then pushes it to Docker Hub.
Docker Authentication via Jenkins
Jenkins securely authenticates to Docker Hub using stored credentials
Credentials are never exposed in logs or pipeline files
This allows Jenkins to perform Docker push operations safely.
Docker Image Build
Jenkins uses the Dockerfile present in the repository
Application source code + runtime environment are packaged into a Docker image
At this point, the application officially becomes a container image
Trivy Image Scan (Security Scan)
After the image is built:
Trivy scans the Docker image
It analyzes:
OS packages
Application dependencies inside the image
Trivy detects: Known CVEs
Vulnerability severity: Critical ,High ,Medium ,Low
stage('Build & Tag Docker Image') {
steps {
script {
echo "Building Docker image..."
withDockerRegistry(credentialsId: 'docker') {
sh 'docker build -t niranjanreddy1231/mongospring:latest .'
}
}
}
}
stage('Trivy Image Scan') {
steps {
echo "Scanning Docker image for vulnerabilities using Trivy..."
sh '''
trivy image --exit-code 0 --severity HIGH,CRITICAL niranjanreddy1231/mongospring:latest
trivy image --exit-code 1 --severity CRITICAL niranjanreddy1231/mongospring:latest || true
'''
}
}
stage('Push Docker Image') {
steps {
script {
echo "Pushing Docker image to DockerHub..."
withDockerRegistry(credentialsId: 'docker') {
sh 'docker push niranjanreddy1231/mongospring:latest'
}
}
}
}
- Now run the Jenkins job Build Status: SUCCESS

10.8 What We See in Jenkins Console Output
In the console output, Trivy displays:
Vulnerable packages present inside the Docker image
CVE IDs for each detected vulnerability
Severity levels such as:
Critical, High, Medium, LowFixed versions (if available) that can resolve the issue
This gives a clear picture of which component is risky and how it can be fixed.

Critical vulnerabilities in libraries like
logback,jacksonClear indication of what version is vulnerable and what version fixes it
10.9 Docker Authentication & Image Push Confirmation
Jenkins securely uses the Docker Hub credentials configured in Jenkins under the credentials ID
docker.These credentials are stored safely in Jenkins
They are never exposed in the pipeline script or console logs
Jenkins uses them only when required (during image build and push)
Image is built and pushed to your Docker Hub repository.
You can confirm it in the Docker Hub UI.
11. EKS Cluster Setup and Jenkins Integration
11.1 Why EKS Setup Is Required
After building, scanning, and pushing the Docker image, the next step is deployment.
To deploy the application into Kubernetes, Jenkins must be able to:
Communicate with AWS
Access the EKS control plane
Execute
kubectlcommands
For this, the Jenkins server itself must be prepared with the required Kubernetes and AWS tools.
11.2 Tools Required on Jenkins Server
The following tools must be installed on the Jenkins EC2 server:
AWS CLI – To authenticate and interact with AWS services
kubectl – To manage Kubernetes resources
eksctl – To create and manage the EKS cluster
AWS credentials – To authorize Jenkins with AWS (Access key, Secret key, Region, Output format)
11.3 Install AWS CLI on Jenkins Server
sudo apt update
sudo apt install unzip curl -y

curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install

Check installation
aws --version

11.4 Configure AWS Credentials
Jenkins needs AWS credentials to access EKS.
aws configure
Enter the following:
Access Key ID
Secret Access Key
Default region (e.g.
ap-south-1)Output format : table

11.5 Install kubectl
kubectl is the CLI used to manage Kubernetes clusters.
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
curl -LO ...downloads the latest stable version ofkubectlfrom the Kubernetes website.sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectlmoveskubectlto the/usr/local/bin/directory with appropriate permissions.

Check version
kubectl version --client

11.6 Install eksctl
eksctl simplifies EKS cluster creation and management.
curl -LO "https://github.com/eksctl-io/eksctl/releases/latest/download/eksctl_Linux_amd64.tar.gz"
tar -xzf eksctl_Linux_amd64.tar.gz
sudo mv eksctl /usr/local/bin/
eksctl version

Check the version
eksctl version
11.7 Create the EKS Cluster Using eksctl
eksctl create cluster \
--name my-cluster \
--region ap-south-1 \
--nodegroup-name mynodes \
--node-type t3.medium \
--nodes 2 \
--nodes-min 2 \
--nodes-max 3 \
--managed
What this does:
Creates a managed EKS cluster named
my-clusterin the Mumbai region (ap-south-1)Adds a managed node group called
mynodesUses
t3.mediumEC2 instancesStarts with 2 nodes and allows scaling up to 3

This creates the following resources when you run eksctl create cluster:
VPC (Virtual Private Cloud)
A private network where your entire EKS infrastructure lives.Subnets & Route Tables
Public and private subnets are created with routing rules.Public subnets allow access to the internet (e.g., for Load Balancers).
Private subnets are used for internal communication (e.g., between pods and worker nodes).
Internet Gateway
Attached to the public subnets, this enables the cluster to access the internet (like pulling Docker images or updates).NAT Gateway (optional)
Allows private subnets (e.g., worker nodes) to securely access the internet.Security Groups
Act like firewalls control which ports are open (like 443 for API server, 22 for SSH).- Includes ingress rules (incoming) and egress rules (outgoing).
EKS Control Plane
AWS-managed Kubernetes control plane that handles the API server, scheduler, etc.- You don’t manage this manually AWS runs it for you.
EC2 Worker Nodes (Node Group)
These are actual EC2 instances created inside the private subnets.- Your application pods run on these nodes.
IAM Roles & Policies
Automatically created for EKS to securely access and control AWS services.

Check if Cluster is Created
Run this command to list all EKS clusters:
You should see
my-clusterin the output.
aws eks list-clusters

Check kubeconfig File
cat /home/ubuntu/.kube/config
This file contains the cluster connection details used by
kubectl.This command displays the contents of the kubeconfig file, which is used by
kubectlto manage your Kubernetes cluster.

Check Worker Nodes
kubectl get nodes
You should see 2 EC2 worker nodes in "Ready" status.
This confirms the worker nodes joined the cluster.

Check Namespaces
kubectl get namespaces
- Default Kubernetes namespaces should appear:

11.8 Verify EKS Cluster in AWS Console
Go to AWS Console
Search for “EKS” service

- Click on your cluster:
my-cluster

- Click the “Compute” tab

Here you’ll see:
The node group (
mynodes)EC2 instances created
Scaling status
12. Configure Jenkins for Kubernetes (EKS Integration)
12.1 Install Required Jenkins Plugins
AWS Credentials Plugin
Kubernetes Plugin
Kubernetes CLI Plugin
Kubernetes Credentials
To interact with an EKS cluster from Jenkins, you typically need to AWS Credentials Plugin


12.2 Add AWS Credentials in Jenkins
Why Add AWS Credentials in Jenkins?
Jenkins doesn't know your AWS credentials by default.
This injects AWS credentials temporarily into your Jenkins shell can authenticate securely with AWS and Kubernetes.
Go to Manage Jenkins page, click on "Manage Credentials”
Now, under (global) or in a specific domain if required, click on (Global credentials)

Credentials → (Global) → Add Credentials
Select the AWS Credentials Type:
In the Kind dropdown, select "AWS Credentials".

Fill in the AWS Credentials:
ID: Provide a unique name for the credentials (e.g.,
aws-eks-cred).Access Key ID: Enter your
AWS_ACCESS_KEY_ID.Secret Access Key: Enter your
AWS_SECRET_ACCESS_KEY.This is used in the
withCredentialsblock in the pipeline.

12.3 Start Writing the Jenkins Pipeline
After Jenkins is configured with AWS credentials, we proceed with the pipeline stages related to Kubernetes.
12.4 Git Checkout Stage
- Now here Jenkins is cloning the code from GitHub repo exactly from the
featurebranch.

12.5 Setup AWS + KubeConfig
Here Jenkins is injecting AWS credentials that we already stored with ID
aws-eks-cred.
This contains Access Key + Secret Key securely stored in Jenkins credentials.Connects Jenkins to your EKS cluster using AWS CLI
Generates or updates
.kube/configfile so thatkubectlcan talk to the EKS control plane.

12.6 Deploy Application to Kubernetes
Important: YAML File Must Be Correct
The file springappmongo.yaml is:

Already present inside the GitHub repository
This file is the blueprint for your Kubernetes deployment.
This YAML Defines:
Deployment
It tells Kubernetes how to create pods for your Spring Boot + MongoDB application.
Example: number of replicas, container image, ports.
Service
It exposes your application so it can be accessed.
If it’s a LoadBalancer type, AWS will create an ELB for you.
Note : If the filename is wrong or not present in the repo, the pipeline will fail

The --validate=false flag is used to skip any API schema checks just apply and go.
This step actually creates the Kubernetes pods and services in your EKS environment."
12.7 Verify Pods and Services
Once deployed, we use kubectl get pods to check if the application is running and kubectl get svc to verify if a LoadBalancer or ClusterIP service is created.

12.8 Trivy Kubernetes Cluster Scan
After successfully deploying the application to the Kubernetes (EKS) cluster, the next critical DevSecOps step is cluster-level security scanning using Trivy.
This scan is performed after deployment, focusing on the Kubernetes environment, not just the code or image.
Why Cluster Scanning Is Important Even if:
Source code is secure (SAST – SonarQube)
Dependencies are scanned (Snyk)
Docker image is scanned (Trivy Image Scan)
Security risks can still exist at the Kubernetes cluster level.
These risks usually come from:
Misconfigured Kubernetes resources
Insecure container runtime settings
Excessive permissions (RBAC issues)
Vulnerable libraries running inside pods
Exposed services or outdated components
12.9 What Happens During Trivy Cluster Scan
Trivy scans the running workloads inside the Kubernetes cluster
It inspects:
Deployed containers
Application libraries
Framework dependencies
OS packages inside pods
It identifies known CVEs that are active after deployment
Cluster scanning ensures that the runtime environment itself is secure, not just the application.

Full pipeline
pipeline {
agent any
tools {
maven 'maven3.9.9'
}
environment {
SNYK_TOKEN = credentials('SNYK_TOKEN') // Snyk API token
}
stages {
stage('Checkout') {
steps {
echo "Cloning Repository..."
git branch: 'feature',
url: 'https://github.com/KandlaguntaVenkataSivaNiranjanReddy/spring-boot-mongo-docker-kkfunda.git'
}
}
stage('Maven Build') {
steps {
echo "Building the Maven Project..."
sh 'mvn clean package -DskipTests'
}
}
stage('SonarQube Analysis') {
steps {
withSonarQubeEnv('sonar') {
echo "Running SonarQube analysis..."
sh '''
mvn sonar:sonar \
-Dsonar.projectKey=spring-boot-mongo \
-Dsonar.projectName="Spring Boot Mongo Project"
'''
}
}
}
stage('Snyk Repo Scan') {
steps {
echo "Running Snyk scan for dependency vulnerabilities..."
sh '''
echo "Authenticating with Snyk..."
snyk auth $SNYK_TOKEN
echo "Running Snyk Test..."
snyk test --all-projects || true
snyk monitor --all-projects || true
'''
}
}
stage('Build & Tag Docker Image') {
steps {
script {
echo "Building Docker image..."
withDockerRegistry(credentialsId: 'docker') {
sh "docker build -t niranjanreddy1231/mongospring:latest ."
}
}
}
}
stage('Trivy Image Scan') {
steps {
echo "Scanning Docker image for vulnerabilities using Trivy..."
sh '''
trivy image --exit-code 0 --severity HIGH,CRITICAL niranjanreddy1231/mongospring:latest
trivy image --exit-code 1 --severity CRITICAL niranjanreddy1231/mongospring:latest || true
'''
}
}
stage('Push Docker Image') {
steps {
script {
echo "Pushing Docker image to DockerHub..."
withDockerRegistry(credentialsId: 'docker') {
sh "docker push niranjanreddy1231/mongospring:latest"
}
}
}
}
stage('Setup KubeConfig') {
steps {
withCredentials([[$class: 'AmazonWebServicesCredentialsBinding',
credentialsId: 'aws-eks-cred']]) {
sh '''
echo "Setting up kubeconfig for EKS cluster..."
# Export AWS credentials explicitly
export AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID
export AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY
export AWS_DEFAULT_REGION=ap-south-1
echo "Verifying AWS Identity..."
aws sts get-caller-identity
echo "Updating kubeconfig for EKS cluster..."
aws eks update-kubeconfig --region ap-south-1 --name my-cluster
echo "Kubeconfig setup complete."
'''
}
}
}
stage('Deploy to Kubernetes') {
steps {
echo "Deploying application to EKS..."
withCredentials([[$class: 'AmazonWebServicesCredentialsBinding',
credentialsId: 'aws-eks-cred']]) {
sh '''
kubectl apply -f springappmongo.yaml --validate=false
'''
}
}
}
stage('Verify Pods and Services') {
steps {
echo "Verifying Kubernetes resources..."
withCredentials([[$class: 'AmazonWebServicesCredentialsBinding',
credentialsId: 'aws-eks-cred']]) {
sh '''
kubectl get pods -o wide
kubectl get svc -o wide
'''
}
}
}
stage('Trivy Cluster Scan') {
steps {
echo "Scanning Kubernetes cluster for vulnerabilities..."
withCredentials([[$class: 'AmazonWebServicesCredentialsBinding',
credentialsId: 'aws-eks-cred']]) {
sh '''
export AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID
export AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY
export AWS_DEFAULT_REGION=ap-south-1
echo "Running Trivy Kubernetes cluster scan..."
trivy k8s --report summary cluster || true
'''
}
}
}
}
post {
success {
echo "Pipeline completed successfully."
}
failure {
echo "Pipeline failed. Please check the logs for details."
}
}
}
12.10 Run the Jenkins Job
- Once the pipeline is set up, go ahead and click “Build Now” in Jenkins.

In the console output, you’ll see:
Now you can see Jenkins first pulling the source code from our GitHub repository, specifically the
featurebranch. This is our application code for Spring Boot with MongoDB.Jenkins is securely injecting our AWS credentials
At this stage, Jenkins updates the kubeconfig file.This connects kubectl to our EKS cluster without this, Jenkins can't run K8s commands.
Now Jenkins is deploying the application by running:
kubectl apply -f springappmongo.yamlThis file has all our K8s objects like the Deployment and Service definitions

Jenkins is verifying everything by listing Pods and Services. It runs:
kubectl get podsto see if the app is runningkubectl get svcto see if the LoadBalancer service is ready”

- Even though Jenkins shows everything in the console output, it's a good habit to manually verify from your EC2 server terminal (Jenkins server)

When you open the Jenkins Console Output, you can clearly see that Trivy Displays:
Vulnerable packages running inside the Kubernetes cluster
CVE IDs for each vulnerability
Severity levels: CRITICAL , HIGH ,MEDIUM ,LOW
Installed version vs Fixed version
Description of the vulnerability
Reference links (Aqua / NVD URLs)
This confirms that Trivy is actively scanning the live cluster environment.

From the console output shown:
Spring Framework vulnerabilities:
spring-beans,spring-web,spring-webmvcThymeleaf vulnerability
Template injection issue
Vulnerabilities such as:
Remote Code Execution (RCE)
Unsafe deserialization
Template injection
Clear indication of:
Vulnerable version
Safe / fixed version
These issues exist inside running Kubernetes pods, not just in source code.
12.11 Access the Application
Now, you can copy this LoadBalancer URL from the console, paste it into your browser.
Now you can add users to your application.

13. Conclusion
In this project, we successfully built a complete end-to-end DevSecOps CI/CD pipeline using Jenkins and AWS EKS.
Key outcomes of this implementation:
Automated code build and quality analysis using Maven and SonarQube
Early dependency vulnerability detection using Snyk (SAST + SCA)
Secure container image scanning using Trivy before deployment
Automated Kubernetes deployment on Amazon EKS
Post-deployment cluster security scanning, ensuring runtime security
This pipeline demonstrates how security can be embedded into every stage of CI/CD, rather than treated as a separate process.
By integrating security early, we reduce risk, improve reliability, and deliver production-ready applications with confidence.



