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:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user