1import ./make-test-python.nix (
2 { pkgs, ... }:
3 {
4 name = "tang";
5 meta = with pkgs.lib.maintainers; {
6 maintainers = [ jfroche ];
7 };
8
9 nodes.server =
10 {
11 config,
12 pkgs,
13 modulesPath,
14 ...
15 }:
16 {
17 imports = [
18 "${modulesPath}/../tests/common/auto-format-root-device.nix"
19 ];
20 virtualisation = {
21 emptyDiskImages = [ 512 ];
22 useBootLoader = true;
23 useEFIBoot = true;
24 # This requires to have access
25 # to a host Nix store as
26 # the new root device is /dev/vdb
27 # an empty 512MiB drive, containing no Nix store.
28 mountHostNixStore = true;
29 };
30
31 boot.loader.systemd-boot.enable = true;
32
33 networking.interfaces.eth1.ipv4.addresses = [
34 {
35 address = "192.168.0.1";
36 prefixLength = 24;
37 }
38 ];
39
40 environment.systemPackages = with pkgs; [
41 clevis
42 tang
43 cryptsetup
44 ];
45 services.tang = {
46 enable = true;
47 ipAddressAllow = [ "127.0.0.1/32" ];
48 };
49 };
50 testScript = ''
51 start_all()
52 machine.wait_for_unit("sockets.target")
53
54 with subtest("Check keys are generated"):
55 machine.wait_until_succeeds("curl -v http://127.0.0.1:7654/adv")
56 key = machine.wait_until_succeeds("tang-show-keys 7654")
57
58 with subtest("Check systemd access list"):
59 machine.succeed("ping -c 3 192.168.0.1")
60 machine.fail("curl -v --connect-timeout 3 http://192.168.0.1:7654/adv")
61
62 with subtest("Check basic encrypt and decrypt message"):
63 machine.wait_until_succeeds(f"""echo 'Hello World' | clevis encrypt tang '{{ "url": "http://127.0.0.1:7654", "thp":"{key}"}}' > /tmp/encrypted""")
64 decrypted = machine.wait_until_succeeds("clevis decrypt < /tmp/encrypted")
65 assert decrypted.strip() == "Hello World"
66 machine.wait_until_succeeds("tang-show-keys 7654")
67
68 with subtest("Check encrypt and decrypt disk"):
69 machine.succeed("cryptsetup luksFormat --force-password --batch-mode /dev/vdb <<<'password'")
70 machine.succeed(f"""clevis luks bind -s1 -y -f -d /dev/vdb tang '{{ "url": "http://127.0.0.1:7654", "thp":"{key}" }}' <<< 'password' """)
71 clevis_luks = machine.succeed("clevis luks list -d /dev/vdb")
72 assert clevis_luks.strip() == """1: tang '{"url":"http://127.0.0.1:7654"}'"""
73 machine.succeed("clevis luks unlock -d /dev/vdb")
74 machine.succeed("find /dev/mapper -name 'luks*' -exec cryptsetup close {} +")
75 machine.succeed("clevis luks unlock -d /dev/vdb")
76 machine.succeed("find /dev/mapper -name 'luks*' -exec cryptsetup close {} +")
77 # without tang available, unlock should fail
78 machine.succeed("systemctl stop tangd.socket")
79 machine.fail("clevis luks unlock -d /dev/vdb")
80 machine.succeed("systemctl start tangd.socket")
81
82 with subtest("Rotate server keys"):
83 machine.succeed("${pkgs.tang}/libexec/tangd-rotate-keys -d /var/lib/tang")
84 machine.succeed("clevis luks unlock -d /dev/vdb")
85 machine.succeed("find /dev/mapper -name 'luks*' -exec cryptsetup close {} +")
86
87 with subtest("Test systemd service security"):
88 output = machine.succeed("systemd-analyze security tangd@.service")
89 machine.log(output)
90 assert output[-9:-1] == "SAFE :-}"
91 '';
92 }
93)