Sbom-operator - Catalogue all images of a Kubernetes cluster to multiple targets with Syft

Overview

sbom-operator

Catalogue all images of a Kubernetes cluster to multiple targets with Syft.

test

Overview

This operator maintains a central place to track all packages and software used in all those images in a Kubernetes cluster. For this a Software Bill of Materials (SBOM) is generated from each image with Syft. They are all stored in one or more targets. Currently only Git is supported. With this it is possible to do further analysis, vulnerability scans and much more in a single place. To prevent scans of images that have already been analyzed pods are annotated with the imageID of the already processed image.

Kubernetes Compatibility

The image contains versions of k8s.io/client-go. Kubernetes aims to provide forwards & backwards compatibility of one minor version between client and server:

access-manager k8s.io/{api,apimachinery,client-go} expected kubernetes compatibility
0.2.0 v0.23.3 1.22.x, 1.23.x, 1.24.x
0.1.0 v0.23.3 1.22.x, 1.23.x, 1.24.x
main v0.23.3 1.22.x, 1.23.x, 1.24.x

However, the operator will work with more versions of Kubernetes in general.

Container Registry Support

The operator relies on the go-containeregistry library to download images. It should work with most registries. These are officially tested (with authentication):

  • ACR (Azure Container Registry)
  • ECR (Amazon Elastic Container Registry)
  • GAR (Google Artifact Registry)
  • GCR (Google Container Registry)
  • GHCR (GitHub Container Registry)
  • DockerHub

Installation

Manifests

kubectl apply -f deploy/

Helm-Chart

Create a YAML file first with the required configurations or use helm-flags instead.

helm repo add ckotzbauer https://ckotzbauer.github.io/helm-charts
helm install ckotzbauer/sbom-operator -f your-values.yaml

Configuration

All parameters are cli-flags.

Parameter Required Default Description
verbosity false info Log-level (debug, info, warn, error, fatal, panic)
cron false @hourly Backround-Service interval (CRON). All options from github.com/robfig/cron are allowed
ignore-annotations false false Force analyzing of all images, including those from annotated pods.
format false json SBOM-Format.
targets false git Comma-delimited list of targets to sent the generated SBOMs to. Possible targets git
git-workingtree false /work Directory to place the git-repo.
git-repository true when git target is used. "" Git-Repository-URL (HTTPS).
git-branch false main Git-Branch to checkout.
git-path false "" Folder-Path inside the Git-Repository.
git-access-token true when git target is used. "" Git-Personal-Access-Token with write-permissions.
git-author-name true when git target is used. "" Author name to use for Git-Commits.
git-author-email true when git target is used. "" Author email to use for Git-Commits.
pod-label-selector false "" Kubernetes Label-Selector for pods.
namespace-label-selector false "" Kubernetes Label-Selector for namespaces.

The flags can be configured as args or as environment-variables prefixed with SBOM_ to inject sensitive configs as secret values.

Example Helm-Config

args:
  targets: git
  git-author-email: XXX
  git-author-name: XXX
  git-repository: https://github.com/XXX/XXX
  git-path: dev-cluster/sboms
  verbosity: debug
  cron: "0 30 * * * *"

envVars:
  - name: SBOM_GIT_ACCESS_TOKEN
    valueFrom:
      secretKeyRef:
        name: "sbom-operator"
        key: "accessToken"

Targets

It is possible to store the generated SBOMs to different targets (even multple at once). Currently the only available target is Git, but this will change soon.

Git

The operator will save all files with a specific folder structure as described below. When a git-path is configured, all folders above this path are not touched from the application. Assuming that git-path is set to dev-cluster/sboms. When no git-path is given, the structure below is directly in the repository-root. The structure is basically <git-path>/<registry-server>/<image-path>/<image-digest>/sbom.json. The file-extension may differ when another output-format is configured. A token-based authentication to the git-repository is used.

dev-cluster
│
└───sboms
    │
    └───docker.io
    |   │
    |   └───library
    |       │
    |       └───busybox
    |           │
    |           └───sha256_ae39a6f5...
    |               │   sbom.json
    |
    └───ghcr.io
        │
        └───kyverno
            │
            └───kyverno
            |   │
            |   └───sha256_9e3f14e5...
            |       │   sbom.json
            |
            └───kyvernopre
                │
                └───sha256_e48f87fd...
                    │   sbom.json
            |
            └───policy-reporter
                │
                └───sha256_b70caa7a...
                    │   sbom.json

Security

The docker-image is based on scratch to reduce the attack-surface and keep the image small. Furthermore the image and release-artifacts are signed with cosign and attested with provenance-files. The release-process satisfies SLSA Level 2. All of those "metadata files" are also stored in a dedicated repository ghcr.io/ckotzbauer/sbom-operator-metadata. Both, SLSA and the signatures are still experimental for this project.

