diff --git a/flake.nix b/flake.nix index 2358ab1..7c17fff 100644 --- a/flake.nix +++ b/flake.nix @@ -18,11 +18,12 @@ pkgs = import nixpkgs { inherit system; }; patosPkgs = self.packages.${system}; version = "0.0.1"; + updateUrl = "http://10.0.2.2:8000"; in { packages = { default = patosPkgs.image; - image = pkgs.callPackage ./pkgs/image { inherit patosPkgs version; }; + image = pkgs.callPackage ./pkgs/image { inherit patosPkgs version updateUrl; }; rootfs = pkgs.callPackage ./pkgs/rootfs/mkrootfs.nix { inherit patosPkgs version; }; initrd = pkgs.callPackage ./pkgs/rootfs/mkinitrd.nix { inherit patosPkgs version; }; kernel = pkgs.callPackage ./pkgs/kernel { }; diff --git a/pkgs/image/default.nix b/pkgs/image/default.nix index 2084901..8f3acbf 100644 --- a/pkgs/image/default.nix +++ b/pkgs/image/default.nix @@ -3,13 +3,14 @@ patosPkgs, version, runCommand, - ... + updateUrl }: let pname = "patos-image"; in runCommand pname { inherit version; + inherit updateUrl; buildInputs = with pkgs; [ erofs-utils @@ -24,7 +25,7 @@ runCommand pname { SYSTEMD_REPART_MKFS_OPTIONS_EROFS = "--all-root"; # -zlz4hc,12 -C1048576 -Efragments,dedupe,ztailpacking"; }; - kernelCmdLine = "console=ttyS0"; + kernelCmdLine = "console=ttyS0 patos.secureboot=true"; } '' mkdir -p $out/init.repart.d $out/final.repart.d @@ -70,6 +71,63 @@ ExecStartPost=rm -rf /boot/sbctl EOF ln -sf ../secure-boot-import-keys.service rootfs/usr/lib/systemd/system/sysinit.target.wants/secure-boot-import-keys.service +# sysupdate +mkdir -p rootfs/etc/sysupdate.d +cat <<EOF > rootfs/etc/sysupdate.d/10-uki.transfer +[Source] +Path=${updateUrl} +MatchPattern=patos_@v.efi +Type=url-file + +[Target] +InstancesMax=2 +MatchPattern=patos_@v+@l-@d.efi patos_@v+@l.efi patos_@v.efi +Mode=0444 +Path=/EFI/Linux +PathRelativeTo=esp +TriesDone=0 +TriesLeft=3 +Type=regular-file + +[Transfer] +Verify=no +EOF + +cat <<EOF > rootfs/etc/sysupdate.d/20-root.transfer +[Source] +Type=url-file +Path=${updateUrl} +MatchPattern=patos_@v_@u.verity + +[Target] +Type=partition +Path=auto +MatchPattern=verity-@v +MatchPartitionType=root-verity +ReadOnly=1 + +[Transfer] +Verify=no +EOF + +cat <<EOF > rootfs/etc/sysupdate.d/22-root.transfer +[Source] +Type=url-file +Path=${updateUrl} +MatchPattern=patos_@v_@u.root + +[Target] +Type=partition +Path=auto +MatchPattern=root-@v +MatchPartitionType=root +ReadOnly=1 + +[Transfer] +Verify=no +EOF + + # Initial partitioning cat <<EOF > init.repart.d/10-root.conf [Partition] @@ -146,8 +204,8 @@ cat <<EOF > final.repart.d/10-esp.conf [Partition] Type=esp Format=vfat -SizeMinBytes=96M -SizeMaxBytes=96M +SizeMinBytes=128M +SizeMaxBytes=128M CopyFiles=/rootfs/boot:/ EOF diff --git a/pkgs/rootfs/mkinitrd.nix b/pkgs/rootfs/mkinitrd.nix index 5cc6411..10399a6 100644 --- a/pkgs/rootfs/mkinitrd.nix +++ b/pkgs/rootfs/mkinitrd.nix @@ -4,7 +4,12 @@ runCommand, ... }: +let + secureBootEnroll = ./secure-boot-enroll.sh; +in runCommand "patos-initrd" { + inherit secureBootEnroll; + buildInputs = with pkgs; [ cpio xz @@ -32,31 +37,7 @@ ln -sf /etc/os-release ./etc/initrd-release ln -sf initrd.target ./usr/lib/systemd/system/default.target # setup secure boot -cat <<EOF > ./usr/bin/secure-boot-enroll -#!/bin/sh -set -ex -o pipefail - -SETUP_MODE=\$(sbctl status --json | xq -r '.setup_mode') - -[ "\$SETUP_MODE" = "false" ] && exit 0 - -cat <<EOL> /run/sbctl.yml ---- -keydir: /sysroot/boot/sbctl/keys -guid: /sysroot/boot/sbctl/GUID -EOL - -ESP=\$(blkid --label ESP) - -mount \$ESP /sysroot/boot && \ - sbctl --config /run/sbctl.yml create-keys && \ - sbctl --config /run/sbctl.yml enroll-keys --yolo && \ - # Sign EFIs - find /sysroot/boot -type f \( -iname "*.efi" -o -iname "*.EFI" \) -print0 | xargs -I {} sbctl --config /run/sbctl.yml sign {} - -umount /sysroot/boot && \ - systemctl reboot -f -EOF +cat $secureBootEnroll > ./usr/bin/secure-boot-enroll chmod +x ./usr/bin/secure-boot-enroll cat <<EOF > ./usr/lib/systemd/system/secure-boot-enroll.service diff --git a/pkgs/rootfs/mkrootfs.nix b/pkgs/rootfs/mkrootfs.nix index f98a219..61e99d1 100644 --- a/pkgs/rootfs/mkrootfs.nix +++ b/pkgs/rootfs/mkrootfs.nix @@ -74,8 +74,8 @@ cat <<EOF > $out/etc/repart.d/10-esp.conf [Partition] Type=esp Format=vfat -SizeMaxBytes=96M -SizeMinBytes=96M +SizeMaxBytes=128M +SizeMinBytes=128M EOF cat <<EOF > $out/etc/repart.d/20-root-a.conf @@ -178,7 +178,12 @@ cp -P ${pkgs.libbpf}/lib/libbpf*.so* $out/usr/lib/ cp -P ${pkgs.sbctl}/bin/sbctl $out/usr/bin/ rm -f $out/usr/bin/blkid cp -P ${pkgs.util-linuxMinimal}/bin/blkid $out/usr/bin/ +cp -P ${pkgs.util-linuxMinimal}/bin/lsblk $out/usr/bin/ +cp -P ${pkgs.bash}/bin/bash $out/usr/bin/ + +### install xq (jq clone) cp -P ${pkgs.xq}/bin/xq $out/usr/bin/ +ln -sf /usr/bin/xq $out/usr/bin/jq ### install ca cert bundle chmod 755 $out/etc/ssl $out/etc/ssl/certs diff --git a/pkgs/rootfs/secure-boot-enroll.sh b/pkgs/rootfs/secure-boot-enroll.sh new file mode 100644 index 0000000..9546027 --- /dev/null +++ b/pkgs/rootfs/secure-boot-enroll.sh @@ -0,0 +1,37 @@ +#!/bin/bash +set -ex -uo pipefail + +enroll= +for o in $(< /proc/cmdline); do + case $o in + patos.secureboot=*) + enroll=${o#*=} + ;; + esac +done + +if [ -z "$enroll" ]; then + echo 'No patos.secureboot= parameter on the kernel command line' >&2 + exit 0 +fi + +SETUP_MODE=$(sbctl status --json | jq -r '.setup_mode') + +[ "$SETUP_MODE" = "false" -o "$enroll" != "true" ] && exit 0 + +cat <<EOL> /run/sbctl.yml +--- +keydir: /sysroot/boot/sbctl/keys +guid: /sysroot/boot/sbctl/GUID +EOL + +ESP=$(blkid --label ESP) + +mount $ESP /sysroot/boot && \ + sbctl --config /run/sbctl.yml create-keys && \ + sbctl --config /run/sbctl.yml enroll-keys --yolo && \ + # Sign EFIs + find /sysroot/boot -type f \( -iname "*.efi" -o -iname "*.EFI" \) -print0 | xargs -I {} sbctl --config /run/sbctl.yml sign {} + +umount /sysroot/boot && \ + systemctl reboot -f