From c80bdbf2db58453127271b5696da508fb062e506 Mon Sep 17 00:00:00 2001 From: Florin Sarbu Date: Thu, 16 Jan 2025 08:07:44 +0000 Subject: [PATCH] image_types_balena.bbclass: Move image signing code here This fixes the following error: cp: cannot stat '/work/build/tmp/deploy/images/generic-amd64/balena-image-generic-amd64.balenaos-img.sig': No such file or directory The signed image symlink is not generated before the flasher needs it so we avoid this dependency issue by defining a new image type for which the build system will automatically create the appropriate symlink. Change-type: patch Signed-off-by: Florin Sarbu --- .../classes/image_types_balena.bbclass | 43 +++++++++++++++++++ .../classes/sign-digest.bbclass | 40 ----------------- .../images/balena-image-flasher.bb | 4 +- .../recipes-core/images/balena-image.bb | 20 +-------- 4 files changed, 47 insertions(+), 60 deletions(-) delete mode 100644 meta-balena-common/classes/sign-digest.bbclass diff --git a/meta-balena-common/classes/image_types_balena.bbclass b/meta-balena-common/classes/image_types_balena.bbclass index 7be1f9e680..98675e8699 100644 --- a/meta-balena-common/classes/image_types_balena.bbclass +++ b/meta-balena-common/classes/image_types_balena.bbclass @@ -400,3 +400,46 @@ IMAGE_CMD:hostapp-ext4 () { truncate -s "$(expr ${ROOTFS_SIZE} \* 1024)" "${BALENA_HOSTAPP_IMG}" mkfs.hostapp -t "${TMPDIR}" -s "${STAGING_DIR_NATIVE}" -i ${BALENA_DOCKER_IMG} -o ${BALENA_HOSTAPP_IMG} } + +IMAGE_TYPEDEP:sign = "balenaos-img" + +IMAGE_CMD:sign () { + if [ "x${SIGN_API}" = "x" ]; then + bbnote "Signing API not defined" + return 0 + fi + if [ "x${SIGN_API_KEY}" = "x" ]; then + bbfatal "Signing API key must be defined" + fi + + for SIGNING_ARTIFACT in ${SIGNING_ARTIFACTS} + do + if [ -z "${SIGNING_ARTIFACT}" ] || [ ! -f "${SIGNING_ARTIFACT}" ]; then + bbfatal "Nothing to sign" + fi + + DIGEST=$(openssl dgst -hex -sha256 "${SIGNING_ARTIFACT}" | awk '{print $2}') + + REQUEST_FILE=$(mktemp) + RESPONSE_FILE=$(mktemp) + echo "{\"cert_id\": \"${SIGN_KMOD_KEY_ID}\", \"digest\": \"${DIGEST}\"}" > "${REQUEST_FILE}" + CURL_CA_BUNDLE="${STAGING_DIR_NATIVE}/etc/ssl/certs/ca-certificates.crt" curl --retry 5 --fail --silent "${SIGN_API}/cert/sign" -X POST -H "Content-Type: application/json" -H "X-API-Key: ${SIGN_API_KEY}" -d "@${REQUEST_FILE}" > "${RESPONSE_FILE}" + jq -r ".signature" < "${RESPONSE_FILE}" | base64 -d > "${SIGNING_ARTIFACT}.sig" + rm -f "${REQUEST_FILE}" "${RESPONSE_FILE}" + done +} + +do_image_sign[network] = "1" +do_image_sign[depends] += " \ + openssl-native:do_populate_sysroot \ + curl-native:do_populate_sysroot \ + jq-native:do_populate_sysroot \ + ca-certificates-native:do_populate_sysroot \ + coreutils-native:do_populate_sysroot \ + gnupg-native:do_populate_sysroot \ + " + +do_image_sign[vardeps] += " \ + SIGN_API \ + SIGN_KMOD_KEY_ID \ + " diff --git a/meta-balena-common/classes/sign-digest.bbclass b/meta-balena-common/classes/sign-digest.bbclass deleted file mode 100644 index c0ed3db692..0000000000 --- a/meta-balena-common/classes/sign-digest.bbclass +++ /dev/null @@ -1,40 +0,0 @@ -do_sign_digest () { - if [ "x${SIGN_API}" = "x" ]; then - bbnote "Signing API not defined" - return 0 - fi - if [ "x${SIGN_API_KEY}" = "x" ]; then - bbfatal "Signing API key must be defined" - fi - - for SIGNING_ARTIFACT in ${SIGNING_ARTIFACTS} - do - if [ -z "${SIGNING_ARTIFACT}" ] || [ ! -f "${SIGNING_ARTIFACT}" ]; then - bbfatal "Nothing to sign" - fi - - DIGEST=$(openssl dgst -hex -sha256 "${SIGNING_ARTIFACT}" | awk '{print $2}') - - REQUEST_FILE=$(mktemp) - RESPONSE_FILE=$(mktemp) - echo "{\"cert_id\": \"${SIGN_KMOD_KEY_ID}\", \"digest\": \"${DIGEST}\"}" > "${REQUEST_FILE}" - CURL_CA_BUNDLE="${STAGING_DIR_NATIVE}/etc/ssl/certs/ca-certificates.crt" curl --retry 5 --fail --silent "${SIGN_API}/cert/sign" -X POST -H "Content-Type: application/json" -H "X-API-Key: ${SIGN_API_KEY}" -d "@${REQUEST_FILE}" > "${RESPONSE_FILE}" - jq -r ".signature" < "${RESPONSE_FILE}" | base64 -d > "${SIGNING_ARTIFACT}.sig" - rm -f "${REQUEST_FILE}" "${RESPONSE_FILE}" - done -} - -do_sign_digest[network] = "1" -do_sign_digest[depends] += " \ - openssl-native:do_populate_sysroot \ - curl-native:do_populate_sysroot \ - jq-native:do_populate_sysroot \ - ca-certificates-native:do_populate_sysroot \ - coreutils-native:do_populate_sysroot \ - gnupg-native:do_populate_sysroot \ - " - -do_sign_digest[vardeps] += " \ - SIGN_API \ - SIGN_KMOD_KEY_ID \ - " diff --git a/meta-balena-common/recipes-core/images/balena-image-flasher.bb b/meta-balena-common/recipes-core/images/balena-image-flasher.bb index f26962bc70..b501f4663f 100644 --- a/meta-balena-common/recipes-core/images/balena-image-flasher.bb +++ b/meta-balena-common/recipes-core/images/balena-image-flasher.bb @@ -13,9 +13,9 @@ IMAGE_FSTYPES = "balenaos-img" BALENA_ROOT_FSTYPE = "ext4" # Make sure you have the resin image ready -do_image_balenaos_img[depends] += "balena-image:do_image_complete" +do_image_balenaos_img[depends] += "balena-image:do_rootfs" -# Ensure we have the raw balena image ready in DEPLOY_DIR_IMAGE +# Ensure we have the raw balena image and the optional signed image ready in DEPLOY_DIR_IMAGE do_image[depends] += "balena-image:do_image_complete" IMAGE_FEATURES:append = " \ diff --git a/meta-balena-common/recipes-core/images/balena-image.bb b/meta-balena-common/recipes-core/images/balena-image.bb index c00043a127..8fd555fee7 100644 --- a/meta-balena-common/recipes-core/images/balena-image.bb +++ b/meta-balena-common/recipes-core/images/balena-image.bb @@ -18,7 +18,7 @@ IMAGE_ROOTFS_MAXSIZE = "${IMAGE_ROOTFS_SIZE}" IMAGE_FSTYPES = "balenaos-img" -inherit core-image image-balena features_check sign-digest +inherit core-image image-balena features_check SPLASH += "plymouth-balena-theme" @@ -58,25 +58,10 @@ generate_hostos_version () { echo "${HOSTOS_VERSION}" > ${DEPLOY_DIR_IMAGE}/VERSION_HOSTOS } -symlink_image_signature () { - # This is probably not the correct way to do it, but it works. - # We sign BALENA_RAW_IMG, which ends up in IMGDEPLOYDIR - # and has a timestamp in the file name. We need to get rid - # of the timestamp for the final deploy, so that the file - # ends up in a predictable location. - - if [ -n "${SIGN_API}" ]; then - ln -sf "${BALENA_RAW_IMG}.sig" "${DEPLOY_DIR_IMAGE}/balena-image-${MACHINE}.balenaos-img.sig" - fi -} - DEPENDS += "jq-native" IMAGE_PREPROCESS_COMMAND:append = " generate_rootfs_fingerprints ; " -IMAGE_POSTPROCESS_COMMAND += " \ - generate_hostos_version ; \ - symlink_image_signature ; \ -" +IMAGE_POSTPROCESS_COMMAND += " generate_hostos_version ; " BALENA_BOOT_PARTITION_FILES:append = " \ balena-logo.png:/splash/balena-logo.png \ @@ -113,4 +98,3 @@ addtask image_size_check after do_image_balenaos_img before do_image_complete do_resin_boot_dirgen_and_deploy[depends] += "redsocks:do_deploy" SIGNING_ARTIFACTS = "${BALENA_RAW_IMG}" -addtask sign_digest after do_image_balenaos_img before do_image_complete