diff --git a/man/systemd-tmpfiles.xml b/man/systemd-tmpfiles.xml index 425ed23dd35..92ab322ba0e 100644 --- a/man/systemd-tmpfiles.xml +++ b/man/systemd-tmpfiles.xml @@ -230,6 +230,31 @@ systemd-tmpfiles --remove --create + + Credentials + + systemd-tmpfiles supports the service credentials logic as implemented by + LoadCredential=/SetCredential= (see + systemd.exec1 for + details). The following credentials are used when passed in: + + + + tmpfiles.extra + + The contents of this credential may contain additional lines to operate on. The + credential contents should follow the same format as any other tmpfiles.d/ + drop-in configuration file. If this credential is passed it is processed after all of the drop-in + files read from the file system. The lines in the credential can hence augment existing lines of the + OS, but not override them. + + + + Note that by default the systemd-tmpfiles-setup.service unit file (and related + unit files) is set up to inherit the tmpfiles.extra credential from the service + manager. + + Environment diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index 0c50c8e1ee3..e2451f1b958 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -25,6 +25,7 @@ #include "chattr-util.h" #include "conf-files.h" #include "copy.h" +#include "creds-util.h" #include "def.h" #include "devnum-util.h" #include "dirent-util.h" @@ -3594,7 +3595,12 @@ static int parse_argv(int argc, char *argv[]) { return 1; } -static int read_config_file(char **config_dirs, const char *fn, bool ignore_enoent, bool *invalid_config) { +static int read_config_file( + char **config_dirs, + const char *fn, + bool ignore_enoent, + bool *invalid_config) { + _cleanup_(hashmap_freep) Hashmap *uid_cache = NULL, *gid_cache = NULL; _cleanup_fclose_ FILE *_f = NULL; _cleanup_free_ char *pp = NULL; @@ -3736,6 +3742,25 @@ static int read_config_files(char **config_dirs, char **args, bool *invalid_conf return 0; } +static int read_credential_lines(bool *invalid_config) { + _cleanup_free_ char *j = NULL; + const char *d; + int r; + + r = get_credentials_dir(&d); + if (r == -ENXIO) + return 0; + if (r < 0) + return log_error_errno(r, "Failed to get credentials directory: %m"); + + j = path_join(d, "tmpfiles.extra"); + if (!j) + return log_oom(); + + (void) read_config_file(/* config_dirs= */ NULL, j, /* ignore_enoent= */ true, invalid_config); + return 0; +} + static int link_parent(ItemArray *a) { const char *path; char *prefix; @@ -3892,6 +3917,10 @@ static int run(int argc, char *argv[]) { if (r < 0) return r; + r = read_credential_lines(&invalid_config); + if (r < 0) + return r; + /* Let's now link up all child/parent relationships */ ORDERED_HASHMAP_FOREACH(a, items) { r = link_parent(a); diff --git a/test/TEST-54-CREDS/test.sh b/test/TEST-54-CREDS/test.sh index 8f66f1c7b84..ac6777be311 100755 --- a/test/TEST-54-CREDS/test.sh +++ b/test/TEST-54-CREDS/test.sh @@ -4,7 +4,7 @@ set -e TEST_DESCRIPTION="test credentials" NSPAWN_ARGUMENTS="${NSPAWN_ARGUMENTS:-} --set-credential=mynspawncredential:strangevalue" -QEMU_OPTIONS="${QEMU_OPTIONS:-} -fw_cfg name=opt/io.systemd.credentials/myqemucredential,string=othervalue -smbios type=11,value=io.systemd.credential:smbioscredential=magicdata -smbios type=11,value=io.systemd.credential.binary:binarysmbioscredential=bWFnaWNiaW5hcnlkYXRh -smbios type=11,value=io.systemd.credential.binary:sysusers.extra=dSBjcmVkdGVzdHVzZXIK" +QEMU_OPTIONS="${QEMU_OPTIONS:-} -fw_cfg name=opt/io.systemd.credentials/myqemucredential,string=othervalue -smbios type=11,value=io.systemd.credential:smbioscredential=magicdata -smbios type=11,value=io.systemd.credential.binary:binarysmbioscredential=bWFnaWNiaW5hcnlkYXRh -smbios type=11,value=io.systemd.credential.binary:sysusers.extra=dSBjcmVkdGVzdHVzZXIK -smbios type=11,value=io.systemd.credential.binary:tmpfiles.extra=ZiAvdG1wL3NvdXJjZWRmcm9tY3JlZGVudGlhbCAtIC0gLSAtIHRtcGZpbGVzc2VjcmV0Cg==" KERNEL_APPEND="${KERNEL_APPEND:-} systemd.set_credential=kernelcmdlinecred:uff systemd.set_credential=sysctl.extra:kernel.domainname=sysctltest rd.systemd.import_credentials=no" # shellcheck source=test/test-functions diff --git a/test/units/testsuite-54.sh b/test/units/testsuite-54.sh index a7ccdca032f..8eff47028d7 100755 --- a/test/units/testsuite-54.sh +++ b/test/units/testsuite-54.sh @@ -43,6 +43,9 @@ elif [ -d /sys/firmware/qemu_fw_cfg/by_name ]; then # Verify that creating a user via sysusers via the kernel cmdline worked grep -q ^credtestuser: /etc/passwd + + # Verify that writing a file via tmpfiles worked + [ "$(cat /tmp/sourcedfromcredential)" = "tmpfilessecret" ] else echo "qemu_fw_cfg support missing in kernel. Sniff!" expected_credential="" diff --git a/units/systemd-tmpfiles-clean.service b/units/systemd-tmpfiles-clean.service index 7aee6463bd5..6ae4e74ddd0 100644 --- a/units/systemd-tmpfiles-clean.service +++ b/units/systemd-tmpfiles-clean.service @@ -20,3 +20,4 @@ Type=oneshot ExecStart=systemd-tmpfiles --clean SuccessExitStatus=DATAERR IOSchedulingClass=idle +LoadCredential=tmpfiles.extra diff --git a/units/systemd-tmpfiles-setup-dev.service b/units/systemd-tmpfiles-setup-dev.service index 0babe78767a..ad0e54fcc41 100644 --- a/units/systemd-tmpfiles-setup-dev.service +++ b/units/systemd-tmpfiles-setup-dev.service @@ -20,3 +20,4 @@ Type=oneshot RemainAfterExit=yes ExecStart=systemd-tmpfiles --prefix=/dev --create --boot SuccessExitStatus=DATAERR CANTCREAT +LoadCredential=tmpfiles.extra diff --git a/units/systemd-tmpfiles-setup.service b/units/systemd-tmpfiles-setup.service index bc29dbc8c9c..6c1ee91a403 100644 --- a/units/systemd-tmpfiles-setup.service +++ b/units/systemd-tmpfiles-setup.service @@ -21,3 +21,4 @@ Type=oneshot RemainAfterExit=yes ExecStart=systemd-tmpfiles --create --remove --boot --exclude-prefix=/dev SuccessExitStatus=DATAERR CANTCREAT +LoadCredential=tmpfiles.extra