]>
Commit | Line | Data |
---|---|---|
fe672fe5 LP |
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 | |
30fd9a2d | 37 | credential data is invisible to all other services. |
fe672fe5 LP |
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 | ||
8de7de46 | 53 | 7. Credentials may be acquired from a hosting VM hypervisor (SMBIOS OEM strings |
df5f51c3 LP |
54 | or qemu `fw_cfg`), a hosting container manager, the kernel command line, |
55 | from the initrd, or from the UEFI environment via the EFI System Partition | |
56 | (via `systemd-stub`). Such system credentials may then be propagated into | |
8de7de46 | 57 | individual services as needed. |
fe672fe5 LP |
58 | |
59 | 8. Credentials are an effective way to pass parameters into services that run | |
60 | with `RootImage=` or `RootDirectory=` and thus cannot read these resources | |
5c90c67a | 61 | directly from the host directory tree. |
0d592a5e | 62 | Specifically, [Portable Services](/PORTABLE_SERVICES) may be |
5c90c67a | 63 | parameterized this way securely and robustly. |
fe672fe5 LP |
64 | |
65 | 9. Credentials can be binary and relatively large (though currently an overall | |
66 | size limit of 1M per service is enforced). | |
67 | ||
68 | ## Configuring per-Service Credentials | |
69 | ||
3a169480 AW |
70 | Within unit files, there are the following settings to configure service |
71 | credentials. | |
fe672fe5 LP |
72 | |
73 | 1. `LoadCredential=` may be used to load a credential from disk, from an | |
74 | `AF_UNIX` socket, or propagate them from a system credential. | |
75 | ||
df5f51c3 LP |
76 | 2. `ImportCredential=` may be used to load one or more (optionally encrypted) |
77 | credentials from disk or from the credential stores. | |
bbfb25f4 | 78 | |
df5f51c3 | 79 | 3. `SetCredential=` may be used to set a credential to a literal string encoded |
fe672fe5 LP |
80 | in the unit file. Because unit files are world-readable (both on disk and |
81 | via D-Bus), this should only be used for credentials that aren't sensitive, | |
5811490a | 82 | e.g. public keys or certificates, but not private keys. |
fe672fe5 | 83 | |
df5f51c3 | 84 | 4. `LoadCredentialEncrypted=` is similar to `LoadCredential=` but will load an |
fe672fe5 LP |
85 | encrypted credential, and decrypt it before passing it to the service. For |
86 | details on credential encryption, see below. | |
87 | ||
df5f51c3 | 88 | 5. `SetCredentialEncrypted=` is similar to `SetCredential=` but expects an |
fe672fe5 LP |
89 | encrypted credential to be specified literally. Unlike `SetCredential=` it |
90 | is thus safe to be used even for sensitive information, because even though | |
91 | unit files are world readable, the ciphertext included in them cannot be | |
92 | decoded unless access to TPM2/encryption key is available. | |
93 | ||
94 | Each credential configured with these options carries a short name (suitable | |
95 | for inclusion in a filename) in the unit file, under which the invoked service | |
96 | code can then retrieve it. Each name should only be specified once. | |
97 | ||
3a169480 | 98 | For details about these settings [see the man |
fe672fe5 LP |
99 | page](https://www.freedesktop.org/software/systemd/man/systemd.exec.html#Credentials). |
100 | ||
101 | It is a good idea to also enable mount namespacing for services that process | |
102 | credentials configured this way. If so, the runtime credential directory of the | |
103 | specific service is not visible to any other service. Use `PrivateMounts=` as | |
104 | minimal option to enable such namespacing. Note that many other sandboxing | |
105 | settings (e.g. `ProtectSystem=`, `ReadOnlyPaths=` and similar) imply | |
106 | `PrivateMounts=`, hence oftentimes it's not necessary to set this option | |
107 | explicitly. | |
108 | ||
109 | ## Programming Interface from Service Code | |
110 | ||
111 | When a service is invoked with one or more credentials set it will have an | |
112 | environment variable `$CREDENTIALS_DIRECTORY` set. It contains an absolute path | |
113 | to a directory the credentials are placed in. In this directory for each | |
114 | configured credential one file is placed. In addition to the | |
115 | `$CREDENTIALS_DIRECTORY` environment variable passed to the service processes | |
116 | the `%d` specifier in unit files resolves to the service's credential | |
117 | directory. | |
118 | ||
119 | Example unit file: | |
120 | ||
121 | ``` | |
122 | … | |
123 | [Service] | |
124 | ExecStart=/usr/bin/myservice.sh | |
125 | LoadCredential=foobar:/etc/myfoobarcredential.txt | |
126 | Environment=FOOBARPATH=%d/foobar | |
127 | … | |
128 | ``` | |
129 | ||
130 | Associated service shell script `/usr/bin/myservice.sh`: | |
131 | ||
132 | ```sh | |
133 | #!/bin/sh | |
134 | ||
c0a18932 | 135 | sha256sum $CREDENTIALS_DIRECTORY/foobar |
fe672fe5 LP |
136 | sha256sum $FOOBARPATH |
137 | ||
138 | ``` | |
139 | ||
140 | A service defined like this will get the contents of the file | |
141 | `/etc/myfoobarcredential.txt` passed as credential `foobar`, which is hence | |
142 | accessible under `$CREDENTIALS_DIRECTORY/foobar`. Since we additionally pass | |
143 | the path to it as environment variable `$FOOBARPATH` the credential is also | |
144 | accessible as the path in that environment variable. When invoked, the service | |
145 | will hence show the same SHA256 hash value of `/etc/myfoobarcredential.txt` | |
146 | twice. | |
147 | ||
148 | In an ideal world, well-behaved service code would directly support credentials | |
149 | passed this way, i.e. look for `$CREDENTIALS_DIRECTORY` and load the credential | |
150 | data it needs from there. For daemons that do not support this but allow | |
151 | passing credentials via a path supplied over the command line use | |
c0a18932 | 152 | `${CREDENTIALS_DIRECTORY}` in the `ExecStart=` command line to reference the |
fe672fe5 | 153 | credentials directory. For daemons that allow passing credentials via a path |
77f081f3 | 154 | supplied as environment variable, use the `%d` specifier in the `Environment=` |
fe672fe5 LP |
155 | setting to build valid paths to specific credentials. |
156 | ||
df5f51c3 LP |
157 | Encrypted credentials are automatically decrypted/authenticated during service |
158 | activation, so that service code only receives plaintext credentials. | |
159 | ||
160 | ## Programming Interface from Generator Code | |
161 | ||
162 | [Generators](https://www.freedesktop.org/software/systemd/man/systemd.generator.html) | |
163 | may generate native unit files from external configuration or system | |
164 | parameters, such as system credentials. Note that they run outside of service | |
165 | context, and hence will not receive encrypted credentials in plaintext | |
166 | form. Specifically, credentials passed into the system in encrypted form will | |
167 | be placed as they are in a directory referenced by the | |
168 | `$ENCRYPTED_CREDENTIALS_DIRECTORY` environment variable, and those passed in | |
169 | plaintext form will be placed in `$CREDENTIALS_DIRECTORY`. Use a command such | |
170 | as `systemd-creds --system cat …` to access both forms of credentials, and | |
171 | decrypt them if needed (see | |
172 | [systemd-creds(1)](https://www.freedesktop.org/software/systemd/man/systemd-creds.html) | |
173 | for details. | |
174 | ||
175 | Note that generators typically run very early during boot (similar to initrd | |
176 | code), earlier than the `/var/` file system is necessarily mounted (which is | |
177 | where the system's credential encryption secret is located). Thus it's a good | |
178 | idea to encrypt credentials with `systemd-creds encrypt --with-key=auto-initrd` | |
179 | if they shall be consumed by a generator, to ensure they are locked to the TPM2 | |
180 | only, not the credentials secret stored below `/var/`. | |
181 | ||
182 | For further details about encrypted credentials, see below. | |
183 | ||
fe672fe5 LP |
184 | ## Tools |
185 | ||
186 | The | |
187 | [`systemd-creds`](https://www.freedesktop.org/software/systemd/man/systemd-creds.html) | |
188 | tool is provided to work with system and service credentials. It may be used to | |
189 | access and enumerate system and service credentials, or to encrypt/decrypt credentials | |
190 | (for details about the latter, see below). | |
191 | ||
192 | When invoked from service context, `systemd-creds` passed without further | |
193 | parameters will list passed credentials. The `systemd-creds cat xyz` command | |
194 | may be used to write the contents of credential `xyz` to standard output. If | |
195 | these calls are combined with the `--system` switch credentials passed to the | |
e347d53a | 196 | system as a whole are shown, instead of those passed to the service the |
fe672fe5 LP |
197 | command is invoked from. |
198 | ||
199 | Example use: | |
200 | ||
201 | ```sh | |
202 | systemd-run -P --wait -p LoadCredential=abc:/etc/hosts systemd-creds cat abc | |
203 | ``` | |
204 | ||
205 | This will invoke a transient service with a credential `abc` sourced from the | |
206 | system's `/etc/hosts` file. This credential is then written to standard output | |
207 | via `systemd-creds cat`. | |
208 | ||
209 | ## Encryption | |
210 | ||
211 | Credentials are supposed to be useful for carrying sensitive information, such | |
3a169480 | 212 | as cryptographic key material. For such purposes (symmetric) encryption and |
e347d53a | 213 | authentication are provided to make storage of the data at rest safer. The data |
fe672fe5 LP |
214 | may be encrypted and authenticated with AES256-GCM. The encryption key can |
215 | either be one derived from the local TPM2 device, or one stored in | |
216 | `/var/lib/systemd/credential.secret`, or a combination of both. If a TPM2 | |
e347d53a | 217 | device is available and `/var/` resides on a persistent storage, the default |
fe672fe5 LP |
218 | behaviour is to use the combination of both for encryption, thus ensuring that |
219 | credentials protected this way can only be decrypted and validated on the | |
220 | local hardware and OS installation. Encrypted credentials stored on disk thus | |
221 | cannot be decrypted without access to the TPM2 chip and the aforementioned key | |
222 | file `/var/lib/systemd/credential.secret`. Moreover, credentials cannot be | |
e347d53a | 223 | prepared on a machine other than the local one. |
fe672fe5 | 224 | |
df5f51c3 LP |
225 | Decryption generally takes place at the moment of service activation. This |
226 | means credentials passed to the system can be either encrypted or plaintext and | |
227 | remain that way all the way while they are propagated to their consumers, until | |
228 | the moment of service activation when they are decrypted and authenticated, so | |
229 | that the service only sees plaintext credentials. | |
230 | ||
fe672fe5 LP |
231 | The `systemd-creds` tool provides the commands `encrypt` and `decrypt` to |
232 | encrypt and decrypt/authenticate credentials. Example: | |
233 | ||
234 | ```sh | |
08b61b40 | 235 | systemd-creds encrypt --name=foobar plaintext.txt ciphertext.cred |
026d48ba | 236 | shred -u plaintext.txt |
fe672fe5 LP |
237 | systemd-run -P --wait -p LoadCredentialEncrypted=foobar:$(pwd)/ciphertext.cred systemd-creds cat foobar |
238 | ``` | |
239 | ||
240 | This will first create an encrypted copy of the file `plaintext.txt` in the | |
241 | encrypted credential file `ciphertext.cred`. It then securely removes the | |
242 | source file. It then runs a transient service, that reads the encrypted file | |
243 | and passes it as decrypted credential `foobar` to the invoked service binary | |
244 | (which here is the `systemd-creds` tool, which just writes the data | |
245 | it received to standard output). | |
246 | ||
247 | Instead of storing the encrypted credential as a separate file on disk, it can | |
248 | also be embedded in the unit file. Example: | |
249 | ||
250 | ``` | |
251 | systemd-creds encrypt -p --name=foobar plaintext.txt - | |
252 | ``` | |
253 | ||
254 | This will output a `SetCredentialEncrypted=` line that can directly be used in | |
255 | a unit file. e.g.: | |
256 | ||
257 | ``` | |
258 | … | |
259 | [Service] | |
260 | ExecStart=/usr/bin/systemd-creds cat foobar | |
261 | SetCredentialEncrypted=foobar: \ | |
262 | k6iUCUh0RJCQyvL8k8q1UyAAAAABAAAADAAAABAAAAC1lFmbWAqWZ8dCCQkAAAAAgAAAA \ | |
263 | AAAAAALACMA0AAAACAAAAAAfgAg9uNpGmj8LL2nHE0ixcycvM3XkpOCaf+9rwGscwmqRJ \ | |
264 | cAEO24kB08FMtd/hfkZBX8PqoHd/yPTzRxJQBoBsvo9VqolKdy9Wkvih0HQnQ6NkTKEdP \ | |
265 | HQ08+x8sv5sr+Mkv4ubp3YT1Jvv7CIPCbNhFtag1n5y9J7bTOKt2SQwBOAAgACwAAABIA \ | |
266 | ID8H3RbsT7rIBH02CIgm/Gv1ukSXO3DMHmVQkDG0wEciABAAII6LvrmL60uEZcp5qnEkx \ | |
267 | SuhUjsDoXrJs0rfSWX4QAx5PwfdFuxPusgEfTYIiCb8a/W6RJc7cMweZVCQMbTARyIAAA \ | |
268 | AAJt7Q9F/Gz0pBv1Lc4Dpn1WpebyBBm+vQ5N/lSKW2XSm8cONwCopxpDc7wJjXg7OTR6r \ | |
269 | xGCpIvGXLt3ibwJl81woLya2RRjIvc/R2zNm/yWzZAjiOLPih4SuHthqiX98ey8PUmZJB \ | |
270 | VGXglCZFjBx+d7eCqTIdghtp5pkDGwMJT6pjw4FfyFK2nJPawFKPAqzw9DK2iYttFeXi5 \ | |
271 | 19xCfLBH9NKS/idlYXrhp+XIEtsr26s4lx5y10Goyc3qDOR3RD2cuZj0gHwV35hhhhcCz \ | |
272 | JaYytef1X/YL+7fYH5kuE4rxSksoUuA/LhtjszBeGbcbIT+O8SuvBJHLKTSHxPL8FTyk3 \ | |
273 | L4FSkEHs0rYwUIkKmnGohDdsYrMJ2fjH3yDNBP16aD1+f/Nuh75cjhUnGsDLt9K4hGg== \ | |
274 | … | |
275 | ``` | |
276 | ||
277 | ## Inheritance from Container Managers, Hypervisors, Kernel Command Line, or the UEFI Boot Environment | |
278 | ||
279 | Sometimes it is useful to parameterize whole systems the same way as services, | |
280 | via `systemd` credentials. In particular, it might make sense to boot a | |
281 | system with a set of credentials that are then propagated to individual | |
282 | services where they are ultimately consumed. | |
283 | ||
df5f51c3 | 284 | `systemd` supports five ways to pass credentials to systems: |
fe672fe5 LP |
285 | |
286 | 1. A container manager may set the `$CREDENTIALS_DIRECTORY` environment | |
287 | variable for systemd running as PID 1 in the container, the same way as | |
f00b3a99 | 288 | systemd would set it for a service it invokes. |
289 | [`systemd-nspawn(1)`](https://www.freedesktop.org/software/systemd/man/systemd-nspawn.html#Credentials)'s | |
fe672fe5 LP |
290 | `--set-credential=` and `--load-credential=` switches implement this, in |
291 | order to pass arbitrary credentials from host to container payload. Also see | |
0d592a5e | 292 | the [Container Interface](/CONTAINER_INTERFACE) documentation. |
fe672fe5 | 293 | |
8de7de46 LP |
294 | 2. Quite similar, VMs can be passed credentials via SMBIOS OEM strings (example |
295 | qemu command line switch `-smbios | |
296 | type=11,value=io.systemd.credential:foo=bar` or `-smbios | |
297 | type=11,value=io.systemd.credential.binary:foo=YmFyCg==`, the latter taking | |
298 | a Base64 encoded argument to permit binary credentials being passed | |
299 | in). Alternatively, qemu VMs can be invoked with `-fw_cfg | |
fe672fe5 | 300 | name=opt/io.systemd.credentials/foo,string=bar` to pass credentials from |
8de7de46 LP |
301 | host through the hypervisor into the VM via qemu's `fw_cfg` mechanism. (All |
302 | three of these specific switches would set credential `foo` to `bar`.) | |
303 | Passing credentials via the SMBIOS mechanism is typically preferable over | |
f00b3a99 | 304 | `fw_cfg` since it is faster and less specific to the chosen VMM implementation. |
305 | Moreover, `fw_cfg` has a 55 character limitation on names passed that way. So some settings may not fit. | |
fe672fe5 | 306 | |
f00b3a99 | 307 | 3. Credentials may be passed from the initrd to the host during the initrd → host transition. |
308 | Provisioning systems that run in the initrd may use this to install credentials on the system. | |
309 | All files placed in `/run/credentials/@initrd/` are imported into the set of file system credentials during the transition. | |
310 | The files (and their directory) are removed once this is completed. | |
fe672fe5 | 311 | |
85fe60b9 | 312 | 4. Credentials may also be passed from the UEFI environment to userspace, if |
fe672fe5 LP |
313 | the |
314 | [`systemd-stub`](https://www.freedesktop.org/software/systemd/man/systemd-stub.html) | |
f00b3a99 | 315 | UEFI kernel stub is used. |
316 | This allows placing encrypted credentials in the EFI System Partition, which are then picked up by `systemd-stub` and passed to the kernel and ultimately userspace where systemd receives them. | |
317 | This is useful to implement secure parameterization of vendor-built and signed | |
55c041b4 LP |
318 | initrds, as userspace can place credentials next to these EFI kernels, and |
319 | be sure they can be accessed securely from initrd context. | |
fe672fe5 | 320 | |
85fe60b9 | 321 | 5. Credentials can also be passed into a system via the kernel command line, |
de70ecb3 | 322 | via the `systemd.set_credential=` and `systemd.set_credential_binary=` |
f00b3a99 | 323 | kernel command line options (the latter takes Base64 encoded binary data). |
324 | Note though that any data specified here is visible to all userspace | |
de70ecb3 LP |
325 | applications (even unprivileged ones) via `/proc/cmdline`. Typically, this |
326 | is hence not useful to pass sensitive information, and should be avoided. | |
df5f51c3 | 327 | |
fe672fe5 LP |
328 | Credentials passed to the system may be enumerated/displayed via `systemd-creds |
329 | --system`. They may also be propagated down to services, via the | |
330 | `LoadCredential=` setting. Example: | |
331 | ||
332 | ``` | |
333 | systemd-nspawn --set-credential=mycred:supersecret -i test.raw -b | |
334 | ``` | |
335 | ||
336 | or | |
337 | ||
338 | ``` | |
339 | qemu-system-x86_64 \ | |
340 | -machine type=q35,accel=kvm,smm=on \ | |
341 | -smp 2 \ | |
342 | -m 1G \ | |
343 | -cpu host \ | |
344 | -nographic \ | |
345 | -nodefaults \ | |
346 | -serial mon:stdio \ | |
347 | -drive if=none,id=hd,file=test.raw,format=raw \ | |
348 | -device virtio-scsi-pci,id=scsi \ | |
349 | -device scsi-hd,drive=hd,bootindex=1 \ | |
8de7de46 | 350 | -smbios type=11,value=io.systemd.credential:mycred=supersecret |
fe672fe5 LP |
351 | ``` |
352 | ||
353 | Either of these lines will boot a disk image `test.raw`, once as container via | |
354 | `systemd-nspawn`, and once as VM via `qemu`. In each case the credential | |
355 | `mycred` is set to `supersecret`. | |
356 | ||
357 | Inside of the system invoked that way the credential may then be viewed: | |
358 | ||
359 | ```sh | |
360 | systemd-creds --system cat mycred | |
361 | ``` | |
362 | ||
363 | Or propagated to services further down: | |
364 | ||
365 | ``` | |
bbfb25f4 | 366 | systemd-run -p ImportCredential=mycred -P --wait systemd-creds cat mycred |
fe672fe5 LP |
367 | ``` |
368 | ||
369 | ## Well-Known Credentials | |
370 | ||
371 | Various services shipped with `systemd` consume credentials for tweaking behaviour: | |
372 | ||
4a91ace5 LB |
373 | * [`systemd(1)`](https://www.freedesktop.org/software/systemd/man/systemd.html) |
374 | (I.E.: PID1, the system manager) will look for the credential `vmm.notify_socket` | |
375 | and will use it to send a `READY=1` datagram when the system has finished | |
f00b3a99 | 376 | booting. |
377 | 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. | |
4a91ace5 | 378 | Note that in case the hypervisor does not support `SOCK_DGRAM` over `AF_VSOCK`, |
f00b3a99 | 379 | `SOCK_SEQPACKET` will be tried instead. |
380 | The credential payload should be in the form: `vsock:<CID>:<PORT>`. | |
381 | 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. | |
4a91ace5 | 382 | |
fe672fe5 LP |
383 | * [`systemd-sysusers(8)`](https://www.freedesktop.org/software/systemd/man/systemd-sysusers.html) |
384 | will look for the credentials `passwd.hashed-password.<username>`, | |
385 | `passwd.plaintext-password.<username>` and `passwd.shell.<username>` to | |
386 | configure the password (either in UNIX hashed form, or plaintext) or shell of | |
f00b3a99 | 387 | system users created. |
388 | Replace `<username>` with the system user of your choice, for example, `root`. | |
fe672fe5 LP |
389 | |
390 | * [`systemd-firstboot(1)`](https://www.freedesktop.org/software/systemd/man/systemd-firstboot.html) | |
391 | will look for the credentials `firstboot.locale`, `firstboot.locale-messages`, | |
392 | `firstboot.keymap`, `firstboot.timezone`, that configure locale, keymap or | |
393 | timezone settings in case the data is not yet set in `/etc/`. | |
394 | ||
b60d3016 LB |
395 | * [`tmpfiles.d(5)`](https://www.freedesktop.org/software/systemd/man/tmpfiles.d.html) |
396 | will look for the credentials `tmpfiles.extra` with arbitrary tmpfiles.d lines. | |
397 | Can be encoded in base64 to allow easily passing it on the command line. | |
398 | ||
df5f51c3 LP |
399 | * Further well-known credentials are documented in |
400 | [`systemd.system-credentials(7)`](https://www.freedesktop.org/software/systemd/man/systemd.system-credentials.html). | |
401 | ||
fe672fe5 LP |
402 | In future more services are likely to gain support for consuming credentials. |
403 | ||
404 | Example: | |
405 | ||
406 | ``` | |
407 | systemd-nspawn -i test.raw \ | |
408 | --set-credential=passwd.hashed-password.root:$(mkpasswd mysecret) \ | |
409 | --set-credential=firstboot.locale:C.UTF-8 \ | |
410 | -b | |
411 | ``` | |
412 | ||
413 | This boots the specified disk image as `systemd-nspawn` container, and passes | |
414 | the root password `mysecret`and default locale `C.UTF-8` to use to it. This | |
415 | data is then propagated by default to `systemd-sysusers.service` and | |
416 | `systemd-firstboot.service`, where it is applied. (Note that these services | |
417 | will only do so if these settings in `/etc/` are so far unset, i.e. they only | |
418 | have an effect on *unprovisioned* systems, and will never override data already | |
419 | established in `/etc/`.) A similar line for qemu is: | |
420 | ||
421 | ``` | |
422 | qemu-system-x86_64 \ | |
423 | -machine type=q35,accel=kvm,smm=on \ | |
424 | -smp 2 \ | |
425 | -m 1G \ | |
426 | -cpu host \ | |
427 | -nographic \ | |
428 | -nodefaults \ | |
429 | -serial mon:stdio \ | |
430 | -drive if=none,id=hd,file=test.raw,format=raw \ | |
431 | -device virtio-scsi-pci,id=scsi \ | |
432 | -device scsi-hd,drive=hd,bootindex=1 \ | |
8de7de46 LP |
433 | -smbios type=11,value=io.systemd.credential:passwd.hashed-password.root=$(mkpasswd mysecret) \ |
434 | -smbios type=11,value=io.systemd.credential:firstboot.locale=C.UTF-8 | |
fe672fe5 LP |
435 | ``` |
436 | ||
b60d3016 | 437 | This boots the specified disk image via qemu, provisioning public key SSH access |
4a91ace5 LB |
438 | for the root user from the caller's key, and sends a notification when booting |
439 | has finished to a process on the host: | |
b60d3016 LB |
440 | |
441 | ``` | |
442 | qemu-system-x86_64 \ | |
443 | -machine type=q35,accel=kvm,smm=on \ | |
444 | -smp 2 \ | |
445 | -m 1G \ | |
446 | -cpu host \ | |
447 | -nographic \ | |
448 | -nodefaults \ | |
449 | -serial mon:stdio \ | |
450 | -drive if=none,id=hd,file=test.raw,format=raw \ | |
451 | -device virtio-scsi-pci,id=scsi \ | |
452 | -device scsi-hd,drive=hd,bootindex=1 \ | |
4a91ace5 LB |
453 | -device vhost-vsock-pci,id=vhost-vsock-pci0,guest-cid=42 \ |
454 | -smbios type=11,value=io.systemd.credential:vmm.notify_socket=vsock:2:1234 \ | |
778abdbf | 455 | -smbios type=11,value=io.systemd.credential.binary:tmpfiles.extra=$(echo -e "d /root/.ssh 0750 root root -\nf~ /root/.ssh/authorized_keys 0600 root root - $(ssh-add -L | base64 -w 0)" | base64 -w 0) |
b60d3016 | 456 | ``` |
4a91ace5 LB |
457 | |
458 | A process on the host can listen for the notification, for example: | |
459 | ||
460 | ``` | |
461 | $ socat - VSOCK-LISTEN:1234,socktype=5 | |
462 | READY=1 | |
463 | ``` | |
464 | ||
fe672fe5 LP |
465 | ## Relevant Paths |
466 | ||
467 | From *service* perspective the runtime path to find loaded credentials in is | |
cf371718 JB |
468 | provided in the `$CREDENTIALS_DIRECTORY` environment variable. For *system |
469 | services* the credential directory will be `/run/credentials/<unit name>`, but | |
470 | hardcoding this path is discouraged, because it does not work for *user | |
471 | services*. Packagers and system administrators may hardcode the credential path | |
472 | as a last resort for software that does not yet search for credentials relative | |
473 | to `$CREDENTIALS_DIRECTORY`. | |
fe672fe5 | 474 | |
df5f51c3 LP |
475 | From *generator* perspective the runtime path to find credentials passed into |
476 | the system in plaintext form in is provided in `$CREDENTIALS_DIRECTORY`, and | |
477 | those passed into the system in encrypted form is provided in | |
478 | `$ENCRYPTED_CREDENTIALS_DIRECTORY`. | |
479 | ||
fe672fe5 LP |
480 | At runtime, credentials passed to the *system* are placed in |
481 | `/run/credentials/@system/` (for regular credentials, such as those passed from | |
482 | a container manager or via qemu) and `/run/credentials/@encrypted/` (for | |
483 | credentials that must be decrypted/validated before use, such as those from | |
484 | `systemd-stub`). | |
485 | ||
bbfb25f4 | 486 | The `ImportCredential=` setting (and the `LoadCredential=` and |
df5f51c3 | 487 | `LoadCredentialEncrypted=` settings when configured with a relative source |
f00b3a99 | 488 | path) will search for the source file to read the credential from automatically. |
489 | 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 | |
490 | `/etc/credstore.encrypted/` and similar directories. | |
491 | `ImportCredential=` will search both the non-encrypted and encrypted directories. | |
492 | These directories are hence a great place to store credentials to load on the system. | |
4f80cfca LP |
493 | |
494 | ## Conditionalizing Services | |
495 | ||
496 | Sometimes it makes sense to conditionalize system services and invoke them only | |
f00b3a99 | 497 | if the right system credential is passed to the system. |
498 | Use the `ConditionCredential=` and `AssertCredential=` unit file settings for that. |