]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
firstboot: allow provisioning of firstboot params via creds too
authorLennart Poettering <lennart@poettering.net>
Thu, 11 Mar 2021 10:47:57 +0000 (11:47 +0100)
committerLennart Poettering <lennart@poettering.net>
Fri, 26 Mar 2021 11:21:18 +0000 (12:21 +0100)
man/systemd-firstboot.xml
src/firstboot/firstboot.c
units/systemd-firstboot.service

index 100192490230d8caea9dd8844489d63a8b771fc9..46fe0a0682cea690e80d61c50ad62ed2185f81d7 100644 (file)
       <xi:include href="standard-options.xml" xpointer="help" />
       <xi:include href="standard-options.xml" xpointer="version" />
     </variablelist>
+  </refsect1>
+
+  <refsect1>
+    <title>Credentials</title>
+
+    <para><command>systemd-firstboot</command> supports the service credentials logic as implemented by
+    <varname>LoadCredential=</varname>/<varname>SetCredential=</varname> (see
+    <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>1</manvolnum></citerefentry> for
+    details). The following credentials are used when passed in:</para>
+
+    <variablelist>
+      <varlistentry>
+        <term><literal>passwd.hashed-password.root</literal></term>
+        <term><literal>passwd.plaintext-password.root</literal></term>
+
+        <listitem><para>A hashed or plaintext version of the root password to use, in place of prompting the
+        user. These credentials are equivalent to the same ones defined for the
+        <citerefentry><refentrytitle>systemd-sysusers.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+        service.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><literal>passwd.shell.root</literal></term>
+
+        <listitem><para>Specifies the shell binary to use for the the specified account when creating
+        it. Equivalent to the credential of the same name defined for the
+        <citerefentry><refentrytitle>systemd-sysusers.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+        service.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><literal>firstboot.locale</literal></term>
+        <term><literal>firstboot.locale-messages</literal></term>
+
+        <listitem><para>These credentials specify the locale settings to set during first boot, in place of
+        prompting the user.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><literal>firstboot.keymap</literal></term>
+
+        <listitem><para>This credential specifies the keyboard setting to set during first boot, in place of
+        prompting the user.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><literal>firstboot.timezone</literal></term>
+
+        <listitem><para>This credential specifies the system timezone setting to set during first boot, in
+        place of prompting the user.</para></listitem>
+      </varlistentry>
+    </variablelist>
+
+    <para>Note that by default the <filename>systemd-firstboot.service</filename> unit file is set up to
+    inherit the listed credentials
+    from the service manager. Thus, when invoking a container with an unpopulated <filename>/etc/</filename>
+    for the first time it is possible to configure the root user's password to be <literal>systemd</literal>
+    like this:</para>
+
+    <para><programlisting># systemd-nspawn --image=… --set-credential=firstboot.locale:de_DE.UTF-8 …</programlisting></para>
 
+    <para>Note that these credentials are only read and applied during the first boot process. Once they are
+    applied they remain applied for subsequent boots, and the credentials are not considered anymore.</para>
   </refsect1>
 
   <refsect1>
index 42b9ca776f92c904ba141b974948c4c37358cc79..01af1033e5f11f45317181d3ea925784394d2568 100644 (file)
@@ -10,6 +10,7 @@
 #include "alloc-util.h"
 #include "ask-password-api.h"
 #include "copy.h"
+#include "creds-util.h"
 #include "dissect-image.h"
 #include "env-file.h"
 #include "fd-util.h"
