mirror of
https://github.com/NixOS/nixpkgs.git
synced 2026-09-29 03:10:19 +00:00
nixos/luksroot: add timeout option for devices (#359882)
This commit is contained in:
@@ -199,6 +199,7 @@ let
|
||||
while true; do
|
||||
echo -n "Passphrase for ${dev.device}: "
|
||||
passphrase=
|
||||
${lib.optionalString (dev.timeout != null) "time_passed=0"}
|
||||
while true; do
|
||||
if [ -e /crypt-ramfs/passphrase ]; then
|
||||
echo "reused"
|
||||
@@ -229,6 +230,13 @@ let
|
||||
echo
|
||||
break
|
||||
fi
|
||||
${lib.optionalString (dev.timeout != null) ''
|
||||
time_passed=$((time_passed + 1))
|
||||
if [ $time_passed -ge ${builtins.toString dev.timeout} ]; then
|
||||
echo "Timeout reached"
|
||||
poweroff -f
|
||||
fi
|
||||
''}
|
||||
fi
|
||||
done
|
||||
echo -n "Verifying passphrase for ${dev.device}..."
|
||||
@@ -328,6 +336,7 @@ let
|
||||
${optionalString dev.yubikey.twoFactor ''
|
||||
echo -n "Enter two-factor passphrase: "
|
||||
k_user=
|
||||
${lib.optionalString (dev.timeout != null) "time_passed=0"}
|
||||
while true; do
|
||||
if [ -e /crypt-ramfs/passphrase ]; then
|
||||
echo "reused"
|
||||
@@ -351,6 +360,13 @@ let
|
||||
echo
|
||||
break
|
||||
fi
|
||||
${lib.optionalString (dev.timeout != null) ''
|
||||
time_passed=$((time_passed + 1))
|
||||
if [ $time_passed -ge ${builtins.toString dev.timeout} ]; then
|
||||
echo "Timeout reached"
|
||||
poweroff -f
|
||||
fi
|
||||
''}
|
||||
fi
|
||||
done
|
||||
''}
|
||||
@@ -451,6 +467,7 @@ let
|
||||
for try in $(seq 3); do
|
||||
echo -n "PIN for GPG Card associated with device ${dev.device}: "
|
||||
pin=
|
||||
${lib.optionalString (dev.timeout != null) "time_passed=0"}
|
||||
while true; do
|
||||
if [ -e /crypt-ramfs/passphrase ]; then
|
||||
echo "reused"
|
||||
@@ -474,6 +491,13 @@ let
|
||||
echo
|
||||
break
|
||||
fi
|
||||
${lib.optionalString (dev.timeout != null) ''
|
||||
time_passed=$((time_passed + 1))
|
||||
if [ $time_passed -ge ${builtins.toString dev.timeout} ]; then
|
||||
echo "Timeout reached"
|
||||
poweroff -f
|
||||
fi
|
||||
''}
|
||||
fi
|
||||
done
|
||||
echo -n "Verifying passphrase for ${dev.device}..."
|
||||
@@ -523,8 +547,22 @@ let
|
||||
''
|
||||
else
|
||||
''
|
||||
read -rsp "FIDO2 salt for ${dev.device}: " passphrase
|
||||
echo
|
||||
${lib.optionalString (dev.timeout != null) "time_passed=0"}
|
||||
echo -n "FIDO2 salt for ${dev.device}: "
|
||||
while true; do
|
||||
IFS= read -t 1 -rs passphrase
|
||||
if [ -n "$passphrase" ]; then
|
||||
echo
|
||||
break
|
||||
fi
|
||||
${lib.optionalString (dev.timeout != null) ''
|
||||
time_passed=$((time_passed + 1))
|
||||
if [ $time_passed -ge ${builtins.toString dev.timeout} ]; then
|
||||
echo "Timeout reached"
|
||||
poweroff -f
|
||||
fi
|
||||
''}
|
||||
done
|
||||
''
|
||||
}
|
||||
${optionalString (lib.versionOlder kernelPackages.kernel.version "5.4") ''
|
||||
@@ -562,27 +600,62 @@ let
|
||||
${dev.postOpenCommands}
|
||||
'';
|
||||
|
||||
askPass = pkgs.writeScriptBin "cryptsetup-askpass" ''
|
||||
#!/bin/sh
|
||||
askPass =
|
||||
let
|
||||
configHasTimeouts = lib.any (dev: dev.timeout != null) (lib.attrValues luks.devices);
|
||||
in
|
||||
pkgs.writeScriptBin "cryptsetup-askpass" ''
|
||||
#!/bin/sh
|
||||
|
||||
${commonFunctions}
|
||||
${commonFunctions}
|
||||
|
||||
while true; do
|
||||
wait_target "luks" /crypt-ramfs/device 10 "LUKS to request a passphrase" || die "Passphrase is not requested now"
|
||||
device=$(cat /crypt-ramfs/device)
|
||||
get_timeout_for_device() {
|
||||
${lib.pipe luks.devices [
|
||||
(lib.filterAttrs (name: dev: dev.timeout != luks.timeout))
|
||||
(lib.mapAttrsToList (
|
||||
name: dev: ''
|
||||
if [ "$1" = "${lib.escapeShellArg dev.device}" ]; then
|
||||
echo "${toString dev.timeout}"
|
||||
return
|
||||
fi
|
||||
''
|
||||
))
|
||||
(lib.concatStringsSep "\n")
|
||||
]}
|
||||
echo "${builtins.toString luks.timeout}"
|
||||
}
|
||||
|
||||
echo -n "Passphrase for $device: "
|
||||
IFS= read -rs passphrase
|
||||
ret=$?
|
||||
echo
|
||||
if [ $ret -ne 0 ]; then
|
||||
die "End of file reached. Exiting shell."
|
||||
fi
|
||||
while true; do
|
||||
wait_target "luks" /crypt-ramfs/device 10 "LUKS to request a passphrase" || die "Passphrase is not requested now"
|
||||
device=$(cat /crypt-ramfs/device)
|
||||
${lib.optionalString configHasTimeouts "time_passed=0"}
|
||||
timeout=$(get_timeout_for_device $device)
|
||||
|
||||
rm /crypt-ramfs/device
|
||||
echo -n "$passphrase" > /crypt-ramfs/passphrase
|
||||
done
|
||||
'';
|
||||
echo -n "Passphrase for $device: "
|
||||
while true; do
|
||||
IFS= read -t 1 -r passphrase
|
||||
ret=$?
|
||||
if [ $ret -eq 1 ]; then
|
||||
echo
|
||||
die "End of file reached. Exiting shell."
|
||||
fi
|
||||
if [ -n "$passphrase" ]; then
|
||||
echo
|
||||
break
|
||||
fi
|
||||
${lib.optionalString configHasTimeouts ''
|
||||
time_passed=$((time_passed + 1))
|
||||
if [ $timeout -gt 0 && $time_passed -ge $timeout ]; then
|
||||
echo "Timeout reached"
|
||||
poweroff -f
|
||||
fi
|
||||
''}
|
||||
done
|
||||
|
||||
rm /crypt-ramfs/device
|
||||
echo -n "$passphrase" > /crypt-ramfs/passphrase
|
||||
done
|
||||
'';
|
||||
|
||||
preLVM = filterAttrs (n: v: v.preLVM) luks.devices;
|
||||
postLVM = filterAttrs (n: v: !v.preLVM) luks.devices;
|
||||
@@ -1015,6 +1088,16 @@ in
|
||||
Extra options to append to the last column of the generated crypttab file.
|
||||
'';
|
||||
};
|
||||
|
||||
timeout = mkOption {
|
||||
type = types.nullOr types.ints.positive;
|
||||
default = luks.timeout;
|
||||
defaultText = "{option}`boot.initrd.luks.timeout`";
|
||||
description = ''
|
||||
The amount of time in seconds to wait on the passphrase prompt.
|
||||
If the timeout is reached, the system will power off.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf (clevis.enable && (hasAttr name clevis.devices)) {
|
||||
@@ -1060,6 +1143,15 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
boot.initrd.luks.timeout = mkOption {
|
||||
type = types.nullOr types.ints.positive;
|
||||
default = null;
|
||||
description = ''
|
||||
The amount of time in seconds to wait on the passphrase prompt.
|
||||
If the timeout is reached, the system will power off.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
config = mkIf (luks.devices != { } || luks.forceLuksSupportInInitrd) {
|
||||
@@ -1251,42 +1343,58 @@ in
|
||||
boot.initrd.systemd.services =
|
||||
let
|
||||
devicesWithClevis = filterAttrs (device: _: (hasAttr device clevis.devices)) luks.devices;
|
||||
devicesWithTimeout = filterAttrs (_: dev: dev.timeout != null) luks.devices;
|
||||
in
|
||||
mkIf (clevis.enable && systemd.enable) (
|
||||
mapAttrs' (
|
||||
name: _:
|
||||
nameValuePair "cryptsetup-clevis-${name}" {
|
||||
wantedBy = [ "systemd-cryptsetup@${utils.escapeSystemdPath name}.service" ];
|
||||
before = [
|
||||
"systemd-cryptsetup@${utils.escapeSystemdPath name}.service"
|
||||
"initrd-switch-root.target"
|
||||
"shutdown.target"
|
||||
];
|
||||
wants = optional clevis.useTang "network-online.target";
|
||||
after = [
|
||||
"systemd-modules-load.service"
|
||||
"tpm2.target"
|
||||
]
|
||||
++ optional clevis.useTang "network-online.target";
|
||||
script = ''
|
||||
mkdir -p /clevis-${name}
|
||||
mount -t ramfs none /clevis-${name}
|
||||
umask 277
|
||||
clevis decrypt < /etc/clevis/${name}.jwe > /clevis-${name}/decrypted
|
||||
'';
|
||||
conflicts = [
|
||||
"initrd-switch-root.target"
|
||||
"shutdown.target"
|
||||
];
|
||||
unitConfig.DefaultDependencies = "no";
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
ExecStop = "${config.boot.initrd.systemd.package.util-linux}/bin/umount /clevis-${name}";
|
||||
};
|
||||
}
|
||||
) devicesWithClevis
|
||||
);
|
||||
mkMerge [
|
||||
(mkIf (clevis.enable && systemd.enable) (
|
||||
mapAttrs' (
|
||||
name: _:
|
||||
nameValuePair "cryptsetup-clevis-${name}" {
|
||||
wantedBy = [ "systemd-cryptsetup@${utils.escapeSystemdPath name}.service" ];
|
||||
before = [
|
||||
"systemd-cryptsetup@${utils.escapeSystemdPath name}.service"
|
||||
"initrd-switch-root.target"
|
||||
"shutdown.target"
|
||||
];
|
||||
wants = optional clevis.useTang "network-online.target";
|
||||
after = [
|
||||
"systemd-modules-load.service"
|
||||
"tpm2.target"
|
||||
]
|
||||
++ optional clevis.useTang "network-online.target";
|
||||
script = ''
|
||||
mkdir -p /clevis-${name}
|
||||
mount -t ramfs none /clevis-${name}
|
||||
umask 277
|
||||
clevis decrypt < /etc/clevis/${name}.jwe > /clevis-${name}/decrypted
|
||||
'';
|
||||
conflicts = [
|
||||
"initrd-switch-root.target"
|
||||
"shutdown.target"
|
||||
];
|
||||
unitConfig.DefaultDependencies = "no";
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
ExecStop = "${config.boot.initrd.systemd.package.util-linux}/bin/umount /clevis-${name}";
|
||||
};
|
||||
}
|
||||
) devicesWithClevis
|
||||
))
|
||||
|
||||
(mkIf systemd.enable (
|
||||
mapAttrs' (
|
||||
name: dev:
|
||||
nameValuePair "systemd-cryptsetup@${utils.escapeSystemdPath name}" {
|
||||
overrideStrategy = "asDropin";
|
||||
unitConfig = {
|
||||
JobTimeoutSec = dev.timeout;
|
||||
JobTimeoutAction = "poweroff";
|
||||
};
|
||||
}
|
||||
) devicesWithTimeout
|
||||
))
|
||||
];
|
||||
|
||||
environment.systemPackages = [ pkgs.cryptsetup ];
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user