Skip to content

Commit e1085f5

Browse files
authored
Add support for Software Bills of Materials (SBOMs) to Strimzi CI (strimzi#9124)
Signed-off-by: Jakub Scholz <[email protected]>
1 parent 7ea6c59 commit e1085f5

File tree

10 files changed

+117
-4
lines changed

10 files changed

+117
-4
lines changed

.azure/scripts/install_syft.sh

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#!/usr/bin/env bash
2+
set -e
3+
4+
readonly VERSION="0.90.0"
5+
6+
ARCH=$1
7+
if [ -z "$ARCH" ]; then
8+
ARCH="amd64"
9+
fi
10+
11+
wget https://github.com/anchore/syft/releases/download/v${VERSION}/syft_${VERSION}_linux_${ARCH}.tar.gz -O syft.tar.gz
12+
tar xf syft.tar.xz -C /tmp
13+
chmod +x /tmp/syft
14+
sudo mv /tmp/syft /usr/bin

.azure/templates/jobs/build/push_containers.yaml

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ jobs:
1212
- template: "../../steps/prerequisites/install_docker.yaml"
1313
- template: "../../steps/prerequisites/install_yq.yaml"
1414
- template: "../../steps/prerequisites/install_cosign.yaml"
15+
- template: "../../steps/prerequisites/install_syft.yaml"
1516

1617
# Get the container archives
1718
- ${{ each arch in parameters.architectures }}:
@@ -76,4 +77,36 @@ jobs:
7677
DOCKER_ORG: "strimzi"
7778
DOCKER_TAG: '${{ parameters.dockerTag }}'
7879
COSIGN_PASSWORD: $(COSIGN_PASSWORD)
79-
COSIGN_PRIVATE_KEY: $(COSIGN_PRIVATE_KEY)
80+
COSIGN_PRIVATE_KEY: $(COSIGN_PRIVATE_KEY)
81+
# SBOMs generation, packaging, and signing
82+
- ${{ each arch in parameters.architectures }}:
83+
- bash: make docker_sbom
84+
displayName: "Generate SBOMs for ${{ arch }} containers"
85+
env:
86+
BUILD_REASON: $(Build.Reason)
87+
BRANCH: $(Build.SourceBranch)
88+
DOCKER_REGISTRY: "quay.io"
89+
DOCKER_ORG: "strimzi"
90+
DOCKER_TAG: '${{ parameters.dockerTag }}'
91+
DOCKER_ARCHITECTURE: ${{ arch }}
92+
COSIGN_PASSWORD: $(COSIGN_PASSWORD)
93+
COSIGN_PRIVATE_KEY: $(COSIGN_PRIVATE_KEY)
94+
- bash: tar -z -C ./sbom/ -cvpf sbom.tar.gz ./
95+
displayName: "Tar the SBOM files"
96+
- publish: $(System.DefaultWorkingDirectory)/sbom.tar.gz
97+
artifact: SBOMs
98+
displayName: "Publish the SBOM files"
99+
# push the SBOMs to container registry only for releases
100+
- ${{ each arch in parameters.architectures }}:
101+
- bash: make docker_push_sbom
102+
displayName: "Push SBOMs for ${{ arch }} containers"
103+
condition: startsWith(variables['build.sourceBranch'], 'refs/heads/release-')
104+
env:
105+
BUILD_REASON: $(Build.Reason)
106+
BRANCH: $(Build.SourceBranch)
107+
DOCKER_REGISTRY: "quay.io"
108+
DOCKER_ORG: "strimzi"
109+
DOCKER_TAG: '${{ parameters.dockerTag }}'
110+
DOCKER_ARCHITECTURE: ${{ arch }}
111+
COSIGN_PASSWORD: $(COSIGN_PASSWORD)
112+
COSIGN_PRIVATE_KEY: $(COSIGN_PRIVATE_KEY)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
steps:
2+
- bash: ".azure/scripts/install_syft.sh"
3+
displayName: "Install Syft"

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
## 0.38.0
44

55
* Sign containers using `cosign`
6+
* Generate and publish Software Bill of Materials (SBOMs) of Strimzi containers
67
* Add support for stopping connectors according to [Strimzi Proposal #54](https://github.com/strimzi/proposals/blob/main/054-stopping-kafka-connect-connectors.md)
78

89
### Changes, deprecations and removals

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ endif
1616

1717
SUBDIRS=kafka-agent mirror-maker-agent tracing-agent crd-annotations test crd-generator api mockkube certificate-manager operator-common config-model config-model-generator cluster-operator topic-operator user-operator kafka-init systemtest docker-images/artifacts packaging/helm-charts/helm3 packaging/install packaging/examples
1818
DOCKERDIRS=docker-images/base docker-images/operator docker-images/kafka-based docker-images/maven-builder docker-images/kaniko-executor
19-
DOCKER_TARGETS=docker_build docker_push docker_tag docker_load docker_save docker_amend_manifest docker_push_manifest docker_sign_manifest docker_delete_manifest docker_delete_archive
19+
DOCKER_TARGETS=docker_build docker_push docker_tag docker_load docker_save docker_amend_manifest docker_push_manifest docker_sign_manifest docker_delete_manifest docker_delete_archive docker_sbom docker_push_sbom
2020
JAVA_TARGETS=java_build java_install java_clean
2121

2222
all: prerequisites_check $(SUBDIRS) $(DOCKERDIRS) crd_install dashboard_install helm_install shellcheck docu_versions docu_check

Makefile.docker

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
# the registry where the image will be pushed (default is Docker Hub).
88
TOPDIR=$(dir $(lastword $(MAKEFILE_LIST)))
99
ARCHIVE_DIR=$(TOPDIR)docker-images/container-archives
10+
SBOM_DIR=$(TOPDIR)sbom
1011

1112
DOCKERFILE_DIR ?= ./
1213
DOCKER_CMD ?= docker
@@ -21,6 +22,7 @@ RELEASE_VERSION ?= $(shell cat $(TOPDIR)/release.version)
2122
ifdef DOCKER_ARCHITECTURE
2223
DOCKER_PLATFORM = --platform linux/$(DOCKER_ARCHITECTURE)
2324
DOCKER_PLATFORM_TAG_SUFFIX = -$(DOCKER_ARCHITECTURE)
25+
SBOM_DIR=$(TOPDIR)sbom/$(DOCKER_ARCHITECTURE)
2426
endif
2527

2628
all: docker_build docker_push
@@ -81,5 +83,33 @@ docker_delete_manifest_default:
8183
# Delete the manifest to the registry, ignore the error if manifest doesn't exist
8284
docker manifest rm $(DOCKER_REGISTRY)/$(DOCKER_ORG)/$(PROJECT_NAME):$(DOCKER_TAG) || true
8385

86+
.PHONY: docker_sbom_default
87+
docker_sbom_default:
88+
# Saves the SBOM of the image
89+
test -d $(SBOM_DIR) || mkdir -p $(SBOM_DIR)
90+
# Generate the text format
91+
MANIFEST_DIGEST=$(shell docker buildx imagetools inspect $(DOCKER_REGISTRY)/$(DOCKER_ORG)/$(PROJECT_NAME):$(DOCKER_TAG)$(DOCKER_PLATFORM_TAG_SUFFIX) --format '{{ json . }}' | jq -r .manifest.digest); \
92+
syft packages $(DOCKER_REGISTRY)/$(DOCKER_ORG)/$(PROJECT_NAME)@$$MANIFEST_DIGEST --output syft-table --file $(SBOM_DIR)/$(DOCKER_REGISTRY)/$(DOCKER_ORG)/$(PROJECT_NAME)/$(DOCKER_TAG)/$$MANIFEST_DIGEST.txt
93+
# Generate the SPDX JSON format for machine processing
94+
MANIFEST_DIGEST=$(shell docker buildx imagetools inspect $(DOCKER_REGISTRY)/$(DOCKER_ORG)/$(PROJECT_NAME):$(DOCKER_TAG)$(DOCKER_PLATFORM_TAG_SUFFIX) --format '{{ json . }}' | jq -r .manifest.digest); \
95+
syft packages $(DOCKER_REGISTRY)/$(DOCKER_ORG)/$(PROJECT_NAME)@$$MANIFEST_DIGEST --output spdx-json --file $(SBOM_DIR)/$(DOCKER_REGISTRY)/$(DOCKER_ORG)/$(PROJECT_NAME)/$(DOCKER_TAG)/$$MANIFEST_DIGEST.json
96+
# Sign the TXT and SPDX-JSON SBOM
97+
@echo $$COSIGN_PRIVATE_KEY | base64 -d > cosign.key
98+
MANIFEST_DIGEST=$(shell docker buildx imagetools inspect $(DOCKER_REGISTRY)/$(DOCKER_ORG)/$(PROJECT_NAME):$(DOCKER_TAG)$(DOCKER_PLATFORM_TAG_SUFFIX) --format '{{ json . }}' | jq -r .manifest.digest); \
99+
cosign sign-blob --tlog-upload=false --key cosign.key --bundle $(SBOM_DIR)/$(DOCKER_REGISTRY)/$(DOCKER_ORG)/$(PROJECT_NAME)/$(DOCKER_TAG)/$$MANIFEST_DIGEST.txt.bundle $(SBOM_DIR)/$(DOCKER_REGISTRY)/$(DOCKER_ORG)/$(PROJECT_NAME)/$(DOCKER_TAG)/$$MANIFEST_DIGEST.txt
100+
MANIFEST_DIGEST=$(shell docker buildx imagetools inspect $(DOCKER_REGISTRY)/$(DOCKER_ORG)/$(PROJECT_NAME):$(DOCKER_TAG)$(DOCKER_PLATFORM_TAG_SUFFIX) --format '{{ json . }}' | jq -r .manifest.digest); \
101+
cosign sign-blob --tlog-upload=false --key cosign.key --bundle $(SBOM_DIR)/$(DOCKER_REGISTRY)/$(DOCKER_ORG)/$(PROJECT_NAME)/$(DOCKER_TAG)/$$MANIFEST_DIGEST.json.bundle $(SBOM_DIR)/$(DOCKER_REGISTRY)/$(DOCKER_ORG)/$(PROJECT_NAME)/$(DOCKER_TAG)/$$MANIFEST_DIGEST.json
102+
@rm cosign.key
103+
104+
.PHONY: docker_push_sbom_default
105+
docker_push_sbom_default:
106+
# Push the SBOMto the container registry and sign it
107+
@echo $$COSIGN_PRIVATE_KEY | base64 -d > cosign.key
108+
MANIFEST_DIGEST=$(shell docker buildx imagetools inspect $(DOCKER_REGISTRY)/$(DOCKER_ORG)/$(PROJECT_NAME):$(DOCKER_TAG)$(DOCKER_PLATFORM_TAG_SUFFIX) --format '{{ json . }}' | jq -r .manifest.digest); \
109+
cosign attach sbom --sbom $(SBOM_DIR)/$(DOCKER_REGISTRY)/$(DOCKER_ORG)/$(PROJECT_NAME)/$(DOCKER_TAG)/$$MANIFEST_DIGEST.json $(DOCKER_REGISTRY)/$(DOCKER_ORG)/$(PROJECT_NAME):$(DOCKER_TAG)$(DOCKER_PLATFORM_TAG_SUFFIX)
110+
MANIFEST_DIGEST=$(shell docker buildx imagetools inspect $(DOCKER_REGISTRY)/$(DOCKER_ORG)/$(PROJECT_NAME):$(DOCKER_TAG)$(DOCKER_PLATFORM_TAG_SUFFIX) --format '{{ json . }}' | jq -r .manifest.digest); \
111+
cosign sign --tlog-upload=false -a author=StrimziCI -a BuildID=$(BUILD_ID) -a Commit=$(BUILD_COMMIT) --key cosign.key --attachment sbom $(DOCKER_REGISTRY)/$(DOCKER_ORG)/$(PROJECT_NAME)@$$MANIFEST_DIGEST
112+
@rm cosign.key
113+
84114
docker_%: docker_%_default
85115
@ true

README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,26 @@ And use it to verify the signature:
8787
cosign verify --key strimzi.pub quay.io/strimzi/operator:latest --insecure-ignore-tlog=true
8888
```
8989

90+
## Software Bill of Materials (SBOM)
91+
92+
From the 0.38.0 release, Strimzi publishes the software bill of materials (SBOM) of our containers.
93+
The SBOMs are published as an archive with `SPDX-JSON` and `Syft-Table` formats signed using cosign.
94+
For releases, they are also pushed into the container registry.
95+
To verify the SBOM signatures, please use the Strimzi public key:
96+
97+
```
98+
-----BEGIN PUBLIC KEY-----
99+
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAET3OleLR7h0JqatY2KkECXhA9ZAkC
100+
TRnbE23Wb5AzJPnpevvQ1QUEQQ5h/I4GobB7/jkGfqYkt6Ct5WOU2cc6HQ==
101+
-----END PUBLIC KEY-----
102+
```
103+
104+
You can use it to verify the signature of the SBOM files with the following command:
105+
106+
```
107+
cosign verify-blob --key cosign.pub --bundle <SBOM-file>.bundle --insecure-ignore-tlog=true <SBOM-file>
108+
```
109+
90110
---
91111

92112
Strimzi is a <a href="http://cncf.io">Cloud Native Computing Foundation</a> sandbox project.

docker-images/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
TOPDIR=$(dir $(lastword $(MAKEFILE_LIST)))
22

33
DOCKERDIRS=base operator kafka-based maven-builder kaniko-executor
4-
DOCKER_TARGETS=docker_build docker_push docker_tag docker_load docker_save docker_amend_manifest docker_push_manifest docker_delete_manifest docker_delete_archive
4+
DOCKER_TARGETS=docker_build docker_push docker_tag docker_load docker_save docker_amend_manifest docker_push_manifest docker_delete_manifest docker_delete_archive docker_sbom docker_push_sbom
55

66
all: $(DOCKERDIRS)
77
$(DOCKER_TARGETS): $(DOCKERDIRS)

docker-images/base/Makefile

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,10 @@ docker_push_manifest:
1515
docker_sign_manifest:
1616
# Do nothing
1717

18+
docker_sbom:
19+
# Do nothing
20+
21+
docker_push_sbom:
22+
# Do nothing
23+
1824
.PHONY: build clean release

docker-images/kafka-based/Makefile

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
TOPDIR = $(dir $(lastword $(MAKEFILE_LIST)))
22
RELEASE_VERSION ?= $(shell cat $(TOPDIR)/release.version)
3-
DOCKER_TARGETS = docker_build docker_push docker_tag docker_load docker_save docker_amend_manifest docker_push_manifest docker_delete_manifest docker_delete_archive
3+
DOCKER_TARGETS = docker_build docker_push docker_tag docker_load docker_save docker_amend_manifest docker_push_manifest docker_delete_manifest docker_delete_archive docker_sbom docker_push_sbom
44
DOCKER_TAG ?= latest
55

66
.PHONY: build clean release all $(DOCKER_TARGETS)
@@ -38,6 +38,12 @@ docker_delete_manifest:
3838
docker_delete_archive:
3939
./build.sh docker_delete_archive
4040

41+
docker_sbom:
42+
./build.sh docker_sbom
43+
44+
docker_push_sbom:
45+
./build.sh docker_push_sbom
46+
4147
all: docker_build docker_push
4248

4349
.PHONY: build clean release all $(SUBDIRS) $(DOCKER_TARGETS) spotbugs

0 commit comments

Comments
 (0)