diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index 13efb162da..0000000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,11 +0,0 @@ -version: 2 -updates: -- package-ecosystem: gomod - directory: "/" - schedule: - interval: daily - allow: - # For now, only enable the deps we know we want to keep fresh - - dependency-name: "github.com/coreos/butane" - - dependency-name: "github.com/coreos/ignition/v2" - - dependency-name: "github.com/coreos/stream-metadata-go" diff --git a/src/cmd-build b/src/cmd-build index 3ee8d9a5c5..1bddd9dc33 100755 --- a/src/cmd-build +++ b/src/cmd-build @@ -1,5 +1,5 @@ #!/usr/bin/env bash -set -euo pipefail +set -euxo pipefail dn=$(dirname "$0") # shellcheck source=src/cmdlib.sh @@ -38,6 +38,8 @@ Usage: coreos-assembler build --help --autolock=VERSION If no base lockfile used, create one from any arch build of `VERSION`. Note this is automatically enabled when adding to an existing multi-arch non-strict build. + --sign-composefs Sign the composeFS metadata and attach the signature to the OSTree commit. + This will also insert the public key into the rootfs for signature verification. Additional environment variables supported: @@ -62,8 +64,9 @@ TAG= STRICT= CONFIG_ARCHIVE=1 AUTOLOCK_VERSION= +SIGN_COMPOSEFS= rc=0 -options=$(getopt --options hfFt: --longoptions tag:,help,fetch,force,version:,parent:,parent-build:,delay-meta-merge,force-nocache,force-image,skip-prune,prepare-only,strict,skip-config-archive,autolock:,versionary -- "$@") || rc=$? +options=$(getopt --options hfFt: --longoptions tag:,help,fetch,force,version:,parent:,parent-build:,delay-meta-merge,force-nocache,force-image,skip-prune,prepare-only,strict,skip-config-archive,autolock:,versionary,sign-composefs -- "$@") || rc=$? [ $rc -eq 0 ] || { print_help exit 1 @@ -123,6 +126,9 @@ while true; do shift TAG=$1 ;; + --sign-composefs) + SIGN_COMPOSEFS=true + ;; --) shift break @@ -257,6 +263,13 @@ if [ -n "${PARENT_BUILD}" ]; then fi fi +# TODO +SIGN_COMPOSEFS=true +# If composeFS signing is enabled, generate the signature key +if test -n "${SIGN_COMPOSEFS}"; then + gen_ed25519_signing_key +fi + # Calculate image input checksum now and gather previous image build variables if any ks_path="${configdir}"/image.ks if [ -f "${ks_path}" ]; then @@ -354,12 +367,14 @@ fi if [ ! -f "${workdir}"/builds/builds.json ] && [ ! -f "${fetch_stamp}" ] ; then fatal "Must fetch before building" fi + composefs="$(jq -r .composefs < "${image_json}")" case "${composefs}" in false) ;; - true) + true | signed) ostree config --repo="${tmprepo}" set ex-integrity.composefs "true" + ostree config --repo="${tmprepo}" set ex-fsverity.required 'true' ;; *) fatal "Unhandled composefs setting: ${composefs}" ;; esac @@ -375,6 +390,84 @@ RUNVM_NONET=1 runcompose_tree --cache-only ${FORCE} \ "${extra_compose_args[@]}" strip_out_lockfile_digests "$lockfile_out".tmp /usr/lib/coreos-assembler/finalize-artifact "${lockfile_out}"{.tmp,} + +commit=$(jq -r '.["ostree-commit"]' < "${composejson}") + +ostree sign \ + --repo "${tmprepo}" \ + --sign-type ed25519 \ + --keys-file "${workdir}/tmp/ostree_signing_key.ed25519" \ + "$commit" + +ostree show --repo "${tmprepo}" "${commit}" +cfs_sig=$(ostree show --repo "${tmprepo}" "$commit" --print-metadata-key=ostree.composefs.digest.v0) +cfs_sig=$(echo "$cfs_sig"| sed 's/\[byte //g; s/\]//g; s/,//g; s/0x//g' | tr -d ' ') +echo "composeFS digest: $cfs_sig" + +kernpath="$(ostree ls --repo "${tmprepo}" "${commit}" /usr/lib/modules | sort -h | tail -1 | awk '{print $5}')" +kernver="$(basename "${kernpath}")" +ostree cat --repo "${tmprepo}" "${commit}" "/usr/lib/modules/${kernver}/vmlinuz" > vmlinuz +ostree cat --repo "${tmprepo}" "${commit}" "/usr/lib/modules/${kernver}/initramfs.img" > initramfs +ostree cat --repo "${tmprepo}" "${commit}" "/usr/lib/os-release" > os-release +mkdir -p "/usr/lib/systemd/boot/efi/" +ostree cat --repo "${tmprepo}" "${commit}" "/usr/lib/systemd/boot/efi/addonx64.efi.stub" > /usr/lib/systemd/boot/efi/addonx64.efi.stub +ostree cat --repo "${tmprepo}" "${commit}" "/usr/lib/systemd/boot/efi/linuxx64.efi.stub" > linuxx64.efi.stub +ostree cat --repo "${tmprepo}" "${commit}" "/usr/lib/systemd/boot/efi/systemd-bootx64.efi" > /usr/lib/systemd/boot/efi/systemd-bootx64.efi +ukify build \ + --linux "vmlinuz" \ + --initrd "initramfs" \ + --cmdline "rw mitigations=auto,nosmt ignition.platform.id=qemu console=tty0 console=ttyS0,115200n8 ostree=/ostree/boot.0/fedora-coreos/$(cat vmlinuz initramfs | sha256sum | awk '{print $1}')/0" \ + --os-release "@os-release" \ + --uname "$kernver" \ + --signtool sbsign \ + --secureboot-private-key "${workdir}/db.key" \ + --secureboot-certificate "${workdir}/db.pem" \ + --output "${workdir}/tmp/uki" \ + --measure +ukify build \ + --linux "vmlinuz" \ + --initrd "initramfs" \ + --cmdline "rw mitigations=auto,nosmt ignition.platform.id=qemu console=tty0 console=ttyS0,115200n8 ostree=/ostree/boot.1/fedora-coreos/$(cat vmlinuz initramfs | sha256sum | awk '{print $1}')/0" \ + --os-release "@os-release" \ + --uname "$kernver" \ + --signtool sbsign \ + --secureboot-private-key "${workdir}/db.key" \ + --secureboot-certificate "${workdir}/db.pem" \ + --output "${workdir}/tmp/uki.1" \ + --measure + +# Sign systemd-boot binary +ostree cat --repo "${tmprepo}" "${commit}" "/usr/lib/systemd/boot/efi/systemd-bootx64.efi" > systemd-bootx64.efi +sbsign \ + --key "${workdir}/db.key" \ + --cert "${workdir}/db.pem" \ + --output "${workdir}/tmp/systemd-bootx64-signed.efi" \ + "/usr/lib/systemd/boot/efi/systemd-bootx64.efi" + +# mkdir -p "ukirootfs/usr/lib/modules/$kernver/" +# mv uki "ukirootfs/usr/lib/modules/$kernver/uki" +# chown 0:0 "ukirootfs/usr/lib/modules/$kernver/uki" +# chmod 644 "ukirootfs/usr/lib/modules/$kernver/uki" + +# ostree_keys=() +# for key in $(ostree show --repo "${tmprepo}" "$commit" --list-metadata-keys); do +# ostree_keys+=("--keep-metadata=$key") +# done + +# commit="$(ostree commit \ +# --repo "${tmprepo}" \ +# --base "$commit" \ +# --parent "$commit" \ +# --branch "fedora/x86_64/coreos/$(basename "$(ls "${tmprepo}/refs/heads/fedora/x86_64/coreos/"*)")" \ +# --subject "$commit + UKI" \ +# --sign-type ed25519 \ +# --sign-from-file="${workdir}/tmp/ostree_signing_key.ed25519" \ +# --generate-composefs-metadata \ +# --bootable \ +# "${ostree_keys[@]}" \ +# ukirootfs)" +# rm -rf ukirootfs + # Very special handling for --write-composejson-to as rpm-ostree doesn't # write it if the commit didn't change. if [ -f "${changed_stamp}" ] && [ -f "${composejson}" ]; then @@ -448,6 +541,17 @@ echo "New build ID: ${buildid}" # Also write out a ref with the build ID ostree --repo="${tmprepo}" refs --create "${buildid}" "${commit}" +# Not sure if we need to add --generate-composefs-metadata as I couldn't find +# any references in ostree man pages. +# is is default since https://github.com/coreos/rpm-ostree/pull/4495/commits/dbe78217c0205dad372c84b2cf0a299003787952 ? + +# TODO +# If composefs signing is enabled, sign the last commit +# if test -n "${SIGN_COMPOSEFS}"; then +# ostree sign --keys-file ${TMPDIR}/cosa_key.ed25519 ${commit} --repo=${tmprepo} +# fi +# TODO + "${dn}"/write-commit-object "${tmprepo}" "${commit}" "$(pwd)" build_timestamp=$(date -u +$RFC3339) @@ -514,6 +618,8 @@ else --label="coreos-assembler.image-input-checksum=${image_input_checksum}" \ --label="org.opencontainers.image.source=${gitsrc}" \ --label="org.opencontainers.image.revision=${config_gitrev}" \ + --label="ostree.commit=${commit}" \ + --label="ostree.commit.composefs.digest=${cfs_sig}" \ --copymeta-opt=fedora-coreos.stream \ "${last_build_manifest[@]}" \ "${labels[@]}" \ diff --git a/src/cmd-buildextend-metal b/src/cmd-buildextend-metal index c7ec9d8795..2bc9f32c07 100755 --- a/src/cmd-buildextend-metal +++ b/src/cmd-buildextend-metal @@ -195,7 +195,7 @@ rootfs_size_mb="$(jq '."estimate-mb".final' "$PWD/tmp/ostree-size.json")" # the size set in the configs since some of them have minimum sizes that # the platforms require and we want a "default" disk size that has some # free space. -nonroot_partition_sizes=513 +nonroot_partition_sizes=2048 # On s390x there is one more build - Secure Execution case, which has # different image layout. We add the sizes of the se and verity # partitions so that they don't "eat into" the 35% buffer (though note diff --git a/src/cmd-fetch b/src/cmd-fetch index 165829b7c4..9a19aeed70 100755 --- a/src/cmd-fetch +++ b/src/cmd-fetch @@ -8,12 +8,12 @@ dn=$(dirname "$0") FILE=cache/pkgcache-repo if [ -d "${FILE}" ] then - pkgcachesize=$(sudo du --bytes --max-depth 0 "${FILE}" \ + pkgcachesize=$( du --bytes --max-depth 0 "${FILE}" \ | awk '{print $1; exit}') pkglimit=$((1024 * 1024 * 1024 * 5)) if [[ "${pkgcachesize}" -gt "${pkglimit}" ]] then - sudo cosa prune --pkgcache + cosa prune --pkgcache fi fi diff --git a/src/cmd-init b/src/cmd-init index 38a6804920..8703fdeb8e 100755 --- a/src/cmd-init +++ b/src/cmd-init @@ -147,7 +147,7 @@ source=$1; shift preflight if has_privileges; then - sudo chown "$USER:" . + chown "$USER:" . elif [ ! -w . ]; then fatal "init: running unprivileged, and current directory not writable" fi diff --git a/src/cmd-prune b/src/cmd-prune index 660eae5790..59092569c5 100755 --- a/src/cmd-prune +++ b/src/cmd-prune @@ -89,7 +89,7 @@ if args.pkgcache: n = len("cache/pkgcache-repo/refs/heads/") if pkg[n:] not in build_pkg: print(f"Deleted {pkg[n:]}") - subprocess.call(f"sudo ostree refs --repo=cache/pkgcache-repo --delete {pkg[n:]}", shell=True) + subprocess.call(f" ostree refs --repo=cache/pkgcache-repo --delete {pkg[n:]}", shell=True) sys.exit(0) diff --git a/src/cmdlib.sh b/src/cmdlib.sh index bc5a07836b..de27ec1a65 100755 --- a/src/cmdlib.sh +++ b/src/cmdlib.sh @@ -56,8 +56,8 @@ has_privileges() { elif ! capsh --print | grep -q 'Bounding.*cap_sys_admin'; then info "Missing CAP_SYS_ADMIN; using virt" COSA_PRIVILEGED=0 - elif [ "$(id -u)" != "0" ] && ! sudo true; then - info "Missing sudo privs; using virt" + elif [ "$(id -u)" != "0" ] && ! true; then + info "Missing privs; using virt" COSA_PRIVILEGED=0 else COSA_PRIVILEGED=1 @@ -113,9 +113,9 @@ preflight_kvm() { if ! has_privileges; then fatal "running unprivileged, and /dev/kvm not writable" else - sudo rm -f /dev/kvm - sudo mknod /dev/kvm c 10 232 - sudo setfacl -m u:"$USER":rw /dev/kvm + rm -f /dev/kvm + mknod /dev/kvm c 10 232 + setfacl -m u:"$USER":rw /dev/kvm fi fi fi @@ -563,8 +563,8 @@ runcompose_tree() { set - "$@" --repo "${repo}" --write-composejson-to "${composejson}" # we hardcode a umask of 0022 here to make sure that composes are run # with a consistent value, regardless of the environment - (umask 0022 && sudo -E "$@") - sudo chown -R -h "${USER}":"${USER}" "${tmprepo}" + (umask 0022 && "$@") + chown -R -h "${USER}":"${USER}" "${tmprepo}" else runvm_with_cache -- "$@" --repo "${repo}" --write-composejson-to "${composejson}" fi @@ -587,8 +587,8 @@ runcompose_extensions() { if has_privileges; then # we hardcode a umask of 0022 here to make sure that composes are run # with a consistent value, regardless of the environment - (umask 0022 && sudo -E "$@") - sudo chown -R -h "${USER}":"${USER}" "${outputdir}" + (umask 0022 && "$@") + chown -R -h "${USER}":"${USER}" "${outputdir}" else # Use a snapshot version of the cache qcow2 to allow multiple users # of the cache at the same time. This is needed because the extensions @@ -1108,3 +1108,25 @@ extract_osrelease_name() { # shellcheck disable=SC1091,SC2153 (. "$out/os-release" && echo "${NAME}") } + + +gen_ed25519_signing_key() { + local key_file="ostree_signing_key" + + # Generate the key + openssl genpkey -algorithm ed25519 -outform PEM -out "${TMPDIR}/${key_file}" + + # Extract the pubkey + local -r pubkey="$(openssl pkey -outform DER -pubout -in "${TMPDIR}/${key_file}" | tail -c 32 | base64)" + + # Write the pubkey in overrides + mkdir -p "${workdir}/overrides/rootfs/etc/ostree/" + echo "$pubkey" > "${workdir}/overrides/rootfs/etc/ostree/initramfs-root-binding.key" + + # Convert the private key to base64 for ostree signing + ## Extract the seed + local -r seed="$(openssl pkey -outform DER -in "${TMPDIR}/${key_file}" | tail -c 32 | base64)" + + ## Secret key is the concatenation of seed and public + echo "${seed}${pubkey}" | base64 -d | base64 -w 0 > "${TMPDIR}/${key_file}.ed25519" +} diff --git a/src/osbuild-manifests/coreos.osbuild.x86_64.mpp.yaml b/src/osbuild-manifests/coreos.osbuild.x86_64.mpp.yaml index bb4f633a19..8a7aba83d4 100644 --- a/src/osbuild-manifests/coreos.osbuild.x86_64.mpp.yaml +++ b/src/osbuild-manifests/coreos.osbuild.x86_64.mpp.yaml @@ -14,8 +14,8 @@ mpp-vars: bios_boot_size_mb: 1 ppc_prep_size_mb: 4 reserved_part_size_mb: 1 - efi_system_size_mb: 127 - boot_size_mb: 384 + efi_system_size_mb: 512 + boot_size_mb: 512 sector_size: 512 four_k_sector_size: 4096 # Filesystem UUID and label definitions. These UUIDs