Continuous integration and continuous deployment can become a continuous pain for security folks. But it doesn’t have to be that way. Integrating security into your CICD pipeline can improve your security posture tremendously and the best part is security folks don’t need to do any additional work. Why Anchore Engine? It’s open source, good coverage and integrates with CI tool.

This post covers setting up anchore engine container, integration of anchore engine with Jenkins plugin, then finally pushing clean docker images to docker hub. This is a beginners guide hence I tried to publish as much information and screenshots as possible.

Simple workflow showing how container security scanning and approval can be integrated with your DevOps pipeline.

Container security scan workflow

This post will cover the below integration:

Anchore engine workflow

Pre-requisite:

Jenkins, Docker, and Docker-compose installed on the host.

The environment used in this tutorial:

Ubuntu 18.0.4 host. Docker version 18.06, docker-compose version 1.22.0, Jenkins 2.138.2.

The high level we will break down the setup and integration in three phases.

First, we will setup anchore engine running inside a docker container. Second, we will setup integration between anchore engine and Jenkins. Lastly we will setup a pipeline to do the policy scan using Anchore engine. If the scan detects high severity issue it will break the build or else the image will be uploaded to a docker hub repo.

Let’s get started!!!!!

Step 1: Install anchore engine docker image from the official repository.



mkdir -p ~/aevolume/db/

cd ~/aevolume/config && curl -O

cd ~/aevolume

curl -O mkdir -p ~/aevolume/configmkdir -p ~/aevolume/db/cd ~/aevolume/config && curl -O https://raw.githubusercontent.com/anchore/anchore-engine/master/scripts/docker-compose/config.yaml && cd —cd ~/aevolumecurl -O https://raw.githubusercontent.com/anchore/anchore-engine/master/scripts/docker-compose/docker-compose.yaml

At this point, your folder structure should look like below:

Step 2: (Optional but recommended): Change the passwords for your anchore-engine from config.yaml file.

nano ~/aevolume/config/config.yaml

config.yaml file

Step 3: Finally run your anchore engine docker image using the below command:



docker-compose up -d

Additional:

I had to download anchore-engine cli as docker-compose was throwing an error. If you face the same issue regarding anchore-engine cli you can download the cli as below:



apt-get update

apt-get install python-pip

pip install anchorecli

https://github.com/anchore/anchore-cli apt-get updateapt-get install python-pippip install anchorecli

Further information can be found at: https://github.com/anchore/anchore-engine

At this point you are all set with anchore-engine. You can scan your containers manually using the anchore-cli. But we wont cover that in this tutorial. You can refer to the GitHub page for more details: https://github.com/anchore/anchore-cli

Second phase Integration between Jenkins and anchore engine

Step 4: Install the jenkins anchore plugin as shown below:

Jenkins Anchore plugin

Step 5: Configure the Anchore plugin, Jenkins-> Manage Jenkins -> Configure System

Ensure you use the same credentials as per your ~/aevolume/config/ config.yaml file

For this tutorial we are using free docker hub account, if you are using your enterprise docker hub repo then you need to update accordingly.

Step 6: Setup docker hub repo credentials in Jenkins for pushing images to docker hub. Go to jenkins-> Credentials->System:

Step 7: Next create a repository to push your image to docker hub if the build is successful.

Docker hub repo

Demo time!!! Now you are all set to scan your first project.

Step 8: Create your Jenkins pipeline:

Jenkins pipeline

Step 9: Input the below pipeline script as part of the pipeline step:



environment {

registry = “tahmed11/demo”

registryCredential = ‘dockerhub’

dockerImage = ‘’}

agent any

stages {

stage(‘Cloning Git’) {

steps {

git ‘

}}

stage(‘Building image’) {

steps{

script {

dockerImage = docker.build registry + “:$BUILD_NUMBER”}}}

stage(‘Container Security Scan’) {

steps {

sh ‘echo “docker.io/tahmed11/demo `pwd`/Dockerfile” > anchore_images’

anchore name: ‘anchore_images’}}

stage(‘Deploy Image’) {

steps{

script {

docker.withRegistry( ‘’, registryCredential ) {

dockerImage.push()

}}}}

stage(‘Cleanup’) {

steps {

sh’’’

for i in `cat anchore_images | awk ‘{print $1}’`;do docker rmi $i; done

‘’’}}}} pipeline {environment {registry = “tahmed11/demo”registryCredential = ‘dockerhub’dockerImage = ‘’}agent anystages {stage(‘Cloning Git’) {steps {git ‘ https://github.com/tahmed11/docker-dvwa.git' }}stage(‘Building image’) {steps{script {dockerImage = docker.build registry + “:$BUILD_NUMBER”}}}stage(‘Container Security Scan’) {steps {sh ‘echo “docker.io/tahmed11/demo `pwd`/Dockerfile” > anchore_images’anchore name: ‘anchore_images’}}stage(‘Deploy Image’) {steps{script {docker.withRegistry( ‘’, registryCredential ) {dockerImage.push()}}}}stage(‘Cleanup’) {steps {sh’’’for i in `cat anchore_images | awk ‘{print $1}’`;do docker rmi $i; done‘’’}}}}

Note the formatting issue on the above code you should change the following characters{‘,”}. Anyways back to the scanning business. I deliberately scanned a vulnerable image for the build to fail. You can test your build using the following vulnerable image.

https://github.com/tahmed11/docker-dvwa.git'



Finally, the pipeline view should look like below if the build failed due to any high severity vulnerability.

Step 10: View the Anchore engine reports for the list of all the issues: