]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
ask-password: Allow configuring the keyring timeout via an environment variable
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Wed, 30 Oct 2024 12:53:31 +0000 (13:53 +0100)
committerLennart Poettering <lennart@poettering.net>
Wed, 30 Oct 2024 16:43:53 +0000 (17:43 +0100)
In mkosi, we want an easy way to set the keyring timeout for every
tool we invoke that might use systemd-ask-password to query for a
password which is then stored in the kernel keyring. Let's make this
possible via a new $SYSTEMD_ASK_PASSWORD_KEYRING_TIMEOUT_SEC environment
variable.

Using an environment variable means we don't have to modify every separate
tool to add a CLI option allowing to specify the timeout. In mkosi specifically,
we'll set up a new session keyring for the mkosi process linked to the user keyring
so that any pins in the user keyring are used if available, and otherwise we'll query
for and store password in mkosi's session keyring with a zero timeout so that they stay
in the keyring until the mkosi process exits at which point they're removed from the
keyring.

docs/ENVIRONMENT.md
src/shared/ask-password-api.c

index cf5fb91eb96862b0e75e4d7107d62e0763170a64..48eeaa508c8f7cd9e22ab633c71d719c6fc6c922 100644 (file)
@@ -735,3 +735,12 @@ Tools using the Varlink protocol (such as `varlinkctl`) or sd-bus (such as
 
 * `SYSTEMD_EXIT_ON_IDLE` – Takes a boolean. When false, the exit-on-idle logic
   of these services is disabled, making it easier to debug them.
+
+`systemd-ask-password`:
+
+* `$SYSTEMD_ASK_PASSWORD_KEYRING_TIMEOUT_SEC` - takes a timespan or `default`,
+  which controls the expiration time of keys stored in the kernel keyring by
+  `systemd-ask-password`. If unset or set to `default`, the default expiration
+  of 150 seconds is used. If set to `0`, keys are not cached in the kernel
+  keyring. If set to `infinity`, keys are cached without an expiration time in
+  the kernel keyring.
index 7b9cdadc547b3d7b231f37e152bbf698ee5fc96d..0c3156cd276bbff96b5eaa1940b485ffb1ca5dc0 100644 (file)
@@ -22,6 +22,7 @@
 #include "ansi-color.h"
 #include "ask-password-api.h"
 #include "creds-util.h"
+#include "env-util.h"
 #include "fd-util.h"
 #include "fileio.h"
 #include "format-util.h"
@@ -113,6 +114,28 @@ static int touch_ask_password_directory(AskPasswordFlags flags) {
         return 1; /* did something */
 }
 
+static usec_t keyring_cache_timeout(void) {
+        static usec_t saved_timeout = USEC_INFINITY;
+        static bool saved_timeout_set = false;
+        int r;
+
+        if (saved_timeout_set)
+                return saved_timeout;
+
+        const char *e = secure_getenv("SYSTEMD_ASK_PASSWORD_KEYRING_TIMEOUT_SEC");
+        if (streq_ptr(e, "default"))
+                saved_timeout = KEYRING_TIMEOUT_USEC;
+        else if (e) {
+                r = parse_sec(e, &saved_timeout);
+                if (r < 0)
+                        log_debug_errno(r, "Invalid value in $SYSTEMD_ASK_PASSWORD_KEYRING_TIMEOUT_SEC, ignoring: %s", e);
+        }
+
+        saved_timeout_set = true;
+
+        return saved_timeout;
+}
+
 static int add_to_keyring(const char *keyname, AskPasswordFlags flags, char **passwords) {
         _cleanup_strv_free_erase_ char **l = NULL;
         _cleanup_(erase_and_freep) char *p = NULL;
@@ -122,7 +145,7 @@ static int add_to_keyring(const char *keyname, AskPasswordFlags flags, char **pa
 
         assert(keyname);
 
-        if (!FLAGS_SET(flags, ASK_PASSWORD_PUSH_CACHE))
+        if (!FLAGS_SET(flags, ASK_PASSWORD_PUSH_CACHE) || keyring_cache_timeout() == 0)
                 return 0;
         if (strv_isempty(passwords))
                 return 0;
@@ -151,9 +174,10 @@ static int add_to_keyring(const char *keyname, AskPasswordFlags flags, char **pa
         if (serial == -1)
                 return -errno;
 
-        if (keyctl(KEYCTL_SET_TIMEOUT,
-                   (unsigned long) serial,
-                   (unsigned long) DIV_ROUND_UP(KEYRING_TIMEOUT_USEC, USEC_PER_SEC), 0, 0) < 0)
+        if (keyring_cache_timeout() != USEC_INFINITY &&
+                keyctl(KEYCTL_SET_TIMEOUT,
+                       (unsigned long) serial,
+                       (unsigned long) DIV_ROUND_UP(keyring_cache_timeout(), USEC_PER_SEC), 0, 0) < 0)
                 log_debug_errno(errno, "Failed to adjust kernel keyring key timeout: %m");
 
         /* Tell everyone to check the keyring */