We want verity protected partitions as well as encrypted state/data along with verified boot. This PR integrates Peter Marshall's awesome little Nixlet project as a starting point, especially the nice testing scaffolding will be super helpful! ✨ https://github.com/petm5/nixlet/
This commit is contained in:
parent
da5bdb3d47
commit
c59ea29957
39 changed files with 1311 additions and 3272 deletions
154
tests/common.nix
Normal file
154
tests/common.nix
Normal file
|
@ -0,0 +1,154 @@
|
|||
{
|
||||
self,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
with import (pkgs.path + "/nixos/lib/testing-python.nix") {
|
||||
inherit pkgs;
|
||||
inherit (pkgs.hostPlatform) system;
|
||||
};
|
||||
|
||||
let
|
||||
qemu-common = import (pkgs.path + "/nixos/lib/qemu-common.nix") { inherit lib pkgs; };
|
||||
|
||||
in
|
||||
rec {
|
||||
|
||||
makeSystem =
|
||||
extraConfig:
|
||||
(import (pkgs.path + "/nixos/lib/eval-config.nix")) {
|
||||
inherit pkgs lib;
|
||||
system = null;
|
||||
modules = [
|
||||
{
|
||||
nixpkgs.hostPlatform = pkgs.hostPlatform;
|
||||
}
|
||||
{
|
||||
users.allowNoPasswordLogin = true;
|
||||
system.stateVersion = lib.versions.majorMinor lib.version;
|
||||
system.image.id = lib.mkDefault "test";
|
||||
system.image.version = lib.mkDefault "1";
|
||||
networking.hosts."10.0.2.1" = [ "server.test" ];
|
||||
}
|
||||
{
|
||||
boot.kernelParams = [
|
||||
"console=ttyS0,115200n8"
|
||||
"systemd.journald.forward_to_console=1"
|
||||
];
|
||||
image.compress = false;
|
||||
boot.initrd.compressor = lib.mkForce "zstd";
|
||||
boot.initrd.compressorArgs = lib.mkForce [ "-8" ];
|
||||
}
|
||||
(pkgs.path + "/nixos/modules/testing/test-instrumentation.nix")
|
||||
self.nixosModules.server
|
||||
self.nixosModules.image
|
||||
extraConfig
|
||||
];
|
||||
};
|
||||
|
||||
makeImage =
|
||||
extraConfig:
|
||||
let
|
||||
system = makeSystem extraConfig;
|
||||
in
|
||||
"${system.config.system.build.image}/${system.config.system.build.image.imageFile}";
|
||||
|
||||
makeUpdatePackage =
|
||||
extraConfig:
|
||||
let
|
||||
system = makeSystem extraConfig;
|
||||
in
|
||||
"${system.config.system.build.updatePackage}";
|
||||
|
||||
makeImageTest =
|
||||
{
|
||||
name,
|
||||
image,
|
||||
script,
|
||||
httpRoot ? null,
|
||||
}:
|
||||
let
|
||||
qemu = qemu-common.qemuBinary pkgs.qemu_test;
|
||||
flags = [
|
||||
"-m"
|
||||
"512M"
|
||||
"-drive"
|
||||
"if=pflash,format=raw,unit=0,readonly=on,file=${pkgs.OVMF.firmware}"
|
||||
"-drive"
|
||||
"if=pflash,format=raw,unit=1,readonly=on,file=${pkgs.OVMF.variables}"
|
||||
"-drive"
|
||||
"if=virtio,file=${mutableImage}"
|
||||
"-chardev"
|
||||
"socket,id=chrtpm,path=${tpmFolder}/swtpm-sock"
|
||||
"-tpmdev"
|
||||
"emulator,id=tpm0,chardev=chrtpm"
|
||||
"-device"
|
||||
"tpm-tis,tpmdev=tpm0"
|
||||
"-netdev"
|
||||
(
|
||||
"'user,id=net0"
|
||||
+ (lib.optionalString (
|
||||
httpRoot != null
|
||||
) ",guestfwd=tcp:10.0.2.1:80-cmd:${pkgs.micro-httpd}/bin/micro_httpd ${httpRoot}")
|
||||
+ "'"
|
||||
)
|
||||
"-device"
|
||||
"virtio-net-pci,netdev=net0"
|
||||
];
|
||||
flagsStr = lib.concatStringsSep " " flags;
|
||||
startCommand = "${qemu} ${flagsStr}";
|
||||
mutableImage = "/tmp/linked-image.qcow2";
|
||||
tpmFolder = "/tmp/emulated_tpm";
|
||||
indentLines = str: lib.concatLines (map (s: " " + s) (lib.splitString "\n" str));
|
||||
in
|
||||
makeTest {
|
||||
inherit name;
|
||||
nodes = { };
|
||||
testScript =
|
||||
''
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
subprocess.check_call(
|
||||
[
|
||||
"qemu-img",
|
||||
"create",
|
||||
"-f",
|
||||
"qcow2",
|
||||
"-F",
|
||||
"raw",
|
||||
"-b",
|
||||
"${image}",
|
||||
"${mutableImage}",
|
||||
]
|
||||
)
|
||||
subprocess.check_call(["qemu-img", "resize", "${mutableImage}", "4G"])
|
||||
|
||||
os.mkdir("${tpmFolder}")
|
||||
os.mkdir("${tpmFolder}/swtpm")
|
||||
|
||||
def start_tpm():
|
||||
subprocess.Popen(
|
||||
[
|
||||
"${pkgs.swtpm}/bin/swtpm",
|
||||
"socket",
|
||||
"--tpmstate", "dir=${tpmFolder}/swtpm",
|
||||
"--ctrl", "type=unixio,path=${tpmFolder}/swtpm-sock",
|
||||
"--tpm2"
|
||||
]
|
||||
)
|
||||
|
||||
machine = create_machine("${startCommand}")
|
||||
|
||||
try:
|
||||
''
|
||||
+ indentLines script
|
||||
+ ''
|
||||
finally:
|
||||
machine.shutdown()
|
||||
'';
|
||||
};
|
||||
|
||||
}
|
9
tests/lib.nix
Normal file
9
tests/lib.nix
Normal file
|
@ -0,0 +1,9 @@
|
|||
test:
|
||||
{ pkgs, self }:
|
||||
let nixos-lib = import (pkgs.path + "/nixos/lib") {};
|
||||
in (nixos-lib.runTest {
|
||||
hostPkgs = pkgs;
|
||||
defaults.documentation.enable = false;
|
||||
node.specialArgs = { inherit self; };
|
||||
imports = [ test ];
|
||||
}).config.result
|
22
tests/podman.nix
Normal file
22
tests/podman.nix
Normal file
|
@ -0,0 +1,22 @@
|
|||
{ pkgs, self }: let
|
||||
|
||||
lib = pkgs.lib;
|
||||
test-common = import ./common.nix { inherit self lib pkgs; };
|
||||
|
||||
image = test-common.makeImage { };
|
||||
|
||||
in test-common.makeImageTest {
|
||||
name = "podman";
|
||||
inherit image;
|
||||
script = ''
|
||||
start_tpm()
|
||||
machine.start()
|
||||
|
||||
machine.wait_for_unit("multi-user.target")
|
||||
machine.wait_for_unit("network-online.target")
|
||||
|
||||
machine.succeed("tar cv --files-from /dev/null | su admin -l -c 'podman import - scratchimg'")
|
||||
|
||||
machine.succeed("su admin -l -c 'podman run --rm -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin scratchimg true'")
|
||||
'';
|
||||
}
|
37
tests/ssh-preseed.nix
Normal file
37
tests/ssh-preseed.nix
Normal file
|
@ -0,0 +1,37 @@
|
|||
{ pkgs, self }:
|
||||
let
|
||||
lib = pkgs.lib;
|
||||
test-common = import ./common.nix { inherit self lib pkgs; };
|
||||
sshKeys = import (pkgs.path + "/nixos/tests/ssh-keys.nix") pkgs;
|
||||
|
||||
image = test-common.makeImage {
|
||||
system.image.sshKeys.keys = [ sshKeys.snakeOilPublicKey ];
|
||||
system.extraDependencies = [ sshKeys.snakeOilPrivateKey ];
|
||||
};
|
||||
|
||||
in
|
||||
test-common.makeImageTest {
|
||||
name = "ssh-preseed";
|
||||
inherit image;
|
||||
script = ''
|
||||
start_tpm()
|
||||
machine.start()
|
||||
|
||||
machine.wait_for_unit("multi-user.target")
|
||||
|
||||
machine.succeed("[ -e /efi/default-ssh-authorized-keys.txt ]")
|
||||
machine.succeed("[ -e /home/admin/.ssh/authorized_keys ]")
|
||||
|
||||
machine.wait_for_open_port(22)
|
||||
|
||||
machine.succeed(
|
||||
"cat ${sshKeys.snakeOilPrivateKey} > privkey.snakeoil"
|
||||
)
|
||||
machine.succeed("chmod 600 privkey.snakeoil")
|
||||
|
||||
machine.succeed(
|
||||
"ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i privkey.snakeoil admin@127.0.0.1 true",
|
||||
timeout=30
|
||||
)
|
||||
'';
|
||||
}
|
45
tests/system-update.nix
Normal file
45
tests/system-update.nix
Normal file
|
@ -0,0 +1,45 @@
|
|||
{ pkgs, self }: let
|
||||
|
||||
lib = pkgs.lib;
|
||||
test-common = import ./common.nix { inherit self lib pkgs; };
|
||||
|
||||
initialImage = test-common.makeImage {
|
||||
system.image.version = "1";
|
||||
system.image.updates.url = "http://server.test/";
|
||||
# The default root-b is too small for uncompressed test images
|
||||
systemd.repart.partitions."32-root-b" = {
|
||||
SizeMinBytes = lib.mkForce "1G";
|
||||
SizeMaxBytes = lib.mkForce "1G";
|
||||
};
|
||||
};
|
||||
|
||||
updatePackage = test-common.makeUpdatePackage {
|
||||
system.image.version = "2";
|
||||
system.image.updates.url = "http://server.test/";
|
||||
};
|
||||
|
||||
in test-common.makeImageTest {
|
||||
name = "system-update";
|
||||
image = initialImage;
|
||||
httpRoot = updatePackage;
|
||||
script = ''
|
||||
start_tpm()
|
||||
machine.start()
|
||||
|
||||
machine.wait_for_unit("multi-user.target")
|
||||
machine.wait_for_unit("network-online.target")
|
||||
|
||||
machine.succeed("/run/current-system/sw/lib/systemd/systemd-sysupdate update")
|
||||
|
||||
machine.shutdown()
|
||||
|
||||
start_tpm()
|
||||
machine.start()
|
||||
|
||||
machine.wait_for_unit("multi-user.target")
|
||||
|
||||
machine.succeed('. /etc/os-release; [ "$IMAGE_VERSION" == "2" ]')
|
||||
|
||||
machine.wait_for_unit("systemd-bless-boot.service")
|
||||
'';
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue