-
-
Notifications
You must be signed in to change notification settings - Fork 3.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RFE: per-service credentials system #15778
Comments
Questions:
Regarding 3., I'd personally stronger separate the second concern from the unit config, maybe even for the simple |
I don't think we should rely on mount namespaces for this. Most of our code is will gracefully degrade if they aren't available (because compiled out in kernel or turned off in containers via seccomp), and I think we should do the same here too. Also, it's kinda nice when exploring this as an admin from the host side, since then you have a different dir there for each service and can easily see who gets what. We have to allocate a per-service ramfs anyway I think because otherwise we cannot populate it "atomically" (meaning: make it show up in the host tree fully populated at once without a phase where it is mounted on the host but not populated), and release it atomically. We need to mount that somewhere hence we need a per-service mount point anyway. I think we also should make sure that what the service sees where things are and what the admin sees from host side where things are should not deviate needlessly...
I explicitly don't want to provide any fancy API for credential plugins. That said, I see two simple ways to hook this up: a. Have a preparatory service that puts the keys somewhere, and then pick them up in the main service from there via LoadCredential= b. If you specify an absolute path to an AF_UNIX file system socket via LoadCredential= we should connect() to it, and read from it until EOF and use that as credential. It's similar how StandardInput= and friends similarly support connect()ing to AF_UNIX sockets. systemd-ask-password really should be about interactive, string-based, NUL-terminated creds only. i.e. passwords, passphrases, recovery keys, i.e. stuff humans type in. For anything else, i.e binary keys, and so on hook it up via a file you put somewhere or the AF_UNIX stuff, systemd-ask-password is a bad fit.
I see what you mean. Not sure it's a big problem though. We could for example say that if you do:
i.e. declare that the same cred called "foo" is to be acquired by three different methods, that this means we'd first try the PassCredential= one, then the LoadCredential= one and finally the AskCredential= one (always in the same order, preferring static over dynamic data). That means vendors can define some basic behaviour, but the admin can override it (via drop-ins) or extend it, and rely on the order how things re tried. |
I agree However, I think credential providers like vault, KMS etc. shouldn't be ignored entirely while designing such an architecture. In cloud environments, they can very likely be the only thing providing secrets. Let's say systemd could also support reading files from a "global" secrets path, where credential providers could mount a fuse filesystem, or create socket file(s). [1] That could be as simple as a "if the path in Secret providers might then just mount a fuse filesystem (accessible to root only), and query their backend on access, or administrators mount their encrypted volume containing secrets to that location during bootup, etc. Distributions/Packagers could even provide some sane defaults in unit files for simple services only requiring a single token to work. What worries me about the current approach is secret rotation and service reloads - currently, there's no nice way to describe a secret being expired, or a way of modelling the dependency between secret (files) and services. By now designing such a credentials system, such a thing could finally be provided. This could be as "simple" as doing some inotify on the secret files, and triggering a reload on change. Other options could be making the socket protocol a bit more complex, to allow specifying expiry dates. What about a single endpoint, and just using HTTP (HEAD, and the expiry headers)? Currently users use yet another external tool like confd watching files and restarting services, together with ugly bash scripts waiting for secrets to be provided, delaying the startup of the existing service. |
My initial implementation of this you find in #16568. Please have a look. The PR is not ready to merge (has no tests), but it does include documentation that should explain what this does. Let's continue discussion there. |
Moved over from @poettering's post in NixOS/rfcs#59 (comment):
BTW, I thought about a creds concept in systemd the past weeks. It's a big topic, but this is what I'd probably propose in systemd:
LoadCredential=<name>:<path>
for loading a credential off disk. The name is some user chosen ID, the path is some file system path to load the credential from.PassCredential=<newname>:<oldname>
which takes a credential systemd itself received (think: pid1 in a container gets some creds from the container manager, or systemd --user from its parent).AskCredential=<name>
for querying a credential from the user via thesystemd-ask-password
framework.CredentialMode=
for configuring how to pass credentials to the service. Can be a combination of options:file
(pass as file in the fs),keyring
(for kernel keyring),fd
(for passing as fd via socket activation). We'd default tofile
andkeyring
. We should be graceful here, i.e. ifkeyring
cannot work (because we are in a container where kernel keyring is blocked), use only the fs. We'd always attempt to pass all configured creds through all methods in parallel.CredentialDirectory=
, similar toRuntimeDirectory=
and its friends, for defining a subdir of/run/credentials/
to pass the creds in in casefile
mode is used. There'd be$CREDENTIAL_DIRECTORY
(again, similar to$RUNTIME_DIRECTORY
and friends) we'd set for services to the resulting dir)ramfs
(and not atmpfs
!) to/run/credentials//
and place the creds there.ramfs
has the benefit of never being swapped out. needs graceful fallback logic to using the dir without mount however, to cover for containers. we'd populate the fs atomically, and keep it read-only afterwards.everything passed will be immutable and only accessible to the user of the service, nothing else. there'd be no API for dynamically requesting more creds.
The text was updated successfully, but these errors were encountered: