Skip to main content

Building Secure Container Images with Shipwright

By July 25, 2024Blog, Project

Contributed by Karan Kumar (@karanibm6) originally published on shipwright.io

Building Secure Container Images with Shipwright

Introduction

In the modern software development era, containers have become an essential tool for developers. They offer a consistent environment for applications to run, making it easier to develop, test, and deploy software across different platforms. However, like any other technology, containers are not immune to security vulnerabilities. This is where vulnerability scanning for container images becomes crucial. In this blog, we will discuss how to run vulnerability scanning on container images with Shipwright while building those images.

Before jumping into this feature, let’s explain what Shipwright is and why vulnerability scanning is important.

What is Shipwright

Shipwright is an open source framework designed to facilitate the building of container images directly within Kubernetes environments. It aims to streamline the development and deployment process by providing a native Kubernetes solution for creating container images from source code. Shipwright supports multiple build strategies and tools, such as Kaniko, Paketo Buildpacks, Ko, Buildkit, and Buildah, providing flexibility and extensibility to meet various application needs. This Kubernetes-native solution helps ensure that container images are built efficiently and securely, leveraging the strengths of the Kubernetes ecosystem.

Shipwright consists of four core components:

  1. Build: defines what source code you are trying to build from, and where the resulting container image should be publish (the what and where?)
  2. BuildRun: defines the when to trigger the building mechanism, telling the Kubernetes cluster when to build your application (the when?)
  3. BuildStrategy and ClusterBuildStrategy: defines how your application is assembled and which build tool to use (how to build?)

You can learn more by visiting this link.

Why is Vulnerability Scanning Important?

Vulnerability scanning for container images involves examining the image for known security vulnerabilities. This is typically done using automated tools that compare the contents of the image against a database of known vulnerabilities. The key reasons for Vulnerability Scanning are:

  • Security: Containers often include third-party libraries and dependencies, which might have known vulnerabilities. If these vulnerabilities are exploited, they can lead to data breaches, unauthorized access, and other security incidents.
  • Compliance: Many industries have regulatory requirements that mandate regular security assessments, including vulnerability scanning. Ensuring your container images are free from known vulnerabilities helps meet these compliance standards.
  • Stability: Vulnerabilities can also impact the stability and performance of your applications. By identifying and fixing these issues early, you can maintain the reliability of your software.

There are many popular tools available for vulnerability scanning of container images, such as Clair, Trivy, Aqua Security, and Snyk.

In Shipwright, we use Trivy under the covers for vulnerability scanning, our rationale for choosing this tool can be found in our SHIP-0033.

Vulnerability Scanning in Shipwright

Before we dive into how it works, let’s explore the features offered by Shipwright for vulnerability scanning of container builds :

spec: output: vulnerabilityScan: enabled: true failOnFinding: true #image won't be push to registry if set to true ignore: issues: - CVE-2022-12345 #specify list of cve to be ignored severity: Low | Medium | High | Critical unfixed: true #ignores the unfixed vulnerabilities

Configuration Options

  • vulnerabilityScan.enabled: Specify whether to run vulnerability scan for image. The supported values are true and false.
  • vulnerabilityScan.failOnFinding: Indicates whether to fail the build run if the vulnerability scan results in vulnerabilities. The supported values are true and false. This field is optional and false by default.
  • vulnerabilityScan.ignore.issues: References the security issues to be ignored in vulnerability scan
  • vulnerabilityScan.ignore.severity: Denotes the severity levels of security issues to be ignored, valid values are:
    • low: it will exclude low severity vulnerabilities, displaying only medium, high, and critical vulnerabilities.
    • medium: it will exclude low and medium-severity vulnerabilities, displaying only high and critical vulnerabilities.
    • high: it will exclude low, medium, and high-severity vulnerabilities, displaying only the critical vulnerabilities.
  • vulnerabilityScan.ignore.unfixed: Indicates to ignore vulnerabilities for which no fix exists. The supported types are true and false.

Let’s dive right in

Now, let’s see vulnerability scanning for a container image with Shipwright in action. If you want to try out in kind cluster, follow the steps from this section until you create the push secret. As a next step, create a build object with vulnerability scanning enabled, replacing <REGISTRY_ORG> with the registry username your push-secret have access to:

