diff options
author | Will Fancher <elvishjerricco@gmail.com> | 2022-12-29 00:00:29 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-12-29 00:00:29 -0500 |
commit | 3d7270abd5b28bc8ef6c64a7eb15f41bdc9717f0 (patch) | |
tree | 1bbf4db316112ef6e28aa2077d260d2a1e70f7f3 | |
parent | 61345687940092e1cfda9aae7aec152a5a716063 (diff) | |
parent | 51809df3028ad65ff81b2badf7fef04bd9ed5921 (diff) | |
download | nixpkgs-3d7270abd5b28bc8ef6c64a7eb15f41bdc9717f0.tar nixpkgs-3d7270abd5b28bc8ef6c64a7eb15f41bdc9717f0.tar.gz nixpkgs-3d7270abd5b28bc8ef6c64a7eb15f41bdc9717f0.tar.bz2 nixpkgs-3d7270abd5b28bc8ef6c64a7eb15f41bdc9717f0.tar.lz nixpkgs-3d7270abd5b28bc8ef6c64a7eb15f41bdc9717f0.tar.xz nixpkgs-3d7270abd5b28bc8ef6c64a7eb15f41bdc9717f0.tar.zst nixpkgs-3d7270abd5b28bc8ef6c64a7eb15f41bdc9717f0.zip |
Merge pull request #203171 from ElvishJerricco/zfs-fix-requested-credentials
nixos/zfs: Ensure pool has datasets to decrypt
-rw-r--r-- | nixos/modules/tasks/filesystems/zfs.nix | 25 | ||||
-rw-r--r-- | nixos/tests/zfs.nix | 174 |
2 files changed, 126 insertions, 73 deletions
diff --git a/nixos/modules/tasks/filesystems/zfs.nix b/nixos/modules/tasks/filesystems/zfs.nix index 0f14f2b501c..6c775964751 100644 --- a/nixos/modules/tasks/filesystems/zfs.nix +++ b/nixos/modules/tasks/filesystems/zfs.nix @@ -97,10 +97,15 @@ let in map (x: "${mountPoint x}.mount") (getPoolFilesystems pool); - getKeyLocations = pool: - if isBool cfgZfs.requestEncryptionCredentials - then "${cfgZfs.package}/sbin/zfs list -rHo name,keylocation,keystatus ${pool}" - else "${cfgZfs.package}/sbin/zfs list -Ho name,keylocation,keystatus ${toString (filter (x: datasetToPool x == pool) cfgZfs.requestEncryptionCredentials)}"; + getKeyLocations = pool: if isBool cfgZfs.requestEncryptionCredentials then { + hasKeys = cfgZfs.requestEncryptionCredentials; + command = "${cfgZfs.package}/sbin/zfs list -rHo name,keylocation,keystatus ${pool}"; + } else let + keys = filter (x: datasetToPool x == pool) cfgZfs.requestEncryptionCredentials; + in { + hasKeys = keys != []; + command = "${cfgZfs.package}/sbin/zfs list -Ho name,keylocation,keystatus ${toString keys}"; + }; createImportService = { pool, systemd, force, prefix ? "" }: nameValuePair "zfs-import-${pool}" { @@ -124,7 +129,9 @@ let RemainAfterExit = true; }; environment.ZFS_FORCE = optionalString force "-f"; - script = (importLib { + script = let + keyLocations = getKeyLocations pool; + in (importLib { # See comments at importLib definition. zpoolCmd = "${cfgZfs.package}/sbin/zpool"; awkCmd = "${pkgs.gawk}/bin/awk"; @@ -139,10 +146,8 @@ let done poolImported "${pool}" || poolImport "${pool}" # Try one last time, e.g. to import a degraded pool. if poolImported "${pool}"; then - ${optionalString (if isBool cfgZfs.requestEncryptionCredentials - then cfgZfs.requestEncryptionCredentials - else cfgZfs.requestEncryptionCredentials != []) '' - ${getKeyLocations pool} | while IFS=$'\t' read ds kl ks; do + ${optionalString keyLocations.hasKeys '' + ${keyLocations.command} | while IFS=$'\t' read ds kl ks; do { if [[ "$ks" != unavailable ]]; then continue @@ -565,7 +570,7 @@ in '' else concatMapStrings (fs: '' zfs load-key -- ${escapeShellArg fs} - '') cfgZfs.requestEncryptionCredentials} + '') (filter (x: datasetToPool x == pool) cfgZfs.requestEncryptionCredentials)} '') rootPools)); # Systemd in stage 1 diff --git a/nixos/tests/zfs.nix b/nixos/tests/zfs.nix index 29df691cecb..3e55369daa0 100644 --- a/nixos/tests/zfs.nix +++ b/nixos/tests/zfs.nix @@ -17,103 +17,151 @@ let makeTest { name = "zfs-" + name; meta = with pkgs.lib.maintainers; { - maintainers = [ adisbladis ]; + maintainers = [ adisbladis elvishjerricco ]; }; nodes.machine = { pkgs, lib, ... }: let usersharePath = "/var/lib/samba/usershares"; in { - virtualisation.emptyDiskImages = [ 4096 ]; + virtualisation = { + emptyDiskImages = [ 4096 4096 ]; + useBootLoader = true; + useEFIBoot = true; + }; + boot.loader.systemd-boot.enable = true; + boot.loader.timeout = 0; + boot.loader.efi.canTouchEfiVariables = true; networking.hostId = "deadbeef"; boot.kernelPackages = kernelPackage; boot.supportedFilesystems = [ "zfs" ]; boot.zfs.enableUnstable = enableUnstable; - services.samba = { - enable = true; - extraConfig = '' - registry shares = yes - usershare path = ${usersharePath} - usershare allow guests = yes - usershare max shares = 100 - usershare owner only = no - ''; + environment.systemPackages = [ pkgs.parted ]; + + # /dev/disk/by-id doesn't get populated in the NixOS test framework + boot.zfs.devNodes = "/dev/disk/by-uuid"; + + specialisation.samba.configuration = { + services.samba = { + enable = true; + extraConfig = '' + registry shares = yes + usershare path = ${usersharePath} + usershare allow guests = yes + usershare max shares = 100 + usershare owner only = no + ''; + }; + systemd.services.samba-smbd.serviceConfig.ExecStartPre = + "${pkgs.coreutils}/bin/mkdir -m +t -p ${usersharePath}"; + virtualisation.fileSystems = { + "/tmp/mnt" = { + device = "rpool/root"; + fsType = "zfs"; + }; + }; }; - systemd.services.samba-smbd.serviceConfig.ExecStartPre = - "${pkgs.coreutils}/bin/mkdir -m +t -p ${usersharePath}"; - environment.systemPackages = [ pkgs.parted ]; + specialisation.encryption.configuration = { + boot.zfs.requestEncryptionCredentials = [ "automatic" ]; + virtualisation.fileSystems."/automatic" = { + device = "automatic"; + fsType = "zfs"; + }; + virtualisation.fileSystems."/manual" = { + device = "manual"; + fsType = "zfs"; + }; + virtualisation.fileSystems."/manual/encrypted" = { + device = "manual/encrypted"; + fsType = "zfs"; + options = [ "noauto" ]; + }; + }; - # Setup regular fileSystems machinery to ensure forceImportAll can be - # tested via the regular service units. - virtualisation.fileSystems = { - "/forcepool" = { + specialisation.forcepool.configuration = { + systemd.services.zfs-import-forcepool.wantedBy = lib.mkVMOverride [ "forcepool.mount" ]; + systemd.targets.zfs.wantedBy = lib.mkVMOverride []; + boot.zfs.forceImportAll = true; + virtualisation.fileSystems."/forcepool" = { device = "forcepool"; fsType = "zfs"; options = [ "noauto" ]; }; }; - - # forcepool doesn't exist at first boot, and we need to manually test - # the import after tweaking the hostId. - systemd.services.zfs-import-forcepool.wantedBy = lib.mkVMOverride []; - systemd.targets.zfs.wantedBy = lib.mkVMOverride []; - boot.zfs.forceImportAll = true; - # /dev/disk/by-id doesn't get populated in the NixOS test framework - boot.zfs.devNodes = "/dev/disk/by-uuid"; }; testScript = '' + machine.wait_for_unit("multi-user.target") machine.succeed( - "modprobe zfs", "zpool status", - "ls /dev", - "mkdir /tmp/mnt", - "udevadm settle", - "parted --script /dev/vdb mklabel msdos", - "parted --script /dev/vdb -- mkpart primary 1024M -1s", - "udevadm settle", - "zpool create rpool /dev/vdb1", - "zfs create -o mountpoint=legacy rpool/root", - # shared datasets cannot have legacy mountpoint - "zfs create rpool/shared_smb", - "mount -t zfs rpool/root /tmp/mnt", - "udevadm settle", - # wait for samba services - "systemctl is-system-running --wait", - "zfs set sharesmb=on rpool/shared_smb", - "zfs share rpool/shared_smb", - "smbclient -gNL localhost | grep rpool_shared_smb", - "umount /tmp/mnt", - "zpool destroy rpool", - "udevadm settle", + "parted --script /dev/vdc mklabel msdos", + "parted --script /dev/vdc -- mkpart primary 1024M -1s", + "parted --script /dev/vdd mklabel msdos", + "parted --script /dev/vdd -- mkpart primary 1024M -1s", ) - machine.succeed( - 'echo password | zpool create -o altroot="/tmp/mnt" ' - + "-O encryption=aes-256-gcm -O keyformat=passphrase rpool /dev/vdb1", - "zfs create -o mountpoint=legacy rpool/root", - "mount -t zfs rpool/root /tmp/mnt", - "udevadm settle", - "umount /tmp/mnt", - "zpool destroy rpool", - "udevadm settle", - ) + with subtest("sharesmb works"): + machine.succeed( + "zpool create rpool /dev/vdc1", + "zfs create -o mountpoint=legacy rpool/root", + # shared datasets cannot have legacy mountpoint + "zfs create rpool/shared_smb", + "bootctl set-default nixos-generation-1-specialisation-samba.conf", + "sync", + ) + machine.crash() + machine.wait_for_unit("multi-user.target") + machine.succeed( + "zfs set sharesmb=on rpool/shared_smb", + "zfs share rpool/shared_smb", + "smbclient -gNL localhost | grep rpool_shared_smb", + "umount /tmp/mnt", + "zpool destroy rpool", + ) + + with subtest("encryption works"): + machine.succeed( + 'echo password | zpool create -O mountpoint=legacy ' + + "-O encryption=aes-256-gcm -O keyformat=passphrase automatic /dev/vdc1", + "zpool create -O mountpoint=legacy manual /dev/vdd1", + "echo otherpass | zfs create " + + "-o encryption=aes-256-gcm -o keyformat=passphrase manual/encrypted", + "bootctl set-default nixos-generation-1-specialisation-encryption.conf", + "sync", + "zpool export automatic", + "zpool export manual", + ) + machine.crash() + machine.start() + machine.wait_for_console_text("Starting password query on") + machine.send_console("password\n") + machine.wait_for_unit("multi-user.target") + machine.succeed( + "zfs get keystatus manual/encrypted | grep unavailable", + "echo otherpass | zfs load-key manual/encrypted", + "systemctl start manual-encrypted.mount", + "umount /automatic /manual/encrypted /manual", + "zpool destroy automatic", + "zpool destroy manual", + ) with subtest("boot.zfs.forceImportAll works"): machine.succeed( "rm /etc/hostid", "zgenhostid deadcafe", - "zpool create forcepool /dev/vdb1 -O mountpoint=legacy", + "zpool create forcepool /dev/vdc1 -O mountpoint=legacy", + "bootctl set-default nixos-generation-1-specialisation-forcepool.conf", + "rm /etc/hostid", + "sync", ) - machine.shutdown() - machine.start() - machine.succeed("udevadm settle") + machine.crash() + machine.wait_for_unit("multi-user.target") machine.fail("zpool import forcepool") machine.succeed( - "systemctl start zfs-import-forcepool.service", - "mount -t zfs forcepool /tmp/mnt", + "systemctl start forcepool.mount", + "mount | grep forcepool", ) '' + extraTest; |