Building Kaniko Image with Embedded Twistcli

In this blog post, we’ll explore how to create a custom Kaniko image that includes Twistcli for security scanning. This setup is especially useful in environments where Docker-in-Docker (DinD) is not feasible, such as standard Kubernetes clusters.

Introduction

Kaniko is a tool to build container images from a Dockerfile inside a container or Kubernetes cluster. It operates entirely in userspace, making it ideal for environments that can’t easily or securely run a Docker daemon. Typically, Kaniko is run as an image (gcr.io/kaniko-project/executor). However, the base Kaniko image lacks essential tools like bash and CLI, which are necessary for downloading binaries. This is why a custom Kaniko image with embedded Twistcli is necessary.

This guide will cover:

  1. Creating a Dockerfile for a custom Kaniko image that includes Twistcli.
  2. Configuring a GitLab CI pipeline to build a custom Kaniko image with embedded Twistcli and push to the docker registry to reuse later on the self-hosted Gitlab runners in AKS pods.

Creating the Custom Kaniko Image

Dockerfile for Custom Kaniko Image

We’ll start by creating a Dockerfile that combines Kaniko and Twistcli. The custom image will allow us to build and scan Docker images in separate stages of the CI pipeline.

FROM alpine

COPY twistcli /usr/local/bin/twistcli
RUN chmod a+x /usr/local/bin/twistcli && export PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin

COPY --from=gcr.io/kaniko-project/executor:debug /kaniko/executor /kaniko/executor

This Dockerfile:

  1. Base Image: Uses alpine as the base image.
  2. Copy Twistcli: Copies the twistcli binary to /usr/local/bin/twistcli and sets executable permissions.
  3. Copy Kaniko Executor: Copies the Kaniko executor from the Kaniko project’s debug image.
Build and Push the Custom Image

Next, we build and push the custom Kaniko image to our registry.

Prerequisites: Access to Prisma Cloud to download twistcli.

Pipeline Stages

Our pipeline will have the following stages:

  1. test – to run any tests in case you have
  2. docker – build and push an image to the docker registry.
.gitlab-ci.yml Configuration

Below is the configuration for .gitlab-ci.yml:

stages:
    - test
    - docker

variables:
  IMAGE_NAME: "kaniko"
  IMAGE_TAG:
    value: "latest"
    description: "Image Tag defaults to latest"
  PRISMA_CLOUD_COMPUTE_URL: https://northamerica-northeast1.cloud.twistlock.com/canada-550205609
  PRISMA_CLOUD_API_URL: $PRISMA_CLOUD_COMPUTE_URL/api/v1/util

BuildAndPush:
  stage: docker
  image: docker:latest
  services:
    - docker:dind
  before_script:
    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
  script:
    - apk update
    - apk add curl git
    - |
      curl -k -u $PRISMA_ACCESS_KEY:$PRISMA_SECRET_KEY -X GET -o twistcli $PRISMA_CLOUD_API_URL/twistcli
      docker build -t $CI_REGISTRY/$IMAGE_NAME:$IMAGE_TAG .
    - docker push $CI_REGISTRY/$IMAGE_NAME:$IMAGE_TAG

Conclusion

Following these steps, you can build a custom Kaniko image with embedded Twistcli. Later, you can use that Kaniko image with twistcli to scan docker images after building and before pushing them to the registry to improve your security posture.