Contributing

License

Changelog

Issues
  • Private ECR repositories give '401 Unauthorized'

    Private ECR repositories give '401 Unauthorized'

    Hi,

    First of all: thanks for this great work! 🥳

    When running v0.9.0 with dependency-track as target, most public available images work fine, except for ECR hosted ones:

    sbom-operator-77fdbbfd87-dbznp sbom-operator time="2022-04-20T10:09:53Z" level=error msg="Image-Pull failed" error="GET https://602401143452.dkr.ecr.eu-west-1.amazonaws.com/v2/amazon-k8s-cni-init/manifests/sha256:6c70af7bf257712105a89a896b2afb86c86ace865d32eb73765bf29163a08c56: unexpected status code 401 Unauthorized: Not Authorized\n"
    

    This ECR repo is provided by AWS and should be available for everyone. Other private ECRs give the same 401 error.

    Some information about the environment:

    Can someone point me in te right direction? I'll add it to the README if useful for others!

    help wanted good first issue kind/feature kind/question 
    opened by sbkg0002 11
  • Docker Image ID Parsing -- Could not parse

    Docker Image ID Parsing -- Could not parse

    Image ID's are retrieved as follows: https://github.com/ckotzbauer/sbom-operator/blob/151dde7a4046091f2ea56eaaabfc900ced1800da/internal/kubernetes/kubernetes.go#L106-L122

    And they are parsed as follows: https://github.com/ckotzbauer/sbom-operator/blob/151dde7a4046091f2ea56eaaabfc900ced1800da/internal/syft/syft.go#L42

    I am seeing the following error logs:

    time="2022-04-06T19:40:03Z" level=error msg="Could not parse imageID docker-pullable://<rest of image id>" error="Error parsing reference: \"docker-pullable://<rest of image id>\" is not a valid repository/tag"
    

    I believe this is because the Image ID is prefixed with docker-pullable://

    I writing a small program to parse <rest of image id> using the same library used by sbom-operator: docker-parserand it works fine.

    I think the simplest fix to this is to either remove the docker-pullable:// prefix or use the img.Image field instead.

    help wanted kind/bug 
    opened by AkashSirimanna 9
  • Support

    Support "Dependency Track" as alternative target for SBOMs

    Instead of storing the generated SBOMs to Git it would be good to support different targets, e.g. "Dependency Track".

    /kind feature /cc @stevespringett

    kind/feature target/dtrack 
    opened by ckotzbauer 7
  • Registry authentication fails when secret contains only .dockercfg

    Registry authentication fails when secret contains only .dockercfg

    Secrets with type = "kubernetes.io/dockercfg" containing the pull secret in the field .dockercfg do not work.

    OpenShift uses this type of secret for the internal registry - so, you cannot provide the type = "kubernetes.io/dockerconfigjson".

    kind/bug 
    opened by derkoe 6
  • store sbom result on OCI registry along with an image

    store sbom result on OCI registry along with an image

    Hello @ckotzbauer, in cosign there is a support for attaching SBOM files to an OCI registry along with an image. So, maybe we can support that too as an alternative way of storing SBOM files instead of just storing them in git. WDYT?

    help wanted kind/feature target/oci 
    opened by developer-guy 6
  • feat: delete unused images from Dependency Track

    feat: delete unused images from Dependency Track

    This adds tags to the Dependency-Track projects to track which were created by the SBOM operator. The following tags are created:

    • sbom-operator
    • kubernetes-cluster={kubernetes-cluster-id}

    The kubernetes-cluster-id can be set via a command line parameter (when not specified default is used).

    This is how the tags look like in the Dependency-Track UI: image You can use the tags to filter for images in a certain cluster

    Closes #27

    size/L 
    opened by derkoe 5
  • Don't continue if list namespaces failes

    Don't continue if list namespaces failes

    We had some networking issues in our cluster. This caused a ListNamespaces to fail. This caused the sbom-operator to delete all sboms in our git directory.

    size/M kind/bug 
    opened by hikhvar 3
  • Integrate vulnerability scanning

    Integrate vulnerability scanning

    There are multiple possible options I have in mind:

    • Trigger Github-Webhook to start a Github-Action for further analysis
    • Built a standalone application to scan the generated SBOMs from this operator (can be triggered with webhook too)
    • Expose metrics for found vulnerabilities (this would be also a feature which should be added to a standalone application) ...

    /kind feature

    kind/feature 
    opened by ckotzbauer 3
  • Feature/multi pull secrets

    Feature/multi pull secrets

    adds the feature to use multiple pull-secrets from the k8s pods additionally there is a possibility to specify a particular pull secret that is used in case all pull secrets from the pods are failing (the global custom pull secret must be in the same namespace as the sbom-operator itself)

    kind/feature size/L 
    opened by steelion 2
  • fix: fix parsing of image id's for different container runtimes

    fix: fix parsing of image id's for different container runtimes

    Some container runtimes (such as Docker) add a prefix prior to the image id. Currently, if such a prefix exists, parsing the image id will fail

    Fixes: #68

    size/S 
    opened by AkashSirimanna 2
  • Feature Request: use syft as library

    Feature Request: use syft as library

    A while ago I've asked from @wagoodman to describe how we can use syft as a go module, thanks to him, he created a gist for us. So, we can use syft as a go module instead of executing its binary.

    👉 https://gist.github.com/wagoodman/57ed59a6d57600c23913071b8470175b

    kind/feature 
    opened by developer-guy 2
  • Feature Request: use ConfigMaps as an additional storage for SBOMs

    Feature Request: use ConfigMaps as an additional storage for SBOMs

    We (w/@dentrax) thought we could store SBOMs in a ConfigMap within the same cluster, so we should create a ConfigMap per container. One drawback of this approach would be the size limit of the ConfigMaps because Kubernetes allows us to store only 1MB of data within the ConfigMap.

    In addition to the idea, Falco announced its plugin system that allows us to create plugins to extend Falco's data sources, so we thought we could use SBOMs as input for Falco. We should develop a plugin to consume SBOns stored in ConfigMaps and apply rules on top of them.

    help wanted kind/feature 
    opened by developer-guy 0
  • Feature Request: Support cache.SharedIndexInformer for auto-triggering

    Feature Request: Support cache.SharedIndexInformer for auto-triggering

    As we already discussed this idea in Slack, dropping here so we do not forget!


    Instead of run operator as scheduled runs using CronJob, we can use NewSharedIndexInformer to create an event loop in order to detect image changes instantly. For example;

    deploymentInformer := cache.NewSharedIndexInformer(
    			&cache.ListWatch{
    				ListFunc: func(options metaV1.ListOptions) (runtime.Object, error) {
    					return clientSet.AppsV1().Deployments(metaV1.NamespaceAll).List(ctx, options)
    				},
    				WatchFunc: func(options metaV1.ListOptions) (watch.Interface, error) {
    					return clientSet.AppsV1().Deployments(metaV1.NamespaceAll).Watch(ctx, options)
    				},
    			},
    			&appsV1.Deployment{},
    			0,
    			cache.Indexers{},
    		)
    

    Eventually we are able to get all add/update/remove events:

    informer.AddEventHandler(cache.ResourceEventHandlerFuncs{
    		AddFunc: func(obj interface{}) {
    			//
    		},
    		UpdateFunc: func(old, new interface{}) {
    			//
    		},
    		DeleteFunc: func(obj interface{}) {
    			//
    		},
    	})
    

    P.S: We also do not want to drop scheduled runs. But both features are actually mutually-exclusive. So one of run type must be chosen in the config.

    cc @developer-guy

    help wanted kind/feature 
    opened by Dentrax 0
  • Feature discussion: AWS Lambda SBOM generation

    Feature discussion: AWS Lambda SBOM generation

    Hello - thank you for starting this project - it has saved me from attempting to build the same thing! ❤️

    Would you be open to a contribution to allow SBOM generation from AWS Lambda functions?

    Broadly, something like:

    1. Use the AWS Lambda Go SDK to call the GetFunction operation, to obtain the Code.Location URL
    2. Fetch the Lambda's function code from the URL to a local temporary dir; this is generally a ZIP file
    3. Invoke Syft on the local code package
    4. (Tidy up?)

    This would enable use of this tool in an environment in which there is a mix of Kubernetes workloads and serverless ones.

    I wanted to guage your interest in whether this aligns with your project goals, before contributing a PR.

    help wanted kind/feature 
    opened by outofcoffee 4
