From 46b00a1ac8024b271a03fdddb65b1d72a3911bb2 Mon Sep 17 00:00:00 2001 From: chaos Date: Mon, 12 Aug 2024 16:52:17 +0100 Subject: [PATCH] seperate out encryptedDrive module & move ssh decrypt into it --- modules/nixos/encryptedDrive.nix | 128 ++---------------- .../nixos/encryptedDriveMod/filesystems.nix | 34 +++++ .../nixos/encryptedDriveMod/kernelModules.nix | 33 +++++ modules/nixos/encryptedDriveMod/options.nix | 35 +++++ .../nixos/encryptedDriveMod/passwordMode.nix | 4 + modules/nixos/encryptedDriveMod/sshMode.nix | 41 ++++++ modules/nixos/encryptedDriveMod/usbMode.nix | 70 ++++++++++ presets/nixos/encryptedDrive.nix | 8 +- presets/nixos/serverEncryptedDrive.nix | 69 +--------- 9 files changed, 233 insertions(+), 189 deletions(-) create mode 100644 modules/nixos/encryptedDriveMod/filesystems.nix create mode 100644 modules/nixos/encryptedDriveMod/kernelModules.nix create mode 100644 modules/nixos/encryptedDriveMod/options.nix create mode 100644 modules/nixos/encryptedDriveMod/passwordMode.nix create mode 100644 modules/nixos/encryptedDriveMod/sshMode.nix create mode 100644 modules/nixos/encryptedDriveMod/usbMode.nix diff --git a/modules/nixos/encryptedDrive.nix b/modules/nixos/encryptedDrive.nix index 38bed04..c905790 100644 --- a/modules/nixos/encryptedDrive.nix +++ b/modules/nixos/encryptedDrive.nix @@ -1,120 +1,10 @@ -{ - self, - config, - lib, - ... -}: let - inherit (lib.modules) mkIf mkBefore; - inherit (lib.options) mkOption mkEnableOption; - inherit (lib) types; - - encryptedUSB = import "${self}/data/drives/encryptedUSB.nix"; - driveData = import "${self}/data/drives/encryptedDrive.nix"; - - cfg = config.boot.encryptedDrive; -in { - options.boot.encryptedDrive = { - enable = mkEnableOption "encrypted drive support for servers and other devices"; - - mode = mkOption { - type = types.enum [ - "encrypted-usb" - "password" - ]; - default = "encrypted-usb"; - }; - - allowPasswordDecrypt = mkOption { - description = "allow fallback to decrypting with a password when using USB based auth, pass cryptsetup_password to kernel cmdline to switch to password input mode"; - type = types.bool; - default = true; - }; - }; - - config = mkIf cfg.enable { - boot = { - initrd.availableKernelModules = [ - # For USB w/ Encryption Key - "usb_storage" - "usbcore" - "uas" - "rtsx_pci_sdmmc" - # For USB Keyboards - "usbhid" - "hid_generic" - # For Cryptography - "aesni_intel" - "cryptd" - "crypto_simd" - ]; - initrd.postDeviceCommands = mkIf (cfg.mode == "encrypted-usb") (mkBefore '' - mkdir -m 0755 -p /keys - mkdir -m 0755 -p ${encryptedUSB.mountpoint} - - ${ - if cfg.allowPasswordDecrypt - then '' - if grep "cryptsetup_password" /proc/cmdline; then - USE_PASSWORD_FALLBACK=true - else - USE_PASSWORD_FALLBACK=false - fi - '' - else '' - USE_PASSWORD_FALLBACK=false - '' - } - - while !(test -b ${encryptedUSB.encryptedPath}) && [ "$USE_PASSWORD_FALLBACK" == "false" ] - do - echo "Please Plug In USB" - sleep 1 - done - - if [ "$USE_PASSWORD_FALLBACK" == "true" ]; then - echo "Please Decrypt Drive" - cryptsetup open ${driveData.encryptedPath} ${driveData.mapperName} - else - echo "Please Decrypt USB" - cryptsetup open ${encryptedUSB.encryptedPath} ${encryptedUSB.preBootMapperName} - fi - - if [ "$USE_PASSWORD_FALLBACK" == "false" ]; then - mount -n -t ${encryptedUSB.unencryptedFSType} -o ro ${encryptedUSB.preBootMapperPath} ${encryptedUSB.mountpoint} - - cp ${encryptedUSB.encryptionKeysPath}/${config.networking.hostName}.key /keys - chmod 0755 /keys/${config.networking.hostName}.key - umount -f ${encryptedUSB.mountpoint} - - cryptsetup close ${encryptedUSB.preBootMapperName} - else - touch /keys/${config.networking.hostName}.key - fi - ''); - initrd.luks.devices = { - "${driveData.mapperName}" = { - device = "${driveData.encryptedPath}"; - keyFile = - if cfg.mode == "encrypted-usb" - then "/keys/${config.networking.hostName}.key" - else null; - preLVM = false; - allowDiscards = true; - # Allows decrypting with a password when key is existant on USB but invalid - fallbackToPassword = cfg.allowPasswordDecrypt; - }; - }; - }; - - fileSystems = { - "/" = { - device = "${driveData.decryptedPath}"; - fsType = "${driveData.unencryptedFSType}"; - }; - "/boot" = { - device = "${driveData.bootPath}"; - fsType = "${driveData.bootFSType}"; - }; - }; - }; +{...}: { + imports = [ + ./encryptedDriveMod/filesystems.nix + ./encryptedDriveMod/kernelModules.nix + ./encryptedDriveMod/options.nix + ./encryptedDriveMod/passwordMode.nix + ./encryptedDriveMod/sshMode.nix + ./encryptedDriveMod/usbMode.nix + ]; } diff --git a/modules/nixos/encryptedDriveMod/filesystems.nix b/modules/nixos/encryptedDriveMod/filesystems.nix new file mode 100644 index 0000000..2f03bf0 --- /dev/null +++ b/modules/nixos/encryptedDriveMod/filesystems.nix @@ -0,0 +1,34 @@ +{ + config, + lib, + self, + ... +}: let + inherit (lib.modules) mkIf; + + driveData = import "${self}/data/drives/encryptedDrive.nix"; + + cfg = config.boot.encryptedDrive; +in { + config = mkIf (cfg.enable) { + boot.initrd.luks.devices = { + "${driveData.mapperName}" = { + device = "${driveData.encryptedPath}"; + preLVM = false; + allowDiscards = true; + fallbackToPassword = cfg.allowPasswordDecrypt; + }; + }; + + fileSystems = { + "/" = { + device = "${driveData.decryptedPath}"; + fsType = "${driveData.unencryptedFSType}"; + }; + "/boot" = { + device = "${driveData.bootPath}"; + fsType = "${driveData.bootFSType}"; + }; + }; + }; +} diff --git a/modules/nixos/encryptedDriveMod/kernelModules.nix b/modules/nixos/encryptedDriveMod/kernelModules.nix new file mode 100644 index 0000000..a7683a0 --- /dev/null +++ b/modules/nixos/encryptedDriveMod/kernelModules.nix @@ -0,0 +1,33 @@ +{ + config, + lib, + pkgs, + ... +}: let + inherit (lib.modules) mkIf; + inherit (lib.lists) flatten optionals; + + cfg = config.boot.encryptedDrive; +in { + config = mkIf (cfg.enable) { + boot.initrd.availableKernelModules = + flatten + [ + # For USB w/ Encryption Key + "usb_storage" + "usbcore" + "uas" + "rtsx_pci_sdmmc" + # For USB Keyboards + "usbhid" + "hid_generic" + # For Cryptography + "cryptd" + "crypto_simd" + + (optionals (pkgs.system == "x86_64_linux") [ + "aesni_intel" + ]) + ]; + }; +} diff --git a/modules/nixos/encryptedDriveMod/options.nix b/modules/nixos/encryptedDriveMod/options.nix new file mode 100644 index 0000000..4cd92da --- /dev/null +++ b/modules/nixos/encryptedDriveMod/options.nix @@ -0,0 +1,35 @@ +{ + self, + config, + lib, + ... +}: let + inherit (lib.modules) mkIf mkBefore; + inherit (lib.options) mkOption mkEnableOption; + inherit (lib.lists) optionals; + inherit (lib) types; + + encryptedUSB = import "${self}/data/drives/encryptedUSB.nix"; + driveData = import "${self}/data/drives/encryptedDrive.nix"; + + cfg = config.boot.encryptedDrive; +in { + options.boot.encryptedDrive = { + enable = mkEnableOption "encrypted drive support for servers and other devices"; + + mode = mkOption { + type = types.enum [ + "encrypted-usb" + "password" + "ssh" + ]; + default = "encrypted-usb"; + }; + + allowPasswordDecrypt = mkOption { + description = "allow fallback to decrypting with a password when using USB based auth, pass cryptsetup_password to kernel cmdline to switch to password input mode"; + type = types.bool; + default = true; + }; + }; +} diff --git a/modules/nixos/encryptedDriveMod/passwordMode.nix b/modules/nixos/encryptedDriveMod/passwordMode.nix new file mode 100644 index 0000000..00f259c --- /dev/null +++ b/modules/nixos/encryptedDriveMod/passwordMode.nix @@ -0,0 +1,4 @@ +{...}: { + # This is the default as implemented by the NixOS LUKS Module + # configured in filesystems.nix +} diff --git a/modules/nixos/encryptedDriveMod/sshMode.nix b/modules/nixos/encryptedDriveMod/sshMode.nix new file mode 100644 index 0000000..b7a2da8 --- /dev/null +++ b/modules/nixos/encryptedDriveMod/sshMode.nix @@ -0,0 +1,41 @@ +{ + config, + lib, + self, + tree, + ... +}: let + inherit (lib.modules) mkIf mkBefore mkDefault mkOverride mkForce; + inherit (lib.options) mkOption mkEnableOption; + inherit (lib.lists) optionals; + inherit (lib) types; + + encryptedUSB = import "${self}/data/drives/encryptedUSB.nix"; + driveData = import "${self}/data/drives/encryptedDrive.nix"; + + cfg = config.boot.encryptedDrive; +in { + config = mkIf (cfg.enable && cfg.mode == "ssh") { + boot.loader.supportsInitrdSecrets = true; + + boot.initrd.secrets = { + # we only support ed25519 for now + "/ssh_host_ed25519_key" = mkForce "/initrd_ssh_host_ed25519_key"; + }; + + boot.initrd.luks.forceLuksSupportInInitrd = true; + + boot.initrd.network = { + enable = true; + ssh = { + enable = true; + port = 22; + authorizedKeys = config.users.users.root.openssh.authorizedKeys.keys; + hostKeys = ["/ssh_host_ed25519_key"]; + }; + postCommands = '' + echo 'cryptsetup-askpass' >> /root/.profile + ''; + }; + }; +} diff --git a/modules/nixos/encryptedDriveMod/usbMode.nix b/modules/nixos/encryptedDriveMod/usbMode.nix new file mode 100644 index 0000000..de1833e --- /dev/null +++ b/modules/nixos/encryptedDriveMod/usbMode.nix @@ -0,0 +1,70 @@ +{ + config, + lib, + self, + ... +}: let + inherit (lib.modules) mkIf mkBefore; + inherit (lib.options) mkOption mkEnableOption; + inherit (lib.lists) optionals; + inherit (lib) types; + + encryptedUSB = import "${self}/data/drives/encryptedUSB.nix"; + driveData = import "${self}/data/drives/encryptedDrive.nix"; + + cfg = config.boot.encryptedDrive; +in { + config = mkIf (cfg.enable && cfg.mode == "encrypted-usb") { + boot = { + initrd.postDeviceCommands = mkBefore '' + mkdir -m 0755 -p /keys + mkdir -m 0755 -p ${encryptedUSB.mountpoint} + + ${ + if cfg.allowPasswordDecrypt + then '' + if grep "cryptsetup_password" /proc/cmdline; then + USE_PASSWORD_FALLBACK=true + else + USE_PASSWORD_FALLBACK=false + fi + '' + else '' + USE_PASSWORD_FALLBACK=false + '' + } + + while !(test -b ${encryptedUSB.encryptedPath}) && [ "$USE_PASSWORD_FALLBACK" == "false" ] + do + echo "Please Plug In USB" + sleep 1 + done + + if [ "$USE_PASSWORD_FALLBACK" == "true" ]; then + echo "Please Decrypt Drive" + cryptsetup open ${driveData.encryptedPath} ${driveData.mapperName} + else + echo "Please Decrypt USB" + cryptsetup open ${encryptedUSB.encryptedPath} ${encryptedUSB.preBootMapperName} + fi + + if [ "$USE_PASSWORD_FALLBACK" == "false" ]; then + mount -n -t ${encryptedUSB.unencryptedFSType} -o ro ${encryptedUSB.preBootMapperPath} ${encryptedUSB.mountpoint} + + cp ${encryptedUSB.encryptionKeysPath}/${config.networking.hostName}.key /keys + chmod 0755 /keys/${config.networking.hostName}.key + umount -f ${encryptedUSB.mountpoint} + + cryptsetup close ${encryptedUSB.preBootMapperName} + else + touch /keys/${config.networking.hostName}.key + fi + ''; + initrd.luks.devices = { + "${driveData.mapperName}" = { + keyFile = "/keys/${config.networking.hostName}.key"; + }; + }; + }; + }; +} diff --git a/presets/nixos/encryptedDrive.nix b/presets/nixos/encryptedDrive.nix index 3126958..26e49fc 100644 --- a/presets/nixos/encryptedDrive.nix +++ b/presets/nixos/encryptedDrive.nix @@ -1,9 +1,7 @@ -{lib, ...}: let - inherit (lib.modules) mkDefault; -in { +{...}: { boot.encryptedDrive = { enable = true; - mode = mkDefault "encrypted-usb"; - allowPasswordDecrypt = mkDefault true; + mode = "encrypted-usb"; + allowPasswordDecrypt = true; }; } diff --git a/presets/nixos/serverEncryptedDrive.nix b/presets/nixos/serverEncryptedDrive.nix index 3654a50..358e5b8 100644 --- a/presets/nixos/serverEncryptedDrive.nix +++ b/presets/nixos/serverEncryptedDrive.nix @@ -1,78 +1,17 @@ { self, - config, tree, - lib, - pkgs, ... }: let - inherit (lib.modules) mkForce; - inherit (lib.lists) optionals; - - inherit (pkgs) system; - driveData = import "${self}/data/drives/encryptedDrive.nix"; in { imports = with tree; [ profiles.nixos.sshd ]; - boot = { - loader.supportsInitrdSecrets = true; - initrd = { - availableKernelModules = - [ - "nvme" - "ahci" - "ehci_pci" - "xhci_pci" - "sd_mod" - "sr_mod" - "usbhid" - "dm_crypt" - "dm_mod" - "cryptd" - ] - ++ (optionals (system == "x86_64_linux") ["aesni_intel"]); - - secrets = { - "/ssh_host_ed25519_key" = mkForce "/initrd_ssh_host_ed25519_key"; - }; - - luks = { - forceLuksSupportInInitrd = true; - devices = { - "${driveData.mapperName}" = { - device = "${driveData.encryptedPath}"; - preLVM = false; - allowDiscards = true; - }; - }; - }; - }; - - initrd.network = { - enable = true; - ssh = { - enable = true; - port = 22; - authorizedKeys = config.users.users.root.openssh.authorizedKeys.keys; - hostKeys = ["/ssh_host_ed25519_key"]; - }; - postCommands = '' - echo 'cryptsetup-askpass' >> /root/.profile - ''; - }; - }; - - fileSystems = { - "/" = { - device = "${driveData.decryptedPath}"; - fsType = "${driveData.unencryptedFSType}"; - }; - "/boot" = { - device = "${driveData.bootPath}"; - fsType = "${driveData.bootFSType}"; - }; + boot.encryptedDrive = { + enable = true; + mode = "ssh"; + allowPasswordDecrypt = true; }; }