From c8edf28301a741d2cc28570ceb643c57fd4729f2 Mon Sep 17 00:00:00 2001 From: Krzesimir Nowak Date: Fri, 3 Jun 2022 14:54:54 +0200 Subject: [PATCH] ci-automation: Sign artifacts and upload the signatures It uses the SIGNER environment variable to decide whether the signatures should be created or not. It expect the key of the SIGNER to exist in GPGHOME, and that's what gpg_setup.sh is already doing. In some places we need to recursively change the owner of the directory that contains artifacts to be signed, otherwise we won't be able to create new files with signatures there. This is because some of the artifacts are either created inside the SDK container (so the created files belong to root outside the container) or are created with `sudo`. --- ci-automation/ci_automation_common.sh | 50 ++++++++++++++++++++++++++- ci-automation/packages.sh | 9 +++-- ci-automation/push_pkgs.sh | 8 +++++ ci-automation/sdk_bootstrap.sh | 8 +++++ ci-automation/vms.sh | 1 + 5 files changed, 72 insertions(+), 4 deletions(-) diff --git a/ci-automation/ci_automation_common.sh b/ci-automation/ci_automation_common.sh index ce01d55765..25e47c12df 100644 --- a/ci-automation/ci_automation_common.sh +++ b/ci-automation/ci_automation_common.sh @@ -175,7 +175,8 @@ function docker_image_to_buildcache() { local tarball="$(basename "$image")-${version}.tar.gz" $docker save "${image}":"${version}" | $PIGZ -c > "${tarball}" - copy_to_buildcache "containers/${version}" "${tarball}" + sign_artifacts "${SIGNER:-}" "${tarball}" + copy_to_buildcache "containers/${version}" "${tarball}"* } # -- @@ -299,3 +300,50 @@ function secret_to_file() { config_ref="/proc/${$}/fd/${fd}" } # -- + +# Creates signatures for the passed files and directories. In case of +# directory, all files inside are signed. Files ending with .asc or +# .sig or .gpg are ignored, though. This function is a noop if signer +# is empty. +# +# Typical use: +# sign_artifacts "${SIGNER}" artifact.tar.gz +# copy_to_buildcache "artifacts/directory" artifact.tar.gz* +# +# Parameters: +# +# 1 - signer whose key is expected to be already imported into the +# keyring +# @ - files and directories to sign +function sign_artifacts() { + local signer="${1}"; shift + # rest of the parameters are directories/files to sign + local to_sign=() + local file + local files + + if [[ -z "${signer}" ]]; then + return + fi + + for file; do + files=() + if [[ -d "${file}" ]]; then + readarray -d '' files < <(find "${file}" ! -type d -print0) + elif [[ -e "${file}" ]]; then + files+=( "${file}" ) + fi + for file in "${files[@]}"; do + if [[ "${file}" =~ \.(asc|gpg|sig)$ ]]; then + continue + fi + to_sign+=( "${file}" ) + done + done + for file in "${to_sign[@]}"; do + gpg --batch --local-user "${signer}" \ + --output "${file}.sig" \ + --detach-sign "${file}" + done +} +# -- diff --git a/ci-automation/packages.sh b/ci-automation/packages.sh index be1775b0c5..a6813e280a 100644 --- a/ci-automation/packages.sh +++ b/ci-automation/packages.sh @@ -175,9 +175,12 @@ function _packages_build_impl() { docker_commit_to_buildcache "${packages_container}" "${packages_image}" "${docker_vernum}" # Publish torcx manifest and docker tarball to "images" cache so tests can pull it later. - copy_to_buildcache "images/${arch}/${vernum}/torcx" \ - "${torcx_tmp}/torcx/${arch}-usr/latest/torcx_manifest.json" - copy_to_buildcache "images/${arch}/${vernum}/torcx" \ + sign_artifacts "${SIGNER}" \ + "${torcx_tmp}/torcx/${arch}-usr/latest/torcx_manifest.json" \ "${torcx_tmp}/torcx/pkgs/${arch}-usr/docker/"*/*.torcx.tgz + copy_to_buildcache "images/${arch}/${vernum}/torcx" \ + "${torcx_tmp}/torcx/${arch}-usr/latest/torcx_manifest.json"* + copy_to_buildcache "images/${arch}/${vernum}/torcx" \ + "${torcx_tmp}/torcx/pkgs/${arch}-usr/docker/"*/*.torcx.tgz* } # -- diff --git a/ci-automation/push_pkgs.sh b/ci-automation/push_pkgs.sh index bb4c0e1b9a..4b0c153148 100644 --- a/ci-automation/push_pkgs.sh +++ b/ci-automation/push_pkgs.sh @@ -49,7 +49,15 @@ function image_build__copy_to_bincache() { source ci-automation/ci_automation_common.sh + # change the owner of the files and directories in __build__ back + # to ourselves, otherwise we could fail to sign the artifacts as + # we lacked write permissions in the directory of the signed + # artifact + local uid=$(id --user) + local gid=$(id --group) cd /build/$arch-usr/var/lib/portage/pkgs/ + sudo chown --recursive "${uid}:${gid}" . + sign_artifacts "${SIGNER}" * copy_to_buildcache "boards/$arch-usr/$version/pkgs" * } # -- diff --git a/ci-automation/sdk_bootstrap.sh b/ci-automation/sdk_bootstrap.sh index c09388cb7e..b35f4192ca 100644 --- a/ci-automation/sdk_bootstrap.sh +++ b/ci-automation/sdk_bootstrap.sh @@ -134,7 +134,15 @@ function _sdk_bootstrap_impl() { source sdk_container/.repo/manifests/version.txt local dest_tarball="flatcar-sdk-${ARCH}-${FLATCAR_SDK_VERSION}.tar.bz2" + # change the owner of the files and directories in __build__ back + # to ourselves, otherwise we could fail to sign the artifacts as + # we lacked write permissions in the directory of the signed + # artifact + local uid=$(id --user) + local gid=$(id --group) + sudo chown --recursive "${uid}:${gid}" __build__ cd "__build__/images/catalyst/builds/flatcar-sdk" + sign_artifacts "${SIGNER}" "${dest_tarball}"* copy_to_buildcache "sdk/${ARCH}/${FLATCAR_SDK_VERSION}" "${dest_tarball}"* cd - } diff --git a/ci-automation/vms.sh b/ci-automation/vms.sh index cfcc6e3a95..ca69164485 100644 --- a/ci-automation/vms.sh +++ b/ci-automation/vms.sh @@ -117,6 +117,7 @@ function _vm_build_impl() { cp --reflink=auto -R "${CONTAINER_IMAGE_ROOT}/${arch}-usr/" "./${images_out}/" cd "images/latest" + sign_artifacts "${SIGNER}" * copy_to_buildcache "images/${arch}/${vernum}/" * } # --