From be46ed7bb0902a99935b95d11cec13f5dc58710c Mon Sep 17 00:00:00 2001 From: Thilo Fromm Date: Wed, 22 Jun 2022 14:55:11 +0200 Subject: [PATCH] profiles/coreos/base/profile.bashrc: SLSA provenance reports This change adds initial support for SLSA provenance report generation. Reports are generated in package build post-install hooks after compilation. See https://slsa.dev/ for SLSA and https://slsa.dev/provenance/v0.2 for the provenance report syntax. Signed-off-by: Thilo Fromm --- .../profiles/coreos/base/profile.bashrc | 3 + .../base/profile.bashrc.slsa-provenance | 181 ++++++++++++++++++ 2 files changed, 184 insertions(+) create mode 100644 sdk_container/src/third_party/coreos-overlay/profiles/coreos/base/profile.bashrc.slsa-provenance diff --git a/sdk_container/src/third_party/coreos-overlay/profiles/coreos/base/profile.bashrc b/sdk_container/src/third_party/coreos-overlay/profiles/coreos/base/profile.bashrc index 4364514f5b..559985a71e 100644 --- a/sdk_container/src/third_party/coreos-overlay/profiles/coreos/base/profile.bashrc +++ b/sdk_container/src/third_party/coreos-overlay/profiles/coreos/base/profile.bashrc @@ -94,6 +94,9 @@ cros_pre_pkg_setup_sysroot_build_bin_dir() { PATH+=":${CROS_BUILD_BOARD_BIN}" } +# Source hooks for SLSA build provenance report generation +source "${BASH_SOURCE[0]}.slsa-provenance" + # Insert our sysroot wrappers into the path SYSROOT_WRAPPERS_BIN="/usr/lib64/sysroot-wrappers/bin" if [[ "$PATH" != *"$SYSROOT_WRAPPERS_BIN"* ]]; then diff --git a/sdk_container/src/third_party/coreos-overlay/profiles/coreos/base/profile.bashrc.slsa-provenance b/sdk_container/src/third_party/coreos-overlay/profiles/coreos/base/profile.bashrc.slsa-provenance new file mode 100644 index 0000000000..8c0200d1dc --- /dev/null +++ b/sdk_container/src/third_party/coreos-overlay/profiles/coreos/base/profile.bashrc.slsa-provenance @@ -0,0 +1,181 @@ +# Build provenance hooks +# ====================== +# The functions below hook into every ebuild's execution and generate provenance files +# to meet the SLSA provenance requirements (https://slsa.dev/spec/v0.1/requirements#available). +# All input files (source tarball / git commit hash) plus added patches / files, +# and all resulting installation binaries and files are captured. +# The information is emitted in SLSA provenance 0.2 format (see https://slsa.dev/provenance/v0.2) + + +# We only record provenance when a package is actually being built. +# See profiles/coreos/base/profile.bashrc for cros_... +cros_post_src_configure_enable_slsa_provenance_report() { + export __slsa_provenance_report="yes" +} +# -- + +# Generate SLSA provenance 0.2 Subject information. +# The information will cover all installation files shipped with a package. +__slsa_provenance_subject() { + local parallel="$(grep -cE '^processor' /proc/cpuinfo)" + local comma="" + + einfo " Provenance: recording subject (output)" + + echo ' "subject": [' + + ( + cd "$D" + find . -type f -print | sed 's:^./::' | xargs -P "$parallel" -L 1 sha512sum + ) | while read checksum filepath; do + echo -en "${comma} {\"name\":\"/$filepath\", \"digest\":{\"sha512\":\"$checksum\"}}" + if [ -z "$comma" ] ; then + comma=',\n' + fi + done + echo -en "\n ]" +} +# -- + +__slsa_provenance_materials() { + local csum="" uri="" repo="" ebuild="" + + local ebuilds_basedir="/mnt/host/source/src/third_party/" + local ebuild="${CATEGORY}/${PN}/${PF}.ebuild" + if [ -f "${ebuilds_basedir}/coreos-overlay/${ebuild}" ] ; then + repo="coreos-overlay" + elif [ -f "${ebuilds_basedir}/portage-stable/${ebuild}" ] ; then + repo="portage-stable" + else + eerror "SLSA provenance: Unable to detect ebuild repository for package '${ebuild}'" + exit 1 + fi + + einfo " Provenance: recording ebuild material (input) '${repo}/${ebuild}'" + echo ' "materials": [' + + # The ebuild. Since "configSource" in "invocation" cannot have more than one (top/level) entry + # we add the ebuild and git repo checksum here, as a material. + csum="$(cat "/mnt/host/source/src/scripts/.git/modules/sdk_container/src/third_party/${repo}/ORIG_HEAD")" + uri="git+https://github.com/flatcar-linux/${repo}.git/${ebuild}" + echo -e " { \"uri\": \"${uri}\"," + echo -n " \"digest\": {\"sha1\":\"${csum}\"} }" + + # The main sources + if [ -n "${A}" ] ; then + # Package is built from downloaded source tarball(s) + # There can be multiple, and can be used conditionally based on use flags, + # and even replaced with different local names ("http://... -> othername.tgz"). So + # we go through what's actually used ($A), then find the corresponding source URI. + local src="" prev_uri="" rename="false" orig_name="" + for src in ${A}; do + local found="false" + for uri in ${SRC_URI}; do + if [ "${uri}" = "->" ] ; then + rename="true" + continue + fi + if [ "${src}" = "$(basename "${uri}")" ] ; then + orig_name="${src}" + if [ "${rename}" = "true" ] ; then + uri="${prev_uri}" + orig_name="$(basename "${uri}")" + fi + einfo " Provenance: recording tarball material (input) '${src}' ('${orig_name}')" + csum="$(sha512sum "${DISTDIR}/${src}" | cut -d' ' -f1)" + echo -e ",\n { \"uri\": \"${uri}\"," + echo -n " \"digest\": {\"sha512\":\"${csum}\"} }" + found="true" + fi + rename="false" + prev_uri="${uri}" + done + if [ "${found}" != "true" ] ; then + eerror "No SRC_URI found for source '${src}', unable to record provenance!" + exit 1 + fi + done + elif [ -n "${EGIT_REPO_URI:-}" ] ; then + # package is built from repo checkout (git) + einfo " Provenance: recording GIT material (input) '${EGIT_REPO_URI}'" + csum="${EGIT_COMMIT}" + uri="${EGIT_REPO_URI}" + echo -e ",\n { \"uri\": \"${uri}\"," + echo -n " \"digest\": {\"sha1\":\"$csum\"} }" + fi + + # Patches / files shipped with the ebuild (if any) + uri="git+https://github.com/flatcar-linux/${repo}.git/${CATEGORY}/${PN}/files" + csum="$(cat "/mnt/host/source/src/scripts/.git/modules/sdk_container/src/third_party/${repo}/ORIG_HEAD")" + if [ -d "${FILESDIR}" ] ; then + for file in $(cd "$FILESDIR" && find . -type f | sed 's:^./::') ; do + einfo " Provenance: recording ebuild material (input) '${file}'" + echo -e ",\n { \"uri\": \"${uri}/${file}\"," + echo -n " \"digest\": {\"sha1\":\"$csum\"} }" + done + fi + + echo -ne '\n ]' +} +# -- + +__slsa_provenance_report() { + local scripts_hash="$(cat "/mnt/host/source/src/scripts/.git/ORIG_HEAD")" + local buildcmd="emerge" + # extract board from e.g. '/build/amd64-usr/build'. Empty if no board is set (SDK build). + local board="$(echo "${CROS_BUILD_BOARD_TREE:-}" | sed -n 's:^/build/\([^/]\+\)/.*:\1:p')" + if [ -n "$board" ] ; then + buildcmd="emerge-${board}" + fi + + # FIXME: Supply SDK image ID and sha256 digest along with the version tag + local sdk_version="$(source /mnt/host/source/.repo/manifests/version.txt; echo ${FLATCAR_SDK_VERSION})" + + # FIXME: add builder ID +cat < "${T}/${report_file}" + + mkdir -p "${dest_dir}" + mv "${T}/${report_file}" "${dest_dir}" +}