From 426413b862563b20afbc22ea9de00929942b77c0 Mon Sep 17 00:00:00 2001 From: Arian van Putten Date: Thu, 25 Jun 2026 09:53:18 +0200 Subject: [PATCH] nixos/tests/credentials: test both vm and container support Assisted-by: Claude --- nixos/tests/all-tests.nix | 16 ++--- nixos/tests/credentials.nix | 106 ++++++++++++++++++++++++++++ nixos/tests/qemu-vm-credentials.nix | 83 ---------------------- 3 files changed, 114 insertions(+), 91 deletions(-) create mode 100644 nixos/tests/credentials.nix delete mode 100644 nixos/tests/qemu-vm-credentials.nix diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index 09b0a4632d28..0e386407529f 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -446,6 +446,14 @@ in }; coturn = runTest ./coturn.nix; couchdb = runTest ./couchdb.nix; + credentials-fwcfg = runTest { + imports = [ ./credentials.nix ]; + _module.args.mechanism = "fw_cfg"; + }; + credentials-smbios = runTestOn [ "x86_64-linux" ] { + imports = [ ./credentials.nix ]; + _module.args.mechanism = "smbios"; + }; cri-o = runTestOn [ "aarch64-linux" "x86_64-linux" ] ./cri-o.nix; croc = runTest ./croc.nix; cross-seed = runTest ./cross-seed.nix; @@ -1415,14 +1423,6 @@ in pykms = runTest ./pykms.nix; qbittorrent = runTest ./qbittorrent.nix; qboot = runTestOn [ "x86_64-linux" "i686-linux" ] ./qboot.nix; - qemu-vm-credentials-fwcfg = runTest { - imports = [ ./qemu-vm-credentials.nix ]; - _module.args.mechanism = "fw_cfg"; - }; - qemu-vm-credentials-smbios = runTestOn [ "x86_64-linux" ] { - imports = [ ./qemu-vm-credentials.nix ]; - _module.args.mechanism = "smbios"; - }; qemu-vm-external-disk-image = runTest ./qemu-vm-external-disk-image.nix; qemu-vm-restrictnetwork = handleTest ./qemu-vm-restrictnetwork.nix { }; qemu-vm-store = runTest ./qemu-vm-store.nix; diff --git a/nixos/tests/credentials.nix b/nixos/tests/credentials.nix new file mode 100644 index 000000000000..7984ffd03593 --- /dev/null +++ b/nixos/tests/credentials.nix @@ -0,0 +1,106 @@ +{ + lib, + pkgs, + mechanism, + ... +}: + +let + secret = '' + foo + bar + baz + ''; + secret-file = "bar"; + + common-credentials = { + secret-default-mechanism = { + text = "default-mechanism"; + }; + secret-file-nix-store = { + source = pkgs.writeText "secret-file-nix-store" secret-file; + }; + secret-file-host = { + source = "./secret-file-host"; + }; + secret-file-host-binary = { + source = "./secret-file-host-binary"; + }; + }; +in + +{ + name = "credentials-${mechanism}"; + + meta.maintainers = with lib.maintainers; [ arianvp ]; + + # No VM<->container traffic in this test; credentials are static. + requiredFeatures.devnet = lib.mkForce false; + + nodes.vm = { + virtualisation.credentials = common-credentials // { + secret = { + inherit mechanism; + text = secret; + }; + }; + }; + + containers.container = { + virtualisation.credentials = common-credentials // { + secret = { + text = secret; + }; + }; + }; + + testScript = '' + import base64 + + secret_file_host = "baz" + # Binary data with null bytes, high bytes, and other problematic characters. + secret_file_host_binary = bytes([ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0xDE, 0xAD, 0xBE, 0xEF, + 0xFF, 0xFE, 0xFD, 0xFC, + 0x00, 0x00, 0x00, 0x00, + 0x80, 0x81, 0x82, 0x83, + ]) + + def assert_credentials(m): + with open(m.state_dir / "secret-file-host", "w") as f: + f.write(secret_file_host) + with open(m.state_dir / "secret-file-host-binary", "wb") as f2: + f2.write(secret_file_host_binary) + + t.assertEqual( + m.succeed("systemd-creds --system cat secret").strip(), + "foo\nbar\nbaz", + ) + t.assertEqual( + m.succeed("systemd-creds --system cat secret-default-mechanism").strip(), + "default-mechanism", + ) + t.assertEqual( + m.succeed("systemd-creds --system cat secret-file-nix-store").strip(), + "${secret-file}", + ) + t.assertEqual( + m.succeed("systemd-creds --system cat secret-file-host").strip(), + secret_file_host, + ) + result = m.succeed( + "systemd-creds --system cat secret-file-host-binary --transcode=base64" + ).strip() + expected = base64.b64encode(secret_file_host_binary).decode("ascii") + t.assertEqual( + result, + expected, + f"Binary credential mismatch: got {result}, expected {expected}", + ) + + assert_credentials(vm) + assert_credentials(container) + ''; +} diff --git a/nixos/tests/qemu-vm-credentials.nix b/nixos/tests/qemu-vm-credentials.nix deleted file mode 100644 index 9ee2d270d8f0..000000000000 --- a/nixos/tests/qemu-vm-credentials.nix +++ /dev/null @@ -1,83 +0,0 @@ -{ - lib, - pkgs, - mechanism, - ... -}: - -let - secret = '' - foo - bar - baz - ''; - secret-file = "bar"; -in - -{ - name = "qemu-vm-credentials-${mechanism}"; - - meta.maintainers = with lib.maintainers; [ arianvp ]; - - nodes = { - machine = { - virtualisation.credentials = { - secret = { - inherit mechanism; - text = secret; - }; - secret-default-mechanism = { - text = "default-mechanism"; - }; - secret-file-nix-store = { - inherit mechanism; - source = pkgs.writeText "secret-file-nix-store" secret-file; - }; - secret-file-host = { - inherit mechanism; - source = "./secret-file-host"; - }; - secret-file-host-binary = { - inherit mechanism; - source = "./secret-file-host-binary"; - }; - }; - }; - }; - - testScript = '' - import base64 - secret_file_host = "baz" - # Binary data with null bytes, high bytes, and all sorts of problematic characters - secret_file_host_binary = bytes([ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, # null and control chars - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - 0xDE, 0xAD, 0xBE, 0xEF, # classic binary pattern - 0xFF, 0xFE, 0xFD, 0xFC, # high bytes - 0x00, 0x00, 0x00, 0x00, # multiple nulls - 0x80, 0x81, 0x82, 0x83, # more high bytes - ]) - - with open(machine.state_dir / "secret-file-host", "w") as f: - f.write(secret_file_host) - with open(machine.state_dir / "secret-file-host-binary", "wb") as f2: - f2.write(secret_file_host_binary) - - - # Test text credential - t.assertEqual(machine.succeed("systemd-creds --system cat secret").strip(), "foo\nbar\nbaz") - - t.assertEqual(machine.succeed("systemd-creds --system cat secret-default-mechanism").strip(), "default-mechanism") - - # Test credential from nix store - t.assertEqual(machine.succeed("systemd-creds --system cat secret-file-nix-store").strip(), "${secret-file}") - - # Test credential from host file - t.assertEqual(machine.succeed("systemd-creds --system cat secret-file-host").strip(), secret_file_host) - - # Test binary credential - verify exact binary content - result = machine.succeed("systemd-creds --system cat secret-file-host-binary --transcode=base64").strip() - expected = base64.b64encode(secret_file_host_binary).decode('ascii') - t.assertEqual(result, expected, f"Binary credential mismatch: got {result}, expected {expected}") - ''; -}