mirror of
https://github.com/morgan9e/systemd
synced 2026-04-14 00:14:32 +09:00
userdb: Add userdb.transient credentials
To implement --bind-user in systemd-vmspawn, we need a transient version of these credentials. These are useful when the home directory of the user is mounted into the container/vm and every trace of the user will be (mostly) gone again when the container/vm is shut down.
This commit is contained in:
committed by
Lennart Poettering
parent
88444243b8
commit
cc43510a13
@@ -475,6 +475,8 @@
|
||||
<varlistentry>
|
||||
<term><varname>userdb.user.*</varname></term>
|
||||
<term><varname>userdb.group.*</varname></term>
|
||||
<term><varname>userdb.transient.user.*</varname></term>
|
||||
<term><varname>userdb.transient.group.*</varname></term>
|
||||
|
||||
<listitem>
|
||||
<para>Configure JSON user and group records. Read by
|
||||
@@ -499,7 +501,10 @@
|
||||
<literal>userdb.user.foobar</literal> the suffix is <literal>foobar</literal>) must match the user
|
||||
or group name field from the user or group record.</para>
|
||||
|
||||
<para>Note that the records are created in <filename>/etc/userdb/</filename>
|
||||
<para>Note that the records created for <varname>userdb.user.*</varname> and
|
||||
<varname>userdb.group.*</varname> credentials are created in <filename>/etc/userdb/</filename> and
|
||||
the records created for <varname>userdb.transient.user.*</varname> and
|
||||
<varname>userdb.transient.group.*</varname> are created in <filename>/run/userdb/</filename>
|
||||
(<filename>/etc/passwd</filename> and <filename>/etc/group</filename> are not modified).</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v258"/>
|
||||
|
||||
@@ -1181,18 +1181,32 @@ static int ssh_authorized_keys(int argc, char *argv[], void *userdata) {
|
||||
return r;
|
||||
}
|
||||
|
||||
static int load_credential_one(int credential_dir_fd, const char *name, int userdb_dir_fd) {
|
||||
static int load_credential_one(
|
||||
int credential_dir_fd,
|
||||
const char *name,
|
||||
int userdb_dir_persist_fd,
|
||||
int userdb_dir_transient_fd) {
|
||||
|
||||
int r;
|
||||
|
||||
assert(credential_dir_fd >= 0);
|
||||
assert(name);
|
||||
assert(userdb_dir_fd >= 0);
|
||||
assert(userdb_dir_persist_fd >= 0);
|
||||
assert(userdb_dir_transient_fd >= 0);
|
||||
|
||||
const char *user = startswith(name, "userdb.user.");
|
||||
const char *group = startswith(name, "userdb.group.");
|
||||
const char *suffix = startswith(name, "userdb.");
|
||||
if (!suffix)
|
||||
return 0;
|
||||
|
||||
const char *transient = startswith(suffix, "transient."),
|
||||
*user = startswith(transient ?: suffix, "user."),
|
||||
*group = startswith(transient ?: suffix, "group.");
|
||||
if (!user && !group)
|
||||
return 0;
|
||||
|
||||
const char *userdb_dir = transient ? "/run/userdb" : "/etc/userdb";
|
||||
int userdb_dir_fd = transient ? userdb_dir_transient_fd : userdb_dir_persist_fd;
|
||||
|
||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
|
||||
unsigned line = 0, column = 0;
|
||||
r = sd_json_parse_file_at(NULL, credential_dir_fd, name, SD_JSON_PARSE_SENSITIVE, &v, &line, &column);
|
||||
@@ -1350,12 +1364,12 @@ static int load_credential_one(int credential_dir_fd, const char *name, int user
|
||||
|
||||
r = write_string_file_at(userdb_dir_fd, fn, formatted, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to write JSON record to /etc/userdb/%s: %m", fn);
|
||||
return log_error_errno(r, "Failed to write JSON record to %s/%s: %m", userdb_dir, fn);
|
||||
|
||||
if (symlinkat(fn, userdb_dir_fd, link) < 0)
|
||||
return log_error_errno(errno, "Failed to create symlink from %s to %s: %m", link, fn);
|
||||
|
||||
log_info("Installed /etc/userdb/%s from credential.", fn);
|
||||
log_info("Installed %s/%s from credential.", userdb_dir, fn);
|
||||
|
||||
if ((ur && !sd_json_variant_is_blank_object(ur_privileged->json)) ||
|
||||
(gr && !sd_json_variant_is_blank_object(gr_privileged->json))) {
|
||||
@@ -1371,7 +1385,7 @@ static int load_credential_one(int credential_dir_fd, const char *name, int user
|
||||
|
||||
r = write_string_file_at(userdb_dir_fd, fn, formatted, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC|WRITE_STRING_FILE_MODE_0600);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to write JSON record to /etc/userdb/%s: %m", fn);
|
||||
return log_error_errno(r, "Failed to write JSON record to %s/%s: %m", userdb_dir, fn);
|
||||
|
||||
link = mfree(link);
|
||||
|
||||
@@ -1386,7 +1400,7 @@ static int load_credential_one(int credential_dir_fd, const char *name, int user
|
||||
if (symlinkat(fn, userdb_dir_fd, link) < 0)
|
||||
return log_error_errno(errno, "Failed to create symlink from %s to %s: %m", link, fn);
|
||||
|
||||
log_info("Installed /etc/userdb/%s from credential.", fn);
|
||||
log_info("Installed %s/%s from credential.", userdb_dir, fn);
|
||||
}
|
||||
|
||||
if (ur)
|
||||
@@ -1399,7 +1413,7 @@ static int load_credential_one(int credential_dir_fd, const char *name, int user
|
||||
if (fd < 0)
|
||||
return log_error_errno(errno, "Failed to create %s: %m", membership);
|
||||
|
||||
log_info("Installed /etc/userdb/%s from credential.", membership);
|
||||
log_info("Installed %s/%s from credential.", userdb_dir, membership);
|
||||
}
|
||||
else
|
||||
STRV_FOREACH(u, gr->members) {
|
||||
@@ -1411,7 +1425,7 @@ static int load_credential_one(int credential_dir_fd, const char *name, int user
|
||||
if (fd < 0)
|
||||
return log_error_errno(errno, "Failed to create %s: %m", membership);
|
||||
|
||||
log_info("Installed /etc/userdb/%s from credential.", membership);
|
||||
log_info("Installed %s/%s from credential.", userdb_dir, membership);
|
||||
}
|
||||
|
||||
if (ur && user_record_disposition(ur) == USER_REGULAR) {
|
||||
@@ -1461,13 +1475,21 @@ static int load_credentials(int argc, char *argv[], void *userdata) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to enumerate credentials: %m");
|
||||
|
||||
_cleanup_close_ int userdb_dir_fd = xopenat_full(
|
||||
AT_FDCWD, "/etc/userdb",
|
||||
/* open_flags= */ O_DIRECTORY|O_CREAT|O_CLOEXEC,
|
||||
/* xopen_flags= */ XO_LABEL,
|
||||
/* mode= */ 0755);
|
||||
if (userdb_dir_fd < 0)
|
||||
return log_error_errno(userdb_dir_fd, "Failed to open %s: %m", "/etc/userdb/");
|
||||
_cleanup_close_ int userdb_persist_dir_fd = xopenat_full(
|
||||
AT_FDCWD, "/etc/userdb",
|
||||
/* open_flags= */ O_DIRECTORY|O_CREAT|O_CLOEXEC,
|
||||
/* xopen_flags= */ XO_LABEL,
|
||||
/* mode= */ 0755);
|
||||
if (userdb_persist_dir_fd < 0)
|
||||
return log_error_errno(userdb_persist_dir_fd, "Failed to open /etc/userdb/: %m");
|
||||
|
||||
_cleanup_close_ int userdb_transient_dir_fd = xopenat_full(
|
||||
AT_FDCWD, "/run/userdb",
|
||||
/* open_flags= */ O_DIRECTORY|O_CREAT|O_CLOEXEC,
|
||||
/* xopen_flags= */ XO_LABEL,
|
||||
/* mode= */ 0755);
|
||||
if (userdb_transient_dir_fd < 0)
|
||||
return log_error_errno(userdb_transient_dir_fd, "Failed to open /run/userdb/: %m");
|
||||
|
||||
FOREACH_ARRAY(i, des->entries, des->n_entries) {
|
||||
struct dirent *de = *i;
|
||||
@@ -1475,7 +1497,11 @@ static int load_credentials(int argc, char *argv[], void *userdata) {
|
||||
if (de->d_type != DT_REG)
|
||||
continue;
|
||||
|
||||
RET_GATHER(r, load_credential_one(credential_dir_fd, de->d_name, userdb_dir_fd));
|
||||
RET_GATHER(r, load_credential_one(
|
||||
credential_dir_fd,
|
||||
de->d_name,
|
||||
userdb_persist_dir_fd,
|
||||
userdb_transient_dir_fd));
|
||||
}
|
||||
|
||||
return r;
|
||||
|
||||
@@ -26,6 +26,8 @@ RemainAfterExit=yes
|
||||
ExecStart=userdbctl load-credentials
|
||||
ImportCredential=userdb.user.*
|
||||
ImportCredential=userdb.group.*
|
||||
ImportCredential=userdb.transient.user.*
|
||||
ImportCredential=userdb.transient.group.*
|
||||
|
||||
[Install]
|
||||
WantedBy=sysinit.target
|
||||
|
||||
Reference in New Issue
Block a user