From 1f815bf1640c7a648d323f9331cd88f19cffc2c9 Mon Sep 17 00:00:00 2001 From: Sam Leonard Date: Wed, 24 Apr 2024 18:08:13 +0100 Subject: [PATCH] machined: add GetMachineSSHInfo method Also adds three properties: - VsockCid: the VSOCK CID of the VM - SshAddress: the address of the VM in a format SSH can connect to - SshPrivateKeyPath: the path to the SSH private key to use to connect to the VM. GetMachineSSHInfo is essentially a convenience method to query both the SshAddress and SshPrivateKeyPath properties at once. --- man/org.freedesktop.machine1.xml | 43 +++++++++++++++++++++++++++++--- src/machine/machine-dbus.c | 29 +++++++++++++++++++++ src/machine/machine-dbus.h | 1 + src/machine/machine.c | 4 +++ src/machine/machine.h | 4 +++ src/machine/machined-dbus.c | 9 +++++++ 6 files changed, 87 insertions(+), 3 deletions(-) diff --git a/man/org.freedesktop.machine1.xml b/man/org.freedesktop.machine1.xml index cc4e61d2d47..24bef6a755c 100644 --- a/man/org.freedesktop.machine1.xml +++ b/man/org.freedesktop.machine1.xml @@ -89,6 +89,9 @@ node /org/freedesktop/machine1 { in i signal); GetMachineAddresses(in s name, out a(iay) addresses); + GetMachineSSHInfo(in s name, + out s ssh_address, + out s ssh_private_key_path); GetMachineOSRelease(in s name, out a{ss} fields); @org.freedesktop.systemd1.Privileged("true") @@ -230,6 +233,8 @@ node /org/freedesktop/machine1 { + + @@ -378,6 +383,10 @@ node /org/freedesktop/machine1 { AF_INET6) and a byte array containing the addresses. This is only supported for containers that make use of network namespacing. + GetMachineSSHInfo() retrieves the SSH information of a machine. This method + returns two strings, the SSH address which can be used to tell SSH where to connect, and the path + to the SSH private key required for the connection to succeed. + GetMachineOSRelease() retrieves the OS release information of a container. This method returns an array of key value pairs read from the os-release5 file in @@ -459,6 +468,8 @@ node /org/freedesktop/machine1/machine/rawhide { Kill(in s who, in i signal); GetAddresses(out a(iay) addresses); + GetSSHInfo(out s ssh_address, + out s ssh_private_key_path); GetOSRelease(out a{ss} fields); GetUIDShift(out u shift); OpenPTY(out h pty, @@ -507,6 +518,12 @@ node /org/freedesktop/machine1/machine/rawhide { readonly s RootDirectory = '...'; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") readonly ai NetworkInterfaces = [...]; + @org.freedesktop.DBus.Property.EmitsChangedSignal("const") + readonly u VSockCID = ...; + @org.freedesktop.DBus.Property.EmitsChangedSignal("const") + readonly s SSHAddress = '...'; + @org.freedesktop.DBus.Property.EmitsChangedSignal("const") + readonly s SSHPrivateKeyPath = '...'; @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly s State = '...'; }; @@ -548,6 +565,8 @@ node /org/freedesktop/machine1/machine/rawhide { + + @@ -590,6 +609,12 @@ node /org/freedesktop/machine1/machine/rawhide { + + + + + + @@ -601,9 +626,9 @@ node /org/freedesktop/machine1/machine/rawhide { take the same arguments as TerminateMachine() and KillMachine() on the Manager interface, respectively. - GetAddresses() and GetOSRelease() get the IP address and OS - release information from the machine. These methods take the same arguments as - GetMachineAddresses() and GetMachineOSRelease() of the + GetAddresses(), GetSSHInfo() and GetOSRelease() get the IP address, + SSH connection and OS release information from the machine. These methods take the same arguments as + GetMachineAddresses(), GetMachineSSHInfo() and GetMachineOSRelease() of the Manager interface, respectively. @@ -636,6 +661,15 @@ node /org/freedesktop/machine1/machine/rawhide { towards the container, the VM or the host. For details about this information see the description of CreateMachineWithNetwork() above. + VSockCID is the VSOCK CID of the VM if it is known, or + VMADDR_CID_ANY otherwise. + + SSHAddress is the address of the VM in a format ssh can understand + if it is known or the empty string. + + SSHPrivateKeyPath is the path to the SSH private key of the VM if it is known + or the empty string. + State is the state of the machine and is one of opening, running, or closing. Note that the state machine is not considered part of the API and states might be removed or added without this being considered API breakage. @@ -675,11 +709,14 @@ $ gdbus introspect --system \ The Manager Object CopyFromMachineWithFlags() and CopyToMachineWithFlags() were added in version 252. + GetMachineSSHInfo() was added in version 256. Machine Objects CopyFromWithFlags() and CopyToWithFlags() were added in version 252. + GetSSHInfo(), VSockCID, SSHAddress + and SSHPrivateKeyPath were added in version 256. diff --git a/src/machine/machine-dbus.c b/src/machine/machine-dbus.c index a7a53eacaf8..a4f04c0b86d 100644 --- a/src/machine/machine-dbus.c +++ b/src/machine/machine-dbus.c @@ -347,6 +347,27 @@ int bus_machine_method_get_addresses(sd_bus_message *message, void *userdata, sd return sd_bus_send(NULL, reply, NULL); } +int bus_machine_method_get_ssh_info(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + Machine *m = ASSERT_PTR(userdata); + int r; + + assert(message); + + r = sd_bus_message_new_method_return(message, &reply); + if (r < 0) + return r; + + if (!m->ssh_address || !m->ssh_private_key_path) + return -ENOENT; + + r = sd_bus_message_append(reply, "ss", m->ssh_address, m->ssh_private_key_path); + if (r < 0) + return r; + + return sd_bus_send(NULL, reply, NULL); +} + #define EXIT_NOT_FOUND 2 int bus_machine_method_get_os_release(sd_bus_message *message, void *userdata, sd_bus_error *error) { @@ -1261,6 +1282,9 @@ static const sd_bus_vtable machine_vtable[] = { SD_BUS_PROPERTY("Class", "s", property_get_class, offsetof(Machine, class), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(Machine, root_directory), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("NetworkInterfaces", "ai", property_get_netif, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("VSockCID", "u", NULL, offsetof(Machine, vsock_cid), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("SSHAddress", "s", NULL, offsetof(Machine, ssh_address), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("SSHPrivateKeyPath", "s", NULL, offsetof(Machine, ssh_private_key_path), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("State", "s", property_get_state, 0, 0), SD_BUS_METHOD("Terminate", @@ -1278,6 +1302,11 @@ static const sd_bus_vtable machine_vtable[] = { SD_BUS_RESULT("a(iay)", addresses), bus_machine_method_get_addresses, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD_WITH_ARGS("GetSSHInfo", + SD_BUS_NO_ARGS, + SD_BUS_RESULT("s", ssh_address, "s", ssh_private_key_path), + bus_machine_method_get_ssh_info, + SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD_WITH_ARGS("GetOSRelease", SD_BUS_NO_ARGS, SD_BUS_RESULT("a{ss}", fields), diff --git a/src/machine/machine-dbus.h b/src/machine/machine-dbus.h index a0133451abc..fccad71d12a 100644 --- a/src/machine/machine-dbus.h +++ b/src/machine/machine-dbus.h @@ -19,6 +19,7 @@ int bus_machine_method_unregister(sd_bus_message *message, void *userdata, sd_bu int bus_machine_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_machine_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_machine_method_get_addresses(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_machine_method_get_ssh_info(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_machine_method_get_os_release(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_machine_method_open_pty(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_machine_method_open_login(sd_bus_message *message, void *userdata, sd_bus_error *error); diff --git a/src/machine/machine.c b/src/machine/machine.c index 2b71ae99661..5c21a039e5e 100644 --- a/src/machine/machine.c +++ b/src/machine/machine.c @@ -27,6 +27,7 @@ #include "path-util.h" #include "process-util.h" #include "serialize.h" +#include "socket-util.h" #include "special.h" #include "stdio-util.h" #include "string-table.h" @@ -53,6 +54,7 @@ int machine_new(MachineClass class, const char *name, Machine **ret) { *m = (Machine) { .leader = PIDREF_NULL, + .vsock_cid = VMADDR_CID_ANY, }; if (name) { @@ -130,6 +132,8 @@ Machine* machine_free(Machine *m) { free(m->service); free(m->root_directory); free(m->netif); + free(m->ssh_address); + free(m->ssh_private_key_path); return mfree(m); } diff --git a/src/machine/machine.h b/src/machine/machine.h index 24ef15894bf..f8146fb55b8 100644 --- a/src/machine/machine.h +++ b/src/machine/machine.h @@ -62,6 +62,10 @@ struct Machine { int *netif; size_t n_netif; + unsigned vsock_cid; + char *ssh_address; + char *ssh_private_key_path; + LIST_HEAD(Operation, operations); LIST_FIELDS(Machine, gc_queue); diff --git a/src/machine/machined-dbus.c b/src/machine/machined-dbus.c index e7c7f6fd695..dbb03f3d67d 100644 --- a/src/machine/machined-dbus.c +++ b/src/machine/machined-dbus.c @@ -462,6 +462,10 @@ static int method_get_machine_addresses(sd_bus_message *message, void *userdata, return redirect_method_to_machine(message, userdata, error, bus_machine_method_get_addresses); } +static int method_get_machine_ssh_info(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return redirect_method_to_machine(message, userdata, error, bus_machine_method_get_ssh_info); +} + static int method_get_machine_os_release(sd_bus_message *message, void *userdata, sd_bus_error *error) { return redirect_method_to_machine(message, userdata, error, bus_machine_method_get_os_release); } @@ -1067,6 +1071,11 @@ const sd_bus_vtable manager_vtable[] = { SD_BUS_RESULT("a(iay)", addresses), method_get_machine_addresses, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD_WITH_ARGS("GetMachineSSHInfo", + SD_BUS_ARGS("s", name), + SD_BUS_RESULT("s", ssh_address, "s", ssh_private_key_path), + method_get_machine_ssh_info, + SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD_WITH_ARGS("GetMachineOSRelease", SD_BUS_ARGS("s", name), SD_BUS_RESULT("a{ss}", fields),