mirror of
https://github.com/systemd/systemd.git
synced 2024-11-23 02:03:37 +08:00
network-generator: pick up .netdev/.link/.network configuration via credentials
To me this is the last major basic functionality that couldn't be configured via credentials: the network. We do not invent any new format for this, but simply copy relevant creds 1:1 into /run/systemd/network/ to open up the full functionality of networkd to VM hosts.
This commit is contained in:
parent
96f1f03c03
commit
1a30285590
@ -117,6 +117,41 @@
|
||||
for option syntax and details.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Credentials</title>
|
||||
|
||||
<para><command>systemd-network-generator</command> supports the service credentials logic as implemented
|
||||
by
|
||||
<varname>ImportCredential=</varname>/<varname>LoadCredential=</varname>/<varname>SetCredential=</varname>
|
||||
(see <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
|
||||
details). The following credentials are used when passed in:</para>
|
||||
|
||||
<variablelist class='system-credentials'>
|
||||
<varlistentry>
|
||||
<term><varname>network.netdev.*</varname></term>
|
||||
<term><varname>network.link.*</varname></term>
|
||||
<term><varname>network.network.*</varname></term>
|
||||
|
||||
<listitem><para>These credentials should contain valid
|
||||
<citerefentry><refentrytitle>systemd.netdev</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>systemd.link</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>systemd.network</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||
configuration data. From each matching credential a separate file is created. Example: a passed
|
||||
credential <filename>network.link.50-foobar</filename> will be copied into a configuration file
|
||||
<filename>50-foobar.link</filename>.</para>
|
||||
|
||||
<para>Note that the resulting files are created world-readable, it's hence recommended to not include
|
||||
secrets in these credentials, but supply them via separate credentials directly to
|
||||
<filename>systemd-networkd.service</filename>.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v256"/></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
<para>Note that by default the <filename>systemd-network-generator.service</filename> unit file is set up
|
||||
to inherit the these credentials from the service manager.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>See Also</title>
|
||||
<para><simplelist type="inline">
|
||||
|
@ -137,6 +137,30 @@
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>network.netdev.*</varname></term>
|
||||
<term><varname>network.link.*</varname></term>
|
||||
<term><varname>network.network.*</varname></term>
|
||||
<listitem>
|
||||
<para>Configures network devices. Read by
|
||||
<citerefentry><refentrytitle>systemd-network-generator.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>. These
|
||||
credentials directly translate to a matching <filename>*.netdev</filename>,
|
||||
<filename>*.link</filename> or <filename>*.network</filename> file. Example: the contents of a
|
||||
credential <filename>network.link.50-foobar</filename> will be copied into a file
|
||||
<filename>50-foobar.link</filename>. See
|
||||
<citerefentry><refentrytitle>systemd.netdev</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>systemd.link</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>systemd.network</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||
for details.</para>
|
||||
|
||||
<para>Note that the resulting files are created world-readable, it's hence recommended to not include
|
||||
secrets in these credentials, but supply them via separate credentials directly to
|
||||
<filename>systemd-networkd.service</filename>.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v256"/>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>passwd.hashed-password.root</varname></term>
|
||||
<term><varname>passwd.plaintext-password.root</varname></term>
|
||||
|
@ -3,6 +3,8 @@
|
||||
#include <getopt.h>
|
||||
|
||||
#include "build.h"
|
||||
#include "copy.h"
|
||||
#include "creds-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "fs-util.h"
|
||||
#include "generator.h"
|
||||
@ -12,6 +14,7 @@
|
||||
#include "network-generator.h"
|
||||
#include "path-util.h"
|
||||
#include "proc-cmdline.h"
|
||||
#include "recurse-dir.h"
|
||||
|
||||
#define NETWORKD_UNIT_DIRECTORY "/run/systemd/network"
|
||||
|
||||
@ -122,6 +125,76 @@ static int context_save(Context *context) {
|
||||
return r;
|
||||
}
|
||||
|
||||
static int pick_up_credentials(void) {
|
||||
_cleanup_close_ int credential_dir_fd = -EBADF;
|
||||
int r, ret = 0;
|
||||
|
||||
credential_dir_fd = open_credentials_dir();
|
||||
if (IN_SET(credential_dir_fd, -ENXIO, -ENOENT)) /* Credential env var not set, or dir doesn't exist. */
|
||||
return 0;
|
||||
if (credential_dir_fd < 0)
|
||||
return log_error_errno(credential_dir_fd, "Failed to open credentials directory: %m");
|
||||
|
||||
_cleanup_free_ DirectoryEntries *des = NULL;
|
||||
r = readdir_all(credential_dir_fd, RECURSE_DIR_SORT|RECURSE_DIR_IGNORE_DOT|RECURSE_DIR_ENSURE_TYPE, &des);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to enumerate credentials: %m");
|
||||
|
||||
FOREACH_ARRAY(i, des->entries, des->n_entries) {
|
||||
static const struct {
|
||||
const char *credential_prefix;
|
||||
const char *filename_suffix;
|
||||
} table[] = {
|
||||
{ "network.link.", ".link" },
|
||||
{ "network.netdev.", ".netdev" },
|
||||
{ "network.network.", ".network" },
|
||||
};
|
||||
|
||||
_cleanup_free_ char *fn = NULL;
|
||||
struct dirent *de = *i;
|
||||
|
||||
if (de->d_type != DT_REG)
|
||||
continue;
|
||||
|
||||
FOREACH_ARRAY(t, table, ELEMENTSOF(table)) {
|
||||
const char *e = startswith(de->d_name, t->credential_prefix);
|
||||
|
||||
if (e) {
|
||||
fn = strjoin(e, t->filename_suffix);
|
||||
if (!fn)
|
||||
return log_oom();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!fn)
|
||||
continue;
|
||||
|
||||
if (!filename_is_valid(fn)) {
|
||||
log_warning("Passed credential '%s' would result in invalid filename '%s', ignoring.", de->d_name, fn);
|
||||
continue;
|
||||
}
|
||||
|
||||
_cleanup_free_ char *output = path_join(NETWORKD_UNIT_DIRECTORY, fn);
|
||||
if (!output)
|
||||
return log_oom();
|
||||
|
||||
r = copy_file_at(
|
||||
credential_dir_fd, de->d_name,
|
||||
AT_FDCWD, output,
|
||||
/* open_flags= */ 0,
|
||||
0644,
|
||||
/* flags= */ 0);
|
||||
if (r < 0)
|
||||
RET_GATHER(ret, log_warning_errno(r, "Failed to copy credential %s → file %s: %m", de->d_name, output));
|
||||
else
|
||||
log_info("Installed %s from credential.", output);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int help(void) {
|
||||
printf("%s [OPTIONS...] [-- KERNEL_CMDLINE]\n"
|
||||
" -h --help Show this help\n"
|
||||
@ -174,7 +247,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
|
||||
static int run(int argc, char *argv[]) {
|
||||
_cleanup_(context_clear) Context context = {};
|
||||
int r;
|
||||
int r, ret = 0;
|
||||
|
||||
log_setup();
|
||||
|
||||
@ -212,7 +285,10 @@ static int run(int argc, char *argv[]) {
|
||||
if (r < 0)
|
||||
return log_warning_errno(r, "Failed to merge multiple command line options: %m");
|
||||
|
||||
return context_save(&context);
|
||||
RET_GATHER(ret, context_save(&context));
|
||||
RET_GATHER(ret, pick_up_credentials());
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
DEFINE_MAIN_FUNCTION(run);
|
||||
|
27
test/units/testsuite-74.network-generator.sh
Executable file
27
test/units/testsuite-74.network-generator.sh
Executable file
@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env bash
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
# shellcheck disable=SC2016
|
||||
set -eux
|
||||
set -o pipefail
|
||||
|
||||
at_exit() {
|
||||
rm -f /run/credstore/network.network.50-testme
|
||||
rm -f /run/systemd/system/systemd-network-generator.service.d/50-testme.conf
|
||||
}
|
||||
|
||||
trap at_exit EXIT
|
||||
|
||||
mkdir -p /run/credstore
|
||||
cat > /run/credstore/network.network.50-testme <<EOF
|
||||
[Match]
|
||||
Property=IDONTEXIST
|
||||
EOF
|
||||
|
||||
systemctl edit systemd-network-generator.service --stdin --drop-in=50-testme.conf <<EOF
|
||||
[Service]
|
||||
LoadCredential=network.network.50-testme
|
||||
EOF
|
||||
|
||||
systemctl restart systemd-network-generator
|
||||
|
||||
test -f /run/systemd/network/50-testme.network
|
@ -21,6 +21,9 @@ Before=shutdown.target initrd-switch-root.target
|
||||
Type=oneshot
|
||||
RemainAfterExit=yes
|
||||
ExecStart={{LIBEXECDIR}}/systemd-network-generator
|
||||
ImportCredential=network.netdev.*
|
||||
ImportCredential=network.link.*
|
||||
ImportCredential=network.network.*
|
||||
|
||||
[Install]
|
||||
WantedBy=sysinit.target
|
||||
|
Loading…
Reference in New Issue
Block a user