Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 31 additions & 4 deletions nix/dm-verity.nix
Original file line number Diff line number Diff line change
Expand Up @@ -30,21 +30,48 @@ in
{
options.dm-verity = {
enable = lib.mkEnableOption "support for the dm-verity roothash signature verification mechanism.";
where = lib.mkOption {
type = lib.types.enum [
"kernel"
"userspace"
"kernel+userspace"
];
};
trustedKeys = lib.mkOption {
type = with lib.types; listOf path;
default = [ ];
example = [ ./certificate.pem ];
description = ''
Trusted certificates for the signature verification of dm-verity partitions. The listed
certificate files will be provided as input for the kernel build process in order
to embed them in the kernel keyring.
Trusted certificates for the signature verification of dm-verity partitions.
They need to be PEM encoded. For userspace validation, only certificate files
with the .crt file extension are recognized by systemd.
'';
};
};

config = lib.mkIf cfg.enable {
boot.kernelPatches = [
enableVerityRoothashSig
]
++ lib.optional (cfg.trustedKeys != [ ]) (provideTrustedKeys (mergeCertificates cfg.trustedKeys));
++ lib.optional (
((cfg.where == "kernel") || (cfg.where == "kernel+userspace")) && cfg.trustedKeys != [ ]
) (provideTrustedKeys (mergeCertificates cfg.trustedKeys));

environment.etc =
let
checkedTrustedKeys =
lib.warnIf (!lib.lists.all (lib.hasSuffix ".crt") cfg.trustedKeys)
"dm-verity: trustedKeys for userspace validation require .crt extension to be considered"
cfg.trustedKeys;
in

lib.listToAttrs (
lib.map (keyPath: {
name = "verity.d/${builtins.baseNameOf keyPath}";
value = {
source = keyPath;
};
}) checkedTrustedKeys
);
};
}
3 changes: 2 additions & 1 deletion nix/tests/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ let
heavyTests =
if enableHeavyTests then
{
dm-verity = runNixosTest ./dm-verity.nix;
dm-verity-userspace = runNixosTest ./dm-verity-userspace.nix;
dm-verity-kernel = runNixosTest ./dm-verity-kernel.nix;
}
else
{ };
Expand Down
5 changes: 3 additions & 2 deletions nix/tests/dm-verity.nix → nix/tests/dm-verity-kernel.nix
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
}:
let
cert_id = "a6b64f7fdadc8ba80554f9da58363cbee9b48d88";
cert = ./fixtures/cert.pem;
cert = ./fixtures/cert.crt;
privk = ./fixtures/privk.pem;
in
{
Expand All @@ -26,7 +26,8 @@ in
# Embed certificate in the kernel's keyring
dm-verity = {
enable = true;
trustedKeys = [ ./fixtures/cert.pem ];
where = "kernel";
trustedKeys = [ cert ];
};

# Define our extension image.
Expand Down
66 changes: 66 additions & 0 deletions nix/tests/dm-verity-userspace.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# 1. Copy confext created with naext into confext search path
# 2. systemd-confext refresh
# 3. Assert that the confext has been activated and the provided file has the expected content
{
pkgs,
...
}:
let
cert_id = "a6b64f7fdadc8ba80554f9da58363cbee9b48d88";
cert = ./fixtures/cert.crt;
privk = ./fixtures/privk.pem;
in
{
name = "confext-dm-verity";
nodes = {
machine =
{
modulesPath,
...
}:
{
imports = [
"${modulesPath}/image/repart.nix"
];

# Embed certificate in the kernel's keyring
dm-verity = {
enable = true;
trustedKeys = [
cert
];
where = "userspace";
};

# Define our extension image.
naext = {
seed = "12345678-1234-1234-1234-123456789123";
privateKey = privk;
certificate = cert;
extensions = {
test = {
extensionType = "confext";
imageFormat = "verity";
files = {
"/etc/test".source = pkgs.writeText "example" ''Hello'';
};
};
};
};
};
};
testScript =
{ nodes, ... }:
let
testExt = nodes.machine.naext.extensions.test;
in
# python
''
with subtest("Confext gets applied successfully"):
machine.copy_from_host("${testExt.image}", "/var/lib/confexts/${testExt.name}.${testExt.extensionType}.raw")
machine.succeed("systemd-confext refresh")
machine.wait_for_file("/etc/test")
content=machine.succeed("cat /etc/test")
assert content=="Hello", "File provided by confext has expected content"
'';
}
File renamed without changes.