Releases(0.13.0)
Owner
Christian Kotzbauer
Web Developer working with TypeScript and Aurelia. Interested in Node.js, Security, Docker and Kubernetes.
Christian Kotzbauer
An operator which complements grafana-operator for custom features which are not feasible to be merged into core operator

Grafana Complementary Operator A grafana which complements grafana-operator for custom features which are not feasible to be merged into core operator

Snapp Cab Incubators 4 May 24, 2022
kube-champ 37 Jun 6, 2022
Example goreleaser + github actions config with keyless signing and SBOM generation

supply-chain-example GoReleaser + Go Mod proxying + Cosign keyless signing + Syft SBOM generation example. How it works GoReleaser manages the entire

GoReleaser 42 Jun 2, 2022
PolarDB-X Operator is a Kubernetes extension that aims to create and manage PolarDB-X cluster on Kubernetes.

GalaxyKube -- PolarDB-X Operator PolarDB-X Operator is a Kubernetes extension that aims to create and manage PolarDB-X cluster on Kubernetes. It follo

null 59 Jun 23, 2022
cluster-api-state-metrics (CASM) is a service that listens to the Kubernetes API server and generates metrics about the state of custom resource objects related of Kubernetes Cluster API.

Overview cluster-api-state-metrics (CASM) is a service that listens to the Kubernetes API server and generates metrics about the state of custom resou