REGISTRY_ORG=<your_registry_org>
cat <<EOF | kubectl apply -f -
apiVersion: shipwright.io/v1beta1
kind: Build
metadata:
  name: buildah-golang-build
spec:
  source:
    type: Git
    git:
      url: https://github.com/shipwright-io/sample-go
    contextDir: docker-build
  strategy:
    name: buildah-shipwright-managed-push
    kind: ClusterBuildStrategy
  paramValues:
  - name: dockerfile
    value: Dockerfile
  output:
    image: docker.io/${REGISTRY_ORG}/sample-golang:latest
    pushSecret: push-secret
    vulnerabilityScan:
      enabled: true
      failOnFinding: true # if set to true, then the image won't be pushed to the registry
EOF

To view the Build which you just created:

$ kubectl get builds NAME REGISTERED REASON BUILDSTRATEGYKIND BUILDSTRATEGYNAME CREATIONTIME buildah-golang-build True Succeeded ClusterBuildStrategy buildah-shipwright-managed-push 72s

Now submit your buildrun

cat <<EOF | kubectl create -f -
apiVersion: shipwright.io/v1beta1
kind: BuildRun
metadata:
  generateName: buildah-golang-buildrun-
spec:
  build:
    name: buildah-golang-build
EOF

Wait until your BuildRun is completed and then you can view it as follows:

$ kubectl get buildruns NAME SUCCEEDED REASON STARTTIME COMPLETIONTIME buildah-golang-buildrun-s9gsh False VulnerabilitiesFound 2m54s 98s

Here, you can see that the buildrun failed with reason VulnerabilitiesFound and it will not push the image to the registry as the failOnFinding option is set to true.

And one can find the list of vulnerabilities in the build run under the .status.output path:

apiVersion: shipwright.io/v1beta1
kind: BuildRun
metadata:
  creationTimestamp: "2024-07-08T08:03:18Z"
  generateName: buildah-golang-buildrun-
  generation: 1
  labels:
    build.shipwright.io/generation: "1"
    build.shipwright.io/name: buildah-golang-build
  name: buildah-golang-buildrun-s9gsh
  namespace: default
  resourceVersion: "19926"
  uid: f3c558e9-e027-4f59-9fdc-438a31c6de11
spec:
  build:
    name: buildah-golang-build
status:
  buildSpec:
    output:
      image: docker.io/karanjmu92/sample-golang:latest
      pushSecret: push-secret
      vulnerabilityScan:
        enabled: true
        failOnFinding: true
    paramValues:
    - name: dockerfile
      value: Dockerfile
    source:
      contextDir: docker-build
      git:
        url: https://github.com/shipwright-io/sample-go
      type: Git
    strategy:
      kind: ClusterBuildStrategy
      name: buildah-shipwright-managed-push
  completionTime: "2024-07-08T08:04:34Z"
  conditions:
  - lastTransitionTime: "2024-07-08T08:04:34Z"
    message: Vulnerabilities have been found in the image which can be seen in the
      buildrun status. For detailed information,see kubectl --namespace default logs
      buildah-golang-buildrun-s9gsh-w488m-pod --container=step-image-processing
    reason: VulnerabilitiesFound
    status: "False"
    type: Succeeded
  failureDetails:
    location:
      container: step-image-processing
      pod: buildah-golang-buildrun-s9gsh-w488m-pod
  output:
    vulnerabilities:
    - id: CVE-2023-24538
      severity: critical
    - id: CVE-2023-24540
      severity: critical
          .
          .
          .
    - id: CVE-2024-24791
      severity: medium
  source:
    git:
      branchName: main
      commitAuthor: OpenShift Merge Robot
      commitSha: 96afb4108fba22e91f42168d8babb5562ac8e5bb
    timestamp: "2023-08-10T15:24:45Z"
  startTime: "2024-07-08T08:03:18Z"
  taskRunName: buildah-golang-buildrun-s9gsh-w488m

Conclusion

Shipwright offers a robust and flexible solution for building container images within Kubernetes environments. By integrating vulnerability scanning directly into the build process, Shipwright ensures that container images are secure and compliant with Industry Standards and gets closer to Supply Chain Security Best Practices.