]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
machined: allow unprivileged registration of VMs/containers
authorLennart Poettering <lennart@poettering.net>
Sat, 11 May 2024 18:18:56 +0000 (20:18 +0200)
committerLennart Poettering <lennart@poettering.net>
Fri, 21 Jun 2024 15:38:23 +0000 (17:38 +0200)
Now that we have a concept of unprivileged VMs and containers, let's
allow unprivileged clients to register with machined too – subject to
Polkit permissions.

src/machine/machine-varlink.c
src/machine/machined-varlink.c
src/machine/org.freedesktop.machine1.policy
src/shared/varlink-io.systemd.Machine.c
src/vmspawn/vmspawn-register.c
src/vmspawn/vmspawn.c

index 6f437c06c4e5924427a79c7dc8a386a81cab4f7b..ea300d71deeb97dfe6040a2add632c25ff6b9052 100644 (file)
@@ -5,6 +5,7 @@
 #include "sd-id128.h"
 #include "sd-json.h"
 
+#include "bus-polkit.h"
 #include "hostname-util.h"
 #include "json-util.h"
 #include "machine-varlink.h"
@@ -136,6 +137,7 @@ int vl_method_register(Varlink *link, sd_json_variant *parameters, VarlinkMethod
                 { "vSockCid",          SD_JSON_VARIANT_UNSIGNED, machine_cid,             offsetof(Machine, vsock_cid),            0                 },
                 { "sshAddress",        SD_JSON_VARIANT_STRING,   sd_json_dispatch_string, offsetof(Machine, ssh_address),          SD_JSON_STRICT    },
                 { "sshPrivateKeyPath", SD_JSON_VARIANT_STRING,   json_dispatch_path,      offsetof(Machine, ssh_private_key_path), 0                 },
+                VARLINK_DISPATCH_POLKIT_FIELD,
                 {}
         };
 
@@ -147,6 +149,16 @@ int vl_method_register(Varlink *link, sd_json_variant *parameters, VarlinkMethod
         if (r != 0)
                 return r;
 
+        r = varlink_verify_polkit_async(
+                        link,
+                        manager->bus,
+                        "org.freedesktop.machine1.create-machine",
+                        (const char**) STRV_MAKE("name", machine->name,
+                                                 "class", machine_class_to_string(machine->class)),
+                        &manager->polkit_registry);
+        if (r <= 0)
+                return r;
+
         if (!pidref_is_set(&machine->leader)) {
                 r = varlink_get_peer_pidref(link, &machine->leader);
                 if (r < 0)
index dc35877c497af25a7234f2fa51dcaa56590447e0..bd092bb2827dc38bf442b7297e126a9205ba9a79 100644 (file)
@@ -433,7 +433,7 @@ static int manager_varlink_init_machine(Manager *m) {
         if (m->varlink_machine_server)
                 return 0;
 
-        r = varlink_server_new(&s, VARLINK_SERVER_ROOT_ONLY|VARLINK_SERVER_INHERIT_USERDATA);
+        r = varlink_server_new(&s, VARLINK_SERVER_ACCOUNT_UID|VARLINK_SERVER_INHERIT_USERDATA);
         if (r < 0)
                 return log_error_errno(r, "Failed to allocate varlink server object: %m");
 
index f031e4e480089cb8849be0ab245fef2720ff1f1c..fe125ed0db344b9cc93eaaaef6c046416ec0308d 100644 (file)
                 <annotate key="org.freedesktop.policykit.imply">org.freedesktop.login1.shell org.freedesktop.login1.login</annotate>
         </action>
 
+        <action id="org.freedesktop.machine1.create-machine">
+                <description gettext-domain="systemd">Create a local virtual machine or container</description>
+                <message gettext-domain="systemd">Authentication is required to create a local virtual machine or container.</message>
+                <defaults>
+                        <allow_any>auth_admin</allow_any>
+                        <allow_inactive>auth_admin</allow_inactive>
+                        <allow_active>auth_admin_keep</allow_active>
+                </defaults>
+                <annotate key="org.freedesktop.policykit.imply">org.freedesktop.login1.shell org.freedesktop.login1.login</annotate>
+        </action>
+
         <action id="org.freedesktop.machine1.manage-images">
                 <description gettext-domain="systemd">Manage local virtual machine and container images</description>
                 <message gettext-domain="systemd">Authentication is required to manage local virtual machine and container images.</message>
index 2d25a345d7979b92e1fff86737996260ed953d6c..76eaf7d13c7968fa552a272cee31ec8388be8c38 100644 (file)
@@ -14,7 +14,9 @@ static VARLINK_DEFINE_METHOD(
                 VARLINK_DEFINE_INPUT(ifIndices,         VARLINK_INT,    VARLINK_ARRAY|VARLINK_NULLABLE),
                 VARLINK_DEFINE_INPUT(vSockCid,          VARLINK_INT,    VARLINK_NULLABLE),
                 VARLINK_DEFINE_INPUT(sshAddress,        VARLINK_STRING, VARLINK_NULLABLE),
-                VARLINK_DEFINE_INPUT(sshPrivateKeyPath, VARLINK_STRING, VARLINK_NULLABLE));
+                VARLINK_DEFINE_INPUT(sshPrivateKeyPath, VARLINK_STRING, VARLINK_NULLABLE),
+                VARLINK_FIELD_COMMENT("Whether to allow interactive authentication on this operation."),
+                VARLINK_DEFINE_INPUT(allowInteractiveAuthentication, VARLINK_BOOL, VARLINK_NULLABLE));
 
 static VARLINK_DEFINE_ERROR(MachineExists);
 
index 2140bba9cd8146a6e0d5bfd725b160731d5f9ec7..2130fd9108badb6847bab6f23c6f7a484f5e24e8 100644 (file)
@@ -70,7 +70,8 @@ int register_machine(
                         SD_JSON_BUILD_PAIR_CONDITION(VSOCK_CID_IS_REGULAR(cid), "vSockCid", SD_JSON_BUILD_UNSIGNED(cid)),
                         SD_JSON_BUILD_PAIR_CONDITION(!!directory, "rootDirectory", SD_JSON_BUILD_STRING(directory)),
                         SD_JSON_BUILD_PAIR_CONDITION(!!address, "sshAddress", SD_JSON_BUILD_STRING(address)),
-                        SD_JSON_BUILD_PAIR_CONDITION(!!key_path, "sshPrivateKeyPath", SD_JSON_BUILD_STRING(key_path)));
+                        SD_JSON_BUILD_PAIR_CONDITION(!!key_path, "sshPrivateKeyPath", SD_JSON_BUILD_STRING(key_path)),
+                        SD_JSON_BUILD_PAIR_CONDITION(isatty(STDIN_FILENO), "allowInteractiveAuthentication", SD_JSON_BUILD_BOOLEAN(true)));
 }
 
 int unregister_machine(sd_bus *bus, const char *machine_name) {
index 73e165feaddc8149372d0e62e616c857d8e39f13..971844e10c721282ccb04f123b57058d84f5629e 100644 (file)
@@ -2229,9 +2229,6 @@ static int verify_arguments(void) {
         if (!strv_isempty(arg_initrds) && !arg_linux)
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Option --initrd= cannot be used without --linux=.");
 
-        if (arg_register && !arg_privileged)
-                return log_error_errno(SYNTHETIC_ERRNO(EPERM), "--register= requires root privileges, refusing.");
-
         return 0;
 }