Daimler Group 56 Jun 20, 2022
The Elastalert Operator is an implementation of a Kubernetes Operator, to easily integrate elastalert with gitops.

Elastalert Operator for Kubernetes The Elastalert Operator is an implementation of a Kubernetes Operator. Getting started Firstly, learn How to use el

null 18 Apr 13, 2022
Minecraft-operator - A Kubernetes operator for Minecraft Java Edition servers

Minecraft Operator A Kubernetes operator for dedicated servers of the video game

James Laverack 6 May 10, 2022
K8s-network-config-operator - Kubernetes network config operator to push network config to switches

Kubernetes Network operator Will add more to the readme later :D Operations The

Daniel Hertzberg 6 May 16, 2022
Pulumi-k8s-operator-example - OpenGitOps Compliant Pulumi Kubernetes Operator Example

Pulumi GitOps Example OpenGitOps Compliant Pulumi Kubernetes Operator Example Pr

Christian Hernandez 3 May 6, 2022
Kubernetes Operator Samples using Go, the Operator SDK and OLM

Kubernetes Operator Patterns and Best Practises This project contains Kubernetes operator samples that demonstrate best practices how to develop opera

International Business Machines 16 Jun 22, 2022
Kubegres is a Kubernetes operator allowing to create a cluster of PostgreSql instances and manage databases replication, failover and backup.

Kubegres is a Kubernetes operator allowing to deploy a cluster of PostgreSql pods with data replication enabled out-of-the box. It brings simplicity w

Reactive Tech Ltd 1k Jun 30, 2022
Nebula Operator manages NebulaGraph clusters on Kubernetes and automates tasks related to operating a NebulaGraph cluster

Nebula Operator manages NebulaGraph clusters on Kubernetes and automates tasks related to operating a NebulaGraph cluster. It evolved from NebulaGraph Cloud Service, makes NebulaGraph a truly cloud-native database.

vesoft inc. 51 Jun 6, 2022
Kubernetes Operator for MySQL NDB Cluster.

MySQL NDB Operator The MySQL NDB Operator is a Kubernetes operator for managing a MySQL NDB Cluster setup inside a Kubernetes Cluster. This is in prev

MySQL 18 Jun 14, 2022
YurtCluster Operator creates and manages OpenYurt cluster atop Kubernetes

YurtCluster Operator Quick Start Prepare a Kubernetes cluster # cat <<EOF | kind create cluster --config=- kind: Cluster apiVersion: kind.x-k8s.io/v1a

OpenYurt 9 Apr 4, 2022
kubetnl tunnels TCP connections from within a Kubernetes cluster to a cluster-external endpoint, e.g. to your local machine. (the perfect complement to kubectl port-forward)

kubetnl kubetnl (kube tunnel) is a command line utility to tunnel TCP connections from within a Kubernetes to a cluster-external endpoint, e.g. to you

null 4 Nov 16, 2021
A Terraform module to manage cluster authentication (aws-auth) for an Elastic Kubernetes (EKS) cluster on AWS.

Archive Notice The terraform-aws-modules/eks/aws v.18.20.0 release has brought back support aws-auth configmap! For this reason, I highly encourage us

Aidan Melen 23 May 31, 2022
Starting and Stopping Services as Mage Targets

Starting and Stopping Services as Mage Targets Mage is a build tool that supports writing targets in Go. This package supports configuring local servi

Scott Dunlop 1 Sep 30, 2021
Awesome-italia-remote - A list of remote-friendly or full-remote companies that targets Italian talents

Awesome Italia Remote A list of remote-friendly or full-remote companies that ta

ItaliaRemote 1.2k Jul 1, 2022
Test Operator using operator-sdk 1.15

test-operator Test Operator using operator-sdk 1.15 operator-sdk init --domain rbt.com --repo github.com/ravitri/test-operator Writing kustomize manif

Ravi Trivedi 0 Dec 28, 2021