From 239c49aae34a2643e8f69a55410de87c58e0475c 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 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 | 47 +++++++++++++++---- 6 files changed, 57 insertions(+), 10 deletions(-) diff --git a/.github/workflows/azure-podvm-image-build.yml b/.github/workflows/azure-podvm-image-build.yml index 27f22ed5b..7bcf60895 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..26f4b16d5 100644 --- a/src/cloud-api-adaptor/podvm/Makefile.inc +++ b/src/cloud-api-adaptor/podvm/Makefile.inc @@ -36,6 +36,20 @@ 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 + +# 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 FORCE_TARGET := $(if $(FORCE),force,) @@ -71,7 +85,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 +105,20 @@ PAUSE_SRC = pause # Allows to override PAUSE_BUNDLE ?= pause_bundle +# $(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 @@ -150,21 +185,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 "$@"