]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
machined: add GetMachineSSHInfo method
authorSam Leonard <sam.leonard@codethink.co.uk>
Wed, 24 Apr 2024 17:08:13 +0000 (18:08 +0100)
committerLuca Boccassi <bluca@debian.org>
Wed, 8 May 2024 08:56:42 +0000 (09:56 +0100)
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
src/machine/machine-dbus.c
src/machine/machine-dbus.h
src/machine/machine.c
src/machine/machine.h
src/machine/machined-dbus.c

index cc4e61d2d476c783c444fc177850d64915babd90..24bef6a755c63d324958b073d39a4eb380a41b1f 100644 (file)
@@ -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 {
 
     <variablelist class="dbus-method" generated="True" extra-ref="GetMachineAddresses()"/>
 
+    <variablelist class="dbus-method" generated="True" extra-ref="GetMachineSSHInfo()"/>
+
     <variablelist class="dbus-method" generated="True" extra-ref="GetMachineOSRelease()"/>
 
     <variablelist class="dbus-method" generated="True" extra-ref="OpenMachinePTY()"/>
@@ -378,6 +383,10 @@ node /org/freedesktop/machine1 {
       <constant>AF_INET6</constant>) and a byte array containing the addresses. This is only supported for
       containers that make use of network namespacing.</para>
 
+      <para><function>GetMachineSSHInfo()</function> 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.</para>
+
       <para><function>GetMachineOSRelease()</function> retrieves the OS release information of a
       container. This method returns an array of key value pairs read from the
       <citerefentry><refentrytitle>os-release</refentrytitle><manvolnum>5</manvolnum></citerefentry> 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 {
 
     <variablelist class="dbus-method" generated="True" extra-ref="GetAddresses()"/>
 
+    <variablelist class="dbus-method" generated="True" extra-ref="GetSSHInfo()"/>
+
     <variablelist class="dbus-method" generated="True" extra-ref="GetOSRelease()"/>
 
     <variablelist class="dbus-method" generated="True" extra-ref="GetUIDShift()"/>
@@ -590,6 +609,12 @@ node /org/freedesktop/machine1/machine/rawhide {
 
     <variablelist class="dbus-property" generated="True" extra-ref="NetworkInterfaces"/>
 
+    <variablelist class="dbus-property" generated="True" extra-ref="VSockCID"/>
+
+    <variablelist class="dbus-property" generated="True" extra-ref="SSHAddress"/>
+
+    <variablelist class="dbus-property" generated="True" extra-ref="SSHPrivateKeyPath"/>
+
     <variablelist class="dbus-property" generated="True" extra-ref="State"/>
 
     <!--End of Autogenerated section-->
@@ -601,9 +626,9 @@ node /org/freedesktop/machine1/machine/rawhide {
       take the same arguments as <function>TerminateMachine()</function> and
       <function>KillMachine()</function> on the Manager interface, respectively.</para>
 
-      <para><function>GetAddresses()</function> and <function>GetOSRelease()</function> get the IP address and OS
-      release information from the machine. These methods take the same arguments as
-      <function>GetMachineAddresses()</function> and <function>GetMachineOSRelease()</function> of the
+      <para><function>GetAddresses()</function>, <function>GetSSHInfo()</function> and <function>GetOSRelease()</function> get the IP address,
+      SSH connection and OS release information from the machine. These methods take the same arguments as
+      <function>GetMachineAddresses()</function>, <function>GetMachineSSHInfo()</function> and <function>GetMachineOSRelease()</function> of the
       Manager interface, respectively.</para>
     </refsect2>
 
@@ -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
       <function>CreateMachineWithNetwork()</function> above.</para>
 
+      <para><varname>VSockCID</varname> is the VSOCK CID of the VM if it is known, or
+      <constant>VMADDR_CID_ANY</constant> otherwise.</para>
+
+      <para><varname>SSHAddress</varname> is the address of the VM in a format <command>ssh</command> can understand
+      if it is known or the empty string.</para>
+
+      <para><varname>SSHPrivateKeyPath</varname> is the path to the SSH private key of the VM if it is known
+      or the empty string.</para>
+
       <para><varname>State</varname> is the state of the machine and is one of <literal>opening</literal>,
       <literal>running</literal>, or <literal>closing</literal>. 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 \
       <title>The Manager Object</title>
       <para><function>CopyFromMachineWithFlags()</function> and
       <function>CopyToMachineWithFlags()</function> were added in version 252.</para>
+      <para><function>GetMachineSSHInfo()</function> was added in version 256.</para>
     </refsect2>
     <refsect2>
       <title>Machine Objects</title>
       <para><function>CopyFromWithFlags()</function> and
       <function>CopyToWithFlags()</function> were added in version 252.</para>
+      <para><function>GetSSHInfo()</function>, <varname>VSockCID</varname>, <varname>SSHAddress</varname>
+      and <varname>SSHPrivateKeyPath</varname> were added in version 256.</para>
     </refsect2>
   </refsect1>
 </refentry>
index a7a53eacaf8861f49c585b3c1fdcf62169a77103..a4f04c0b86df39abb7a4a5d7594b28a7247036bf 100644 (file)
@@ -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),
index a0133451abcd36fb8318fac5dce416337098fcfb..fccad71d12a13cc18fd703da8defd62b2f95cea0 100644 (file)
@@ -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);
index 2b71ae99661143bfb222cc3a8d091b1f7638f8a0..5c21a039e5e351990b13e095f06e498b61bb2327 100644 (file)
@@ -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);
 }
 
index 24ef15894bf809448b171b53ebc4d692f4379c96..f8146fb55b8da8eee6ff530f99f6d2fcece7fbe9 100644 (file)
@@ -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);
index e7c7f6fd69598b70451b2b61cd8b795321a454d8..dbb03f3d67d073de03db9c087ae5d6dfdfe9efb1 100644 (file)
@@ -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),