]>
Commit | Line | Data |
---|---|---|
812862db LP |
1 | --- |
2 | title: JSON User Records | |
5fe63895 | 3 | category: Users, Groups and Home Directories |
812862db | 4 | layout: default |
0aff7b75 | 5 | SPDX-License-Identifier: LGPL-2.1-or-later |
812862db LP |
6 | --- |
7 | ||
8 | # JSON User Records | |
9 | ||
10 | systemd optionally processes user records that go beyond the classic UNIX (or | |
11 | glibc NSS) `struct passwd`. Various components of systemd are able to provide | |
12 | and consume records in a more extensible format of a dictionary of key/value | |
13 | pairs, encoded as JSON. Specifically: | |
14 | ||
15 | 1. [`systemd-homed.service`](https://www.freedesktop.org/software/systemd/man/systemd-homed.service.html) | |
16 | manages `human` user home directories and embeds these JSON records | |
5c90c67a BF |
17 | directly in the home directory images |
18 | (see [Home Directories](HOME_DIRECTORY.md) for details). | |
812862db LP |
19 | |
20 | 2. [`pam_systemd`](https://www.freedesktop.org/software/systemd/man/pam_systemd.html) | |
21 | processes these JSON records for users that log in, and applies various | |
22 | settings to the activated session, including environment variables, nice | |
23 | levels and more. | |
24 | ||
25 | 3. [`systemd-logind.service`](https://www.freedesktop.org/software/systemd/man/systemd-logind.service.html) | |
26 | processes these JSON records of users that log in, and applies various | |
27 | resource management settings to the per-user slice units it manages. This | |
28 | allows setting global limits on resource consumption by a specific user. | |
29 | ||
30 | 4. [`nss-systemd`](https://www.freedesktop.org/software/systemd/man/nss-systemd.html) | |
31 | is a glibc NSS module that synthesizes classic NSS records from these JSON | |
32 | records, providing full backwards compatibility with the classic UNIX APIs | |
33 | both for look-up and enumeration. | |
34 | ||
35 | 5. The service manager (PID 1) exposes dynamic users (i.e. users synthesized as | |
36 | effect of `DynamicUser=` in service unit files) as these advanced JSON | |
37 | records, making them discoverable to the rest of the system. | |
38 | ||
39 | 6. [`systemd-userdbd.service`](https://www.freedesktop.org/software/systemd/man/systemd-userdbd.service.html) | |
40 | is a small service that can translate UNIX/glibc NSS records to these JSON | |
41 | user records. It also provides a unified [Varlink](https://varlink.org/) API | |
42 | for querying and enumerating records of this type, optionally acquiring them | |
43 | from various other services. | |
44 | ||
45 | JSON user records may contain various fields that are not available in `struct | |
46 | passwd`, and are extensible for other applications. For example, the record may | |
47 | contain information about: | |
48 | ||
49 | 1. Additional security credentials (PKCS#11 security token information, | |
50 | biometrical authentication information, SSH public key information) | |
51 | ||
52 | 2. Additional user metadata, such as a picture, email address, location string, | |
53 | preferred language or timezone | |
54 | ||
55 | 3. Resource Management settings (such as CPU/IO weights, memory and tasks | |
56 | limits, classic UNIX resource limits or nice levels) | |
57 | ||
58 | 4. Runtime parameters such as environment variables or the `nodev`, `noexec`, | |
59 | `nosuid` flags to use for the home directory | |
60 | ||
61 | 5. Information about where to mount the home directory from | |
62 | ||
63 | And various other things. The record is intended to be extensible, for example | |
64 | the following extensions are envisioned: | |
65 | ||
66 | 1. Windows network credential information | |
67 | ||
68 | 2. Information about default IMAP, SMTP servers to use for this user | |
69 | ||
70 | 3. Parental control information to enforce on this user | |
71 | ||
72 | 4. Default parameters for backup applications and similar | |
73 | ||
5c90c67a BF |
74 | Similar to JSON User Records there are also |
75 | [JSON Group Records](GROUP_RECORD.md) that encapsulate UNIX groups. | |
812862db LP |
76 | |
77 | JSON User Records may be transferred or written to disk in various protocols | |
78 | and formats. To inquire about such records defined on the local system use the | |
5c90c67a BF |
79 | [User/Group Lookup API via Varlink](USER_GROUP_API.md). User/group records may |
80 | also be dropped in number of drop-in directories as files. See | |
f2147ed5 LP |
81 | [`nss-systemd(8)`](https://www.freedesktop.org/software/systemd/man/nss-systemd.html) |
82 | for details. | |
812862db LP |
83 | |
84 | ## Why JSON? | |
85 | ||
86 | JSON is nicely extensible and widely used. In particular it's easy to | |
87 | synthesize and process with numerous programming languages. It's particularly | |
88 | popular in the web communities, which hopefully should make it easy to link | |
89 | user credential data from the web and from local systems more closely together. | |
90 | ||
a21e88d4 LP |
91 | Please note that this specification assumes that JSON numbers may cover the full |
92 | integer range of -2^63 … 2^64-1 without loss of precision (i.e. INT64_MIN … | |
93 | UINT64_MAX). Please read, write and process user records as defined by this | |
94 | specification only with JSON implementations that provide this number range. | |
95 | ||
812862db LP |
96 | ## General Structure |
97 | ||
98 | The JSON user records generated and processed by systemd follow a general | |
99 | structure, consisting of seven distinct "sections". Specifically: | |
100 | ||
101 | 1. Various fields are placed at the top-level of user record (the `regular` | |
102 | section). These are generally fields that shall apply unconditionally to the | |
103 | user in all contexts, are portable and not security sensitive. | |
104 | ||
105 | 2. A number of fields are located in the `privileged` section (a sub-object of | |
106 | the user record). Fields contained in this object are security sensitive, | |
107 | i.e. contain information that the user and the administrator should be able | |
108 | to see, but other users should not. In many ways this matches the data | |
109 | stored in `/etc/shadow` in classic Linux user accounts, i.e. includes | |
110 | password hashes and more. Algorithmically, when a user record is passed to | |
111 | an untrusted client, by monopolizing such sensitive records in a single | |
112 | object field we can easily remove it from view. | |
113 | ||
114 | 3. A number of fields are located in objects inside the `perMachine` section | |
115 | (an array field of the user record). Primarily these are resource | |
116 | management-related fields, as those tend to make sense on a specific system | |
117 | only, e.g. limiting a user's memory use to 1G only makes sense on a specific | |
118 | system that has more than 1G of memory. Each object inside the `perMachine` | |
119 | array comes with a `matchMachineId` or `matchHostname` field which indicate | |
120 | which systems to apply the listed settings to. Note that many fields | |
121 | accepted in the `perMachine` section can also be set at the top level (the | |
122 | `regular` section), where they define the fallback if no matching object in | |
123 | `perMachine` is found. | |
124 | ||
125 | 4. Various fields are located in the `binding` section (a sub-sub-object of the | |
126 | user record; an intermediary object is inserted which is keyed by the | |
127 | machine ID of the host). Fields included in this section "bind" the object | |
128 | to a specific system. They generally include non-portable information about | |
129 | paths or UID assignments, that are true on a specific system, but not | |
130 | necessarily on others, and which are managed automatically by some user | |
131 | record manager (such as `systemd-homed`). Data in this section is considered | |
132 | part of the user record only in the local context, and is generally not | |
133 | ported to other systems. Due to that it is not included in the reduced user | |
134 | record the cryptographic signature defined in the `signature` section is | |
135 | calculated on. In `systemd-homed` this section is also removed when the | |
136 | user's record is stored in the `~/.identity` file in the home directory, so | |
137 | that every system with access to the home directory can manage these | |
138 | `binding` fields individually. Typically, the binding section is persisted | |
139 | to the local disk. | |
140 | ||
141 | 5. Various fields are located in the `status` section (a sub-sub-object of the | |
142 | user record, also with an intermediary object between that is keyed by the | |
143 | machine ID, similar to the way the `binding` section is organized). This | |
144 | section is augmented during runtime only, and never persisted to disk. The | |
145 | idea is that this section contains information about current runtime | |
146 | resource usage (for example: currently used disk space of the user), that | |
147 | changes dynamically but is otherwise immediately associated with the user | |
148 | record and for many purposes should be considered to be part of the user | |
149 | record. | |
150 | ||
151 | 6. The `signature` section contains one or more cryptographic signatures of a | |
152 | reduced version of the user record. This is used to ensure that only user | |
153 | records defined by a specific source are accepted on a system, by validating | |
154 | the signature against the set of locally accepted signature public keys. The | |
155 | signature is calculated from the JSON user record with all sections removed, | |
156 | except for `regular`, `privileged`, `perMachine`. Specifically, `binding`, | |
157 | `status`, `signature` itself and `secret` are removed first and thus not | |
158 | covered by the signature. This section is optional, and is only used when | |
159 | cryptographic validation of user records is required (as it is by | |
160 | `systemd-homed.service` for example). | |
161 | ||
162 | 7. The `secret` section contains secret user credentials, such as password or | |
163 | PIN information. This data is never persisted, and never returned when user | |
164 | records are inquired by a client, privileged or not. This data should only | |
165 | be included in a user record very briefly, for example when certain very | |
166 | specific operations are executed. For example, in tools such as | |
167 | `systemd-homed` this section may be included in user records, when creating | |
168 | a new home directory, as passwords and similar credentials need to be | |
169 | provided to encrypt the home directory with. | |
170 | ||
171 | Here's a tabular overview of the sections and their properties: | |
172 | ||
173 | | Section | Included in Signature | Persistent | Security Sensitive | Contains Host-Specific Data | | |
174 | |------------|-----------------------|------------|--------------------|-----------------------------| | |
175 | | regular | yes | yes | no | no | | |
176 | | privileged | yes | yes | yes | no | | |
177 | | perMachine | yes | yes | no | yes | | |
178 | | binding | no | yes | no | yes | | |
179 | | status | no | no | no | yes | | |
180 | | signature | no | yes | no | no | | |
181 | | secret | no | no | yes | no | | |
182 | ||
183 | Note that services providing user records to the local system are free to | |
184 | manage only a subset of these sections and never include the others in | |
185 | them. For example, a service that has no concept of signed records (for example | |
186 | because the records it manages are inherently trusted anyway) does not have to | |
187 | bother with the `signature` section. A service that only defines records in a | |
188 | strictly local context and without signatures doesn't have to deal with the | |
189 | `perMachine` or `binding` sections and can include its data exclusively in the | |
190 | regular section. A service that uses a separate, private channel for | |
191 | authenticating users (or that doesn't have a concept of authentication at all) | |
cd990847 | 192 | does not need to be concerned with the `secret` section of user records, as |
812862db LP |
193 | the fields included therein are only useful when executing authentication |
194 | operations natively against JSON user records. | |
195 | ||
58345a23 | 196 | The `systemd-homed` manager uses all seven sections for various |
812862db LP |
197 | purposes. Inside the home directories (and if the LUKS2 backend is used, also |
198 | in the LUKS2 header) a user record containing the `regular`, `privileged`, | |
199 | `perMachine` and `signature` sections is stored. `systemd-homed` also stores a | |
200 | version of the record on the host, with the same four sections and augmented | |
201 | with an additional, fifth `binding` section. When a local client enquires about | |
202 | a user record managed by `systemd-homed` the service will add in some | |
203 | additional information about the user and home directory in the `status` | |
204 | section — this version is only transferred via IPC and never written to | |
205 | disk. Finally the `secret` section is used during authentication operations via | |
206 | IPC to transfer the user record along with its authentication tokens in one go. | |
207 | ||
208 | ## Fields in the `regular` section | |
209 | ||
210 | As mentioned, the `regular` section's fields are placed at the top level | |
211 | object. The following fields are currently defined: | |
212 | ||
213 | `userName` → The UNIX user name for this record. Takes a string with a valid | |
214 | UNIX user name. This field is the only mandatory field, all others are | |
30fd9a2d | 215 | optional. Corresponds with the `pw_name` field of `struct passwd` and the |
812862db | 216 | `sp_namp` field of `struct spwd` (i.e. the shadow user record stored in |
5c90c67a | 217 | `/etc/shadow`). See [User/Group Name Syntax](USER_NAMES.md) for |
887a8fa3 | 218 | the (relaxed) rules the various systemd components enforce on user/group names. |
812862db LP |
219 | |
220 | `realm` → The "realm" a user is defined in. This concept allows distinguishing | |
221 | users with the same name that originate in different organizations or | |
222 | installations. This should take a string in DNS domain syntax, but doesn't have | |
223 | to refer to an actual DNS domain (though it is recommended to use one for | |
224 | this). The idea is that the user `lpoetter` in the `redhat.com` realm might be | |
225 | distinct from the same user in the `poettering.hq` realm. User records for the | |
226 | same user name that have different realm fields are considered referring to | |
227 | different users. When updating a user record it is required that any new | |
228 | version has to match in both `userName` and `realm` field. This field is | |
229 | optional, when unset the user should not be considered part of any realm. A | |
230 | user record with a realm set is never compatible (for the purpose of updates, | |
231 | see above) with a user record without one set, even if the `userName` field matches. | |
232 | ||
072779f0 LP |
233 | `realName` → The real name of the user, a string. This should contain the |
234 | user's real ("human") name, and corresponds loosely to the GECOS field of | |
235 | classic UNIX user records. When converting a `struct passwd` to a JSON user | |
236 | record this field is initialized from GECOS (i.e. the `pw_gecos` field), and | |
237 | vice versa when converting back. That said, unlike GECOS this field is supposed | |
238 | to contain only the real name and no other information. This field must not | |
239 | contain control characters (such as `\n`) or colons (`:`), since those are used | |
240 | as record separators in classic `/etc/passwd` files and similar formats. | |
812862db LP |
241 | |
242 | `emailAddress` → The email address of the user, formatted as | |
243 | string. [`pam_systemd`](https://www.freedesktop.org/software/systemd/man/pam_systemd.html) | |
244 | initializes the `$EMAIL` environment variable from this value for all login | |
245 | sessions. | |
246 | ||
247 | `iconName` → The name of an icon picked by the user, for example for the | |
248 | purpose of an avatar. This must be a string, and should follow the semantics | |
249 | defined in the [Icon Naming | |
250 | Specification](https://standards.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html). | |
251 | ||
252 | `location` → A free-form location string describing the location of the user, | |
253 | if that is applicable. It's probably wise to use a location string processable | |
254 | by geo-location subsystems, but this is not enforced nor required. Example: | |
255 | `Berlin, Germany` or `Basement, Room 3a`. | |
256 | ||
257 | `disposition` → A string, one of `intrinsic`, `system`, `dynamic`, `regular`, | |
258 | `container`, `reserved`. If specified clarifies the disposition of the user, | |
259 | i.e. the context it is defined in. For regular, "human" users this should be | |
260 | `regular`, for system users (i.e. users that system services run under, and | |
261 | similar) this should be `system`. The `intrinsic` disposition should be used | |
262 | only for the two users that have special meaning to the OS kernel itself, | |
263 | i.e. the `root` and `nobody` users. The `container` string should be used for | |
264 | users that are used by an OS container, and hence will show up in `ps` listings | |
265 | and such, but are only defined in container context. Finally `reserved` should | |
266 | be used for any users outside of these use-cases. Note that this property is | |
267 | entirely optional and applications are assumed to be able to derive the | |
268 | disposition of a user automatically from a record even in absence of this | |
269 | field, based on other fields, for example the numeric UID. By setting this | |
270 | field explicitly applications can override this default determination. | |
271 | ||
da890466 | 272 | `lastChangeUSec` → An unsigned 64-bit integer value, referring to a timestamp in µs |
812862db LP |
273 | since the epoch 1970, indicating when the user record (specifically, any of the |
274 | `regular`, `privileged`, `perMachine` sections) was last changed. This field is | |
275 | used when comparing two records of the same user to identify the newer one, and | |
276 | is used for example for automatic updating of user records, where appropriate. | |
277 | ||
da890466 | 278 | `lastPasswordChangeUSec` → Similar, also an unsigned 64-bit integer value, |
812862db LP |
279 | indicating the point in time the password (or any authentication token) of the |
280 | user was last changed. This corresponds to the `sp_lstchg` field of `struct | |
281 | spwd`, i.e. the matching field in the user shadow database `/etc/shadow`, | |
282 | though provides finer resolution. | |
283 | ||
284 | `shell` → A string, referring to the shell binary to use for terminal logins of | |
285 | this user. This corresponds with the `pw_shell` field of `struct passwd`, and | |
286 | should contain an absolute file system path. For system users not suitable for | |
287 | terminal log-in this field should not be set. | |
288 | ||
289 | `umask` → The `umask` to set for the user's login sessions. Takes an | |
290 | integer. Note that usually on UNIX the umask is noted in octal, but JSON's | |
291 | integers are generally written in decimal, hence in this context we denote it | |
292 | umask in decimal too. The specified value should be in the valid range for | |
293 | umasks, i.e. 0000…0777 (in octal as typical in UNIX), or 0…511 (in decimal, how | |
294 | it actually appears in the JSON record). This `umask` is automatically set by | |
295 | [`pam_systemd`](https://www.freedesktop.org/software/systemd/man/pam_systemd.html) | |
296 | for all login sessions of the user. | |
297 | ||
298 | `environment` → An array of strings, each containing an environment variable | |
299 | and its value to set for the user's login session, in a format compatible with | |
e2285c57 | 300 | [`putenv()`](https://man7.org/linux/man-pages/man3/putenv.3.html). Any |
812862db LP |
301 | environment variable listed here is automatically set by |
302 | [`pam_systemd`](https://www.freedesktop.org/software/systemd/man/pam_systemd.html) | |
303 | for all login sessions of the user. | |
304 | ||
305 | `timeZone` → A string indicating a preferred timezone to use for the user. When | |
306 | logging in | |
307 | [`pam_systemd`](https://www.freedesktop.org/software/systemd/man/pam_systemd.html) | |
308 | will automatically initialize the `$TZ` environment variable from this | |
309 | string. The string should be a `tzdata` compatible location string, for | |
310 | example: `Europe/Berlin`. | |
311 | ||
312 | `preferredLanguage` → A string indicating the preferred language/locale for the | |
49e55abb AV |
313 | user. It is combined with the `additionalLanguages` field to initialize the `$LANG` |
314 | and `$LANGUAGE` environment variables on login; see below for more details. This string | |
315 | should be in a format compatible with the `$LANG` environment variable, for example: | |
316 | `de_DE.UTF-8`. | |
317 | ||
318 | `additionalLanguages` → An array of strings indicating the preferred languages/locales | |
319 | that should be used in the event that translations for the `preferredLanguage` are | |
320 | missing, listed in order of descending priority. This allows multi-lingual users to | |
321 | specify all the languages that they know, so software lacking translations in the user's | |
322 | primary language can try another language that the user knows rather than falling back to | |
323 | the default English. All entries in this field must be valid locale names, compatible with | |
324 | the `$LANG` variable, for example: `de_DE.UTF-8`. When logging in | |
812862db | 325 | [`pam_systemd`](https://www.freedesktop.org/software/systemd/man/pam_systemd.html) |
49e55abb AV |
326 | will prepend `preferredLanguage` (if set) to this list (if set), remove duplicates, |
327 | and then automatically initialize the `$LANGUAGE` variable with the resulting list. | |
328 | It will also initialize `$LANG` variable with the first entry in the resulting list. | |
812862db LP |
329 | |
330 | `niceLevel` → An integer value in the range -20…19. When logging in | |
331 | [`pam_systemd`](https://www.freedesktop.org/software/systemd/man/pam_systemd.html) | |
332 | will automatically initialize the login process' nice level to this value with, | |
333 | which is then inherited by all the user's processes, see | |
e2285c57 | 334 | [`setpriority()`](https://man7.org/linux/man-pages/man2/setpriority.2.html) for |
812862db LP |
335 | more information. |
336 | ||
337 | `resourceLimits` → An object, where each key refers to a Linux resource limit | |
338 | (such as `RLIMIT_NOFILE` and similar). Their values should be an object with | |
339 | two keys `cur` and `max` for the soft and hard resource limit. When logging in | |
340 | [`pam_systemd`](https://www.freedesktop.org/software/systemd/man/pam_systemd.html) | |
341 | will automatically initialize the login process' resource limits to these | |
342 | values, which is then inherited by all the user's processes, see | |
e2285c57 | 343 | [`setrlimit()`](https://man7.org/linux/man-pages/man2/setrlimit.2.html) for more |
812862db LP |
344 | information. |
345 | ||
f223fd6a | 346 | `locked` → A boolean value. If true, the user account is locked, the user may |
812862db LP |
347 | not log in. If this field is missing it should be assumed to be false, |
348 | i.e. logins are permitted. This field corresponds to the `sp_expire` field of | |
349 | `struct spwd` (i.e. the `/etc/shadow` data for a user) being set to zero or | |
350 | one. | |
351 | ||
da890466 | 352 | `notBeforeUSec` → An unsigned 64-bit integer value, indicating a time in µs since |
812862db LP |
353 | the UNIX epoch (1970) before which the record should be considered invalid for |
354 | the purpose of logging in. | |
355 | ||
356 | `notAfterUSec` → Similar, but indicates the point in time *after* which logins | |
357 | shall not be permitted anymore. This corresponds to the `sp_expire` field of | |
358 | `struct spwd`, when it is set to a value larger than one, but provides finer | |
359 | granularity. | |
360 | ||
361 | `storage` → A string, one of `classic`, `luks`, `directory`, `subvolume`, | |
362 | `fscrypt`, `cifs`. Indicates the storage mechanism for the user's home | |
363 | directory. If `classic` the home directory is a plain directory as in classic | |
364 | UNIX. When `directory`, the home directory is a regular directory, but the | |
365 | `~/.identity` file in it contains the user's user record, so that the directory | |
366 | is self-contained. Similar, `subvolume` is a `btrfs` subvolume that also | |
367 | contains a `~/.identity` user record; `fscrypt` is an `fscrypt`-encrypted | |
368 | directory, also containing the `~/.identity` user record; `luks` is a per-user | |
369 | LUKS volume that is mounted as home directory, and `cifs` a home directory | |
370 | mounted from a Windows File Share. The five latter types are primarily used by | |
371 | `systemd-homed` when managing home directories, but may be used if other | |
f223fd6a | 372 | managers are used too. If this is not set, `classic` is the implied default. |
812862db | 373 | |
da890466 | 374 | `diskSize` → An unsigned 64-bit integer, indicating the intended home directory |
812862db | 375 | disk space in bytes to assign to the user. Depending on the selected storage |
f223fd6a | 376 | type this might be implemented differently: for `luks` this is the intended size |
812862db LP |
377 | of the file system and LUKS volume, while for the others this likely translates |
378 | to classic file system quota settings. | |
379 | ||
380 | `diskSizeRelative` → Similar to `diskSize` but takes a relative value, but | |
381 | specifies a fraction of the available disk space on the selected storage medium | |
382 | to assign to the user. This unsigned integer value is normalized to 2^32 = | |
383 | 100%. | |
384 | ||
385 | `skeletonDirectory` → Takes a string with the absolute path to the skeleton | |
386 | directory to populate a new home directory from. This is only used when a home | |
387 | directory is first created, and defaults to `/etc/skel` if not defined. | |
388 | ||
389 | `accessMode` → Takes an unsigned integer in the range 0…511 indicating the UNIX | |
390 | access mask for the home directory when it is first created. | |
391 | ||
da890466 | 392 | `tasksMax` → Takes an unsigned 64-bit integer indicating the maximum number of |
8dc647fd ZJS |
393 | tasks the user may start in parallel during system runtime. This counts |
394 | all tasks (i.e. threads, where each process is at least one thread) the user starts or that are | |
395 | forked from these processes even if the user identity is changed (for example | |
396 | by setuid binaries/`su`/`sudo` and similar). | |
397 | [`systemd-logind.service`](https://www.freedesktop.org/software/systemd/man/systemd-logind.service.html) | |
812862db LP |
398 | enforces this by setting the `TasksMax` slice property for the user's slice |
399 | `user-$UID.slice`. | |
400 | ||
da890466 | 401 | `memoryHigh`/`memoryMax` → These take unsigned 64-bit integers indicating upper |
812862db LP |
402 | memory limits for all processes of the user (plus all processes forked off them |
403 | that might have changed user identity), in bytes. Enforced by | |
404 | [`systemd-logind.service`](https://www.freedesktop.org/software/systemd/man/systemd-logind.service.html), | |
405 | similar to `tasksMax`. | |
406 | ||
8b51950f MK |
407 | `cpuWeight`/`ioWeight` → These take unsigned integers in the range 1…10000 |
408 | (defaults to 100) and configure the CPU and IO scheduling weights for the | |
409 | user's processes as a whole. Also enforced by | |
812862db LP |
410 | [`systemd-logind.service`](https://www.freedesktop.org/software/systemd/man/systemd-logind.service.html), |
411 | similar to `tasksMax`, `memoryHigh` and `memoryMax`. | |
412 | ||
413 | `mountNoDevices`/`mountNoSuid`/`mountNoExecute` → Three booleans that control | |
414 | the `nodev`, `nosuid`, `noexec` mount flags of the user's home | |
415 | directories. Note that these booleans are only honored if the home directory | |
416 | is managed by a subsystem such as `systemd-homed.service` that automatically | |
417 | mounts home directories on login. | |
418 | ||
419 | `cifsDomain` → A string indicating the Windows File Sharing domain (CIFS) to | |
420 | use. This is generally useful, but particularly when `cifs` is used as storage | |
421 | mechanism for the user's home directory, see above. | |
422 | ||
423 | `cifsUserName` → A string indicating the Windows File Sharing user name (CIFS) | |
424 | to associate this user record with. This is generally useful, but particularly | |
425 | useful when `cifs` is used as storage mechanism for the user's home directory, | |
426 | see above. | |
427 | ||
428 | `cifsService` → A string indicating the Windows File Share service (CIFS) to | |
bf15879b LP |
429 | mount as home directory of the user on login. Should be in format |
430 | `//<host>/<service>/<directory/…>`. The directory part is optional. If missing | |
431 | the top-level directory of the CIFS share is used. | |
812862db | 432 | |
4c2ee5c7 LP |
433 | `cifsExtraMountOptions` → A string with additional mount options to pass to |
434 | `mount.cifs` when mounting the home directory CIFS share. | |
435 | ||
812862db LP |
436 | `imagePath` → A string with an absolute file system path to the file, directory |
437 | or block device to use for storage backing the home directory. If the `luks` | |
f223fd6a | 438 | storage is used, this refers to the loopback file or block device node to store |
812862db LP |
439 | the LUKS volume on. For `fscrypt`, `directory`, `subvolume` this refers to the |
440 | directory to bind mount as home directory on login. Not defined for `classic` | |
441 | or `cifs`. | |
442 | ||
443 | `homeDirectory` → A string with an absolute file system path to the home | |
444 | directory. This is where the image indicated in `imagePath` is mounted to on | |
445 | login and thus indicates the application facing home directory while the home | |
446 | directory is active, and is what the user's `$HOME` environment variable is set | |
447 | to during log-in. It corresponds to the `pw_dir` field of `struct passwd`. | |
448 | ||
449 | `uid` → An unsigned integer in the range 0…4294967295: the numeric UNIX user ID (UID) to | |
450 | use for the user. This corresponds to the `pw_uid` field of `struct passwd`. | |
451 | ||
452 | `gid` → An unsigned integer in the range 0…4294967295: the numeric UNIX group | |
453 | ID (GID) to use for the user. This corresponds to the `pw_gid` field of | |
454 | `struct passwd`. | |
455 | ||
456 | `memberOf` → An array of strings, each indicating a UNIX group this user shall | |
457 | be a member of. The listed strings must be valid group names, but it is not | |
458 | required that all groups listed exist in all contexts: any entry for which no | |
459 | group exists should be silently ignored. | |
460 | ||
461 | `fileSystemType` → A string, one of `ext4`, `xfs`, `btrfs` (possibly others) to | |
462 | use as file system for the user's home directory. This is primarily relevant | |
463 | when the storage mechanism used is `luks` as a file system to use inside the | |
464 | LUKS container must be selected. | |
465 | ||
466 | `partitionUuid` → A string containing a lower-case, text-formatted UUID, referencing | |
467 | the GPT partition UUID the home directory is located in. This is primarily | |
468 | relevant when the storage mechanism used is `luks`. | |
469 | ||
470 | `luksUuid` → A string containing a lower-case, text-formatted UUID, referencing | |
471 | the LUKS volume UUID the home directory is located in. This is primarily | |
472 | relevant when the storage mechanism used is `luks`. | |
473 | ||
474 | `fileSystemUuid` → A string containing a lower-case, text-formatted UUID, | |
475 | referencing the file system UUID the home directory is located in. This is | |
476 | primarily relevant when the storage mechanism used is `luks`. | |
477 | ||
f223fd6a | 478 | `luksDiscard` → A boolean. If true and `luks` storage is used, controls whether |
812862db LP |
479 | the loopback block devices, LUKS and the file system on top shall be used in |
480 | `discard` mode, i.e. erased sectors should always be returned to the underlying | |
481 | storage. If false and `luks` storage is used turns this behavior off. In | |
482 | addition, depending on this setting an `FITRIM` or `fallocate()` operation is | |
483 | executed to make sure the image matches the selected option. | |
484 | ||
c0440512 LP |
485 | `luksOfflineDiscard` → A boolean. Similar to `luksDiscard`, it controls whether |
486 | to trim/allocate the file system/backing file when deactivating the home | |
487 | directory. | |
488 | ||
5dd57a00 LP |
489 | `luksExtraMountOptions` → A string with additional mount options to append to |
490 | the default mount options for the file system in the LUKS volume. | |
491 | ||
812862db LP |
492 | `luksCipher` → A string, indicating the cipher to use for the LUKS storage mechanism. |
493 | ||
494 | `luksCipherMode` → A string, selecting the cipher mode to use for the LUKS storage mechanism. | |
495 | ||
496 | `luksVolumeKeySize` → An unsigned integer, indicating the volume key length in | |
497 | bytes to use for the LUKS storage mechanism. | |
498 | ||
499 | `luksPbkdfHashAlgorithm` → A string, selecting the hash algorithm to use for | |
500 | the PBKDF operation for the LUKS storage mechanism. | |
501 | ||
502 | `luksPbkdfType` → A string, indicating the PBKDF type to use for the LUKS storage mechanism. | |
503 | ||
da890466 | 504 | `luksPbkdfForceIterations` → An unsigned 64-bit integer, indicating the intended |
b04ff66b AD |
505 | number of iterations for the PBKDF operation, when LUKS storage is used. |
506 | ||
da890466 | 507 | `luksPbkdfTimeCostUSec` → An unsigned 64-bit integer, indicating the intended |
812862db | 508 | time cost for the PBKDF operation, when the LUKS storage mechanism is used, in |
b04ff66b | 509 | µs. Ignored when `luksPbkdfForceIterations` is set. |
812862db | 510 | |
da890466 | 511 | `luksPbkdfMemoryCost` → An unsigned 64-bit integer, indicating the intended |
812862db LP |
512 | memory cost for the PBKDF operation, when LUKS storage is used, in bytes. |
513 | ||
da890466 | 514 | `luksPbkdfParallelThreads` → An unsigned 64-bit integer, indicating the intended |
812862db LP |
515 | required parallel threads for the PBKDF operation, when LUKS storage is used. |
516 | ||
da890466 | 517 | `luksSectorSize` → An unsigned 64-bit integer, indicating the sector size to |
fd83c98e AD |
518 | use for the LUKS storage mechanism, in bytes. Must be a power of two between |
519 | 512 and 4096. | |
520 | ||
2f09e2ee LP |
521 | `autoResizeMode` → A string, one of `off`, `grow`, `shrink-and-grow`. Unless |
522 | set to `off`, controls whether the home area shall be grown automatically to | |
523 | the size configured in `diskSize` automatically at login time. If set to | |
524 | `shrink-and-grown` the home area is also shrunk to the minimal size possible | |
525 | (as dictated by used disk space and file system constraints) on logout. | |
526 | ||
9aa3e5eb LP |
527 | `rebalanceWeight` → An unsigned integer, `null` or a boolean. Configures the |
528 | free disk space rebalancing weight for the home area. The integer must be in | |
529 | the range 1…10000 to configure an explicit weight. If unset, or set to `null` | |
530 | or `true` the default weight of 100 is implied. If set to 0 or `false` | |
531 | rebalancing is turned off for this home area. | |
532 | ||
812862db LP |
533 | `service` → A string declaring the service that defines or manages this user |
534 | record. It is recommended to use reverse domain name notation for this. For | |
535 | example, if `systemd-homed` manages a user a string of `io.systemd.Home` is | |
536 | used for this. | |
537 | ||
da890466 | 538 | `rateLimitIntervalUSec` → An unsigned 64-bit integer that configures the |
812862db LP |
539 | authentication rate limiting enforced on the user account. This specifies a |
540 | timer interval (in µs) within which to count authentication attempts. When the | |
541 | counter goes above the value configured n `rateLimitIntervalBurst` log-ins are | |
542 | temporarily refused until the interval passes. | |
543 | ||
da890466 | 544 | `rateLimitIntervalBurst` → An unsigned 64-bit integer, closely related to |
812862db LP |
545 | `rateLimitIntervalUSec`, that puts a limit on authentication attempts within |
546 | the configured time interval. | |
547 | ||
548 | `enforcePasswordPolicy` → A boolean. Configures whether to enforce the system's | |
549 | password policy when creating the home directory for the user or changing the | |
550 | user's password. By default the policy is enforced, but if this field is false | |
551 | it is bypassed. | |
552 | ||
553 | `autoLogin` → A boolean. If true the user record is marked as suitable for | |
554 | auto-login. Systems are supposed to automatically log in a user marked this way | |
555 | during boot, if there's exactly one user on it defined this way. | |
556 | ||
da890466 | 557 | `stopDelayUSec` → An unsigned 64-bit integer, indicating the time in µs the |
812862db LP |
558 | per-user service manager is kept around after the user fully logged out. This |
559 | value is honored by | |
560 | [`systemd-logind.service`](https://www.freedesktop.org/software/systemd/man/systemd-logind.service.html). If | |
561 | set to zero the per-user service manager is immediately terminated when the | |
562 | user logs out, and longer values optimize high-frequency log-ins as the | |
563 | necessary work to set up and tear down a log-in is reduced if the service | |
564 | manager stays running. | |
565 | ||
566 | `killProcesses` → A boolean. If true all processes of the user are | |
567 | automatically killed when the user logs out. This is enforced by | |
568 | [`systemd-logind.service`](https://www.freedesktop.org/software/systemd/man/systemd-logind.service.html). If | |
569 | false any processes left around when the user logs out are left running. | |
570 | ||
da890466 | 571 | `passwordChangeMinUSec`/`passwordChangeMaxUSec` → An unsigned 64-bit integer, |
812862db LP |
572 | encoding how much time has to pass at least/at most between password changes of |
573 | the user. This corresponds with the `sp_min` and `sp_max` fields of `struct | |
574 | spwd` (i.e. the `/etc/shadow` entries of the user), but offers finer | |
575 | granularity. | |
576 | ||
da890466 | 577 | `passwordChangeWarnUSec` → An unsigned 64-bit integer, encoding how much time to |
812862db LP |
578 | warn the user before their password expires, in µs. This corresponds with the |
579 | `sp_warn` field of `struct spwd`. | |
580 | ||
da890466 | 581 | `passwordChangeInactiveUSec` → An unsigned 64-bit integer, encoding how much |
812862db LP |
582 | time has to pass after the password expired that the account is |
583 | deactivated. This corresponds with the `sp_inact` field of `struct spwd`. | |
584 | ||
585 | `passwordChangeNow` → A boolean. If true the user has to change their password | |
586 | on next login. This corresponds with the `sp_lstchg` field of `struct spwd` | |
587 | being set to zero. | |
588 | ||
589 | `pkcs11TokenUri` → An array of strings, each with an RFC 7512 compliant PKCS#11 | |
590 | URI referring to security token (or smart card) of some form, that shall be | |
591 | associated with the user and may be used for authentication. The URI is used to | |
592 | search for an X.509 certificate and associated private key that may be used to | |
593 | decrypt an encrypted secret key that is used to unlock the user's account (see | |
594 | below). It's undefined how precise the URI is: during log-in it is tested | |
595 | against all plugged in security tokens and if there's exactly one matching | |
596 | private key found with it it is used. | |
597 | ||
fe2520fb | 598 | `fido2HmacCredential` → An array of strings, each with a Base64-encoded FIDO2 |
f223fd6a | 599 | credential ID that shall be used for authentication with FIDO2 devices that |
fe2520fb LP |
600 | implement the `hmac-secret` extension. The salt to pass to the FIDO2 device is |
601 | found in `fido2HmacSalt`. | |
602 | ||
64abd37a LP |
603 | `recoveryKeyType` → An array of strings, each indicating the type of one |
604 | recovery key. The only supported recovery key type at the moment is `modhex64`, | |
605 | for details see the description of `recoveryKey` below. An account may have any | |
606 | number of recovery keys defined, and the array should have one entry for each. | |
607 | ||
e1ef1e5d | 608 | `privileged` → An object, which contains the fields of the `privileged` section |
812862db LP |
609 | of the user record, see below. |
610 | ||
611 | `perMachine` → An array of objects, which contain the `perMachine` section of | |
612 | the user record, and thus fields to apply on specific systems only, see below. | |
613 | ||
614 | `binding` → An object, keyed by machine IDs formatted as strings, pointing | |
615 | to objects that contain the `binding` section of the user record, | |
616 | i.e. additional fields that bind the user record to a specific machine, see | |
617 | below. | |
618 | ||
619 | `status` → An object, keyed by machine IDs formatted as strings, pointing to | |
620 | objects that contain the `status` section of the user record, i.e. additional | |
621 | runtime fields that expose the current status of the user record on a specific | |
622 | system, see below. | |
623 | ||
624 | `signature` → An array of objects, which contain cryptographic signatures of | |
625 | the user record, i.e. the fields of the `signature` section of the user record, | |
626 | see below. | |
627 | ||
628 | `secret` → An object, which contains the fields of the `secret` section of the | |
629 | user record, see below. | |
630 | ||
631 | ## Fields in the `privileged` section | |
632 | ||
633 | As mentioned, the `privileged` section is encoded in a sub-object of the user | |
634 | record top-level object, in the `privileged` field. Any data included in this | |
635 | object shall only be visible to the administrator and the user themselves, and | |
636 | be suppressed implicitly when other users get access to a user record. It thus | |
637 | takes the role of the `/etc/shadow` records for each user, which has similarly | |
638 | restrictive access semantics. The following fields are currently defined: | |
639 | ||
640 | `passwordHint` → A user-selected password hint in free-form text. This should | |
641 | be a string like "What's the name of your first pet?", but is entirely for the | |
642 | user to choose. | |
643 | ||
ffc8eeae | 644 | `hashedPassword` → An array of strings, each containing a hashed UNIX password |
812862db | 645 | string, in the format |
e2285c57 | 646 | [`crypt(3)`](https://man7.org/linux/man-pages/man3/crypt.3.html) generates. This |
812862db LP |
647 | corresponds with `sp_pwdp` field of `struct spwd` (and in a way the `pw_passwd` |
648 | field of `struct passwd`). | |
649 | ||
650 | `sshAuthorizedKeys` → An array of strings, each listing an SSH public key that | |
651 | is authorized to access the account. The strings should follow the same format | |
13bf3216 | 652 | as the lines in the traditional `~/.ssh/authorized_keys` file. |
812862db LP |
653 | |
654 | `pkcs11EncryptedKey` → An array of objects. Each element of the array should be | |
655 | an object consisting of three string fields: `uri` shall contain a PKCS#11 | |
fe2520fb | 656 | security token URI, `data` shall contain a Base64-encoded encrypted key and |
812862db LP |
657 | `hashedPassword` shall contain a UNIX password hash to test the key |
658 | against. Authenticating with a security token against this account shall work | |
659 | as follows: the encrypted secret key is converted from its Base64 | |
660 | representation into binary, then decrypted with the PKCS#11 `C_Decrypt()` | |
661 | function of the PKCS#11 module referenced by the specified URI, using the | |
662 | private key found on the same token. The resulting decrypted key is then | |
663 | Base64-encoded and tested against the specified UNIX hashed password. The | |
fe2520fb | 664 | Base64-encoded decrypted key may also be used to unlock further resources |
812862db LP |
665 | during log-in, for example the LUKS or `fscrypt` storage backend. It is |
666 | generally recommended that for each entry in `pkcs11EncryptedKey` there's also | |
667 | a matching one in `pkcs11TokenUri` and vice versa, with the same URI, appearing | |
668 | in the same order, but this should not be required by applications processing | |
669 | user records. | |
670 | ||
fe2520fb LP |
671 | `fido2HmacSalt` → An array of objects, implementing authentication support with |
672 | FIDO2 devices that implement the `hmac-secret` extension. Each element of the | |
673 | array should be an object consisting of three string fields: `credential`, | |
17e7561a LP |
674 | `salt`, `hashedPassword`, and three boolean fields: `up`, `uv` and |
675 | `clientPin`. The first two string fields shall contain Base64-encoded binary | |
fe2520fb LP |
676 | data: the FIDO2 credential ID and the salt value to pass to the FIDO2 |
677 | device. During authentication this salt along with the credential ID is sent to | |
678 | the FIDO2 token, which will HMAC hash the salt with its internal secret key and | |
679 | return the result. This resulting binary key should then be Base64-encoded and | |
680 | used as string password for the further layers of the stack. The | |
681 | `hashedPassword` field of the `fido2HmacSalt` field shall be a UNIX password | |
17e7561a LP |
682 | hash to test this derived secret key against for authentication. The `up`, `uv` |
683 | and `clientPin` booleans map to the FIDO2 concepts of the same name and encode | |
684 | whether the `uv`/`up` options are enabled during the authentication, and | |
685 | whether a PIN shall be required. It is generally recommended that for each | |
686 | entry in `fido2HmacSalt` there's also a matching one in `fido2HmacCredential`, | |
687 | and vice versa, with the same credential ID, appearing in the same order, but | |
688 | this should not be required by applications processing user records. | |
fe2520fb | 689 | |
64abd37a LP |
690 | `recoveryKey`→ An array of objects, each defining a recovery key. The object |
691 | has two mandatory fields: `type` indicates the type of recovery key. The only | |
692 | currently permitted value is the string `modhex64`. The `hashedPassword` field | |
693 | contains a UNIX password hash of the normalized recovery key. Recovery keys are | |
694 | in most ways similar to regular passwords, except that they are generated by | |
695 | the computer, not chosen by the user, and are longer. Currently, the only | |
696 | supported recovery key format is `modhex64`, which consists of 64 | |
697 | [modhex](https://developers.yubico.com/yubico-c/Manuals/modhex.1.html) | |
698 | characters (i.e. 256bit of information), in groups of 8 chars separated by | |
699 | dashes, | |
700 | e.g. `lhkbicdj-trbuftjv-tviijfck-dfvbknrh-uiulbhui-higltier-kecfhkbk-egrirkui`. Recovery | |
701 | keys should be accepted wherever regular passwords are. The `recoveryKey` field | |
702 | should always be accompanied by a `recoveryKeyType` field (see above), and each | |
703 | entry in either should map 1:1 to an entry in the other, in the same order and | |
704 | matching the type. When accepting a recovery key it should be brought | |
705 | automatically into normalized form, i.e. the dashes inserted when missing, and | |
706 | converted into lowercase before tested against the UNIX password hash, so that | |
707 | recovery keys are effectively case-insensitive. | |
708 | ||
812862db LP |
709 | ## Fields in the `perMachine` section |
710 | ||
711 | As mentioned, the `perMachine` section contains settings that shall apply to | |
712 | specific systems only. This is primarily interesting for resource management | |
713 | properties as they tend to require a per-system focus, however they may be used | |
714 | for other purposes too. | |
715 | ||
716 | The `perMachine` field in the top-level object is an array of objects. When | |
717 | processing the user record first the various fields on the top-level object | |
7480859a LP |
718 | should be parsed. Then, the `perMachine` array should be iterated in order, and |
719 | the various settings within each contained object should be applied that match | |
720 | either the indicated machine ID or host name, overriding any corresponding | |
721 | settings previously parsed from the top-level object. There may be multiple | |
722 | array entries that match a specific system, in which case all settings should | |
723 | be applied. If the same option is set in the top-level object as in a | |
724 | per-machine object then the per-machine setting wins and entirely undoes the | |
725 | setting in the top-level object (i.e. no merging of properties that are arrays | |
726 | is done). If the same option is set in multiple per-machine objects the one | |
727 | specified later in the array wins (and here too no merging of individual fields | |
728 | is done, the later field always wins in full). To summarize, the order of | |
729 | application is (last one wins): | |
730 | ||
731 | 1. Settings in the top-level object | |
732 | 2. Settings in the first matching `perMachine` array entry | |
733 | 3. Settings in the second matching `perMachine` array entry | |
734 | 4. … | |
735 | 5. Settings in the last matching `perMachine` array entry | |
812862db LP |
736 | |
737 | The following fields are defined in this section: | |
738 | ||
da890466 | 739 | `matchMachineId` → An array of strings that are formatted 128-bit IDs in |
812862db | 740 | hex. If any of the specified IDs match the system's local machine ID |
7480859a LP |
741 | (i.e. matches `/etc/machine-id`) the fields in this object are honored. (As a |
742 | special case, if only a single machine ID is listed this field may be a single | |
743 | string rather than an array of strings.) | |
812862db | 744 | |
7480859a LP |
745 | `matchHostname` → An array of strings that are valid hostnames. If any of the |
746 | specified hostnames match the system's local hostname, the fields in this | |
812862db LP |
747 | object are honored. If both `matchHostname` and `matchMachineId` are used |
748 | within the same array entry, the object is honored when either match succeeds, | |
7480859a | 749 | i.e. the two match types are combined in OR, not in AND. (As a special case, if |
a15b9768 | 750 | only a single hostname is listed this field may be a single string rather |
7480859a | 751 | than an array of strings.) |
812862db LP |
752 | |
753 | These two are the only two fields specific to this section. All other fields | |
754 | that may be used in this section are identical to the equally named ones in the | |
755 | `regular` section (i.e. at the top-level object). Specifically, these are: | |
756 | ||
757 | `iconName`, `location`, `shell`, `umask`, `environment`, `timeZone`, | |
49e55abb | 758 | `preferredLanguage`, `additionalLanguages`, `niceLevel`, `resourceLimits`, `locked`, `notBeforeUSec`, |
812862db LP |
759 | `notAfterUSec`, `storage`, `diskSize`, `diskSizeRelative`, `skeletonDirectory`, |
760 | `accessMode`, `tasksMax`, `memoryHigh`, `memoryMax`, `cpuWeight`, `ioWeight`, | |
761 | `mountNoDevices`, `mountNoSuid`, `mountNoExecute`, `cifsDomain`, | |
4c2ee5c7 LP |
762 | `cifsUserName`, `cifsService`, `cifsExtraMountOptions`, `imagePath`, `uid`, |
763 | `gid`, `memberOf`, `fileSystemType`, `partitionUuid`, `luksUuid`, | |
764 | `fileSystemUuid`, `luksDiscard`, `luksOfflineDiscard`, `luksCipher`, | |
765 | `luksCipherMode`, `luksVolumeKeySize`, `luksPbkdfHashAlgorithm`, | |
b04ff66b | 766 | `luksPbkdfType`, `luksPbkdfForceIterations`, `luksPbkdfTimeCostUSec`, `luksPbkdfMemoryCost`, |
fd83c98e | 767 | `luksPbkdfParallelThreads`, `luksSectorSize`, `autoResizeMode`, `rebalanceWeight`, |
9aa3e5eb LP |
768 | `rateLimitIntervalUSec`, `rateLimitBurst`, `enforcePasswordPolicy`, |
769 | `autoLogin`, `stopDelayUSec`, `killProcesses`, `passwordChangeMinUSec`, | |
770 | `passwordChangeMaxUSec`, `passwordChangeWarnUSec`, | |
4c2ee5c7 LP |
771 | `passwordChangeInactiveUSec`, `passwordChangeNow`, `pkcs11TokenUri`, |
772 | `fido2HmacCredential`. | |
812862db LP |
773 | |
774 | ## Fields in the `binding` section | |
775 | ||
776 | As mentioned, the `binding` section contains additional fields about the user | |
777 | record, that bind it to the local system. These fields are generally used by a | |
778 | local user manager (such as `systemd-homed.service`) to add in fields that make | |
779 | sense in a local context but not necessarily in a global one. For example, a | |
780 | user record that contains no `uid` field in the regular section is likely | |
781 | extended with one in the `binding` section to assign a local UID if no global | |
782 | UID is defined. | |
783 | ||
784 | All fields in the `binding` section only make sense in a local context and are | |
785 | suppressed when the user record is ported between systems. The `binding` section | |
786 | is generally persisted on the system but not in the home directories themselves | |
787 | and the home directory is supposed to be fully portable and thus not contain | |
788 | the information that `binding` is supposed to contain that binds the portable | |
789 | record to a specific system. | |
790 | ||
791 | The `binding` sub-object on the top-level user record object is keyed by the | |
792 | machine ID the binding is intended for, which point to an object with the | |
793 | fields of the bindings. These fields generally match fields that may also be | |
794 | defined in the `regular` and `perMachine` sections, however override | |
795 | both. Usually, the `binding` value should not contain settings different from | |
796 | those set via `regular` or `perMachine`, however this might happen if some | |
797 | settings are not supported locally (think: `fscrypt` is recorded as intended | |
798 | storage mechanism in the `regular` section, but the local kernel does not | |
799 | support `fscrypt`, hence `directory` was chosen as implicit fallback), or have | |
800 | been changed in the `regular` section through updates (e.g. a home directory | |
801 | was created with `luks` as storage mechanism but later the user record was | |
802 | updated to prefer `subvolume`, which however doesn't change the actual storage | |
803 | used already which is pinned in the `binding` section). | |
804 | ||
805 | The following fields are defined in the `binding` section. They all have an | |
806 | identical format and override their equally named counterparts in the `regular` | |
807 | and `perMachine` sections: | |
808 | ||
809 | `imagePath`, `homeDirectory`, `partitionUuid`, `luksUuid`, `fileSystemUuid`, | |
810 | `uid`, `gid`, `storage`, `fileSystemType`, `luksCipher`, `luksCipherMode`, | |
811 | `luksVolumeKeySize`. | |
812 | ||
813 | ## Fields in the `status` section | |
814 | ||
815 | As mentioned, the `status` section contains additional fields about the user | |
816 | record that are exclusively acquired during runtime, and that expose runtime | |
817 | metrics of the user and similar metadata that shall not be persisted but are | |
818 | only acquired "on-the-fly" when requested. | |
819 | ||
820 | This section is arranged similarly to the `binding` section: the `status` | |
821 | sub-object of the top-level user record object is keyed by the machine ID, | |
822 | which points to the object with the fields defined here. The following fields | |
823 | are defined: | |
824 | ||
da890466 | 825 | `diskUsage` → An unsigned 64-bit integer. The currently used disk space of the |
812862db LP |
826 | home directory in bytes. This value might be determined in different ways, |
827 | depending on the selected storage mechanism. For LUKS storage this is the file | |
828 | size of the loopback file or block device size. For the | |
829 | directory/subvolume/fscrypt storage this is the current disk space used as | |
830 | reported by the file system quota subsystem. | |
831 | ||
da890466 | 832 | `diskFree` → An unsigned 64-bit integer, denoting the number of "free" bytes in |
812862db LP |
833 | the disk space allotment, i.e. usually the difference between the disk size as |
834 | reported by `diskSize` and the used already as reported in `diskFree`, but | |
835 | possibly skewed by metadata sizes, disk compression and similar. | |
836 | ||
da890466 | 837 | `diskSize` → An unsigned 64-bit integer, denoting the disk space currently |
812862db LP |
838 | allotted to the user, in bytes. Depending on the storage mechanism this can mean |
839 | different things (see above). In contrast to the top-level field of the same | |
840 | (or the one in the `perMachine` section), this field reports the current size | |
841 | allotted to the user, not the intended one. The values may differ when user | |
842 | records are updated without the home directory being re-sized. | |
843 | ||
da890466 | 844 | `diskCeiling`/`diskFloor` → Unsigned 64-bit integers indicating upper and lower |
812862db LP |
845 | bounds when changing the `diskSize` value, in bytes. These values are typically |
846 | derived from the underlying data storage, and indicate in which range the home | |
847 | directory may be re-sized in, i.e. in which sensible range the `diskSize` value | |
848 | should be kept. | |
849 | ||
850 | `state` → A string indicating the current state of the home directory. The | |
851 | precise set of values exposed here are up to the service managing the home | |
852 | directory to define (i.e. are up to the service identified with the `service` | |
853 | field below). However, it is recommended to stick to a basic vocabulary here: | |
854 | `inactive` for a home directory currently not mounted, `absent` for a home | |
855 | directory that cannot be mounted currently because it does not exist on the | |
856 | local system, `active` for a home directory that is currently mounted and | |
857 | accessible. | |
858 | ||
859 | `service` → A string identifying the service that manages this user record. For | |
860 | example `systemd-homed.service` sets this to `io.systemd.Home` to all user | |
861 | records it manages. This is particularly relevant to define clearly the context | |
862 | in which `state` lives, see above. Note that this field also exists on the | |
863 | top-level object (i.e. in the `regular` section), which it overrides. The | |
864 | `regular` field should be used if conceptually the user record can only be | |
865 | managed by the specified service, and this `status` field if it can | |
866 | conceptually be managed by different managers, but currently is managed by the | |
867 | specified one. | |
868 | ||
869 | `signedLocally` → A boolean. If true indicates that the user record is signed | |
870 | by a public key for which the private key is available locally. This means that | |
871 | the user record may be modified locally as it can be re-signed with the private | |
872 | key. If false indicates that the user record is signed by a public key | |
873 | recognized by the local manager but whose private key is not available | |
874 | locally. This means the user record cannot be modified locally as it couldn't | |
875 | be signed afterwards. | |
876 | ||
da890466 | 877 | `goodAuthenticationCounter` → An unsigned 64-bit integer. This counter is |
812862db LP |
878 | increased by one on every successful authentication attempt, i.e. an |
879 | authentication attempt where a security token of some form was presented and it | |
880 | was correct. | |
881 | ||
da890466 | 882 | `badAuthenticationCounter` → An unsigned 64-bit integer. This counter is |
812862db LP |
883 | increased by one on every unsuccessfully authentication attempt, i.e. an |
884 | authentication attempt where a security token of some form was presented and it | |
885 | was incorrect. | |
886 | ||
da890466 | 887 | `lastGoodAuthenticationUSec` → An unsigned 64-bit integer, indicating the time |
812862db LP |
888 | of the last successful authentication attempt in µs since the UNIX epoch (1970). |
889 | ||
890 | `lastBadAuthenticationUSec` → Similar, but the timestamp of the last | |
891 | unsuccessfully authentication attempt. | |
892 | ||
da890466 | 893 | `rateLimitBeginUSec` → An unsigned 64-bit integer: the µs timestamp since the |
812862db LP |
894 | UNIX epoch (1970) where the most recent rate limiting interval has been |
895 | started, as configured with `rateLimitIntervalUSec`. | |
896 | ||
da890466 | 897 | `rateLimitCount` → An unsigned 64-bit integer, counting the authentication |
812862db LP |
898 | attempts in the current rate limiting interval, see above. If this counter |
899 | grows beyond the value configured in `rateLimitBurst` authentication attempts | |
900 | are temporarily refused. | |
901 | ||
902 | `removable` → A boolean value. If true the manager of this user record | |
903 | determined the home directory being on removable media. If false it was | |
904 | determined the home directory is in internal built-in media. (This is used by | |
905 | `systemd-logind.service` to automatically pick the right default value for | |
906 | `stopDelayUSec` if the field is not explicitly specified: for home directories | |
907 | on removable media the delay is selected very low to minimize the chance the | |
908 | home directory remains in unclean state if the storage device is removed from | |
909 | the system by the user). | |
910 | ||
a6f44d61 YW |
911 | `accessMode` → The access mode currently in effect for the home directory |
912 | itself. | |
67a6d399 LP |
913 | |
914 | `fileSystemType` → The file system type backing the home directory: a short | |
915 | string, such as "btrfs", "ext4", "xfs". | |
916 | ||
46c60f72 LP |
917 | `fallbackShell`, `fallbackHomeDirectory` → These fields have the same contents |
918 | and format as the `shell` and `homeDirectory` fields (see above). When the | |
919 | `useFallback` field (see below) is set to true, the data from these fields | |
920 | should override the fields of the same name without the `fallback` prefix. | |
921 | ||
922 | `useFallback` → A boolean that allows choosing between the regular `shell` and | |
923 | `homeDirectory` fields or the fallback fields of the same name (see above). If | |
924 | `true` the fallback fields should be used in place of the regular fields, if | |
925 | `false` or unset the regular fields should be used. This mechanism is used for | |
926 | enable subsystems such as SSH to allow logins into user accounts, whose homed | |
927 | directories need further unlocking (because the SSH native authentication | |
928 | cannot release a suitabable disk encryption key), which the fallback shell | |
929 | provides. | |
930 | ||
812862db LP |
931 | ## Fields in the `signature` section |
932 | ||
933 | As mentioned, the `signature` section of the user record may contain one or | |
934 | more cryptographic signatures of the user record. Like all others, this section | |
935 | is optional, and only used when cryptographic validation of user records shall | |
936 | be used. Specifically, all user records managed by `systemd-homed.service` will | |
937 | carry such signatures and the service refuses managing user records that come | |
938 | without signature or with signatures not recognized by any locally defined | |
939 | public key. | |
940 | ||
941 | The `signature` field in the top-level user record object is an array of | |
942 | objects. Each object encapsulates one signature and has two fields: `data` and | |
943 | `key` (both are strings). The `data` field contains the actual signature, | |
fe2520fb | 944 | encoded in Base64, the `key` field contains a copy of the public key whose |
812862db LP |
945 | private key was used to make the signature, in PEM format. Currently only |
946 | signatures with Ed25519 keys are defined. | |
947 | ||
948 | Before signing the user record should be brought into "normalized" form, | |
949 | i.e. the keys in all objects should be sorted alphabetically. All redundant | |
950 | white-space and newlines should be removed and the JSON text then signed. | |
951 | ||
952 | The signatures only cover the `regular`, `perMachine` and `privileged` sections | |
953 | of the user records, all other sections (include `signature` itself), are | |
954 | removed before the signature is calculated. | |
955 | ||
956 | Rationale for signing and threat model: while a multi-user operating system | |
957 | like Linux strives for being sufficiently secure even after a user acquired a | |
958 | local login session reality tells us this is not the case. Hence it is | |
959 | essential to restrict carefully which users may gain access to a system and | |
960 | which ones shall not. A minimal level of trust must be established between | |
961 | system, user record and the user themselves before a log-in request may be | |
962 | permitted. In particular if the home directory is provided in its own LUKS2 | |
963 | encapsulated file system it is essential this trust is established before the | |
964 | user logs in (and hence the file system mounted), since file system | |
965 | implementations on Linux are well known to be relatively vulnerable to rogue | |
966 | disk images. User records and home directories in many context are expected to | |
967 | be something shareable between multiple systems, and the transfer between them | |
968 | might not happen via exclusively trusted channels. Hence it's essential that | |
969 | the user record is not manipulated between uses. Finally, resource management | |
970 | (which may be done by the various fields of the user record) is security | |
971 | sensitive, since it should forcefully lock the user into the assigned resource | |
972 | usage and not allow them to use more. The requirement of being able to trust | |
973 | the user record data combined with the potential transfer over untrusted | |
974 | channels suggest a cryptographic signature mechanism where only user records | |
975 | signed by a recognized key are permitted to log in locally. | |
976 | ||
977 | Note that other mechanisms for establishing sufficient trust exist too, and are | |
978 | perfectly valid as well. For example, systems like LDAP/ActiveDirectory | |
979 | generally insist on user record transfer from trusted servers via encrypted TLS | |
980 | channels only. Or traditional UNIX users created locally in `/etc/passwd` never | |
981 | exist outside of the local trusted system, hence transfer and trust in the | |
982 | source are not an issue. The major benefit of operating with signed user | |
983 | records is that they are self-sufficiently trusted, not relying on a secure | |
984 | channel for transfer, and thus being compatible with a more distributed model | |
985 | of home directory transfer, including on USB sticks and such. | |
986 | ||
987 | ## Fields in the `secret` section | |
988 | ||
989 | As mentioned, the `secret` section of the user record should never be persisted | |
990 | nor transferred across machines. It is only defined in short-lived operations, | |
991 | for example when a user record is first created or registered, as the secret | |
992 | key data needs to be available to derive encryption keys from and similar. | |
993 | ||
994 | The `secret` field of the top-level user record contains the following fields: | |
995 | ||
996 | `password` → an array of strings, each containing a plain text password. | |
997 | ||
c0bde0d2 LP |
998 | `tokenPin` → an array of strings, each containing a plain text PIN, suitable |
999 | for unlocking security tokens that require that. (The field `pkcs11Pin` should | |
1000 | be considered a compatibility alias for this field, and merged with `tokenPin` | |
1001 | in case both are set.) | |
812862db LP |
1002 | |
1003 | `pkcs11ProtectedAuthenticationPathPermitted` → a boolean. If set to true allows | |
1004 | the receiver to use the PKCS#11 "protected authentication path" (i.e. a | |
1005 | physical button/touch element on the security token) for authenticating the | |
fe2520fb LP |
1006 | user. If false or unset, authentication this way shall not be attempted. |
1007 | ||
1008 | `fido2UserPresencePermitted` → a boolean. If set to true allows the receiver to | |
1009 | use the FIDO2 "user presence" flag. This is similar to the concept of | |
17e7561a LP |
1010 | `pkcs11ProtectedAuthenticationPathPermitted`, but exposes the FIDO2 "up" |
1011 | concept behind it. If false or unset authentication this way shall not be | |
1012 | attempted. | |
1013 | ||
1014 | `fido2UserVerificationPermitted` → a boolean. If set to true allows the | |
1015 | receiver to use the FIDO2 "user verification" flag. This is similar to the | |
1016 | concept of `pkcs11ProtectedAuthenticationPathPermitted`, but exposes the FIDO2 | |
1017 | "uv" concept behind it. If false or unset authentication this way shall not be | |
1018 | attempted. | |
812862db LP |
1019 | |
1020 | ## Mapping to `struct passwd` and `struct spwd` | |
1021 | ||
1022 | When mapping classic UNIX user records (i.e. `struct passwd` and `struct spwd`) | |
1023 | to JSON user records the following mappings should be applied: | |
1024 | ||
1025 | | Structure | Field | Section | Field | Condition | | |
1026 | |-----------------|-------------|--------------|------------------------------|----------------------------| | |
1027 | | `struct passwd` | `pw_name` | `regular` | `userName` | | | |
1028 | | `struct passwd` | `pw_passwd` | `privileged` | `password` | (See notes below) | | |
1029 | | `struct passwd` | `pw_uid` | `regular` | `uid` | | | |
1030 | | `struct passwd` | `pw_gid` | `regular` | `gid` | | | |
1031 | | `struct passwd` | `pw_gecos` | `regular` | `realName` | | | |
1032 | | `struct passwd` | `pw_dir` | `regular` | `homeDirectory` | | | |
1033 | | `struct passwd` | `pw_shell` | `regular` | `shell` | | | |
1034 | | `struct spwd` | `sp_namp` | `regular` | `userName` | | | |
1035 | | `struct spwd` | `sp_pwdp` | `privileged` | `password` | (See notes below) | | |
1036 | | `struct spwd` | `sp_lstchg` | `regular` | `lastPasswordChangeUSec` | (if `sp_lstchg` > 0) | | |
1037 | | `struct spwd` | `sp_lstchg` | `regular` | `passwordChangeNow` | (if `sp_lstchg` == 0) | | |
1038 | | `struct spwd` | `sp_min` | `regular` | `passwordChangeMinUSec` | | | |
1039 | | `struct spwd` | `sp_max` | `regular` | `passwordChangeMaxUSec` | | | |
1040 | | `struct spwd` | `sp_warn` | `regular` | `passwordChangeWarnUSec` | | | |
1041 | | `struct spwd` | `sp_inact` | `regular` | `passwordChangeInactiveUSec` | | | |
1042 | | `struct spwd` | `sp_expire` | `regular` | `locked` | (if `sp_expire` in [0, 1]) | | |
1043 | | `struct spwd` | `sp_expire` | `regular` | `notAfterUSec` | (if `sp_expire` > 1) | | |
1044 | ||
1045 | At this time almost all Linux machines employ shadow passwords, thus the | |
1046 | `pw_passwd` field in `struct passwd` is set to `"x"`, and the actual password | |
1047 | is stored in the shadow entry `struct spwd`'s field `sp_pwdp`. | |
1048 | ||
1049 | ## Extending These Records | |
1050 | ||
1051 | User records following this specifications are supposed to be extendable for | |
1052 | various applications. In general, subsystems are free to introduce their own | |
1053 | keys, as long as: | |
1054 | ||
1055 | * Care should be taken to place the keys in the right section, i.e. the most | |
1056 | appropriate for the data field. | |
1057 | ||
1058 | * Care should be taken to avoid namespace clashes. Please prefix your fields | |
1059 | with a short identifier of your project to avoid ambiguities and | |
1060 | incompatibilities. | |
1061 | ||
1062 | * This specification is supposed to be a living specification. If you need | |
1063 | additional fields, please consider submitting them upstream for inclusion in | |
1064 | this specification. If they are reasonably universally useful, it would be | |
1065 | best to list them here. | |
1066 | ||
1067 | ## Examples | |
1068 | ||
1069 | The shortest valid user record looks like this: | |
1070 | ||
1071 | ```json | |
1072 | { | |
1073 | "userName" : "u" | |
1074 | } | |
1075 | ``` | |
1076 | ||
1077 | A reasonable user record for a system user might look like this: | |
1078 | ||
1079 | ```json | |
1080 | { | |
1081 | "userName" : "httpd", | |
1082 | "uid" : 473, | |
1083 | "gid" : 473, | |
1084 | "disposition" : "system", | |
1085 | "locked" : true | |
1086 | } | |
1087 | ``` | |
1088 | ||
1089 | A fully featured user record associated with a home directory managed by | |
1090 | `systemd-homed.service` might look like this: | |
1091 | ||
1092 | ```json | |
1093 | { | |
1094 | "autoLogin" : true, | |
1095 | "binding" : { | |
1096 | "15e19cf24e004b949ddaac60c74aa165" : { | |
1097 | "fileSystemType" : "ext4", | |
1098 | "fileSystemUuid" : "758e88c8-5851-4a2a-b88f-e7474279c111", | |
1099 | "gid" : 60232, | |
1100 | "homeDirectory" : "/home/grobie", | |
1101 | "imagePath" : "/home/grobie.home", | |
1102 | "luksCipher" : "aes", | |
1103 | "luksCipherMode" : "xts-plain64", | |
1104 | "luksUuid" : "e63581ba-79fb-4226-b9de-1888393f7573", | |
1105 | "luksVolumeKeySize" : 32, | |
1106 | "partitionUuid" : "41f9ce04-c827-4b74-a981-c669f93eb4dc", | |
1107 | "storage" : "luks", | |
1108 | "uid" : 60232 | |
1109 | } | |
1110 | }, | |
1111 | "disposition" : "regular", | |
1112 | "enforcePasswordPolicy" : false, | |
1113 | "lastChangeUSec" : 1565950024279735, | |
1114 | "memberOf" : [ | |
1115 | "wheel" | |
1116 | ], | |
1117 | "privileged" : { | |
1118 | "hashedPassword" : [ | |
1119 | "$6$WHBKvAFFT9jKPA4k$OPY4D4TczKN/jOnJzy54DDuOOagCcvxxybrwMbe1SVdm.Bbr.zOmBdATp.QrwZmvqyr8/SafbbQu.QZ2rRvDs/" | |
1120 | ] | |
1121 | }, | |
1122 | "signature" : [ | |
1123 | { | |
1124 | "data" : "LU/HeVrPZSzi3MJ0PVHwD5m/xf51XDYCrSpbDRNBdtF4fDVhrN0t2I2OqH/1yXiBidXlV0ptMuQVq8KVICdEDw==", | |
1125 | "key" : "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEA/QT6kQWOAMhDJf56jBmszEQQpJHqDsGDMZOdiptBgRk=\n-----END PUBLIC KEY-----\n" | |
1126 | } | |
1127 | ], | |
1128 | "userName" : "grobie", | |
1129 | "status" : { | |
1130 | "15e19cf24e004b949ddaac60c74aa165" : { | |
1131 | "goodAuthenticationCounter" : 16, | |
1132 | "lastGoodAuthenticationUSec" : 1566309343044322, | |
1133 | "rateLimitBeginUSec" : 1566309342340723, | |
1134 | "rateLimitCount" : 1, | |
1135 | "state" : "inactive", | |
1136 | "service" : "io.systemd.Home", | |
1137 | "diskSize" : 161118667776, | |
1138 | "diskCeiling" : 190371729408, | |
1139 | "diskFloor" : 5242880, | |
1140 | "signedLocally" : true | |
1141 | } | |
1142 | } | |
1143 | } | |
1144 | ``` | |
1145 | ||
1146 | When `systemd-homed.service` manages a home directory it will also include a | |
1147 | version of the user record in the home directory itself in the `~/.identity` | |
1148 | file. This version lacks the `binding` and `status` sections which are used for | |
1149 | local management of the user, but are not intended to be portable between | |
1150 | systems. It would hence look like this: | |
1151 | ||
1152 | ```json | |
1153 | { | |
1154 | "autoLogin" : true, | |
1155 | "disposition" : "regular", | |
1156 | "enforcePasswordPolicy" : false, | |
1157 | "lastChangeUSec" : 1565950024279735, | |
1158 | "memberOf" : [ | |
1159 | "wheel" | |
1160 | ], | |
1161 | "privileged" : { | |
1162 | "hashedPassword" : [ | |
1163 | "$6$WHBKvAFFT9jKPA4k$OPY4D4TczKN/jOnJzy54DDuOOagCcvxxybrwMbe1SVdm.Bbr.zOmBdATp.QrwZmvqyr8/SafbbQu.QZ2rRvDs/" | |
1164 | ] | |
1165 | }, | |
1166 | "signature" : [ | |
1167 | { | |
1168 | "data" : "LU/HeVrPZSzi3MJ0PVHwD5m/xf51XDYCrSpbDRNBdtF4fDVhrN0t2I2OqH/1yXiBidXlV0ptMuQVq8KVICdEDw==", | |
1169 | "key" : "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEA/QT6kQWOAMhDJf56jBmszEQQpJHqDsGDMZOdiptBgRk=\n-----END PUBLIC KEY-----\n" | |
1170 | } | |
1171 | ], | |
1172 | "userName" : "grobie", | |
1173 | } | |
1174 | ``` |