@@ -232,11 +233,29 @@ static bool locale_is_ok(const char *name) {
 
 static int prompt_locale(void) {
         _cleanup_strv_free_ char **locales = NULL;
+        bool acquired_from_creds = false;
         int r;
 
         if (arg_locale || arg_locale_messages)
                 return 0;
 
+        r = read_credential("firstboot.locale", (void**) &arg_locale, NULL);
+        if (r < 0)
+                log_debug_errno(r, "Failed to read credential firstboot.locale, ignoring: %m");
+        else
+                acquired_from_creds = true;
+
+        r = read_credential("firstboot.locale-messages", (void**) &arg_locale_messages, NULL);
+        if (r < 0)
+                log_debug_errno(r, "Failed to read credential firstboot.locale-message, ignoring: %m");
+        else
+                acquired_from_creds = true;
+
+        if (acquired_from_creds) {
+                log_debug("Acquired locale from credentials.");
+                return 0;
+        }
+
         if (!arg_prompt_locale)
                 return 0;
 
@@ -336,6 +355,14 @@ static int prompt_keymap(void) {
         if (arg_keymap)
                 return 0;
 
+        r = read_credential("firstboot.keymap", (void**) &arg_keymap, NULL);
+        if (r < 0)
+                log_debug_errno(r, "Failed to read credential firstboot.keymap, ignoring: %m");
+        else {
+                log_debug("Acquired keymap from credential.");
+                return 0;
+        }
+
         if (!arg_prompt_keymap)
                 return 0;
 
@@ -407,6 +434,14 @@ static int prompt_timezone(void) {
         if (arg_timezone)
                 return 0;
 
+        r = read_credential("firstboot.timezone", (void**) &arg_timezone, NULL);
+        if (r < 0)
+                log_debug_errno(r, "Failed to read credential firstboot.timezone, ignoring: %m");
+        else {
+                log_debug("Acquired timezone from credential.");
+                return 0;
+        }
+
         if (!arg_prompt_timezone)
                 return 0;
 
@@ -558,6 +593,22 @@ static int prompt_root_password(void) {
         if (arg_root_password)
                 return 0;
 
+        r = read_credential("passwd.hashed-password.root", (void**) &arg_root_password, NULL);
+        if (r == -ENOENT) {
+                r = read_credential("passwd.plaintext-password.root", (void**) &arg_root_password, NULL);
+                if (r < 0)
+                        log_debug_errno(r, "Couldn't read credential 'passwd.{hashed|plaintext}-password.root', ignoring: %m");
+                else {
+                        arg_root_password_is_hashed = false;
+                        return 0;
+                }
+        } else if (r < 0)
+                log_debug_errno(r, "Couldn't read credential 'passwd.hashed-password.root', ignoring: %m");
+        else {
+                arg_root_password_is_hashed = true;
+                return 0;
+        }
+
         if (!arg_prompt_root_password)
                 return 0;
 
@@ -631,7 +682,18 @@ static int find_shell(const char *path, const char *root) {
 static int prompt_root_shell(void) {
         int r;
 
-        if (arg_root_shell || !arg_prompt_root_shell)
+        if (arg_root_shell)
+                return 0;
+
+        r = read_credential("passwd.shell.root", (void**) &arg_root_shell, NULL);
+        if (r < 0)
+                log_debug_errno(r, "Failed to read credential passwd.shell.root, ignoring: %m");
+        else {
+                log_debug("Acquired root shell from credential.");
+                return 0;
+        }
+
+        if (!arg_prompt_root_shell)
                 return 0;
 
         print_welcome();
index d7f445ef359f1ad2d00704c7f74dfc2a41b87f85..2e57b064c183d9a2219fa97829109d458578bd17 100644 (file)
@@ -25,3 +25,14 @@ ExecStart=systemd-firstboot --prompt-locale --prompt-timezone --prompt-root-pass
 StandardOutput=tty
 StandardInput=tty
 StandardError=tty
+
+# Optionally, pick up basic fields from credentials passed to the service
+# manager. This is useful for importing this data from nspawn's
+# --set-credential= switch.
+LoadCredential=passwd.hashed-password.root
+LoadCredential=passwd.plaintext-password.root
+LoadCredential=passwd.shell.root
+LoadCredential=firstboot.locale
+LoadCredential=firstboot.locale-messages
+LoadCredential=firstboot.keymap
+LoadCredential=firstboot.timezone