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:
Lennart Poettering
2024-01-08 12:59:08 +01:00
parent 96f1f03c03
commit 1a30285590
5 changed files with 167 additions and 2 deletions
+78 -2
View File
@@ -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);