]> git.ipfire.org Git - thirdparty/systemd.git/blob - docs/CREDENTIALS.md
doc: add new markdown docs for credentials
[thirdparty/systemd.git] / docs / CREDENTIALS.md
1 ---
2 title: Credentials
3 category: Concepts
4 layout: default
5 SPDX-License-Identifier: LGPL-2.1-or-later
6 ---
7
8 # System and Service Credentials
9
10 The `systemd` service manager supports a "credential" concept for securely
11 acquiring and passing credential data to systems and services. The precise
12 nature of the credential data is up to applications, but the concept is
13 intended to provide systems and services with potentially security sensitive
14 cryptographic keys, certificates, passwords, identity information and similar
15 types of information. It may also be used as generic infrastructure for
16 parameterizing systems and services.
17
18 Traditionally, data of this nature has often been provided to services via
19 environment variables (which is problematic because by default they are
20 inherited down the process tree, have size limitations, and issues with binary
21 data) or simple, unencrypted files on disk. `systemd`'s system and service
22 credentials are supposed to provide a better alternative for this
23 purpose. Specifically, the following features are provided:
24
25 1. Service credentials are acquired at the moment of service activation, and
26 released on service deactivation. They are immutable during the service
27 runtime.
28
29 2. Service credentials are accessible to service code as regular files, the
30 path to access them is derived from the environment variable
31 `$CREDENTIALS_DIRECTORY`.
32
33 3. Access to credentials is restricted to the service's user. Unlike
34 environment variables the credential data is not propagated down the process
35 tree. Instead each time a credential is accessed an access check is enforced
36 by the kernel. If the service is using file system namespacing the loaded
37 credential data is invisble to any other services.
38
39 4. Service credentials may be acquired from files on disk, specified as literal
40 strings in unit files, acquired from another service dynamically via an
41 `AF_UNIX` socket, or inherited from the system credentials the system itself
42 received.
43
44 5. Credentials may optionally be encrypted and authenticated, either with a key
45 derived from a local TPM2 chip, or one stored in `/var/`, or both. This
46 encryption is supposed to *just* *work*, and requires no manual setup. (That
47 is besides first encrypting relevant credentials with one simple command,
48 see below.)
49
50 6. Service credentials are placed in non-swappable memory. (If permissions
51 allow it, via `ramfs`.)
52
53 7. Credentials may be acquired from a hosting VM hypervisor (qemu `fw_cfg`), a
54 hosting container manager, the kernel command line, or from the UEFI
55 environment and the EFI System Partition (via `systemd-stub`). Such system
56 credentials may then be propagated into individual services as needed.
57
58 8. Credentials are an effective way to pass parameters into services that run
59 with `RootImage=` or `RootDirectory=` and thus cannot read these resources
60 directly from the host directory tree. Specifically, [Portable
61 Services](https://systemd.io/PORTABLE_SERVICES) may be parameterized this
62 way securely and robustly.
63
64 9. Credentials can be binary and relatively large (though currently an overall
65 size limit of 1M per service is enforced).
66
67 ## Configuring per-Service Credentials
68
69 Within unit files, there are four settings to configure service credentials.
70
71 1. `LoadCredential=` may be used to load a credential from disk, from an
72 `AF_UNIX` socket, or propagate them from a system credential.
73
74 2. `SetCredential=` may be used to set a credential to a literal string encoded
75 in the unit file. Because unit files are world-readable (both on disk and
76 via D-Bus), this should only be used for credentials that aren't sensitive,
77 i.e. public keys/certificates – but not private keys.
78
79 3. `LoadCredentialEncrypted=` is similar to `LoadCredential=` but will load an
80 encrypted credential, and decrypt it before passing it to the service. For
81 details on credential encryption, see below.
82
83 4. `SetCredentialEncrypted=` is similar to `SetCredential=` but expects an
84 encrypted credential to be specified literally. Unlike `SetCredential=` it
85 is thus safe to be used even for sensitive information, because even though
86 unit files are world readable, the ciphertext included in them cannot be
87 decoded unless access to TPM2/encryption key is available.
88
89 Each credential configured with these options carries a short name (suitable
90 for inclusion in a filename) in the unit file, under which the invoked service
91 code can then retrieve it. Each name should only be specified once.
92
93 For details about these four settings [see the man
94 page](https://www.freedesktop.org/software/systemd/man/systemd.exec.html#Credentials).
95
96 It is a good idea to also enable mount namespacing for services that process
97 credentials configured this way. If so, the runtime credential directory of the
98 specific service is not visible to any other service. Use `PrivateMounts=` as
99 minimal option to enable such namespacing. Note that many other sandboxing
100 settings (e.g. `ProtectSystem=`, `ReadOnlyPaths=` and similar) imply
101 `PrivateMounts=`, hence oftentimes it's not necessary to set this option
102 explicitly.
103
104 ## Programming Interface from Service Code
105
106 When a service is invoked with one or more credentials set it will have an
107 environment variable `$CREDENTIALS_DIRECTORY` set. It contains an absolute path
108 to a directory the credentials are placed in. In this directory for each
109 configured credential one file is placed. In addition to the
110 `$CREDENTIALS_DIRECTORY` environment variable passed to the service processes
111 the `%d` specifier in unit files resolves to the service's credential
112 directory.
113
114 Example unit file:
115
116 ```
117
118 [Service]
119 ExecStart=/usr/bin/myservice.sh
120 LoadCredential=foobar:/etc/myfoobarcredential.txt
121 Environment=FOOBARPATH=%d/foobar
122
123 ```
124
125 Associated service shell script `/usr/bin/myservice.sh`:
126
127 ```sh
128 #!/bin/sh
129
130 sha256sum $CREDENTIAL_PATH/foobar
131 sha256sum $FOOBARPATH
132
133 ```
134
135 A service defined like this will get the contents of the file
136 `/etc/myfoobarcredential.txt` passed as credential `foobar`, which is hence
137 accessible under `$CREDENTIALS_DIRECTORY/foobar`. Since we additionally pass
138 the path to it as environment variable `$FOOBARPATH` the credential is also
139 accessible as the path in that environment variable. When invoked, the service
140 will hence show the same SHA256 hash value of `/etc/myfoobarcredential.txt`
141 twice.
142
143 In an ideal world, well-behaved service code would directly support credentials
144 passed this way, i.e. look for `$CREDENTIALS_DIRECTORY` and load the credential
145 data it needs from there. For daemons that do not support this but allow
146 passing credentials via a path supplied over the command line use
147 `${CREDENTIAL_PATH}` in the `ExecStart=` command line to reference the
148 credentials directory. For daemons that allow passing credentials via a path
149 supplied as environment variabe, use the `%d` specifier in the `Environment=`
150 setting to build valid paths to specific credentials.
151
152 ## Tools
153
154 The
155 [`systemd-creds`](https://www.freedesktop.org/software/systemd/man/systemd-creds.html)
156 tool is provided to work with system and service credentials. It may be used to
157 access and enumerate system and service credentials, or to encrypt/decrypt credentials
158 (for details about the latter, see below).
159
160 When invoked from service context, `systemd-creds` passed without further
161 parameters will list passed credentials. The `systemd-creds cat xyz` command
162 may be used to write the contents of credential `xyz` to standard output. If
163 these calls are combined with the `--system` switch credentials passed to the
164 system as a whole are shown, instead of the those passed to the service the
165 command is invoked from.
166
167 Example use:
168
169 ```sh
170 systemd-run -P --wait -p LoadCredential=abc:/etc/hosts systemd-creds cat abc
171 ```
172
173 This will invoke a transient service with a credential `abc` sourced from the
174 system's `/etc/hosts` file. This credential is then written to standard output
175 via `systemd-creds cat`.
176
177 ## Encryption
178
179 Credentials are supposed to be useful for carrying sensitive information, such
180 as cryptographic key material. For this kind of data (symmetric) encryption and
181 authentication is provided to make storage of the data at rest safer. The data
182 may be encrypted and authenticated with AES256-GCM. The encryption key can
183 either be one derived from the local TPM2 device, or one stored in
184 `/var/lib/systemd/credential.secret`, or a combination of both. If a TPM2
185 device is available and `/var/` resides on persistent storage the default
186 behaviour is to use the combination of both for encryption, thus ensuring that
187 credentials protected this way can only be decrypted and validated on the
188 local hardware and OS installation. Encrypted credentials stored on disk thus
189 cannot be decrypted without access to the TPM2 chip and the aforementioned key
190 file `/var/lib/systemd/credential.secret`. Moreover, credentials cannot be
191 prepared on another machine than the local one.
192
193 The `systemd-creds` tool provides the commands `encrypt` and `decrypt` to
194 encrypt and decrypt/authenticate credentials. Example:
195
196 ```sh
197 systemd-creds encrypt plaintext.txt ciphertext.cred
198 shred -u plaintext-txt
199 systemd-run -P --wait -p LoadCredentialEncrypted=foobar:$(pwd)/ciphertext.cred systemd-creds cat foobar
200 ```
201
202 This will first create an encrypted copy of the file `plaintext.txt` in the
203 encrypted credential file `ciphertext.cred`. It then securely removes the
204 source file. It then runs a transient service, that reads the encrypted file
205 and passes it as decrypted credential `foobar` to the invoked service binary
206 (which here is the `systemd-creds` tool, which just writes the data
207 it received to standard output).
208
209 Instead of storing the encrypted credential as a separate file on disk, it can
210 also be embedded in the unit file. Example:
211
212 ```
213 systemd-creds encrypt -p --name=foobar plaintext.txt -
214 ```
215
216 This will output a `SetCredentialEncrypted=` line that can directly be used in
217 a unit file. e.g.:
218
219 ```
220
221 [Service]
222 ExecStart=/usr/bin/systemd-creds cat foobar
223 SetCredentialEncrypted=foobar: \
224 k6iUCUh0RJCQyvL8k8q1UyAAAAABAAAADAAAABAAAAC1lFmbWAqWZ8dCCQkAAAAAgAAAA \
225 AAAAAALACMA0AAAACAAAAAAfgAg9uNpGmj8LL2nHE0ixcycvM3XkpOCaf+9rwGscwmqRJ \
226 cAEO24kB08FMtd/hfkZBX8PqoHd/yPTzRxJQBoBsvo9VqolKdy9Wkvih0HQnQ6NkTKEdP \
227 HQ08+x8sv5sr+Mkv4ubp3YT1Jvv7CIPCbNhFtag1n5y9J7bTOKt2SQwBOAAgACwAAABIA \
228 ID8H3RbsT7rIBH02CIgm/Gv1ukSXO3DMHmVQkDG0wEciABAAII6LvrmL60uEZcp5qnEkx \
229 SuhUjsDoXrJs0rfSWX4QAx5PwfdFuxPusgEfTYIiCb8a/W6RJc7cMweZVCQMbTARyIAAA \
230 AAJt7Q9F/Gz0pBv1Lc4Dpn1WpebyBBm+vQ5N/lSKW2XSm8cONwCopxpDc7wJjXg7OTR6r \
231 xGCpIvGXLt3ibwJl81woLya2RRjIvc/R2zNm/yWzZAjiOLPih4SuHthqiX98ey8PUmZJB \
232 VGXglCZFjBx+d7eCqTIdghtp5pkDGwMJT6pjw4FfyFK2nJPawFKPAqzw9DK2iYttFeXi5 \
233 19xCfLBH9NKS/idlYXrhp+XIEtsr26s4lx5y10Goyc3qDOR3RD2cuZj0gHwV35hhhhcCz \
234 JaYytef1X/YL+7fYH5kuE4rxSksoUuA/LhtjszBeGbcbIT+O8SuvBJHLKTSHxPL8FTyk3 \
235 L4FSkEHs0rYwUIkKmnGohDdsYrMJ2fjH3yDNBP16aD1+f/Nuh75cjhUnGsDLt9K4hGg== \
236
237 ```
238
239 ## Inheritance from Container Managers, Hypervisors, Kernel Command Line, or the UEFI Boot Environment
240
241 Sometimes it is useful to parameterize whole systems the same way as services,
242 via `systemd` credentials. In particular, it might make sense to boot a
243 system with a set of credentials that are then propagated to individual
244 services where they are ultimately consumed.
245
246 `systemd` supports four ways to pass credentials to systems:
247
248 1. A container manager may set the `$CREDENTIALS_DIRECTORY` environment
249 variable for systemd running as PID 1 in the container, the same way as
250 systemd would set it for a service it
251 invokes. [`systemd-nspawn(1)`](https://www.freedesktop.org/software/systemd/man/systemd-nspawn.html#Credentials)'s
252 `--set-credential=` and `--load-credential=` switches implement this, in
253 order to pass arbitrary credentials from host to container payload. Also see
254 the [Container Interface](https://systemd.io/CONTAINER_INTERFACE)
255 documentation.
256
257 2. Quite similar, qemu VMs can be invoked with `-fw_cfg
258 name=opt/io.systemd.credentials/foo,string=bar` to pass credentials from
259 host through the hypervisor into the VM. (This specific switch would set
260 credential `foo` to `bar`.)
261
262 3. Credentials can also be passed into a system via the kernel command line,
263 via the `systemd.set-credential=` kernel command line option. Note though
264 that any data specified here is visible to any userspace application via
265 `/proc/cmdline`. This is hence typically not useful to pass sensitive
266 information.
267
268 4. Credentials may also be passed from the UEFI environment to userspace, if
269 the
270 [`systemd-stub`](https://www.freedesktop.org/software/systemd/man/systemd-stub.html)
271 UEFI kernel stub is used. This allows placing encrypted credentials in the
272 EFI System Partition, which are then picked up by `systemd-stub` and passed
273 to the kernel and ultimately userpace where systemd receives them. This is
274 useful to implement secure parameterization of vendor-built and signed
275 initial RAM disks, as userspace can place credentials next to these EFI
276 kernels, and be sure they can be accessed securely from initrd context.
277
278 Credentials passed to the system may be enumerated/displayed via `systemd-creds
279 --system`. They may also be propagated down to services, via the
280 `LoadCredential=` setting. Example:
281
282 ```
283 systemd-nspawn --set-credential=mycred:supersecret -i test.raw -b
284 ```
285
286 or
287
288 ```
289 qemu-system-x86_64 \
290 -machine type=q35,accel=kvm,smm=on \
291 -smp 2 \
292 -m 1G \
293 -cpu host \
294 -nographic \
295 -nodefaults \
296 -serial mon:stdio \
297 -drive if=none,id=hd,file=test.raw,format=raw \
298 -device virtio-scsi-pci,id=scsi \
299 -device scsi-hd,drive=hd,bootindex=1 \
300 -fw_cfg name=opt/io.systemd.credentials/mycred,string=supersecret
301 ```
302
303 Either of these lines will boot a disk image `test.raw`, once as container via
304 `systemd-nspawn`, and once as VM via `qemu`. In each case the credential
305 `mycred` is set to `supersecret`.
306
307 Inside of the system invoked that way the credential may then be viewed:
308
309 ```sh
310 systemd-creds --system cat mycred
311 ```
312
313 Or propagated to services further down:
314
315 ```
316 systemd-run -p LoadCredential=mycred -P --wait systemd-creds cat mycred
317 ```
318
319 ## Well-Known Credentials
320
321 Various services shipped with `systemd` consume credentials for tweaking behaviour:
322
323 * [`systemd-sysusers(8)`](https://www.freedesktop.org/software/systemd/man/systemd-sysusers.html)
324 will look for the credentials `passwd.hashed-password.<username>`,
325 `passwd.plaintext-password.<username>` and `passwd.shell.<username>` to
326 configure the password (either in UNIX hashed form, or plaintext) or shell of
327 system users created. Replace `<username>` with the system user of your
328 choice, for example `root`.
329
330 * [`systemd-firstboot(1)`](https://www.freedesktop.org/software/systemd/man/systemd-firstboot.html)
331 will look for the credentials `firstboot.locale`, `firstboot.locale-messages`,
332 `firstboot.keymap`, `firstboot.timezone`, that configure locale, keymap or
333 timezone settings in case the data is not yet set in `/etc/`.
334
335 In future more services are likely to gain support for consuming credentials.
336
337 Example:
338
339 ```
340 systemd-nspawn -i test.raw \
341 --set-credential=passwd.hashed-password.root:$(mkpasswd mysecret) \
342 --set-credential=firstboot.locale:C.UTF-8 \
343 -b
344 ```
345
346 This boots the specified disk image as `systemd-nspawn` container, and passes
347 the root password `mysecret`and default locale `C.UTF-8` to use to it. This
348 data is then propagated by default to `systemd-sysusers.service` and
349 `systemd-firstboot.service`, where it is applied. (Note that these services
350 will only do so if these settings in `/etc/` are so far unset, i.e. they only
351 have an effect on *unprovisioned* systems, and will never override data already
352 established in `/etc/`.) A similar line for qemu is:
353
354 ```
355 qemu-system-x86_64 \
356 -machine type=q35,accel=kvm,smm=on \
357 -smp 2 \
358 -m 1G \
359 -cpu host \
360 -nographic \
361 -nodefaults \
362 -serial mon:stdio \
363 -drive if=none,id=hd,file=test.raw,format=raw \
364 -device virtio-scsi-pci,id=scsi \
365 -device scsi-hd,drive=hd,bootindex=1 \
366 -fw_cfg name=opt/io.systemd.credentials/passwd.hashed-password.root,string=$(mkpasswd mysecret) \
367 -fw_cfg name=opt/io.systemd.credentials/firstboot.locale,string=C.UTF-8
368 ```
369
370 ## Relevant Paths
371
372 From *service* perspective the runtime path to find loaded credentials in is
373 provided in the `$CREDENTIALS_DIRECTORY` environment variable.
374
375 At runtime, credentials passed to the *system* are placed in
376 `/run/credentials/@system/` (for regular credentials, such as those passed from
377 a container manager or via qemu) and `/run/credentials/@encrypted/` (for
378 credentials that must be decrypted/validated before use, such as those from
379 `systemd-stub`).
380
381 The `LoadCredential=` and `LoadCredentialEncrypted=` settings when configured
382 with a relative source path will search for the source file to read the
383 credential from automatically. Primarily, these credentials are searched among
384 the credentials passed into the system. If not found there, they are searched
385 in `/etc/credstore/`, `/run/credstore/`,
386 `/usr/lib/credstore/`. `LoadCredentialEncrypted=` will also search
387 `/etc/credstore.encrypted/` and similar directories. These directories are
388 hence a great place to store credentials to load on the system.