seperate out encryptedDrive module & move ssh decrypt into it

This commit is contained in:
chaos 2024-08-12 16:52:17 +01:00
parent c2594dbc3b
commit 46b00a1ac8
No known key found for this signature in database
9 changed files with 233 additions and 189 deletions

View file

@ -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"
{...}: {
imports = [
./encryptedDriveMod/filesystems.nix
./encryptedDriveMod/kernelModules.nix
./encryptedDriveMod/options.nix
./encryptedDriveMod/passwordMode.nix
./encryptedDriveMod/sshMode.nix
./encryptedDriveMod/usbMode.nix
];
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}";
};
};
};
}

View file

@ -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}";
};
};
};
}

View file

@ -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"
])
];
};
}

View file

@ -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;
};
};
}

View file

@ -0,0 +1,4 @@
{...}: {
# This is the default as implemented by the NixOS LUKS Module
# configured in filesystems.nix
}

View file

@ -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
'';
};
};
}

View file

@ -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";
};
};
};
};
}

View file

@ -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;
};
}

View file

@ -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 = {
boot.encryptedDrive = {
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}";
};
mode = "ssh";
allowPasswordDecrypt = true;
};
}