diff options
author | Lennart Poettering <lennart@poettering.net> | 2021-03-11 11:47:57 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2021-03-26 12:21:18 +0100 |
commit | 416f7b3a11e00d1a43da950fb4a00bc6c2707013 (patch) | |
tree | 0dd0d39b17eeb1857f6ad4a0c1bf94fabad0fa90 | |
parent | f8fd093001ac6bf90e0a7c96c0cd451d8031f669 (diff) | |
download | systemd-416f7b3a11e00d1a43da950fb4a00bc6c2707013.tar.gz |
firstboot: allow provisioning of firstboot params via creds too
-rw-r--r-- | man/systemd-firstboot.xml | 62 | ||||
-rw-r--r-- | src/firstboot/firstboot.c | 64 | ||||
-rw-r--r-- | units/systemd-firstboot.service | 11 |
3 files changed, 136 insertions, 1 deletions
diff --git a/man/systemd-firstboot.xml b/man/systemd-firstboot.xml index 1001924902..46fe0a0682 100644 --- a/man/systemd-firstboot.xml +++ b/man/systemd-firstboot.xml @@ -283,7 +283,69 @@ <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> diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c index 42b9ca776f..01af1033e5 100644 --- a/src/firstboot/firstboot.c +++ b/src/firstboot/firstboot.c @@ -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(); diff --git a/units/systemd-firstboot.service b/units/systemd-firstboot.service index d7f445ef35..2e57b064c1 100644 --- a/units/systemd-firstboot.service +++ b/units/systemd-firstboot.service @@ -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 |