From 1f951474d850dbb097c0668066de25c6cb542b3c Mon Sep 17 00:00:00 2001 From: MichaIng Date: Sun, 17 Sep 2023 17:01:56 +0200 Subject: [PATCH] v8.22 - Images | SHA256 hashes and GPG signatures are now provided for all our images, linked from our download page or found here: https://dietpi.com/downloads/images/. Our public GPG keyring can be found at https://github.com/MichaIng.gpg. --- .build/images/dietpi-build | 27 +++++++++++++++++++++------ .build/images/dietpi-imager | 8 ++++++-- .github/workflows/dietpi-build.yml | 5 ++++- CHANGELOG.txt | 3 ++- 4 files changed, 33 insertions(+), 10 deletions(-) diff --git a/.build/images/dietpi-build b/.build/images/dietpi-build index 7d10996fb7..b73378140b 100755 --- a/.build/images/dietpi-build +++ b/.build/images/dietpi-build @@ -46,6 +46,7 @@ GITOWNER='MichaIng' EDITION= SUFFIX= ADD_DOS_PART=1 +SIGN_PASS= while (( $# )) do case $1 in @@ -61,6 +62,7 @@ do '-e') shift; EDITION=$1;; '-s') shift; SUFFIX=$1;; '--no-dos-part') ADD_DOS_PART=0;; + '--sign') shift; SIGN_PASS=$1;; *) G_DIETPI-NOTIFY 1 "Invalid input \"$1\", aborting..."; exit 1;; esac shift @@ -468,6 +470,7 @@ G_EXEC losetup -d "$FP_LOOP" export FP_ROOT_DEV CLONING_TOOL OUTPUT_IMG_NAME MOUNT_IT='Off' SKIP_ARCHIVE SKIP_FIRSTBOOT_RESIZE=1 IMAGER_ARGS=("$OUTPUT_IMG_NAME.img") (( $ADD_DOS_PART )) && IMAGER_ARGS+=('--add-dos-part') +[[ $SIGN_PASS ]] && IMAGER_ARGS+=('--sign' "$SIGN_PASS") if [[ ! $EDITION || $EDITION == 'all' ]] then G_DIETPI-NOTIFY 2 "Running DietPi-Imager for $G_GITOWNER/$G_GITBRANCH" @@ -726,7 +729,9 @@ _EOF_ G_EXEC_DESC='Creating VMware tar.xz archive' XZ_OPT="-e9 ${limit_threads[*]}" G_EXEC tar -cJf "$image_name.tar.xz" "$image_name.vmdk" "$image_name.vmx" G_EXEC rm "$image_name.vmdk" "$image_name.vmx" G_EXEC_DESC='Generating SHA256 hash' G_EXEC eval "sha256sum '$image_name.tar.xz' > '$image_name.tar.xz.sha256'" - [[ -x 'upload.sh' ]] && G_EXEC_OUTPUT=1 G_EXEC ./upload.sh "$image_name.tar.xz"{,.sha256} && G_EXEC rm "$image_name.tar.xz"{,.sha256} + signature=() + [[ $SIGN_PASS ]] && { G_DIETPI-NOTIFY 2 'Signing archive ...'; gpg --batch --pinentry-mode loopback --passphrase "$SIGN_PASS" --armor "$image_name.tar.xz" || exit 1; signature=("$image_name.tar.xz.asc"); } + [[ -x 'upload.sh' ]] && G_EXEC_OUTPUT=1 G_EXEC ./upload.sh "$image_name.tar.xz"{,.sha256} "${signature[@]}" && G_EXEC rm "$image_name.tar.xz"{,.sha256} "${signature[@]}" fi ####### ESXi ############################# @@ -853,7 +858,9 @@ _EOF_ [[ ( -t 0 || -t 1 ) && $TERM != 'dumb' ]] && G_EXEC_OUTPUT=1 G_EXEC_DESC='Creating ESXi xz archive' G_EXEC xz -9e "${limit_threads[@]}" "$image_name.ova" G_EXEC_DESC='Generating SHA256 hash' G_EXEC eval "sha256sum '$image_name.ova.xz' > '$image_name.ova.xz.sha256'" - [[ -x 'upload.sh' ]] && G_EXEC_OUTPUT=1 G_EXEC ./upload.sh "$image_name.ova.xz"{,.sha256} && G_EXEC rm "$image_name.ova.xz"{,.sha256} + signature=() + [[ $SIGN_PASS ]] && { G_DIETPI-NOTIFY 2 'Signing archive ...'; gpg --batch --pinentry-mode loopback --passphrase "$SIGN_PASS" --armor "$image_name.ova.xz" || exit 1; signature=("$image_name.ova.xz.asc"); } + [[ -x 'upload.sh' ]] && G_EXEC_OUTPUT=1 G_EXEC ./upload.sh "$image_name.ova.xz"{,.sha256} "${signature[@]}" && G_EXEC rm "$image_name.ova.xz"{,.sha256} "${signature[@]}" fi ####### VirtualBox ####################### @@ -1003,7 +1010,9 @@ _EOF_ [[ ( -t 0 || -t 1 ) && $TERM != 'dumb' ]] && G_EXEC_OUTPUT=1 G_EXEC_DESC='Creating VirtualBox xz archive' G_EXEC xz -9e "${limit_threads[@]}" "$image_name.ova" G_EXEC_DESC='Generating SHA256 hash' G_EXEC eval "sha256sum '$image_name.ova.xz' > '$image_name.ova.xz.sha256'" - [[ -x 'upload.sh' ]] && G_EXEC_OUTPUT=1 G_EXEC ./upload.sh "$image_name.ova.xz"{,.sha256} && G_EXEC rm "$image_name.ova.xz"{,.sha256} + signature=() + [[ $SIGN_PASS ]] && { G_DIETPI-NOTIFY 2 'Signing archive ...'; gpg --batch --pinentry-mode loopback --passphrase "$SIGN_PASS" --armor "$image_name.ova.xz" || exit 1; signature=("$image_name.ova.xz.asc"); } + [[ -x 'upload.sh' ]] && G_EXEC_OUTPUT=1 G_EXEC ./upload.sh "$image_name.ova.xz"{,.sha256} "${signature[@]}" && G_EXEC rm "$image_name.ova.xz"{,.sha256} "${signature[@]}" fi ####### Hyper-V ########################## @@ -1016,7 +1025,9 @@ then [[ ( -t 0 || -t 1 ) && $TERM != 'dumb' ]] && G_EXEC_OUTPUT=1 G_EXEC_DESC='Creating Hyper-V xz archive' G_EXEC xz -9e "${limit_threads[@]}" "$image_name.vhdx" G_EXEC_DESC='Generating SHA256 hash' G_EXEC eval "sha256sum '$image_name.vhdx.xz' > '$image_name.vhdx.xz.sha256'" - [[ -x 'upload.sh' ]] && G_EXEC_OUTPUT=1 G_EXEC ./upload.sh "$image_name.vhdx.xz"{,.sha256} && G_EXEC rm "$image_name.vhdx.xz"{,.sha256} + signature=() + [[ $SIGN_PASS ]] && { G_DIETPI-NOTIFY 2 'Signing archive ...'; gpg --batch --pinentry-mode loopback --passphrase "$SIGN_PASS" --armor "$image_name.vhdx.xz" || exit 1; signature=("$image_name.vhdx.xz.asc"); } + [[ -x 'upload.sh' ]] && G_EXEC_OUTPUT=1 G_EXEC ./upload.sh "$image_name.vhdx.xz"{,.sha256} "${signature[@]}" && G_EXEC rm "$image_name.vhdx.xz"{,.sha256} "${signature[@]}" fi ####### Proxmox ############################ @@ -1033,7 +1044,9 @@ then [[ ( -t 0 || -t 1 ) && $TERM != 'dumb' ]] && G_EXEC_OUTPUT=1 G_EXEC_DESC='Creating Proxmox xz archive' G_EXEC xz -9e "${limit_threads[@]}" "${keep[@]}" "$image_name.qcow2" G_EXEC_DESC='Generating SHA256 hash' G_EXEC eval "sha256sum '$image_name.qcow2.xz' > '$image_name.qcow2.xz.sha256'" - [[ -x 'upload.sh' ]] && G_EXEC_OUTPUT=1 G_EXEC ./upload.sh "$image_name.qcow2.xz"{,.sha256} && G_EXEC rm "$image_name.qcow2.xz"{,.sha256} + signature=() + [[ $SIGN_PASS ]] && { G_DIETPI-NOTIFY 2 'Signing archive ...'; gpg --batch --pinentry-mode loopback --passphrase "$SIGN_PASS" --armor "$image_name.qcow2.xz" || exit 1; signature=("$image_name.qcow2.xz.asc"); } + [[ -x 'upload.sh' ]] && G_EXEC_OUTPUT=1 G_EXEC ./upload.sh "$image_name.qcow2.xz"{,.sha256} "${signature[@]}" && G_EXEC rm "$image_name.qcow2.xz"{,.sha256} "${signature[@]}" fi ####### UTM ############################## @@ -1203,7 +1216,9 @@ _EOF_ G_EXEC_DESC='Creating UTM tar.xz archive' XZ_OPT="-e9 ${limit_threads[*]}" G_EXEC tar -cJf "$image_name.tar.xz" "$image_name.utm" G_EXEC rm -R "$image_name.utm" G_EXEC_DESC='Generating SHA256 hash' G_EXEC eval "sha256sum '$image_name.tar.xz' > '$image_name.tar.xz.sha256'" - [[ -x 'upload.sh' ]] && G_EXEC_OUTPUT=1 G_EXEC ./upload.sh "$image_name.tar.xz"{,.sha256} && G_EXEC rm "$image_name.tar.xz"{,.sha256} + signature=() + [[ $SIGN_PASS ]] && { G_DIETPI-NOTIFY 2 'Signing archive ...'; gpg --batch --pinentry-mode loopback --passphrase "$SIGN_PASS" --armor "$image_name.tar.xz" || exit 1; signature=("$image_name.tar.xz.asc"); } + [[ -x 'upload.sh' ]] && G_EXEC_OUTPUT=1 G_EXEC ./upload.sh "$image_name.tar.xz"{,.sha256} "${signature[@]}" && G_EXEC rm "$image_name.tar.xz"{,.sha256} "${signature[@]}" fi # Cleanup diff --git a/.build/images/dietpi-imager b/.build/images/dietpi-imager index ab097ddc03..d6e16f1c6b 100644 --- a/.build/images/dietpi-imager +++ b/.build/images/dietpi-imager @@ -62,10 +62,12 @@ [[ $SHRINK_ONLY == 1 ]] || SHRINK_ONLY=0 [[ $SKIP_ARCHIVE == 1 ]] || SKIP_ARCHIVE=0 ADD_DOS_PART=0 + SIGN_PASS= while (( $# )) do case $1 in '--add-dos-part') ADD_DOS_PART=1;; + '--sign') shift; SIGN_PASS=$1;; *) if [[ -b $1 ]] then @@ -729,14 +731,16 @@ _EOF_ [[ ( -t 0 || -t 1 ) && $TERM != 'dumb' ]] && G_EXEC_OUTPUT=1 G_EXEC_DESC='Creating final xz archive' G_EXEC xz -9e "${limit_threads[@]}" "$OUTPUT_IMG_NAME.$OUTPUT_IMG_EXT" G_EXEC_DESC='Generating SHA256 hash' G_EXEC eval "sha256sum '$OUTPUT_IMG_NAME.$OUTPUT_IMG_EXT.xz' > '$OUTPUT_IMG_NAME.$OUTPUT_IMG_EXT.xz.sha256'" + local signature=() sig_text='' + [[ $SIGN_PASS ]] && { G_DIETPI-NOTIFY 2 'Signing archive ...'; gpg --batch --pinentry-mode loopback --passphrase "$SIGN_PASS" -b --armor "$OUTPUT_IMG_NAME.$OUTPUT_IMG_EXT.xz" || exit 1; signature=("$OUTPUT_IMG_NAME.$OUTPUT_IMG_EXT.xz.asc") sig_text="Signature: $PWD/${signature[*]}"; } G_DIETPI-NOTIFY 0 "DietPi-Imager has successfully finished. Image file: $PWD/$OUTPUT_IMG_NAME.$OUTPUT_IMG_EXT xz archive: $PWD/$OUTPUT_IMG_NAME.$OUTPUT_IMG_EXT.xz -SHA256 hash: $PWD/$OUTPUT_IMG_NAME.$OUTPUT_IMG_EXT.xz.sha256" +SHA256 hash: $PWD/$OUTPUT_IMG_NAME.$OUTPUT_IMG_EXT.xz.sha256$sig_text" # Upload archive automatically if there is an upload.sh in the same directory - [[ -x 'upload.sh' ]] && G_EXEC_OUTPUT=1 G_EXEC ./upload.sh "$OUTPUT_IMG_NAME.$OUTPUT_IMG_EXT.xz"{,.sha256} && G_EXEC rm -R "$OUTPUT_IMG_NAME.$OUTPUT_IMG_EXT.xz"{,.sha256} + [[ -x 'upload.sh' ]] && G_EXEC_OUTPUT=1 G_EXEC ./upload.sh "$OUTPUT_IMG_NAME.$OUTPUT_IMG_EXT.xz"{,.sha256} "${signature[@]}" && G_EXEC rm -R "$OUTPUT_IMG_NAME.$OUTPUT_IMG_EXT.xz"{,.sha256} "${signature[@]}" } diff --git a/.github/workflows/dietpi-build.yml b/.github/workflows/dietpi-build.yml index a78f1a78cb..83bcfddf04 100644 --- a/.github/workflows/dietpi-build.yml +++ b/.github/workflows/dietpi-build.yml @@ -117,5 +117,8 @@ jobs: curl -T "{$*}" --key /root/.ssh/id_ed25519 '\''${{ secrets.UPLOAD_URL }}testing/'\'' curl -H '\''Authorization: Bearer ${{ secrets.CF_TOKEN }}'\'' -H '\''Content-Type: application/json'\'' -d "{\"files\":[$urls]}" '\''https://api.cloudflare.com/client/v4/zones/${{ secrets.CF_ZONE }}/purge_cache'\'' echo' | sudo tee upload.sh > /dev/null + sudo gpg --batch --import << _EOF_ + ${{ secrets.GPG_KEY }} + _EOF_ - name: Run DietPi-Build - run: sudo bash -c "G_GITOWNER=$GITHUB_REPOSITORY_OWNER G_GITBRANCH=${GITHUB_REF#refs/heads/}; $(curl -sSf "https://raw.githubusercontent.com/$GITHUB_REPOSITORY_OWNER/DietPi/${GITHUB_REF#refs/heads/}/.build/images/dietpi-build")" 'DietPi-Build' ${{ matrix.buildargs }} + run: sudo bash -c "G_GITOWNER=$GITHUB_REPOSITORY_OWNER G_GITBRANCH=${GITHUB_REF#refs/heads/}; $(curl -sSf "https://raw.githubusercontent.com/$GITHUB_REPOSITORY_OWNER/DietPi/${GITHUB_REF#refs/heads/}/.build/images/dietpi-build")" 'DietPi-Build' ${{ matrix.buildargs }} --sign '${{ secrets.GPG_PASS }}' diff --git a/CHANGELOG.txt b/CHANGELOG.txt index fddb209565..d05edc0553 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -6,7 +6,8 @@ New software: Enhancements: - Images | DietPi images are now shipped with a trailing FAT partition which contains dietpi.txt and other config files for easier pre-configuration and automation from Windows and macOS hosts. The partition is removed automatically on first boot, after copying all supported config files/scripts. Related CLI flags have been added to our build scripts: "--add-fat-part" for dietpi-imager and "--no-fat-part" for dietpi-build. Many thanks to @dirkhh for implementing this feature: https://github.com/MichaIng/DietPi/pull/6602 -- Images | All our images are now compressed via xz instead of 7z. These are a little easier to handle, especially on Linux hosts, and many flashing utilities allow to flash zx-compressed images directly to disk, without the need to manually decompress them first. As xz compresses files and no directories, the dedicated README.md and hash text files are not included anymore. The hashes for integrity checks within an archive have no real purpose, as the compression algorithms imply hashes internally (CRC64 in case of xz), which are checked and integrity of the content assed as part of the decompression. +- Images | All our images are now compressed via xz instead of 7z. These are a little easier to handle, especially on Linux hosts, and many flashing utilities allow to flash zx-compressed images directly to disk, without the need to manually decompress them first. As xz compresses files and no directories, the dedicated README.md and hash text files are not included anymore. The hashes for integrity checks within an archive have no real purpose, as the compression algorithms imply hashes internally (CRC64 in case of xz), which are checked and integrity of the content assured as part of the decompression. +- Images | SHA256 hashes and GPG signatures are now provided for all our images, linked from our download page or found here: https://dietpi.com/downloads/images/. Our public GPG keyring can be found at https://github.com/MichaIng.gpg. - DietPi-Software | Docker: Enabled for Trixie and RISC-V via "docker.io" package from Debian repository. - DietPi-Software | Portainer: Enabled for RISC-V as Docker is now supported on RISC-V as well.