]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core: also check boot ID and product UUID in ConditionHost=
authorLennart Poettering <lennart@poettering.net>
Wed, 19 Feb 2025 16:15:41 +0000 (17:15 +0100)
committerLennart Poettering <lennart@poettering.net>
Thu, 20 Feb 2025 17:13:38 +0000 (18:13 +0100)
Sometimes it's interesting to condition units not just on the
installation but on the physical device. Let's make ConditionHost=
useful for that kind of checks, and while we are at it, also allow it to
be used for condition checks on the boot id.

Overloading like this is safe, since UUIDs are globally unique after
all, and hence there should be no conflicts between the namespace of
boot ids, machine ids and product ids.

Finally, relax rules on uuid checking: if the specified string parses
as uuid or id, also check it against the hostname, for setups where
people name hosts after uuids. I wouldn't know why anyone would do that,
but also, why not? shouldn'rt hurt allowing them and should not create
ambiguity conflicts.

man/systemd.unit.xml
src/shared/condition.c

index 6280300608626ac6c16757ffe5e9185f6406bbf2..e931ef6f76b2fb893ca548c7dbdbba542fcdfc57 100644 (file)
         <varlistentry>
           <term><varname>ConditionHost=</varname></term>
 
-          <listitem><para><varname>ConditionHost=</varname> may be used to match against the hostname or
-          machine ID of the host. This either takes a hostname string (optionally with shell style globs)
-          which is tested against the locally set hostname as returned by
+          <listitem><para><varname>ConditionHost=</varname> may be used to match against the hostname,
+          machine ID, boot ID or product UUID of the host. This either takes a hostname string (optionally
+          with shell style globs) which is tested against the locally set hostname as returned by
           <citerefentry><refentrytitle>gethostname</refentrytitle><manvolnum>2</manvolnum></citerefentry>, or
-          a machine ID formatted as string (see
-          <citerefentry><refentrytitle>machine-id</refentrytitle><manvolnum>5</manvolnum></citerefentry>).
-          The test may be negated by prepending an exclamation mark.</para>
+          a 128bit ID or UUID, formatted as string. The latter is compared against machine ID, boot ID and the
+          firmware product UUID if there is any. See
+          <citerefentry><refentrytitle>machine-id</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
+          details about the machine ID. The test may be negated by prepending an exclamation mark.</para>
 
           <xi:include href="version-info.xml" xpointer="v244"/>
           </listitem>
index c0c656d2e6996b146096d643f574faf72f091a84..ebfd1e1aabe53d057ddf382206680ab6dc104a18 100644 (file)
@@ -40,6 +40,7 @@
 #include "glob-util.h"
 #include "hostname-util.h"
 #include "ima-util.h"
+#include "id128-util.h"
 #include "initrd-util.h"
 #include "limits-util.h"
 #include "list.h"
@@ -622,20 +623,36 @@ static int condition_test_firmware(Condition *c, char **env) {
 
 static int condition_test_host(Condition *c, char **env) {
         _cleanup_free_ char *h = NULL;
-        sd_id128_t x, y;
         int r;
 
         assert(c);
         assert(c->parameter);
         assert(c->type == CONDITION_HOST);
 
+        sd_id128_t x;
         if (sd_id128_from_string(c->parameter, &x) >= 0) {
+                static const struct {
+                        const char *name;
+                        int (*get_id)(sd_id128_t *ret);
+                } table[] = {
+                        { "machine ID",   sd_id128_get_machine },
+                        { "boot ID",      sd_id128_get_boot    },
+                        { "product UUID", id128_get_product    },
+                };
+
+                /* If this is a UUID, check if this matches the machine ID, boot ID or product UUID */
+                FOREACH_ELEMENT(i, table) {
+                        sd_id128_t y;
+
+                        r = i->get_id(&y);
+                        if (r < 0)
+                                log_debug_errno(r, "Failed to get %s, ignoring: %m", i->name);
+                        else if (sd_id128_equal(x, y))
+                                return true;
+                }
 
-                r = sd_id128_get_machine(&y);
-                if (r < 0)
-                        return r;
-
-                return sd_id128_equal(x, y);
+                /* Fall through, also allow setups where people set hostnames to UUIDs. Kinda weird, but no
+                 * reason not to allow that */
         }
 
         h = gethostname_malloc();