nixosTests.systemd-confinement: Port to Python

This commit is contained in:
Jacek Galowicz 2020-02-14 09:48:42 +01:00
parent 14474ff8b5
commit 1320f23a6b

View File

@ -1,4 +1,4 @@
import ./make-test.nix { import ./make-test-python.nix {
name = "systemd-confinement"; name = "systemd-confinement";
machine = { pkgs, lib, ... }: let machine = { pkgs, lib, ... }: let
@ -17,7 +17,7 @@ import ./make-test.nix {
exit "''${ret:-1}" exit "''${ret:-1}"
''; '';
mkTestStep = num: { description, config ? {}, testScript }: { mkTestStep = num: { config ? {}, testScript }: {
systemd.sockets."test${toString num}" = { systemd.sockets."test${toString num}" = {
description = "Socket for Test Service ${toString num}"; description = "Socket for Test Service ${toString num}";
wantedBy = [ "sockets.target" ]; wantedBy = [ "sockets.target" ];
@ -34,52 +34,48 @@ import ./make-test.nix {
}; };
} // removeAttrs config [ "confinement" "serviceConfig" ]; } // removeAttrs config [ "confinement" "serviceConfig" ];
__testSteps = lib.mkOrder num '' __testSteps = lib.mkOrder num (''
subtest '${lib.escape ["\\" "'"] description}', sub { machine.succeed("echo ${toString num} > /teststep")
$machine->succeed('echo ${toString num} > /teststep'); '' + testScript);
${testScript}
};
'';
}; };
in { in {
imports = lib.imap1 mkTestStep [ imports = lib.imap1 mkTestStep [
{ description = "chroot-only confinement"; { config.confinement.mode = "chroot-only";
config.confinement.mode = "chroot-only";
testScript = '' testScript = ''
$machine->succeed( with subtest("chroot-only confinement"):
'test "$(chroot-exec ls -1 / | paste -sd,)" = bin,nix', machine.succeed(
'test "$(chroot-exec id -u)" = 0', 'test "$(chroot-exec ls -1 / | paste -sd,)" = bin,nix',
'chroot-exec chown 65534 /bin', 'test "$(chroot-exec id -u)" = 0',
); "chroot-exec chown 65534 /bin",
)
''; '';
} }
{ description = "full confinement with APIVFS"; { testScript = ''
testScript = '' with subtest("full confinement with APIVFS"):
$machine->fail( machine.fail(
'chroot-exec ls -l /etc', "chroot-exec ls -l /etc",
'chroot-exec ls -l /run', "chroot-exec ls -l /run",
'chroot-exec chown 65534 /bin', "chroot-exec chown 65534 /bin",
); )
$machine->succeed( machine.succeed(
'test "$(chroot-exec id -u)" = 0', 'test "$(chroot-exec id -u)" = 0', "chroot-exec chown 0 /bin",
'chroot-exec chown 0 /bin', )
);
''; '';
} }
{ description = "check existence of bind-mounted /etc"; { config.serviceConfig.BindReadOnlyPaths = [ "/etc" ];
config.serviceConfig.BindReadOnlyPaths = [ "/etc" ];
testScript = '' testScript = ''
$machine->succeed('test -n "$(chroot-exec cat /etc/passwd)"'); with subtest("check existence of bind-mounted /etc"):
machine.succeed('test -n "$(chroot-exec cat /etc/passwd)"')
''; '';
} }
{ description = "check if User/Group really runs as non-root"; { config.serviceConfig.User = "chroot-testuser";
config.serviceConfig.User = "chroot-testuser";
config.serviceConfig.Group = "chroot-testgroup"; config.serviceConfig.Group = "chroot-testgroup";
testScript = '' testScript = ''
$machine->succeed('chroot-exec ls -l /dev'); with subtest("check if User/Group really runs as non-root"):
$machine->succeed('test "$(chroot-exec id -u)" != 0'); machine.succeed("chroot-exec ls -l /dev")
$machine->fail('chroot-exec touch /bin/test'); machine.succeed('test "$(chroot-exec id -u)" != 0')
machine.fail("chroot-exec touch /bin/test")
''; '';
} }
(let (let
@ -87,62 +83,60 @@ import ./make-test.nix {
target = pkgs.writeText "symlink-target" "got me\n"; target = pkgs.writeText "symlink-target" "got me\n";
} "ln -s \"$target\" \"$out\""; } "ln -s \"$target\" \"$out\"";
in { in {
description = "check if symlinks are properly bind-mounted";
config.confinement.packages = lib.singleton symlink; config.confinement.packages = lib.singleton symlink;
testScript = '' testScript = ''
$machine->fail('chroot-exec test -e /etc'); with subtest("check if symlinks are properly bind-mounted"):
$machine->succeed('chroot-exec cat ${symlink} >&2'); machine.fail("chroot-exec test -e /etc")
$machine->succeed('test "$(chroot-exec cat ${symlink})" = "got me"'); machine.succeed(
"chroot-exec cat ${symlink} >&2",
'test "$(chroot-exec cat ${symlink})" = "got me"',
)
''; '';
}) })
{ description = "check if StateDirectory works"; { config.serviceConfig.User = "chroot-testuser";
config.serviceConfig.User = "chroot-testuser";
config.serviceConfig.Group = "chroot-testgroup"; config.serviceConfig.Group = "chroot-testgroup";
config.serviceConfig.StateDirectory = "testme"; config.serviceConfig.StateDirectory = "testme";
testScript = '' testScript = ''
$machine->succeed('chroot-exec touch /tmp/canary'); with subtest("check if StateDirectory works"):
$machine->succeed('chroot-exec "echo works > /var/lib/testme/foo"'); machine.succeed("chroot-exec touch /tmp/canary")
$machine->succeed('test "$(< /var/lib/testme/foo)" = works'); machine.succeed('chroot-exec "echo works > /var/lib/testme/foo"')
$machine->succeed('test ! -e /tmp/canary'); machine.succeed('test "$(< /var/lib/testme/foo)" = works')
machine.succeed("test ! -e /tmp/canary")
''; '';
} }
{ description = "check if /bin/sh works"; { testScript = ''
with subtest("check if /bin/sh works"):
machine.succeed(
"chroot-exec test -e /bin/sh",
'test "$(chroot-exec \'/bin/sh -c "echo bar"\')" = bar',
)
'';
}
{ config.confinement.binSh = null;
testScript = '' testScript = ''
$machine->succeed( with subtest("check if suppressing /bin/sh works"):
'chroot-exec test -e /bin/sh', machine.succeed("chroot-exec test ! -e /bin/sh")
'test "$(chroot-exec \'/bin/sh -c "echo bar"\')" = bar', machine.succeed('test "$(chroot-exec \'/bin/sh -c "echo foo"\')" != foo')
);
''; '';
} }
{ description = "check if suppressing /bin/sh works"; { config.confinement.binSh = "${pkgs.hello}/bin/hello";
config.confinement.binSh = null;
testScript = '' testScript = ''
$machine->succeed( with subtest("check if we can set /bin/sh to something different"):
'chroot-exec test ! -e /bin/sh', machine.succeed("chroot-exec test -e /bin/sh")
'test "$(chroot-exec \'/bin/sh -c "echo foo"\')" != foo', machine.succeed('test "$(chroot-exec /bin/sh -g foo)" = foo')
);
''; '';
} }
{ description = "check if we can set /bin/sh to something different"; { config.environment.FOOBAR = pkgs.writeText "foobar" "eek\n";
config.confinement.binSh = "${pkgs.hello}/bin/hello";
testScript = '' testScript = ''
$machine->succeed( with subtest("check if only Exec* dependencies are included"):
'chroot-exec test -e /bin/sh', machine.succeed('test "$(chroot-exec \'cat "$FOOBAR"\')" != eek')
'test "$(chroot-exec /bin/sh -g foo)" = foo',
);
''; '';
} }
{ description = "check if only Exec* dependencies are included"; { config.environment.FOOBAR = pkgs.writeText "foobar" "eek\n";
config.environment.FOOBAR = pkgs.writeText "foobar" "eek\n";
testScript = ''
$machine->succeed('test "$(chroot-exec \'cat "$FOOBAR"\')" != eek');
'';
}
{ description = "check if all unit dependencies are included";
config.environment.FOOBAR = pkgs.writeText "foobar" "eek\n";
config.confinement.fullUnit = true; config.confinement.fullUnit = true;
testScript = '' testScript = ''
$machine->succeed('test "$(chroot-exec \'cat "$FOOBAR"\')" = eek'); with subtest("check if all unit dependencies are included"):
machine.succeed('test "$(chroot-exec \'cat "$FOOBAR"\')" = eek')
''; '';
} }
]; ];
@ -162,7 +156,6 @@ import ./make-test.nix {
}; };
testScript = { nodes, ... }: '' testScript = { nodes, ... }: ''
$machine->waitForUnit('multi-user.target'); machine.wait_for_unit("multi-user.target")
${nodes.machine.config.__testSteps} '' + nodes.machine.config.__testSteps;
'';
} }