summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWeijia Wang <9713184+wegank@users.noreply.github.com>2024-11-24 11:28:39 +0100
committerGitHub <noreply@github.com>2024-11-24 11:28:39 +0100
commit267d58a0e213fcb760fe0f4e1458b3fac4576fdc (patch)
tree641ab720966e0195bf536ec22ed273839d162abc
parent[Backport release-24.11] home-assistant-custom-components.xiaomi_miot: 0.7.21... (diff)
parentnixos/tests/incus: test incus-user (diff)
downloadnixpkgs-267d58a0e213fcb760fe0f4e1458b3fac4576fdc.tar.gz
[Backport release-24.11] nixos/incus: add incus-user service and socket (#356398)
-rw-r--r--nixos/doc/manual/release-notes/rl-2411.section.md2
-rw-r--r--nixos/modules/virtualisation/incus.nix38
-rw-r--r--nixos/tests/incus/incusd-options.nix80
3 files changed, 92 insertions, 28 deletions
diff --git a/nixos/doc/manual/release-notes/rl-2411.section.md b/nixos/doc/manual/release-notes/rl-2411.section.md
index 0fcc161f71e0..fbad6d513bc6 100644
--- a/nixos/doc/manual/release-notes/rl-2411.section.md
+++ b/nixos/doc/manual/release-notes/rl-2411.section.md
@@ -890,6 +890,8 @@
- `qgis` and `qgis-ltr` are now built without `grass` by default. `grass` support can be enabled with `qgis.override { withGrass = true; }`.
+- `virtualisation.incus` module gained new `incus-user.service` and `incus-user.socket` systemd units. It is now possible to add a user to `incus` group instead of `incus-admin` for increased security.
+
## Detailed Migration Information {#sec-release-24.11-migration}
### `sound` options removal {#sec-release-24.11-migration-sound}
diff --git a/nixos/modules/virtualisation/incus.nix b/nixos/modules/virtualisation/incus.nix
index 777e3b28f200..aa2102f49f0d 100644
--- a/nixos/modules/virtualisation/incus.nix
+++ b/nixos/modules/virtualisation/incus.nix
@@ -153,7 +153,10 @@ in
Users in the "incus-admin" group can interact with
the daemon (e.g. to start or stop containers) using the
- {command}`incus` command line tool, among others
+ {command}`incus` command line tool, among others.
+ Users in the "incus" group can also interact with
+ the daemon, but with lower permissions
+ (i.e. administrative operations are forbidden).
'';
package = lib.mkPackageOption pkgs "incus-lts" { };
@@ -359,6 +362,27 @@ in
};
};
+ systemd.services.incus-user = {
+ description = "Incus Container and Virtual Machine Management User Daemon";
+
+ inherit environment;
+
+ after = [
+ "incus.service"
+ "incus-user.socket"
+ ];
+
+ requires = [
+ "incus-user.socket"
+ ];
+
+ serviceConfig = {
+ ExecStart = "${cfg.package}/bin/incus-user --group incus";
+
+ Restart = "on-failure";
+ };
+ };
+
systemd.services.incus-startup = lib.mkIf cfg.softDaemonRestart {
description = "Incus Instances Startup/Shutdown";
@@ -391,6 +415,17 @@ in
};
};
+ systemd.sockets.incus-user = {
+ description = "Incus user UNIX socket";
+ wantedBy = [ "sockets.target" ];
+
+ socketConfig = {
+ ListenStream = "/var/lib/incus/unix.socket.user";
+ SocketMode = "0660";
+ SocketGroup = "incus";
+ };
+ };
+
systemd.services.incus-preseed = lib.mkIf (cfg.preseed != null) {
description = "Incus initialization with preseed file";
@@ -409,6 +444,7 @@ in
};
};
+ users.groups.incus = { };
users.groups.incus-admin = { };
users.users.root = {
diff --git a/nixos/tests/incus/incusd-options.nix b/nixos/tests/incus/incusd-options.nix
index a223f1c8cb55..634d236b05d9 100644
--- a/nixos/tests/incus/incusd-options.nix
+++ b/nixos/tests/incus/incusd-options.nix
@@ -44,7 +44,7 @@ import ../make-test-python.nix (
preseed = {
networks = [
{
- name = "nixostestbr0";
+ name = "incusbr0";
type = "bridge";
config = {
"ipv4.address" = "10.0.100.1/24";
@@ -58,12 +58,12 @@ import ../make-test-python.nix (
devices = {
eth0 = {
name = "eth0";
- network = "nixostestbr0";
+ network = "incusbr0";
type = "nic";
};
root = {
path = "/";
- pool = "nixostest_pool";
+ pool = "default";
size = "35GiB";
type = "disk";
};
@@ -72,43 +72,69 @@ import ../make-test-python.nix (
];
storage_pools = [
{
- name = "nixostest_pool";
+ name = "default";
driver = "dir";
}
];
};
};
+
};
+
networking.nftables.enable = true;
+
+ users.users.testuser = {
+ isNormalUser = true;
+ shell = pkgs.bashInteractive;
+ group = "incus";
+ uid = 1000;
+ };
};
- testScript = ''
- def instance_is_up(_) -> bool:
- status, _ = machine.execute("incus exec container --disable-stdin --force-interactive /run/current-system/sw/bin/systemctl -- is-system-running")
- return status == 0
+ testScript = # python
+ ''
+ def wait_for_instance(name: str, project: str = "default"):
+ def instance_is_up(_) -> bool:
+ status, _ = machine.execute(f"incus exec {name} --disable-stdin --force-interactive --project {project} -- /run/current-system/sw/bin/systemctl is-system-running")
+ return status == 0
+
+ with machine.nested(f"Waiting for instance {name} to start and be usable"):
+ retry(instance_is_up)
+
+ machine.wait_for_unit("incus.service")
+ machine.wait_for_unit("incus-preseed.service")
+
+ with subtest("Container image can be imported"):
+ machine.succeed("incus image import ${container-image-metadata} ${container-image-rootfs} --alias nixos")
- machine.wait_for_unit("incus.service")
- machine.wait_for_unit("incus-preseed.service")
+ with subtest("Container can be launched and managed"):
+ machine.succeed("incus launch nixos instance1")
+ wait_for_instance("instance1")
+ machine.succeed("echo true | incus exec instance1 /run/current-system/sw/bin/bash -")
- with subtest("Container image can be imported"):
- machine.succeed("incus image import ${container-image-metadata} ${container-image-rootfs} --alias nixos")
+ with subtest("Verify preseed resources created"):
+ machine.succeed("incus profile show default")
+ machine.succeed("incus network info incusbr0")
+ machine.succeed("incus storage show default")
- with subtest("Container can be launched and managed"):
- machine.succeed("incus launch nixos container")
- with machine.nested("Waiting for instance to start and be usable"):
- retry(instance_is_up)
- machine.succeed("echo true | incus exec container /run/current-system/sw/bin/bash -")
+ with subtest("Instance is stopped when softDaemonRestart is disabled and services is stopped"):
+ pid = machine.succeed("incus info instance1 | grep 'PID'").split(":")[1].strip()
+ machine.succeed(f"ps {pid}")
+ machine.succeed("systemctl stop incus")
+ machine.fail(f"ps {pid}")
- with subtest("Verify preseed resources created"):
- machine.succeed("incus profile show default")
- machine.succeed("incus network info nixostestbr0")
- machine.succeed("incus storage show nixostest_pool")
+ with subtest("incus-user allows restricted access for users"):
+ machine.fail("incus project show user-1000")
+ machine.succeed("su - testuser bash -c 'incus list'")
+ # a project is created dynamically for the user
+ machine.succeed("incus project show user-1000")
+ # users shouldn't be able to list storage pools
+ machine.fail("su - testuser bash -c 'incus storage list'")
- with subtest("Instance is stopped when softDaemonRestart is disabled and services is stopped"):
- pid = machine.succeed("incus info container | grep 'PID'").split(":")[1].strip()
- machine.succeed(f"ps {pid}")
- machine.succeed("systemctl stop incus")
- machine.fail(f"ps {pid}")
- '';
+ with subtest("incus-user allows users to launch instances"):
+ machine.succeed("su - testuser bash -c 'incus image import ${container-image-metadata} ${container-image-rootfs} --alias nixos'")
+ machine.succeed("su - testuser bash -c 'incus launch nixos instance2'")
+ wait_for_instance("instance2", "user-1000")
+ '';
}
)