Skip to content

Commit e9f1c78

Browse files
committed
add wip verity
1 parent d32f2d1 commit e9f1c78

File tree

1 file changed

+195
-0
lines changed

1 file changed

+195
-0
lines changed

lib/types/verity.nix

+195
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
{ config, options, lib, diskoLib, parent, device, ... }:
2+
let
3+
keyFile =
4+
if config.settings ? "keyFile"
5+
then config.settings.keyFile
6+
else if config.askPassword
7+
then ''<(set +x; echo -n "$password"; set -x)''
8+
else if config.passwordFile != null
9+
# do not print the password to the console
10+
then ''<(set +x; echo -n "$(cat ${config.passwordFile})"; set -x)''
11+
else if config.keyFile != null
12+
then
13+
lib.warn
14+
("The option `keyFile` is deprecated."
15+
+ "Use passwordFile instead if you want to use interactive login or settings.keyFile if you want to use key file login")
16+
config.keyFile
17+
else null;
18+
keyFileArgs = ''
19+
${lib.optionalString (keyFile != null) "--key-file ${keyFile}"} \
20+
${lib.optionalString (lib.hasAttr "keyFileSize" config.settings) "--keyfile-size ${builtins.toString config.settings.keyFileSize}"} \
21+
${lib.optionalString (lib.hasAttr "keyFileOffset" config.settings) "--keyfile-offset ${builtins.toString config.settings.keyFileOffset}"} \
22+
'';
23+
cryptsetupOpen = ''
24+
cryptsetup open "${config.device}" "${config.name}" \
25+
${lib.optionalString (config.settings.allowDiscards or false) "--allow-discards"} \
26+
${lib.optionalString (config.settings.bypassWorkqueues or false) "--perf-no_read_workqueue --perf-no_write_workqueue"} \
27+
${toString config.extraOpenArgs} \
28+
${keyFileArgs} \
29+
'';
30+
in
31+
{
32+
options = {
33+
type = lib.mkOption {
34+
type = lib.types.enum [ "luks" ];
35+
internal = true;
36+
description = "Type";
37+
};
38+
device = lib.mkOption {
39+
type = lib.types.str;
40+
description = "Device to encrypt";
41+
default = device;
42+
};
43+
name = lib.mkOption {
44+
type = lib.types.str;
45+
description = "Name of the LUKS";
46+
};
47+
keyFile = lib.mkOption {
48+
type = lib.types.nullOr diskoLib.optionTypes.absolute-pathname;
49+
default = null;
50+
description = "DEPRECATED use passwordFile or settings.keyFile. Path to the key for encryption";
51+
example = "/tmp/disk.key";
52+
};
53+
passwordFile = lib.mkOption {
54+
type = lib.types.nullOr diskoLib.optionTypes.absolute-pathname;
55+
default = null;
56+
description = "Path to the file which contains the password for initial encryption";
57+
example = "/tmp/disk.key";
58+
};
59+
askPassword = lib.mkOption {
60+
type = lib.types.bool;
61+
default = config.keyFile == null && config.passwordFile == null && (! config.settings ? "keyFile");
62+
defaultText = "true if neither keyFile nor passwordFile are set";
63+
description = "Whether to ask for a password for initial encryption";
64+
};
65+
settings = lib.mkOption {
66+
type = lib.types.attrsOf lib.types.anything;
67+
default = { };
68+
description = "LUKS settings (as defined in configuration.nix in boot.initrd.luks.devices.<name>)";
69+
example = ''{
70+
keyFile = "/tmp/disk.key";
71+
keyFileSize = 2048;
72+
keyFileOffset = 1024;
73+
fallbackToPassword = true;
74+
allowDiscards = true;
75+
};
76+
'';
77+
};
78+
additionalKeyFiles = lib.mkOption {
79+
type = lib.types.listOf diskoLib.optionTypes.absolute-pathname;
80+
default = [ ];
81+
description = "Path to additional key files for encryption";
82+
example = [ "/tmp/disk2.key" ];
83+
};
84+
initrdUnlock = lib.mkOption {
85+
type = lib.types.bool;
86+
default = true;
87+
description = "Whether to add a boot.initrd.luks.devices entry for the specified disk.";
88+
};
89+
extraFormatArgs = lib.mkOption {
90+
type = lib.types.listOf lib.types.str;
91+
default = [ ];
92+
description = "Extra arguments to pass to `cryptsetup luksFormat` when formatting";
93+
example = [ "--pbkdf argon2id" ];
94+
};
95+
extraOpenArgs = lib.mkOption {
96+
type = lib.types.listOf lib.types.str;
97+
default = [ ];
98+
description = "Extra arguments to pass to `cryptsetup luksOpen` when opening";
99+
example = [ "--timeout 10" ];
100+
};
101+
content = diskoLib.deviceType { parent = config; device = "/dev/mapper/${config.name}"; };
102+
_parent = lib.mkOption {
103+
internal = true;
104+
default = parent;
105+
};
106+
_meta = lib.mkOption {
107+
internal = true;
108+
readOnly = true;
109+
type = lib.types.functionTo diskoLib.jsonType;
110+
default = dev:
111+
lib.optionalAttrs (config.content != null) (config.content._meta dev);
112+
description = "Metadata";
113+
};
114+
_create = diskoLib.mkCreateOption {
115+
inherit config options;
116+
default = ''
117+
if ! blkid "${config.device}" >/dev/null || ! (blkid "${config.device}" -o export | grep -q '^TYPE='); then
118+
${lib.optionalString config.askPassword ''
119+
askPassword() {
120+
if [ -z ''${IN_DISKO_TEST+x} ]; then
121+
set +x
122+
echo "Enter password for ${config.device}: "
123+
IFS= read -r -s password
124+
echo "Enter password for ${config.device} again to be safe: "
125+
IFS= read -r -s password_check
126+
export password
127+
[ "$password" = "$password_check" ]
128+
set -x
129+
else
130+
export password=disko
131+
fi
132+
}
133+
until askPassword; do
134+
echo "Passwords did not match, please try again."
135+
done
136+
''}
137+
cryptsetup -q luksFormat "${config.device}" ${toString config.extraFormatArgs} ${keyFileArgs}
138+
${cryptsetupOpen} --persistent
139+
${toString (lib.forEach config.additionalKeyFiles (keyFile: ''
140+
cryptsetup luksAddKey "${config.device}" ${keyFile} ${keyFileArgs}
141+
''))}
142+
fi
143+
${lib.optionalString (config.content != null) config.content._create}
144+
'';
145+
};
146+
_mount = diskoLib.mkMountOption {
147+
inherit config options;
148+
default =
149+
let
150+
contentMount = config.content._mount;
151+
in
152+
{
153+
dev = ''
154+
if ! cryptsetup status "${config.name}" >/dev/null 2>/dev/null; then
155+
${lib.optionalString config.askPassword ''
156+
if [ -z ''${IN_DISKO_TEST+x} ]; then
157+
set +x
158+
echo "Enter password for ${config.device}"
159+
IFS= read -r -s password
160+
export password
161+
set -x
162+
else
163+
export password=disko
164+
fi
165+
''}
166+
${cryptsetupOpen}
167+
fi
168+
${lib.optionalString (config.content != null) contentMount.dev or ""}
169+
'';
170+
fs = lib.optionalAttrs (config.content != null) contentMount.fs or { };
171+
};
172+
};
173+
_config = lib.mkOption {
174+
internal = true;
175+
readOnly = true;
176+
default = [ ]
177+
# If initrdUnlock is true, then add a device entry to the initrd.luks.devices config.
178+
++ (lib.optional config.initrdUnlock [
179+
{
180+
boot.initrd.luks.devices.${config.name} = {
181+
inherit (config) device;
182+
} // config.settings;
183+
}
184+
]) ++ (lib.optional (config.content != null) config.content._config);
185+
description = "NixOS configuration";
186+
};
187+
_pkgs = lib.mkOption {
188+
internal = true;
189+
readOnly = true;
190+
type = lib.types.functionTo (lib.types.listOf lib.types.package);
191+
default = pkgs: [ pkgs.gnugrep pkgs.cryptsetup ] ++ (lib.optionals (config.content != null) (config.content._pkgs pkgs));
192+
description = "Packages";
193+
};
194+
};
195+
}

0 commit comments

Comments
 (0)