tangled
alpha
login
or
join now
pyrox.dev
/
nixpkgs
0
fork
atom
lol
0
fork
atom
overview
issues
pulls
pipelines
nixos/tests: adopt newest TPM support in test infra
Raito Bezarius
2 years ago
83b131bb
25872524
+23
-116
3 changed files
expand all
collapse all
unified
split
nixos
tests
systemd-credentials-tpm2.nix
systemd-cryptenroll.nix
systemd-initrd-luks-tpm2.nix
+2
-57
nixos/tests/systemd-credentials-tpm2.nix
···
1
1
-
import ./make-test-python.nix ({ lib, pkgs, system, ... }:
2
2
-
3
3
-
let
4
4
-
tpmSocketPath = "/tmp/swtpm-sock";
5
5
-
tpmDeviceModels = {
6
6
-
x86_64-linux = "tpm-tis";
7
7
-
aarch64-linux = "tpm-tis-device";
8
8
-
};
9
9
-
in
10
10
-
1
1
+
import ./make-test-python.nix ({ lib, pkgs, ... }:
11
2
{
12
3
name = "systemd-credentials-tpm2";
13
4
···
16
7
};
17
8
18
9
nodes.machine = { pkgs, ... }: {
19
19
-
virtualisation = {
20
20
-
qemu.options = [
21
21
-
"-chardev socket,id=chrtpm,path=${tpmSocketPath}"
22
22
-
"-tpmdev emulator,id=tpm_dev_0,chardev=chrtpm"
23
23
-
"-device ${tpmDeviceModels.${system}},tpmdev=tpm_dev_0"
24
24
-
];
25
25
-
};
26
26
-
27
27
-
boot.initrd.availableKernelModules = [ "tpm_tis" ];
28
28
-
10
10
+
virtualisation.tpm.enable = true;
29
11
environment.systemPackages = with pkgs; [ diffutils ];
30
12
};
31
13
32
14
testScript = ''
33
33
-
import subprocess
34
34
-
from tempfile import TemporaryDirectory
35
35
-
36
36
-
# From systemd-initrd-luks-tpm2.nix
37
37
-
class Tpm:
38
38
-
def __init__(self):
39
39
-
self.state_dir = TemporaryDirectory()
40
40
-
self.start()
41
41
-
42
42
-
def start(self):
43
43
-
self.proc = subprocess.Popen(["${pkgs.swtpm}/bin/swtpm",
44
44
-
"socket",
45
45
-
"--tpmstate", f"dir={self.state_dir.name}",
46
46
-
"--ctrl", "type=unixio,path=${tpmSocketPath}",
47
47
-
"--tpm2",
48
48
-
])
49
49
-
50
50
-
# Check whether starting swtpm failed
51
51
-
try:
52
52
-
exit_code = self.proc.wait(timeout=0.2)
53
53
-
if exit_code is not None and exit_code != 0:
54
54
-
raise Exception("failed to start swtpm")
55
55
-
except subprocess.TimeoutExpired:
56
56
-
pass
57
57
-
58
58
-
"""Check whether the swtpm process exited due to an error"""
59
59
-
def check(self):
60
60
-
exit_code = self.proc.poll()
61
61
-
if exit_code is not None and exit_code != 0:
62
62
-
raise Exception("swtpm process died")
63
63
-
64
15
CRED_NAME = "testkey"
65
16
CRED_RAW_FILE = f"/root/{CRED_NAME}"
66
17
CRED_FILE = f"/root/{CRED_NAME}.cred"
···
84
35
raise Exception(f"systemd_run failed (status {status})")
85
36
86
37
machine.log("systemd-run finished successfully")
87
87
-
88
88
-
tpm = Tpm()
89
89
-
90
90
-
@polling_condition
91
91
-
def swtpm_running():
92
92
-
tpm.check()
93
38
94
39
machine.wait_for_unit("multi-user.target")
95
40
+20
-33
nixos/tests/systemd-cryptenroll.nix
···
8
8
environment.systemPackages = [ pkgs.cryptsetup ];
9
9
virtualisation = {
10
10
emptyDiskImages = [ 512 ];
11
11
-
qemu.options = [
12
12
-
"-chardev socket,id=chrtpm,path=/tmp/swtpm-sock"
13
13
-
"-tpmdev emulator,id=tpm0,chardev=chrtpm"
14
14
-
"-device tpm-tis,tpmdev=tpm0"
15
15
-
];
11
11
+
tpm.enable = true;
16
12
};
17
13
};
18
14
19
15
testScript = ''
20
20
-
import subprocess
21
21
-
import tempfile
16
16
+
machine.start()
22
17
23
23
-
def start_swtpm(tpmstate):
24
24
-
subprocess.Popen(["${pkgs.swtpm}/bin/swtpm", "socket", "--tpmstate", "dir="+tpmstate, "--ctrl", "type=unixio,path=/tmp/swtpm-sock", "--log", "level=0", "--tpm2"])
18
18
+
# Verify the TPM device is available and accessible by systemd-cryptenroll
19
19
+
machine.succeed("test -e /dev/tpm0")
20
20
+
machine.succeed("test -e /dev/tpmrm0")
21
21
+
machine.succeed("systemd-cryptenroll --tpm2-device=list")
25
22
26
26
-
with tempfile.TemporaryDirectory() as tpmstate:
27
27
-
start_swtpm(tpmstate)
28
28
-
machine.start()
23
23
+
# Create LUKS partition
24
24
+
machine.succeed("echo -n lukspass | cryptsetup luksFormat -q /dev/vdb -")
25
25
+
# Enroll new LUKS key and bind it to Secure Boot state
26
26
+
# For more details on PASSWORD variable, check the following issue:
27
27
+
# https://github.com/systemd/systemd/issues/20955
28
28
+
machine.succeed("PASSWORD=lukspass systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=7 /dev/vdb")
29
29
+
# Add LUKS partition to /etc/crypttab to test auto unlock
30
30
+
machine.succeed("echo 'luks /dev/vdb - tpm2-device=auto' >> /etc/crypttab")
29
31
30
30
-
# Verify the TPM device is available and accessible by systemd-cryptenroll
31
31
-
machine.succeed("test -e /dev/tpm0")
32
32
-
machine.succeed("test -e /dev/tpmrm0")
33
33
-
machine.succeed("systemd-cryptenroll --tpm2-device=list")
34
34
-
35
35
-
# Create LUKS partition
36
36
-
machine.succeed("echo -n lukspass | cryptsetup luksFormat -q /dev/vdb -")
37
37
-
# Enroll new LUKS key and bind it to Secure Boot state
38
38
-
# For more details on PASSWORD variable, check the following issue:
39
39
-
# https://github.com/systemd/systemd/issues/20955
40
40
-
machine.succeed("PASSWORD=lukspass systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=7 /dev/vdb")
41
41
-
# Add LUKS partition to /etc/crypttab to test auto unlock
42
42
-
machine.succeed("echo 'luks /dev/vdb - tpm2-device=auto' >> /etc/crypttab")
43
43
-
machine.shutdown()
32
32
+
machine.shutdown()
33
33
+
machine.start()
44
34
45
45
-
start_swtpm(tpmstate)
46
46
-
machine.start()
47
47
-
48
48
-
# Test LUKS partition automatic unlock on boot
49
49
-
machine.wait_for_unit("systemd-cryptsetup@luks.service")
50
50
-
# Wipe TPM2 slot
51
51
-
machine.succeed("systemd-cryptenroll --wipe-slot=tpm2 /dev/vdb")
35
35
+
# Test LUKS partition automatic unlock on boot
36
36
+
machine.wait_for_unit("systemd-cryptsetup@luks.service")
37
37
+
# Wipe TPM2 slot
38
38
+
machine.succeed("systemd-cryptenroll --wipe-slot=tpm2 /dev/vdb")
52
39
'';
53
40
})
54
41
+1
-26
nixos/tests/systemd-initrd-luks-tpm2.nix
···
9
9
# Booting off the TPM2-encrypted device requires an available init script
10
10
mountHostNixStore = true;
11
11
useEFIBoot = true;
12
12
-
qemu.options = ["-chardev socket,id=chrtpm,path=/tmp/mytpm1/swtpm-sock -tpmdev emulator,id=tpm0,chardev=chrtpm -device tpm-tis,tpmdev=tpm0"];
12
12
+
tpm.enable = true;
13
13
};
14
14
boot.loader.systemd-boot.enable = true;
15
15
···
33
33
};
34
34
35
35
testScript = ''
36
36
-
import subprocess
37
37
-
import os
38
38
-
import time
39
39
-
40
40
-
41
41
-
class Tpm:
42
42
-
def __init__(self):
43
43
-
os.mkdir("/tmp/mytpm1")
44
44
-
self.start()
45
45
-
46
46
-
def start(self):
47
47
-
self.proc = subprocess.Popen(["${pkgs.swtpm}/bin/swtpm", "socket", "--tpmstate", "dir=/tmp/mytpm1", "--ctrl", "type=unixio,path=/tmp/mytpm1/swtpm-sock", "--log", "level=20", "--tpm2"])
48
48
-
49
49
-
def wait_for_death_then_restart(self):
50
50
-
while self.proc.poll() is None:
51
51
-
print("waiting for tpm to die")
52
52
-
time.sleep(1)
53
53
-
assert self.proc.returncode == 0
54
54
-
self.start()
55
55
-
56
56
-
tpm = Tpm()
57
57
-
58
58
-
59
36
# Create encrypted volume
60
37
machine.wait_for_unit("multi-user.target")
61
38
machine.succeed("echo -n supersecret | cryptsetup luksFormat -q --iter-time=1 /dev/vdb -")
···
65
42
machine.succeed("bootctl set-default nixos-generation-1-specialisation-boot-luks.conf")
66
43
machine.succeed("sync")
67
44
machine.crash()
68
68
-
69
69
-
tpm.wait_for_death_then_restart()
70
45
71
46
# Boot and decrypt the disk
72
47
machine.wait_for_unit("multi-user.target")