From ca04b04872e1b4355b70da89278f3fd802a4e6d8 Mon Sep 17 00:00:00 2001 From: Magnus Kulke Date: Mon, 14 Oct 2024 18:20:06 +0200 Subject: [PATCH] ci: verify provenance for guest-components The GC and agent artifacts attestations are being verified, so far this is only toggled on for mkosi on fedora images. Signed-off-by: Magnus Kulke --- .github/workflows/azure-podvm-image-build.yml | 5 +- .../hack/verify-provenance.sh | 5 ++ src/cloud-api-adaptor/podvm-mkosi/Makefile | 2 + .../podvm/Dockerfile.podvm_binaries.fedora | 2 + .../podvm/Dockerfile.podvm_builder.fedora | 6 +- src/cloud-api-adaptor/podvm/Makefile.inc | 74 ++++++++++++++++--- src/cloud-api-adaptor/versions.yaml | 2 +- 7 files changed, 83 insertions(+), 13 deletions(-) diff --git a/.github/workflows/azure-podvm-image-build.yml b/.github/workflows/azure-podvm-image-build.yml index 7c3e2cced..3fb836f5c 100644 --- a/.github/workflows/azure-podvm-image-build.yml +++ b/.github/workflows/azure-podvm-image-build.yml @@ -61,9 +61,12 @@ jobs: sudo mv uplosi /usr/local/bin - name: Build binaries + env: + TEE_PLATFORM: az-cvm-vtpm + VERIFY_PROVENANCE: yes run: | make fedora-binaries-builder - TEE_PLATFORM=az-cvm-vtpm make binaries + make binaries - name: Build image run: make image diff --git a/src/cloud-api-adaptor/hack/verify-provenance.sh b/src/cloud-api-adaptor/hack/verify-provenance.sh index fd30cd4a9..8e78b1299 100755 --- a/src/cloud-api-adaptor/hack/verify-provenance.sh +++ b/src/cloud-api-adaptor/hack/verify-provenance.sh @@ -62,6 +62,11 @@ if [[ "$oci_artifact" =~ @sha256:[a-fA-F0-9]{32}$ ]]; then exit 1 fi +cleanup() { + rm -f "$attestation_bundle" +} +trap cleanup EXIT SIGINT SIGTERM + # Convention by gh cli attestation_bundle="${oci_artifact#*@}.jsonl" diff --git a/src/cloud-api-adaptor/podvm-mkosi/Makefile b/src/cloud-api-adaptor/podvm-mkosi/Makefile index 48a8e0624..63fc7189f 100644 --- a/src/cloud-api-adaptor/podvm-mkosi/Makefile +++ b/src/cloud-api-adaptor/podvm-mkosi/Makefile @@ -10,6 +10,7 @@ PODVM_DISTRO ?= fedora PODVM_TAG ?= $(VERSIONS_HASH) PODVM_NAME ?= $(REGISTRY)/podvm-generic-$(PODVM_DISTRO)-$(ARCH) PODVM_CONTAINER_NAME ?= $(REGISTRY)/podvm-docker-image +VERIFY_PROVENANCE ?= no .DEFAULT_GOAL := all .PHONY: all @@ -56,6 +57,7 @@ endif --build-arg PAUSE_VERSION=$(PAUSE_VERSION) \ --build-arg PAUSE_BIN=$(PAUSE_BIN) \ --build-arg IMAGE_NAME=mkosi-podvm-binaries \ + --build-arg VERIFY_PROVENANCE=$(VERIFY_PROVENANCE) \ $(if $(AUTHFILE),--build-arg AUTHFILE=$(AUTHFILE),) \ $(if $(DEFAULT_AGENT_POLICY_FILE),--build-arg DEFAULT_AGENT_POLICY_FILE=$(DEFAULT_AGENT_POLICY_FILE),) \ -o type=local,dest="./resources/binaries-tree" \ diff --git a/src/cloud-api-adaptor/podvm/Dockerfile.podvm_binaries.fedora b/src/cloud-api-adaptor/podvm/Dockerfile.podvm_binaries.fedora index 567770eb1..74d9c294d 100644 --- a/src/cloud-api-adaptor/podvm/Dockerfile.podvm_binaries.fedora +++ b/src/cloud-api-adaptor/podvm/Dockerfile.podvm_binaries.fedora @@ -25,6 +25,7 @@ ARG PAUSE_REPO ARG PAUSE_VERSION ARG PAUSE_BIN ARG IMAGE_NAME +ARG VERIFY_PROVENANCE ENV AUTHFILE=${AUTHFILE} ENV PAUSE_REPO=${PAUSE_REPO} @@ -38,6 +39,7 @@ ENV TEE_PLATFORM=${TEE_PLATFORM} ENV ARCH=${ARCH} ENV DEFAULT_AGENT_POLICY_FILE=${DEFAULT_AGENT_POLICY_FILE} ENV IMAGE_NAME=${IMAGE_NAME} +ENV VERIFY_PROVENANCE=${VERIFY_PROVENANCE} # Set these as they are required in the Makefile ENV IMAGE_URL="none" diff --git a/src/cloud-api-adaptor/podvm/Dockerfile.podvm_builder.fedora b/src/cloud-api-adaptor/podvm/Dockerfile.podvm_builder.fedora index e1f4c7475..ba6698a34 100644 --- a/src/cloud-api-adaptor/podvm/Dockerfile.podvm_builder.fedora +++ b/src/cloud-api-adaptor/podvm/Dockerfile.podvm_builder.fedora @@ -21,9 +21,13 @@ RUN dnf groupinstall -y 'Development Tools' && \ dnf install -y yum-utils gnupg git perl-core pkg-config libseccomp-devel gpgme-devel \ device-mapper-devel unzip libassuan-devel \ perl-FindBin openssl-devel tpm2-tss-devel \ - clang which xz && \ + clang which xz jq && \ dnf clean all +RUN dnf install 'dnf-command(config-manager)' && \ + dnf config-manager --add-repo https://cli.github.com/packages/rpm/gh-cli.repo && \ + dnf install -y gh --repo gh-cli + ADD https://dl.google.com/go/go${GO_VERSION}.linux-${ARCH}.tar.gz go${GO_VERSION}.linux-${ARCH}.tar.gz RUN rm -rf /usr/local/go && tar -C /usr/local -xzf go${GO_VERSION}.linux-${ARCH}.tar.gz && rm -f go${GO_VERSION}.linux-${ARCH}.tar.gz diff --git a/src/cloud-api-adaptor/podvm/Makefile.inc b/src/cloud-api-adaptor/podvm/Makefile.inc index f42406708..6a553c295 100644 --- a/src/cloud-api-adaptor/podvm/Makefile.inc +++ b/src/cloud-api-adaptor/podvm/Makefile.inc @@ -36,6 +36,32 @@ AGENT_POLICY ?= yes AGENT_POLICY_PATH := $(FILES_DIR)/etc/kata-opa DEFAULT_AGENT_POLICY_FILE ?= allow-all.rego +# Run github artifact provenance verifications +VERIFY_PROVENANCE ?= no +GUEST_COMPONENTS_REPO := confidential-containers/guest-components +KATA_REPO := kata-containers/kata-containers + +# probe version if the ref does not appear to be a git commit digest +ifeq ($(shell echo $(GUEST_COMPONENTS_REF) | grep -E "[0-9a-f]{40}"),) + GUEST_COMPONENTS_COMMIT := $(shell curl \ + --silent \ + --retry 3 \ + https://api.github.com/repos/$(GUEST_COMPONENTS_REPO)/commits/v$(GUEST_COMPONENTS_REF) \ + | jq -e -r .sha) +else + GUEST_COMPONENTS_COMMIT := $(GUEST_COMPONENTS_REF) +endif + +# probe version if the ref does not appear to be a git commit digest +ifeq ($(shell echo $(KATA_REF) | grep -E "[0-9a-f]{40}"),) + KATA_COMMIT := $(shell curl \ + --silent \ + --retry 3 \ + https://api.github.com/repos/$(KATA_REPO)/commits/v$(KATA_REF) \ + | jq -e -r .sha) +else + KATA_COMMIT := $(KATA_REF) +endif FORCE_TARGET := $(if $(FORCE),force,) @@ -71,7 +97,14 @@ PROCESS_USER_DATA = $(FILES_DIR)/usr/local/bin/process-user-data # Allow BINARIES to be overriden externally -BINARIES ?= $(AGENT_PROTOCOL_FORWARDER) $(KATA_AGENT) $(PAUSE) $(ATTESTATION_AGENT) $(CONFIDENTIAL_DATA_HUB) $(API_SERVER_REST) $(PROCESS_USER_DATA) +BINARIES ?= \ + $(AGENT_PROTOCOL_FORWARDER) \ + $(API_SERVER_REST) \ + $(ATTESTATION_AGENT) \ + $(CONFIDENTIAL_DATA_HUB) \ + $(KATA_AGENT) \ + $(PAUSE) \ + $(PROCESS_USER_DATA) SKOPEO_SRC ?= skopeo SKOPEO_BIN ?= $(SKOPEO_SRC)/bin/skopeo @@ -84,6 +117,32 @@ PAUSE_SRC = pause # Allows to override PAUSE_BUNDLE ?= pause_bundle +define pull_agent_artifact + $(eval $(call generate_tag,tag,$(KATA_REF),$(ARCH))) + $(eval OCI_IMAGE := $(KATA_REGISTRY)/agent) + $(eval OCI_DIGEST := $(shell oras resolve $(OCI_IMAGE):${tag})) + $(eval OCI_REF := $(OCI_IMAGE)@$(OCI_DIGEST)) + $(if $(filter yes,$(VERIFY_PROVENANCE)),$(ROOT_DIR)hack/verify-provenance.sh \ + -a $(OCI_REF) \ + -r $(KATA_REPO) \ + -d $(KATA_COMMIT)) + oras pull $(OCI_REF) +endef + +# $(1) - Artifact name +# $(2) - Tag suffix +define pull_gc_artifact + $(eval $(call generate_tag,tag,$(GUEST_COMPONENTS_REF),$(2))) + $(eval OCI_IMAGE := $(GUEST_COMPONENTS_REGISTRY)/$(1)) + $(eval OCI_DIGEST := $(shell oras resolve $(OCI_IMAGE):${tag})) + $(eval OCI_REF := $(OCI_IMAGE)@$(OCI_DIGEST)) + $(if $(filter yes,$(VERIFY_PROVENANCE)),$(ROOT_DIR)hack/verify-provenance.sh \ + -a $(OCI_REF) \ + -r $(GUEST_COMPONENTS_REPO) \ + -d $(GUEST_COMPONENTS_COMMIT)) + oras pull $(OCI_REF) +endef + # Clone a specific commit/tag/branch of a repo. # $(1) - Repository URL # $(2) - Destination directory @@ -119,8 +178,7 @@ $(PROCESS_USER_DATA): always install -D --compare "$(ROOT_DIR)/process-user-data" "$@" $(KATA_AGENT): $(FORCE_TARGET) - $(eval $(call generate_tag,tag,$(KATA_REF),$(ARCH))) - oras pull $(KATA_REGISTRY)/agent:${tag} + $(call pull_agent_artifact) tar xvJpf kata-static-agent.tar.xz install -D --compare "./usr/bin/kata-agent" "$@" @@ -150,21 +208,17 @@ $(PAUSE): | $(PAUSE_SRC) $(UMOCI_SRC)/umoci $(UMOCI_SRC)/umoci unpack --rootless --image "$(PAUSE_SRC):$(PAUSE_VERSION)" "${FILES_DIR}/$(PAUSE_BUNDLE)" $(ATTESTATION_AGENT): $(FORCE_TARGET) - $(eval SUFFIX := $(TEE_PLATFORM)_$(ARCH)) - $(eval $(call generate_tag,tag,$(GUEST_COMPONENTS_REF),$(SUFFIX))) - oras pull $(GUEST_COMPONENTS_REGISTRY)/attestation-agent:${tag} + $(call pull_gc_artifact,attestation-agent,$(TEE_PLATFORM)_$(ARCH)) tar xvJpf attestation-agent.tar.xz install -D --compare attestation-agent "$@" $(CONFIDENTIAL_DATA_HUB): $(FORCE_TARGET) - $(eval $(call generate_tag,tag,$(GUEST_COMPONENTS_REF),$(ARCH))) - oras pull $(GUEST_COMPONENTS_REGISTRY)/confidential-data-hub:${tag} + $(call pull_gc_artifact,confidential-data-hub,$(ARCH)) tar xvJpf confidential-data-hub.tar.xz install -D --compare confidential-data-hub "$@" $(API_SERVER_REST): $(FORCE_TARGET) - $(eval $(call generate_tag,tag,$(GUEST_COMPONENTS_REF),$(ARCH))) - oras pull $(GUEST_COMPONENTS_REGISTRY)/api-server-rest:${tag} + $(call pull_gc_artifact,api-server-rest,$(ARCH)) tar xvJpf api-server-rest.tar.xz install -D --compare api-server-rest "$@" diff --git a/src/cloud-api-adaptor/versions.yaml b/src/cloud-api-adaptor/versions.yaml index 0eeaf9789..080462b93 100644 --- a/src/cloud-api-adaptor/versions.yaml +++ b/src/cloud-api-adaptor/versions.yaml @@ -50,7 +50,7 @@ oci: tag: 3.9 kata-containers: registry: ghcr.io/kata-containers/cached-artefacts - reference: 3.9.0 + reference: 9a33a3413b222868232402a7412562f4f6fb5736 guest-components: registry: ghcr.io/confidential-containers/guest-components reference: d8da69072424e496486dfb5421a26f16ff2a7abf