User and group handling in packages
This guideline is for packaging cases that require creation of users and groups. Note that for the moment, we primarily address the case where the mapping from user/group names to uids/gids is decided dynamically by target systems at package install time. Some options for system administrators for making this mapping static even though the package scriptlets use a dynamic scheme are also discussed below, and more are being investigated, including possibilities to make the mapping static at package build time.
To create users and groups in packages, use the following:
Requires(pre): shadow-utils [...] %pre getent group GROUPNAME >/dev/null || groupadd -r GROUPNAME getent passwd USERNAME >/dev/null || \ useradd -r -g GROUPNAME -d HOMEDIR -s /sbin/nologin \ -c "Useful comment about the purpose of this account" USERNAME exit 0
HOMEDIR
should usually be a directory created and owned by the package, with appropriately restrictive permissions. One good choice for the location of the directory is the package's data directory in case it has one.
User accounts created by packages are rarely used for interactive logons, and should thus generally use /sbin/nologin
as the user's shell.
We want to invoke groupadd
explicitly instead of relying on useradd
to create the group for us. This is because useradd
alone would fail if the group it tries to create already existed. Note: even though the useradd
manual page doesn't mention it (as of FC6), -g GROUPNAME
appears to imply -n
.
The exit 0
at the end will result in the %pre
scriptlet passing through even if the user/group creation fails for some reason. This is suboptimal but has less potential for system wide breakage than allowing it to fail. If the user/group aren't available at the time the package's payload is unpacked, rpm will fall back to getting those files owned by root.
We run getent
before groupadd
and useradd
to check whether the user/group we're about to create already exists, and we skip the creation if they do. This is in order to provide a possibility for local system administrators to create the users/groups beforehand in case they wish to get a predefined static UID/GID mapping for those users. Creating users eg. when using unattended kickstart installations is a case where creating users/groups beforehand is a bit tricky; one way to accomplish that is to create a customized version of the "setup
" package with the desired users/groups along with their static UID/GID mappings are in place, and to make sure the install transaction uses that package instead of the vanilla distro one.
We run the groupadd
/useradd
always -- both on initial installs and upgrades -- in %pre
. This is made possible by the getent
checks above, and should fix things up if the user/group has disappeared after the package to be upgraded was initially installed (just like file permissions get reset on upgrades etc).
We never remove users or groups created by packages. There's no sane way to check if files owned by those users/groups are left behind (and even if there would, what would we do to them?), and leaving those behind with ownerships pointing to now nonexistent users/groups may result in security issues when a semantically unrelated user/group is created later and reuses the UID/GID. Also, in some setups deleting the user/group might not be possible or/nor desirable (eg. when using a shared remote user/group database). Cleanup of unused users/groups is left to the system administrators to take care of if they so desire.
In some cases it is desirable to create only a group without a user account. Usually this is because there are some system resources to which we want to control access by using that group, and a separate user account would add no value. Examples of common such cases include (but are not limited to) games whose executables are setgid for the purpose of sharing high score files or the like, and/or software that needs exceptional permissions to some hardware devices and it wouldn't be appropriate to grant those to all system users nor even only those logged in on the console. In these cases, apply only the groupadd
parts of the above recipe.
Note that the practice of not creating users/groups if they exist has a drawback of possibly unrelated but coincidentally same named existing system users and/or groups unnecessarily and undesirably getting access to things in a package that uses the same user/group names. This version of the users/groups guideline does not address that issue in any way, but it is possible that future revisions will if a good enough way to do that is found.
Collection of past random notes
Moved to PackagingDrafts/UsersAndGroupsThoughts (note that these are not part of this guideline).