2022-04-22 21:43:11 +08:00
|
|
|
|
---
|
|
|
|
|
title: Credentials
|
|
|
|
|
category: Concepts
|
|
|
|
|
layout: default
|
|
|
|
|
SPDX-License-Identifier: LGPL-2.1-or-later
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
# System and Service Credentials
|
|
|
|
|
|
|
|
|
|
The `systemd` service manager supports a "credential" concept for securely
|
|
|
|
|
acquiring and passing credential data to systems and services. The precise
|
|
|
|
|
nature of the credential data is up to applications, but the concept is
|
|
|
|
|
intended to provide systems and services with potentially security sensitive
|
|
|
|
|
cryptographic keys, certificates, passwords, identity information and similar
|
|
|
|
|
types of information. It may also be used as generic infrastructure for
|
|
|
|
|
parameterizing systems and services.
|
|
|
|
|
|
|
|
|
|
Traditionally, data of this nature has often been provided to services via
|
|
|
|
|
environment variables (which is problematic because by default they are
|
|
|
|
|
inherited down the process tree, have size limitations, and issues with binary
|
|
|
|
|
data) or simple, unencrypted files on disk. `systemd`'s system and service
|
|
|
|
|
credentials are supposed to provide a better alternative for this
|
|
|
|
|
purpose. Specifically, the following features are provided:
|
|
|
|
|
|
|
|
|
|
1. Service credentials are acquired at the moment of service activation, and
|
|
|
|
|
released on service deactivation. They are immutable during the service
|
|
|
|
|
runtime.
|
|
|
|
|
|
|
|
|
|
2. Service credentials are accessible to service code as regular files, the
|
|
|
|
|
path to access them is derived from the environment variable
|
|
|
|
|
`$CREDENTIALS_DIRECTORY`.
|
|
|
|
|
|
|
|
|
|
3. Access to credentials is restricted to the service's user. Unlike
|
|
|
|
|
environment variables the credential data is not propagated down the process
|
|
|
|
|
tree. Instead each time a credential is accessed an access check is enforced
|
|
|
|
|
by the kernel. If the service is using file system namespacing the loaded
|
2022-05-03 00:04:35 +08:00
|
|
|
|
credential data is invisible to any other services.
|
2022-04-22 21:43:11 +08:00
|
|
|
|
|
|
|
|
|
4. Service credentials may be acquired from files on disk, specified as literal
|
|
|
|
|
strings in unit files, acquired from another service dynamically via an
|
|
|
|
|
`AF_UNIX` socket, or inherited from the system credentials the system itself
|
|
|
|
|
received.
|
|
|
|
|
|
|
|
|
|
5. Credentials may optionally be encrypted and authenticated, either with a key
|
|
|
|
|
derived from a local TPM2 chip, or one stored in `/var/`, or both. This
|
|
|
|
|
encryption is supposed to *just* *work*, and requires no manual setup. (That
|
|
|
|
|
is besides first encrypting relevant credentials with one simple command,
|
|
|
|
|
see below.)
|
|
|
|
|
|
|
|
|
|
6. Service credentials are placed in non-swappable memory. (If permissions
|
|
|
|
|
allow it, via `ramfs`.)
|
|
|
|
|
|
2022-07-14 00:26:44 +08:00
|
|
|
|
7. Credentials may be acquired from a hosting VM hypervisor (SMBIOS OEM strings
|
|
|
|
|
or qemu `fw_cfg`), a hosting container manager, the kernel command line, or
|
|
|
|
|
from the UEFI environment and the EFI System Partition (via
|
|
|
|
|
`systemd-stub`). Such system credentials may then be propagated into
|
|
|
|
|
individual services as needed.
|
2022-04-22 21:43:11 +08:00
|
|
|
|
|
|
|
|
|
8. Credentials are an effective way to pass parameters into services that run
|
|
|
|
|
with `RootImage=` or `RootDirectory=` and thus cannot read these resources
|
2022-05-18 06:05:38 +08:00
|
|
|
|
directly from the host directory tree.
|
|
|
|
|
Specifically, [Portable Services](PORTABLE_SERVICES.md) may be
|
|
|
|
|
parameterized this way securely and robustly.
|
2022-04-22 21:43:11 +08:00
|
|
|
|
|
|
|
|
|
9. Credentials can be binary and relatively large (though currently an overall
|
|
|
|
|
size limit of 1M per service is enforced).
|
|
|
|
|
|
|
|
|
|
## Configuring per-Service Credentials
|
|
|
|
|
|
|
|
|
|
Within unit files, there are four settings to configure service credentials.
|
|
|
|
|
|
|
|
|
|
1. `LoadCredential=` may be used to load a credential from disk, from an
|
|
|
|
|
`AF_UNIX` socket, or propagate them from a system credential.
|
|
|
|
|
|
|
|
|
|
2. `SetCredential=` may be used to set a credential to a literal string encoded
|
|
|
|
|
in the unit file. Because unit files are world-readable (both on disk and
|
|
|
|
|
via D-Bus), this should only be used for credentials that aren't sensitive,
|
|
|
|
|
i.e. public keys/certificates – but not private keys.
|
|
|
|
|
|
|
|
|
|
3. `LoadCredentialEncrypted=` is similar to `LoadCredential=` but will load an
|
|
|
|
|
encrypted credential, and decrypt it before passing it to the service. For
|
|
|
|
|
details on credential encryption, see below.
|
|
|
|
|
|
|
|
|
|
4. `SetCredentialEncrypted=` is similar to `SetCredential=` but expects an
|
|
|
|
|
encrypted credential to be specified literally. Unlike `SetCredential=` it
|
|
|
|
|
is thus safe to be used even for sensitive information, because even though
|
|
|
|
|
unit files are world readable, the ciphertext included in them cannot be
|
|
|
|
|
decoded unless access to TPM2/encryption key is available.
|
|
|
|
|
|
|
|
|
|
Each credential configured with these options carries a short name (suitable
|
|
|
|
|
for inclusion in a filename) in the unit file, under which the invoked service
|
|
|
|
|
code can then retrieve it. Each name should only be specified once.
|
|
|
|
|
|
|
|
|
|
For details about these four settings [see the man
|
|
|
|
|
page](https://www.freedesktop.org/software/systemd/man/systemd.exec.html#Credentials).
|
|
|
|
|
|
|
|
|
|
It is a good idea to also enable mount namespacing for services that process
|
|
|
|
|
credentials configured this way. If so, the runtime credential directory of the
|
|
|
|
|
specific service is not visible to any other service. Use `PrivateMounts=` as
|
|
|
|
|
minimal option to enable such namespacing. Note that many other sandboxing
|
|
|
|
|
settings (e.g. `ProtectSystem=`, `ReadOnlyPaths=` and similar) imply
|
|
|
|
|
`PrivateMounts=`, hence oftentimes it's not necessary to set this option
|
|
|
|
|
explicitly.
|
|
|
|
|
|
|
|
|
|
## Programming Interface from Service Code
|
|
|
|
|
|
|
|
|
|
When a service is invoked with one or more credentials set it will have an
|
|
|
|
|
environment variable `$CREDENTIALS_DIRECTORY` set. It contains an absolute path
|
|
|
|
|
to a directory the credentials are placed in. In this directory for each
|
|
|
|
|
configured credential one file is placed. In addition to the
|
|
|
|
|
`$CREDENTIALS_DIRECTORY` environment variable passed to the service processes
|
|
|
|
|
the `%d` specifier in unit files resolves to the service's credential
|
|
|
|
|
directory.
|
|
|
|
|
|
|
|
|
|
Example unit file:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
…
|
|
|
|
|
[Service]
|
|
|
|
|
ExecStart=/usr/bin/myservice.sh
|
|
|
|
|
LoadCredential=foobar:/etc/myfoobarcredential.txt
|
|
|
|
|
Environment=FOOBARPATH=%d/foobar
|
|
|
|
|
…
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Associated service shell script `/usr/bin/myservice.sh`:
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
#!/bin/sh
|
|
|
|
|
|
2022-08-28 15:56:46 +08:00
|
|
|
|
sha256sum $CREDENTIALS_DIRECTORY/foobar
|
2022-04-22 21:43:11 +08:00
|
|
|
|
sha256sum $FOOBARPATH
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
A service defined like this will get the contents of the file
|
|
|
|
|
`/etc/myfoobarcredential.txt` passed as credential `foobar`, which is hence
|
|
|
|
|
accessible under `$CREDENTIALS_DIRECTORY/foobar`. Since we additionally pass
|
|
|
|
|
the path to it as environment variable `$FOOBARPATH` the credential is also
|
|
|
|
|
accessible as the path in that environment variable. When invoked, the service
|
|
|
|
|
will hence show the same SHA256 hash value of `/etc/myfoobarcredential.txt`
|
|
|
|
|
twice.
|
|
|
|
|
|
|
|
|
|
In an ideal world, well-behaved service code would directly support credentials
|
|
|
|
|
passed this way, i.e. look for `$CREDENTIALS_DIRECTORY` and load the credential
|
|
|
|
|
data it needs from there. For daemons that do not support this but allow
|
|
|
|
|
passing credentials via a path supplied over the command line use
|
2022-08-28 15:56:46 +08:00
|
|
|
|
`${CREDENTIALS_DIRECTORY}` in the `ExecStart=` command line to reference the
|
2022-04-22 21:43:11 +08:00
|
|
|
|
credentials directory. For daemons that allow passing credentials via a path
|
2022-05-03 00:16:32 +08:00
|
|
|
|
supplied as environment variable, use the `%d` specifier in the `Environment=`
|
2022-04-22 21:43:11 +08:00
|
|
|
|
setting to build valid paths to specific credentials.
|
|
|
|
|
|
|
|
|
|
## Tools
|
|
|
|
|
|
|
|
|
|
The
|
|
|
|
|
[`systemd-creds`](https://www.freedesktop.org/software/systemd/man/systemd-creds.html)
|
|
|
|
|
tool is provided to work with system and service credentials. It may be used to
|
|
|
|
|
access and enumerate system and service credentials, or to encrypt/decrypt credentials
|
|
|
|
|
(for details about the latter, see below).
|
|
|
|
|
|
|
|
|
|
When invoked from service context, `systemd-creds` passed without further
|
|
|
|
|
parameters will list passed credentials. The `systemd-creds cat xyz` command
|
|
|
|
|
may be used to write the contents of credential `xyz` to standard output. If
|
|
|
|
|
these calls are combined with the `--system` switch credentials passed to the
|
2023-01-15 16:00:00 +08:00
|
|
|
|
system as a whole are shown, instead of those passed to the service the
|
2022-04-22 21:43:11 +08:00
|
|
|
|
command is invoked from.
|
|
|
|
|
|
|
|
|
|
Example use:
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
systemd-run -P --wait -p LoadCredential=abc:/etc/hosts systemd-creds cat abc
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
This will invoke a transient service with a credential `abc` sourced from the
|
|
|
|
|
system's `/etc/hosts` file. This credential is then written to standard output
|
|
|
|
|
via `systemd-creds cat`.
|
|
|
|
|
|
|
|
|
|
## Encryption
|
|
|
|
|
|
|
|
|
|
Credentials are supposed to be useful for carrying sensitive information, such
|
|
|
|
|
as cryptographic key material. For this kind of data (symmetric) encryption and
|
2023-01-15 16:00:00 +08:00
|
|
|
|
authentication are provided to make storage of the data at rest safer. The data
|
2022-04-22 21:43:11 +08:00
|
|
|
|
may be encrypted and authenticated with AES256-GCM. The encryption key can
|
|
|
|
|
either be one derived from the local TPM2 device, or one stored in
|
|
|
|
|
`/var/lib/systemd/credential.secret`, or a combination of both. If a TPM2
|
2023-01-15 16:00:00 +08:00
|
|
|
|
device is available and `/var/` resides on a persistent storage, the default
|
2022-04-22 21:43:11 +08:00
|
|
|
|
behaviour is to use the combination of both for encryption, thus ensuring that
|
|
|
|
|
credentials protected this way can only be decrypted and validated on the
|
|
|
|
|
local hardware and OS installation. Encrypted credentials stored on disk thus
|
|
|
|
|
cannot be decrypted without access to the TPM2 chip and the aforementioned key
|
|
|
|
|
file `/var/lib/systemd/credential.secret`. Moreover, credentials cannot be
|
2023-01-15 16:00:00 +08:00
|
|
|
|
prepared on a machine other than the local one.
|
2022-04-22 21:43:11 +08:00
|
|
|
|
|
|
|
|
|
The `systemd-creds` tool provides the commands `encrypt` and `decrypt` to
|
|
|
|
|
encrypt and decrypt/authenticate credentials. Example:
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
systemd-creds encrypt plaintext.txt ciphertext.cred
|
2022-05-12 20:05:12 +08:00
|
|
|
|
shred -u plaintext.txt
|
2022-04-22 21:43:11 +08:00
|
|
|
|
systemd-run -P --wait -p LoadCredentialEncrypted=foobar:$(pwd)/ciphertext.cred systemd-creds cat foobar
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
This will first create an encrypted copy of the file `plaintext.txt` in the
|
|
|
|
|
encrypted credential file `ciphertext.cred`. It then securely removes the
|
|
|
|
|
source file. It then runs a transient service, that reads the encrypted file
|
|
|
|
|
and passes it as decrypted credential `foobar` to the invoked service binary
|
|
|
|
|
(which here is the `systemd-creds` tool, which just writes the data
|
|
|
|
|
it received to standard output).
|
|
|
|
|
|
|
|
|
|
Instead of storing the encrypted credential as a separate file on disk, it can
|
|
|
|
|
also be embedded in the unit file. Example:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
systemd-creds encrypt -p --name=foobar plaintext.txt -
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
This will output a `SetCredentialEncrypted=` line that can directly be used in
|
|
|
|
|
a unit file. e.g.:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
…
|
|
|
|
|
[Service]
|
|
|
|
|
ExecStart=/usr/bin/systemd-creds cat foobar
|
|
|
|
|
SetCredentialEncrypted=foobar: \
|
|
|
|
|
k6iUCUh0RJCQyvL8k8q1UyAAAAABAAAADAAAABAAAAC1lFmbWAqWZ8dCCQkAAAAAgAAAA \
|
|
|
|
|
AAAAAALACMA0AAAACAAAAAAfgAg9uNpGmj8LL2nHE0ixcycvM3XkpOCaf+9rwGscwmqRJ \
|
|
|
|
|
cAEO24kB08FMtd/hfkZBX8PqoHd/yPTzRxJQBoBsvo9VqolKdy9Wkvih0HQnQ6NkTKEdP \
|
|
|
|
|
HQ08+x8sv5sr+Mkv4ubp3YT1Jvv7CIPCbNhFtag1n5y9J7bTOKt2SQwBOAAgACwAAABIA \
|
|
|
|
|
ID8H3RbsT7rIBH02CIgm/Gv1ukSXO3DMHmVQkDG0wEciABAAII6LvrmL60uEZcp5qnEkx \
|
|
|
|
|
SuhUjsDoXrJs0rfSWX4QAx5PwfdFuxPusgEfTYIiCb8a/W6RJc7cMweZVCQMbTARyIAAA \
|
|
|
|
|
AAJt7Q9F/Gz0pBv1Lc4Dpn1WpebyBBm+vQ5N/lSKW2XSm8cONwCopxpDc7wJjXg7OTR6r \
|
|
|
|
|
xGCpIvGXLt3ibwJl81woLya2RRjIvc/R2zNm/yWzZAjiOLPih4SuHthqiX98ey8PUmZJB \
|
|
|
|
|
VGXglCZFjBx+d7eCqTIdghtp5pkDGwMJT6pjw4FfyFK2nJPawFKPAqzw9DK2iYttFeXi5 \
|
|
|
|
|
19xCfLBH9NKS/idlYXrhp+XIEtsr26s4lx5y10Goyc3qDOR3RD2cuZj0gHwV35hhhhcCz \
|
|
|
|
|
JaYytef1X/YL+7fYH5kuE4rxSksoUuA/LhtjszBeGbcbIT+O8SuvBJHLKTSHxPL8FTyk3 \
|
|
|
|
|
L4FSkEHs0rYwUIkKmnGohDdsYrMJ2fjH3yDNBP16aD1+f/Nuh75cjhUnGsDLt9K4hGg== \
|
|
|
|
|
…
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Inheritance from Container Managers, Hypervisors, Kernel Command Line, or the UEFI Boot Environment
|
|
|
|
|
|
|
|
|
|
Sometimes it is useful to parameterize whole systems the same way as services,
|
|
|
|
|
via `systemd` credentials. In particular, it might make sense to boot a
|
|
|
|
|
system with a set of credentials that are then propagated to individual
|
|
|
|
|
services where they are ultimately consumed.
|
|
|
|
|
|
|
|
|
|
`systemd` supports four ways to pass credentials to systems:
|
|
|
|
|
|
|
|
|
|
1. A container manager may set the `$CREDENTIALS_DIRECTORY` environment
|
|
|
|
|
variable for systemd running as PID 1 in the container, the same way as
|
|
|
|
|
systemd would set it for a service it
|
|
|
|
|
invokes. [`systemd-nspawn(1)`](https://www.freedesktop.org/software/systemd/man/systemd-nspawn.html#Credentials)'s
|
|
|
|
|
`--set-credential=` and `--load-credential=` switches implement this, in
|
|
|
|
|
order to pass arbitrary credentials from host to container payload. Also see
|
2022-05-18 06:05:38 +08:00
|
|
|
|
the [Container Interface](CONTAINER_INTERFACE.md)
|
2022-04-22 21:43:11 +08:00
|
|
|
|
documentation.
|
|
|
|
|
|
2022-07-14 00:26:44 +08:00
|
|
|
|
2. Quite similar, VMs can be passed credentials via SMBIOS OEM strings (example
|
|
|
|
|
qemu command line switch `-smbios
|
|
|
|
|
type=11,value=io.systemd.credential:foo=bar` or `-smbios
|
|
|
|
|
type=11,value=io.systemd.credential.binary:foo=YmFyCg==`, the latter taking
|
|
|
|
|
a Base64 encoded argument to permit binary credentials being passed
|
|
|
|
|
in). Alternatively, qemu VMs can be invoked with `-fw_cfg
|
2022-04-22 21:43:11 +08:00
|
|
|
|
name=opt/io.systemd.credentials/foo,string=bar` to pass credentials from
|
2022-07-14 00:26:44 +08:00
|
|
|
|
host through the hypervisor into the VM via qemu's `fw_cfg` mechanism. (All
|
|
|
|
|
three of these specific switches would set credential `foo` to `bar`.)
|
|
|
|
|
Passing credentials via the SMBIOS mechanism is typically preferable over
|
|
|
|
|
`fw_cfg` since it is faster and less specific to the chosen VMM
|
2022-08-10 20:21:50 +08:00
|
|
|
|
implementation. Moreover, `fw_cfg` has a 55 character limitation
|
|
|
|
|
on names passed that way. So some settings may not fit.
|
2022-04-22 21:43:11 +08:00
|
|
|
|
|
|
|
|
|
3. Credentials can also be passed into a system via the kernel command line,
|
|
|
|
|
via the `systemd.set-credential=` kernel command line option. Note though
|
|
|
|
|
that any data specified here is visible to any userspace application via
|
|
|
|
|
`/proc/cmdline`. This is hence typically not useful to pass sensitive
|
|
|
|
|
information.
|
|
|
|
|
|
|
|
|
|
4. Credentials may also be passed from the UEFI environment to userspace, if
|
|
|
|
|
the
|
|
|
|
|
[`systemd-stub`](https://www.freedesktop.org/software/systemd/man/systemd-stub.html)
|
|
|
|
|
UEFI kernel stub is used. This allows placing encrypted credentials in the
|
|
|
|
|
EFI System Partition, which are then picked up by `systemd-stub` and passed
|
2022-05-03 00:16:32 +08:00
|
|
|
|
to the kernel and ultimately userspace where systemd receives them. This is
|
2022-04-22 21:43:11 +08:00
|
|
|
|
useful to implement secure parameterization of vendor-built and signed
|
2022-09-23 21:10:06 +08:00
|
|
|
|
initrds, as userspace can place credentials next to these EFI kernels, and
|
|
|
|
|
be sure they can be accessed securely from initrd context.
|
2022-04-22 21:43:11 +08:00
|
|
|
|
|
|
|
|
|
Credentials passed to the system may be enumerated/displayed via `systemd-creds
|
|
|
|
|
--system`. They may also be propagated down to services, via the
|
|
|
|
|
`LoadCredential=` setting. Example:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
systemd-nspawn --set-credential=mycred:supersecret -i test.raw -b
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
or
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
qemu-system-x86_64 \
|
|
|
|
|
-machine type=q35,accel=kvm,smm=on \
|
|
|
|
|
-smp 2 \
|
|
|
|
|
-m 1G \
|
|
|
|
|
-cpu host \
|
|
|
|
|
-nographic \
|
|
|
|
|
-nodefaults \
|
|
|
|
|
-serial mon:stdio \
|
|
|
|
|
-drive if=none,id=hd,file=test.raw,format=raw \
|
|
|
|
|
-device virtio-scsi-pci,id=scsi \
|
|
|
|
|
-device scsi-hd,drive=hd,bootindex=1 \
|
2022-07-14 00:26:44 +08:00
|
|
|
|
-smbios type=11,value=io.systemd.credential:mycred=supersecret
|
2022-04-22 21:43:11 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Either of these lines will boot a disk image `test.raw`, once as container via
|
|
|
|
|
`systemd-nspawn`, and once as VM via `qemu`. In each case the credential
|
|
|
|
|
`mycred` is set to `supersecret`.
|
|
|
|
|
|
|
|
|
|
Inside of the system invoked that way the credential may then be viewed:
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
systemd-creds --system cat mycred
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Or propagated to services further down:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
systemd-run -p LoadCredential=mycred -P --wait systemd-creds cat mycred
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Well-Known Credentials
|
|
|
|
|
|
|
|
|
|
Various services shipped with `systemd` consume credentials for tweaking behaviour:
|
|
|
|
|
|
2023-01-04 01:11:04 +08:00
|
|
|
|
* [`systemd(1)`](https://www.freedesktop.org/software/systemd/man/systemd.html)
|
|
|
|
|
(I.E.: PID1, the system manager) will look for the credential `vmm.notify_socket`
|
|
|
|
|
and will use it to send a `READY=1` datagram when the system has finished
|
|
|
|
|
booting. This is useful for hypervisors/VMMs or other processes on the host
|
|
|
|
|
to receive a notification via VSOCK when a virtual machine has finished booting.
|
|
|
|
|
Note that in case the hypervisor does not support `SOCK_DGRAM` over `AF_VSOCK`,
|
|
|
|
|
`SOCK_SEQPACKET` will be tried instead. The credential payload should be in the
|
2023-01-16 04:11:23 +08:00
|
|
|
|
form: `vsock:<CID>:<PORT>`. Also note that this requires support for VHOST to be
|
|
|
|
|
built-in both the guest and the host kernels, and the kernel modules to be loaded.
|
2023-01-04 01:11:04 +08:00
|
|
|
|
|
2022-04-22 21:43:11 +08:00
|
|
|
|
* [`systemd-sysusers(8)`](https://www.freedesktop.org/software/systemd/man/systemd-sysusers.html)
|
|
|
|
|
will look for the credentials `passwd.hashed-password.<username>`,
|
|
|
|
|
`passwd.plaintext-password.<username>` and `passwd.shell.<username>` to
|
|
|
|
|
configure the password (either in UNIX hashed form, or plaintext) or shell of
|
|
|
|
|
system users created. Replace `<username>` with the system user of your
|
2023-01-15 16:00:00 +08:00
|
|
|
|
choice, for example, `root`.
|
2022-04-22 21:43:11 +08:00
|
|
|
|
|
|
|
|
|
* [`systemd-firstboot(1)`](https://www.freedesktop.org/software/systemd/man/systemd-firstboot.html)
|
|
|
|
|
will look for the credentials `firstboot.locale`, `firstboot.locale-messages`,
|
|
|
|
|
`firstboot.keymap`, `firstboot.timezone`, that configure locale, keymap or
|
|
|
|
|
timezone settings in case the data is not yet set in `/etc/`.
|
|
|
|
|
|
2022-09-08 23:33:24 +08:00
|
|
|
|
* [`tmpfiles.d(5)`](https://www.freedesktop.org/software/systemd/man/tmpfiles.d.html)
|
|
|
|
|
will look for the credentials `tmpfiles.extra` with arbitrary tmpfiles.d lines.
|
|
|
|
|
Can be encoded in base64 to allow easily passing it on the command line.
|
|
|
|
|
|
2022-04-22 21:43:11 +08:00
|
|
|
|
In future more services are likely to gain support for consuming credentials.
|
|
|
|
|
|
|
|
|
|
Example:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
systemd-nspawn -i test.raw \
|
|
|
|
|
--set-credential=passwd.hashed-password.root:$(mkpasswd mysecret) \
|
|
|
|
|
--set-credential=firstboot.locale:C.UTF-8 \
|
|
|
|
|
-b
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
This boots the specified disk image as `systemd-nspawn` container, and passes
|
|
|
|
|
the root password `mysecret`and default locale `C.UTF-8` to use to it. This
|
|
|
|
|
data is then propagated by default to `systemd-sysusers.service` and
|
|
|
|
|
`systemd-firstboot.service`, where it is applied. (Note that these services
|
|
|
|
|
will only do so if these settings in `/etc/` are so far unset, i.e. they only
|
|
|
|
|
have an effect on *unprovisioned* systems, and will never override data already
|
|
|
|
|
established in `/etc/`.) A similar line for qemu is:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
qemu-system-x86_64 \
|
|
|
|
|
-machine type=q35,accel=kvm,smm=on \
|
|
|
|
|
-smp 2 \
|
|
|
|
|
-m 1G \
|
|
|
|
|
-cpu host \
|
|
|
|
|
-nographic \
|
|
|
|
|
-nodefaults \
|
|
|
|
|
-serial mon:stdio \
|
|
|
|
|
-drive if=none,id=hd,file=test.raw,format=raw \
|
|
|
|
|
-device virtio-scsi-pci,id=scsi \
|
|
|
|
|
-device scsi-hd,drive=hd,bootindex=1 \
|
2022-07-14 00:26:44 +08:00
|
|
|
|
-smbios type=11,value=io.systemd.credential:passwd.hashed-password.root=$(mkpasswd mysecret) \
|
|
|
|
|
-smbios type=11,value=io.systemd.credential:firstboot.locale=C.UTF-8
|
2022-04-22 21:43:11 +08:00
|
|
|
|
```
|
|
|
|
|
|
2022-09-08 23:33:24 +08:00
|
|
|
|
This boots the specified disk image via qemu, provisioning public key SSH access
|
2023-01-04 01:11:04 +08:00
|
|
|
|
for the root user from the caller's key, and sends a notification when booting
|
|
|
|
|
has finished to a process on the host:
|
2022-09-08 23:33:24 +08:00
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
qemu-system-x86_64 \
|
|
|
|
|
-machine type=q35,accel=kvm,smm=on \
|
|
|
|
|
-smp 2 \
|
|
|
|
|
-m 1G \
|
|
|
|
|
-cpu host \
|
|
|
|
|
-nographic \
|
|
|
|
|
-nodefaults \
|
|
|
|
|
-serial mon:stdio \
|
|
|
|
|
-drive if=none,id=hd,file=test.raw,format=raw \
|
|
|
|
|
-device virtio-scsi-pci,id=scsi \
|
|
|
|
|
-device scsi-hd,drive=hd,bootindex=1 \
|
2023-01-04 01:11:04 +08:00
|
|
|
|
-device vhost-vsock-pci,id=vhost-vsock-pci0,guest-cid=42 \
|
|
|
|
|
-smbios type=11,value=io.systemd.credential:vmm.notify_socket=vsock:2:1234 \
|
2022-09-08 23:33:24 +08:00
|
|
|
|
-smbios type=11,value=io.systemd.credential.binary:tmpfiles.extra=$(echo "f~ /root/.ssh/authorized_keys 700 root root - $(ssh-add -L | base64 -w 0)" | base64 -w 0)
|
|
|
|
|
```
|
2023-01-04 01:11:04 +08:00
|
|
|
|
|
|
|
|
|
A process on the host can listen for the notification, for example:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
$ socat - VSOCK-LISTEN:1234,socktype=5
|
|
|
|
|
READY=1
|
|
|
|
|
```
|
|
|
|
|
|
2022-04-22 21:43:11 +08:00
|
|
|
|
## Relevant Paths
|
|
|
|
|
|
|
|
|
|
From *service* perspective the runtime path to find loaded credentials in is
|
|
|
|
|
provided in the `$CREDENTIALS_DIRECTORY` environment variable.
|
|
|
|
|
|
|
|
|
|
At runtime, credentials passed to the *system* are placed in
|
|
|
|
|
`/run/credentials/@system/` (for regular credentials, such as those passed from
|
|
|
|
|
a container manager or via qemu) and `/run/credentials/@encrypted/` (for
|
|
|
|
|
credentials that must be decrypted/validated before use, such as those from
|
|
|
|
|
`systemd-stub`).
|
|
|
|
|
|
|
|
|
|
The `LoadCredential=` and `LoadCredentialEncrypted=` settings when configured
|
|
|
|
|
with a relative source path will search for the source file to read the
|
|
|
|
|
credential from automatically. Primarily, these credentials are searched among
|
|
|
|
|
the credentials passed into the system. If not found there, they are searched
|
|
|
|
|
in `/etc/credstore/`, `/run/credstore/`,
|
|
|
|
|
`/usr/lib/credstore/`. `LoadCredentialEncrypted=` will also search
|
|
|
|
|
`/etc/credstore.encrypted/` and similar directories. These directories are
|
|
|
|
|
hence a great place to store credentials to load on the system.
|
2022-07-13 16:38:53 +08:00
|
|
|
|
|
|
|
|
|
## Conditionalizing Services
|
|
|
|
|
|
|
|
|
|
Sometimes it makes sense to conditionalize system services and invoke them only
|
2023-01-15 16:00:00 +08:00
|
|
|
|
if the right system credential is passed to the system. Use the
|
2022-07-13 16:38:53 +08:00
|
|
|
|
`ConditionCredential=` and `AssertCredential=` unit file settings for that.
|