DEV Community

Cover image for Integrate Docker Image Signing in CI Pipeline
Ahaiwe Emmanuel
Ahaiwe Emmanuel

Posted on

Integrate Docker Image Signing in CI Pipeline

Why Bother with Docker Image Signing?

a. Supply chain security: Ensures that the image is vetted before deployment to a production environment.

b. To pass vulnerability tests and checks: Vulnerability assessment tools used by QA engineers and other testers analyze the integrity of images to ensure it is unmodified and original. It verifies that the image is from the expected source.

c. Customer Trust: Customers and consumers of the image can have confidence in its originality and integrity.

d. Image Integrity: If anyone without access to the source tries to modify it, the signature verification would fail. Hence only you can sign your image with your chosen password or key.

As an engineer, you want to maintain the integrity of the applications you are deploying to the production environment, even when there are attacks by shady internet characters. For Docker, there is a manual way to do this by doing docker sign trust image:tag before pushing the image to your repository and subsequently, deployment. Automating this process on your continuous integration is what this article focuses on. Our tools of choice are Github and CircleCI and cosign.

Prerequisite

  1. Integrate CircleCI with GitHub as seen here

  2. Container repository

  3. A Dockerfile to build your image.

Let's Dive Right In

  • Create CircleCI Folder Create a CircleCI job with Docker and Nodejs preinstalled into the workflow. To do this, create a .circleci folder at the root of your project. In that folder, create a config.yml file with the given configurations:
version: 2.1
jobs:
  deploy-sign-images-to-production:
    docker:
      - image: wecs/circle-ci-gcloud-node:0.1.0
    working_directory: ~/signed-images
      - run:
          name: Build and Deploy Signed Images
          command: |
            chmod u+x ./deployment.sh
            if [ "${CIRCLE_BRANCH}" == "main" ]; then
              ./deploy.sh
            fi
Enter fullscreen mode Exit fullscreen mode
  • Create Bash Script Create a bash file called deploy.sh still in the root of your project. This will help install cosign to sign the docker image.
# !/bin/sh
set -e
set -o pipefail

# login to docker hub
echo “$DOCKERHUB_PASSWORD” | docker login -u “$DOCKERHUB_USERNAME” — password-stdin
docker build -t dockerhuburl/imagename:$CIRCLE_SHA1 .

# download cosign
curl -LO https://github.com/sigstore/cosign/releases/latest/download/cosign-linux-amd64

# give cosign executable access
chmod +x cosign-linux-amd64

# move cosign to your CI machine bin folder
mv cosign-linux-amd64 /usr/local/bin/cosign

# check cosign version and that it installed successfully
cosign version

# generate key pair using set $COSIGN_PASSWORD
cosign generate-key-pair

# push to docker hub
docker -- push dockerhuburl/imagename:$CIRCLE_SHA1

# sign image
cosign sign --key cosign.key dockerhuburl/imagename:tag:$CIRCLE_SHA1 -y

# verify image
cosign verify --key cosign.pub dockerhuburl/imagename:tag:$CIRCLE_SHA1:$CIRCLE_SHA1
Enter fullscreen mode Exit fullscreen mode
  • Explaining Environmental Variables Created
    First, we set need to set CircleCI environment variables. Read this article https://circleci.com/docs/env-vars/ for more insight. Set $DOCKERHUB_PASSWORD and $DOCKERHUB_USERNAME to your docker hub login details. You do not need to set $CIRCLE_SHA1 as it is a unique variable generated by CircleCI you can take advantage of in your pipeline. Then finally create an environment variable called $COSIGN_PASSWORD and pass any value you want to it. For this tutorial, I use 1234 as the password. This would be the password to help generate the cosign.key and cosign.pub files.

  • Final Review
    Very importantly, we need to note that we need the image to first exist in the docker repository so we can be able to sign it. Hence, why we push the image first before signing and verifying it, don't forget to have a Dockerfile in your environment. Create a pull request and merge it to your main branch on GitHub. Switch to your project dashboard on CircleCI to monitor your build. You should have your signed image pushed to docker hub. Hurray!!!

The sequel article would touch on how to create a policy that allows only signed images to be deployed in your Kubernetes cluster.

Top comments (1)

Collapse
 
monwuzua profile image
monwuzua

insightful