From: Lennart Poettering Date: Wed, 13 Jul 2022 12:55:45 +0000 (+0200) Subject: tmpfiles: add ^ line modifier for loading file contents from specific credential X-Git-Tag: v252-rc1~606^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e52f6f6358e515f55c26c5aed1eb2dc1fbc8efec;p=thirdparty%2Fsystemd.git tmpfiles: add ^ line modifier for loading file contents from specific credential --- diff --git a/man/tmpfiles.d.xml b/man/tmpfiles.d.xml index 79d0ff6bddf..15b5148622c 100644 --- a/man/tmpfiles.d.xml +++ b/man/tmpfiles.d.xml @@ -160,9 +160,10 @@ L /tmp/foobar - - - - /dev/null Type - The type consists of a single letter and optionally a plus sign (+), - exclamation mark (!), minus sign (-), equals sign - (=) and/or tilde character (~). + The type consists of a single letter and optionally one or emore modifier characters: a plus sign + (+), exclamation mark (!), minus sign (-), + equals sign (=), tilde character (~) and/or caret + (^). The following line types are understood: @@ -493,9 +494,19 @@ w- /proc/sys/vm/swappiness - - - - 10 If the tilde character (~) is used, the argument (i.e. 6th) column is Base64 decoded before use. This modifier is only supported on line types that can write file contents, i.e. f, - f+, w. This is useful for writing arbitrary binary data - (including newlines and NUL bytes) to files. Note that if this switch is used, the argument is not - subject to specifier expansion, neither before nor after Base64 decoding. + f+, w, +. This is useful for writing arbitrary + binary data (including newlines and NUL bytes) to files. Note that if this switch is used, the argument + is not subject to specifier expansion, neither before nor after Base64 decoding. + + If the caret character (^) is used, the argument (i.e. 6th) column takes a + service credential name to read the argument data from. See System and Service Credentials for details about the + credentials concept. This modifier is only supported on line types that can write file contents, + i.e. f, f+, w, w+. This is + useful for writing arbitrary files with contents sourced from elsewhere, including from VM or container + managers further up. If the specified credential is not set for the systemd-tmpfiles + service, the line is silently skipped. If ^ and ~ are combined + Base64 decoding is applied to the credential contents. Note that for all line types that result in creation of any kind of file node (i.e. f/F, diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index e2451f1b958..07432a1e51e 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -2978,7 +2978,7 @@ static int parse_line( ItemArray *existing; OrderedHashmap *h; int r, pos; - bool append_or_force = false, boot = false, allow_failure = false, try_replace = false, unbase64 = false; + bool append_or_force = false, boot = false, allow_failure = false, try_replace = false, unbase64 = false, from_cred = false; assert(fname); assert(line >= 1); @@ -3051,6 +3051,8 @@ static int parse_line( try_replace = true; else if (action[pos] == '~' && !unbase64) unbase64 = true; + else if (action[pos] == '^' && !from_cred) + from_cred = true; else { *invalid_config = true; return log_syntax(NULL, LOG_ERR, fname, line, SYNTHETIC_ERRNO(EBADMSG), "Unknown modifiers in command '%s'", action); @@ -3240,13 +3242,8 @@ static int parse_line( if (!should_include_path(i.path)) return 0; - if (unbase64) { - if (i.argument) { - r = unbase64mem(i.argument, SIZE_MAX, &i.binary_argument, &i.binary_argument_size); - if (r < 0) - return log_syntax(NULL, LOG_ERR, fname, line, r, "Failed to base64 decode specified argument '%s': %m", i.argument); - } - } else { + if (!unbase64) { + /* Do specifier expansion except if base64 mode is enabled */ r = specifier_expansion_from_arg(specifier_table, &i); if (r == -ENXIO) return log_unresolvable_specifier(fname, line); @@ -3257,6 +3254,35 @@ static int parse_line( } } + if (from_cred) { + if (!i.argument) + return log_syntax(NULL, LOG_ERR, fname, line, SYNTHETIC_ERRNO(EINVAL), "Reading from credential requested, but no credential name specified."); + if (!credential_name_valid(i.argument)) + return log_syntax(NULL, LOG_ERR, fname, line, SYNTHETIC_ERRNO(EINVAL), "Credential name not valid: %s", i.argument); + + r = read_credential(i.argument, &i.binary_argument, &i.binary_argument_size); + if (IN_SET(r, -ENXIO, -ENOENT)) { + /* Silently skip over lines that have no credentials passed */ + log_syntax(NULL, LOG_INFO, fname, line, 0, "Credential '%s' not specified, skipping line.", i.argument); + return 0; + } + if (r < 0) + return log_error_errno(r, "Failed to read credential '%s': %m", i.argument); + } + + /* If base64 decoding is requested, do so now */ + if (unbase64 && item_binary_argument(&i)) { + _cleanup_free_ void *data = NULL; + size_t data_size = 0; + + r = unbase64mem(item_binary_argument(&i), item_binary_argument_size(&i), &data, &data_size); + if (r < 0) + return log_syntax(NULL, LOG_ERR, fname, line, r, "Failed to base64 decode specified argument '%s': %m", i.argument); + + free_and_replace(i.binary_argument, data); + i.binary_argument_size = data_size; + } + if (!empty_or_root(arg_root)) { char *p;