Skip to content

Commit 5add888

Browse files
cgwaltersjmarrero
authored andcommitted
docs/users-and-groups: expand on static users and systemd-sysusers
Co-authored-by: Colin Walters <[email protected]> Signed-off-by: Colin Walters <[email protected]> Signed-off-by: Joseph Marrero Corchado <[email protected]>
1 parent 4d3eac1 commit 5add888

File tree

1 file changed

+69
-35
lines changed

1 file changed

+69
-35
lines changed

docs/src/building/users-and-groups.md

Lines changed: 69 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -55,31 +55,45 @@ credentials from a [CRD](https://kubernetes.io/docs/tasks/extend-kubernetes/cust
5555
hosted in the API server. (To do things like this
5656
it's suggested to reuse the kubelet credentials)
5757

58-
### Adding users and credentials statically in the container build
58+
### System users and groups (added via packages, etc)
5959

60-
Relative to package-oriented systems, a new ability is to inject
61-
users and credentials as part of a derived build:
60+
It is common for packages (deb/rpm/etc) to allocate system users
61+
or groups as part of e.g `apt|dnf install <server package>` such as Apache or MySQL,
62+
and this is often done by directly invoking `useradd` or `groupadd` as part
63+
of package pre/post installation scripts.
6264

63-
```dockerfile
64-
RUN useradd someuser
65-
```
65+
With the`shadow-utils` implementation of `useradd` and the default glibc `files` this will
66+
result in changes to the traditional `/etc/passwd` and `/etc/shadow` files
67+
as part of the container build.
6668

67-
However, it is important to understand some two very important issues
68-
with this as it exists today (the `shadow-utils` implementation of `useradd`)
69-
and the default glibc `files` backend for the traditional `/etc/passwd`
70-
and `/etc/shadow` files.
69+
#### System drift from local /etc/passwd modifications
7170

72-
It is common for user/group IDs are allocated dynamically, and this can result in "drift" (see below).
71+
When the system is initially installed, the `/etc/passwd` in the container image will be
72+
applied and contain desired users.
7373

74-
Further, if `/etc/passwd` is modified locally (because there is a machine-local user),
75-
then any added users injected via `useradd` *will not appear* on subsequent updates by default (they will be
74+
By default (without `etc = transient`, see below), the `/etc` directory is machine-local
75+
persistent state. If subsequently `/etc/passwd` is modified local to the machine
76+
(as is common for e.g. setting a root password) then any new changes in the container
77+
image (such as users from new packages) *will not appear* on subsequent updates by default (they will be
7678
in `/usr/etc/passwd` instead - the default image version).
7779

78-
These "system users" that may be created by packaging tools invoking `useradd` (e.g. `apt|dnf install httpd`) that do
79-
not also install a `sysusers.d` file. Currently for example, this is the case with
80-
the CentOS Stream 9 `httpd` package. Per below, the general solution to this
81-
is to avoid invoking `useradd` in container builds, and prefer one of the below
82-
solutions.
80+
The general best fix for this is to use `systemd-sysusers` instead of allocating
81+
a user/group at build time at all.
82+
83+
##### Using systemd-sysusers
84+
85+
See [systemd-sysusers](https://www.freedesktop.org/software/systemd/man/latest/systemd-sysusers.html).
86+
For example in your derived build:
87+
88+
```
89+
COPY mycustom-user.conf /usr/lib/sysusers.d
90+
```
91+
92+
A key aspect of how this works is that `sysusers` will make changes
93+
to the traditional `/etc/passwd` file as necessary on boot instead
94+
of at build time. If `/etc` is persistent, this can avoid uid/gid drift (but
95+
in the general case it does mean that uid/gid allocation can
96+
depend on how a specific machine was upgraded over time).
8397

8498
#### User and group home directories and `/var`
8599

@@ -96,20 +110,6 @@ This is significantly better than the pattern of allocating users/groups
96110
at "package install time" (e.g. [Fedora package user/group guidelines](https://docs.fedoraproject.org/en-US/packaging-guidelines/UsersAndGroups/)) because
97111
it avoids potential UID/GID drift (see below).
98112

99-
#### Using systemd-sysusers
100-
101-
See [systemd-sysusers](https://www.freedesktop.org/software/systemd/man/latest/systemd-sysusers.html). For example in your derived build:
102-
103-
```
104-
COPY mycustom-user.conf /usr/lib/sysusers.d
105-
```
106-
107-
A key aspect of how this works is that `sysusers` will make changes
108-
to the traditional `/etc/passwd` file as necessary on boot. If
109-
`/etc` is persistent, this can avoid uid/gid drift (but
110-
in the general case it does mean that uid/gid allocation can
111-
depend on how a specific machine was upgraded over time).
112-
113113
#### Using systemd JSON user records
114114

115115
See [JSON user records](https://systemd.io/USER_RECORD/). Unlike `sysusers`,
@@ -193,6 +193,23 @@ them; this is the pattern used by cloud-init and [afterburn](https://github.com/
193193

194194
### UID/GID drift
195195

196+
Any invocation of `useradd` or `groupadd` that does not allocate a *fixed* UID/GID may
197+
be subject to "drift" in subsequent rebuilds by default.
198+
199+
One possibility is to explicitly force these user/group allocations into a static
200+
state, via `systemd-sysusers` (per above) or explicitly adding the users with
201+
static IDs *before* a dpkg/RPM installation script operates on it:
202+
203+
```
204+
RUN <<EORUN
205+
set -xeuo pipefail
206+
groupadd -g 10044 mycustom-group
207+
useradd -u 10044 -g 10044 -d /dev/null -M mycustom-user
208+
dnf install -y mycustom-package.rpm
209+
bootc container lint
210+
EORUN
211+
```
212+
196213
Ultimately the `/etc/passwd` and similar files are a mapping
197214
between names and numeric identifiers. A problem then becomes
198215
when this mapping is dynamic and mixed with "stateless"
@@ -212,11 +229,28 @@ and data in `/var/lib/postgres` will always be owned by that UID.
212229
However in contrast, the cockpit project allocates
213230
[a floating cockpit-ws user](https://gitlab.com/redhat/centos-stream/rpms/cockpit/-/blob/1909236ad28c7d93238b8b3b806ecf9c4feb7e46/cockpit.spec#L506).
214231

215-
This means that each container image build (without additional work)
216-
may (due to RPM installation ordering or other reasons) result
217-
in the uid changing.
232+
This means that each container image build (without additional work, unlike the
233+
example at the begining of this section),may (due to RPM installation
234+
ordering or other reasons) result in the uid changing.
218235

219236
This can be a problem if that user maintains persistent state.
220237
Such cases are best handled by being converted to use `sysusers.d`
221238
(see [Fedora change](https://fedoraproject.org/wiki/Changes/Adopting_sysusers.d_format)) - or again even better, using `DynamicUser=yes` (see above).
222239

240+
241+
#### tmpfiles.d use for setting ownership
242+
243+
Systemd's [tmpfiles.d](https://www.freedesktop.org/software/systemd/man/latest/tmpfiles.d.html) provides a way
244+
to define files and directories in a way that will be processes at startup as needed. One way to work around
245+
SELinux security context and user or group ownership of a directory or file can be by using the z or Z directives.
246+
247+
These directives will adjust the access mode, user and group ownership and the SELinux security context as
248+
stated on the doc linked above.
249+
250+
For example, if we need `/var/lib/my_file.conf` to be part of the `tss` group but owned by `root`
251+
we could create a tmpfiles.d entry with:
252+
253+
```
254+
+z /var/lib/my_file 0640 root tss -
255+
```
256+

0 commit comments

Comments
 (0)