DevSecOps - Kubernetes DevOps & Security
DevSecOps Pipeline
Demo OPA Conftest Kubernetes
In this hands-on tutorial, you’ll integrate OPA Conftest into a Jenkins pipeline to enforce custom policy-as-code for Kubernetes Deployments and Services. Scanning your manifests before they reach the cluster helps prevent misconfigurations and potential security vulnerabilities.
Prerequisites
- Jenkins server with Docker installed
- Kubernetes cluster and
kubectl
configured - OPA Conftest CLI available locally or via Docker
Note
Ensure your kubeconfig
credentials are stored in Jenkins (e.g., under credentialsId: 'kubeconfig'
) before starting.
Jenkins Pipeline Stages
Add a vulnerability scan stage between the Docker build and Kubernetes deployment:
pipeline {
agent any
stages {
stage('Docker Build and Push') {
steps {
withDockerRegistry([credentialsId: 'docker-hub', url: '']) {
sh 'sudo docker build -t siddharth67/numeric-app:${GIT_COMMIT} .'
sh 'docker push siddharth67/numeric-app:${GIT_COMMIT}'
}
}
}
stage('Vulnerability Scan - Kubernetes') {
steps {
sh '''\
docker run --rm \
-v $(pwd):/project \
openpolicyagent/conftest test \
--policy opa-k8s-security.rego \
k8s_deployment_service.yaml
'''
}
}
stage('Kubernetes Deployment - DEV') {
steps {
withKubeConfig([credentialsId: 'kubeconfig']) {
sh 'sed -i "s|replace|siddharth67/numeric-app:${GIT_COMMIT}|" k8s_deployment_service.yaml'
sh 'kubectl apply -f k8s_deployment_service.yaml'
}
}
}
}
}
Defining the OPA Policy
Create opa-k8s-security.rego
at the root of your project:
package main
deny[msg] {
input.kind == "Service"
not input.spec.type == "NodePort"
msg = "Service type should be NodePort"
}
deny[msg] {
input.kind == "Deployment"
not input.spec.template.spec.containers[0].securityContext.runAsNonRoot
msg = "Containers must not run as root - set runAsNonRoot: true"
}
Resource Kind | Rule Description |
---|---|
Service | spec.type must be NodePort |
Deployment | Containers require securityContext.runAsNonRoot |
Running Conftest
From your project directory, run:
docker run --rm \
-v $(pwd):/project \
openpolicyagent/conftest test \
--policy opa-k8s-security.rego \
k8s_deployment_service.yaml
Warning
If any policy is violated, Conftest exits with a non-zero code and prints the error. Your Jenkins pipeline will fail until you address the violation.
Example failure output:
FAIL: k8s_deployment_service.yaml - main - Containers must not run as root - set runAsNonRoot: true
script returned exit code 1
Fixing Policy Violations
1. Enforce runAsNonRoot
Update your Deployment spec to include a securityContext
:
apiVersion: apps/v1
kind: Deployment
metadata:
name: devsecops
labels:
app: devsecops
spec:
replicas: 2
selector:
matchLabels:
app: devsecops
template:
metadata:
labels:
app: devsecops
spec:
containers:
- name: devsecops-container
image: replace
securityContext:
runAsNonRoot: true
---
apiVersion: v1
kind: Service
metadata:
name: devsecops
labels:
app: devsecops
spec:
type: NodePort
ports:
- port: 8080
targetPort: 8080
protocol: TCP
selector:
app: devsecops
Re-run the Conftest command to confirm that all tests pass.
2. Specify Numeric User (Optional)
If you encounter a CreateContainerConfigError
due to a non-numeric user, add runAsUser
:
securityContext:
runAsNonRoot: true
runAsUser: 100
Commit, push, and trigger a new build.
Verifying Deployment
After a successful pipeline run, validate your resources:
kubectl get all
You should see the Deployment and Service running without errors.
Links and References
Watch Video
Watch video content