Users and groups
Creating users and groups is governed by GLEP 81. It is implemented
via acct-user
and acct-group
eclasses. New users and groups
are created as packages respectively in acct-user
and acct-group
categories.
First, check the UID/GID
assignment list and choose a free UID/GID in the range between 101 and
749. If you are adding a user and a group with the same name, use the same
number for their UID and GID, respectively. When in doubt, take the next free
number from 101 upwards. The helper script ./bin/used_free_uidgids.sh
available in the data/api.git repository can be used to find the next available
UID or GID.
Add your new user(s) and group(s) to the uid-gid.txt
file
located in the
data/api.git
repository and push them before adding the actual packages.
This counts as reserving the identifiers and will prevent collisions.
Afterwards, you can push the new ebuilds.
The historical way of using user.eclass
directly is now deprecated
and must not be used for new packages.
Group ebuilds
Group ebuilds are placed in acct-group
category, with the package name
matching the group name. The following ebuild for acct-group/suricata
can be used as a template for writing group ebuilds:
# Copyright 2019-2021 Gentoo Authors # Distributed under the terms of the GNU General Public License v2 EAPI=7 inherit acct-group DESCRIPTION="Group for Suricata IDS" ACCT_GROUP_ID=477
ACCT_GROUP_ID
must be set to the requested GID.
User ebuilds
User ebuilds are placed in acct-user
category, with the package name
matching the user name. The following ebuild for acct-user/suricata
can be used as a template for writing user ebuilds:
# Copyright 2019-2021 Gentoo Authors # Distributed under the terms of the GNU General Public License v2 EAPI=7 inherit acct-user DESCRIPTION="User for Suricata IDS" ACCT_USER_ID=477 ACCT_USER_GROUPS=( ${PN} ) acct-user_add_deps
ACCT_USER_ID
must be set to the requested GID. ACCT_USER_GROUPS
should list all the groups user belongs to, the primary group first. All
the other keys are optional.
ACCT_USER_SHELL
can be used to set the shell for the user. If unset,
the best system equivalent of nologin is used. ACCT_USER_HOME
specifies
the home directory, with /dev/null
being the default.
ACCT_USER_HOME_OWNER
can be used to override the ownership of the home
directory, and ACCT_USER_HOME_PERMS
to override the default permissions.
The defaults are the user and primary group for the owner, and 0755 for the
permissions.
You should embark upon a GLEP81 migration like an EAPI
update. Rather than simply copy your user's settings into an
acct-user
package, you should take the opportunity to
re-evaluate your user's name, shell, home directory, and its
permissions. Our GLEP 81 implementation will reveal many user
management issues that were allowed to fester in the past.
Choosing a shell
In most cases, the default shell (that is, no shell) should be
used. Services can still be started as a user who has no shell, and
daemons are able to drop privileges to a user who has no shell. If
necessary, the administrator can override a user's default shell with
su -s <shell> <username>
. This is sufficient for
testing, management of SSH credentials, and for initial configuration
in an ebuild's pkg_config
phase.
An obvious exception to this rule is if a human being will need to log
into the account interactively, as is the case with the root
user. Other exceptions certainly exist, but should be evaluated
case-by-case. In other words, if you haven't checked, don't set your
user's shell to /bin/bash
because you think he might
need it.
The goal here is twofold. First, the principle of least privilege says that if a user doesn't need a real shell, he shouldn't have one. And along those same lines, not having a shell gives the system administrator some peace of mind: he doesn't have to be as concerned with whether or not that user has a password (and how strong it is), or whether or not its filesystem permissions are all set correctly, or whether or not it can log in via SSH, et cetera.
Choosing a home directory
In most cases, the default home directory (that is, no home directory) should be used. GLEP81 changed two aspects of user management with respect to home directories:
-
Creating a user can now modify the permissions on an existing
directory. Should the need arise, this is necessary for a new
version of an
acct-user
package to be able to fix the ownership and permissions of its home directory. -
All user data aside from the username became non-local to ebuilds
that depend on that user. This is merely a side-effect of moving
the user creation out of the client package, and into a separate
acct-user
package.
The first item means that you should be conservative when choosing a
home directory. If at all possible, avoid choosing a home directory
that is used by another package. In particular, no two
acct-user
packages should use the same home directory. At best,
the ownership and permissions on a shared home directory would need to
be kept synchronized between all packages that share it. At worst, one
package goes out-of-sync and introduces a security hole for the others
who no longer have the expected permissions.
The second item means that if your package requires a user, you can
no longer be sure of that user's home directory or its ownership and
permissions. If your package requires a directory to be owned and
writable by some user, then your package's ebuild should create that
directory and ensure that it is writable by the user. In other
words, you should not rely on the directory being created
"transitively" by a dependency, even if that dependency is an
acct-user
package.
In summary,
-
Avoid using an
ACCT_USER_HOME
that belongs to another package. -
No two acct-user packages should define the same
ACCT_USER_HOME
. -
If for example your package's configuration needs <username>
to be able to write to
/var/lib/<username>
, then your package's ebuild should create that directory and set its ownership and permissions. Barring any other considerations, the correspondingacct-user
package should leaveACCT_USER_HOME
at its default (empty) value; settingACCT_USER_HOME=/var/lib/<username>
creates unnecessary duplication and risks desynchronizing the permissions.
Choosing home directory ownership
In most cases, the default home directory ownership is correct. If a
non-default home directory is needed at all, then it should be
writable by its user and giving ownership of it to someone else would
prevent that. Being unwritable indicates that a shared and potentially
sensitive location was chosen. Moreover, the fact that the home
directory is not writable suggests that the default home directory
(which is also not writable) would suffice instead; the home directory
guidelines explain why the default is preferable in that case. For
example, setting ACCT_USER_HOME_OWNER="root:root"
is suspicious
because it appears intended to "undo" the ownership changed by your
user package, and that would only be necessary if the path in question
is used by some other package.
Choosing home directory permissions
In many cases, the default home directory permissions (0755) will suffice. But, if your package will work with mode 0700 or 0750, then those are preferable. This is the principle of least privilege again. If your package works with a non-writable home directory, then you should probably be using the default of no home directory!
ACCT_USER_HOME_PERMS
. This should never be necessary, and is
usually exploitable.
Epilogue
These suggestions are not rules and are not written in stone, except
perhaps for the world-writable warning. There are packages in the tree
that chroot()
to $HOME
, and require that directory to be
owned by root:root
for security reasons. In cases like that,
it's impossible to avoid implicitly tying the user to the package that
needs it via the home directory, and the best you can do is attempt to
ensure that the users and paths are unique so that no conflicts arise.
Unless your package is exceptional, though, following these guidelines will minimize the potential for problems down the road.
Utilizing users and groups in packages
In order to make your package install specific users and groups, specify them
as dependencies. Accounts needed at build time must be included
in DEPEND
, and accounts needed at runtime must be included
in RDEPEND
.
For example, an ebuild requiring the user and group foo
at runtime would
specify:
RDEPEND=" acct-user/foo acct-group/foo"
This would also be sufficient if ownership of installed files were set
in pkg_preinst
. However, if the ebuild needs the user and group
to be present at build-time already, it would specify:
RDEPEND=" acct-user/foo acct-group/foo" DEPEND="${RDEPEND}"