From Fedora Project Wiki

(Reformat <pre> section to repair damage from old wiki conversion.)
(Update from the approved draft https://fedorahosted.org/fpc/ticket/269)
Line 1: Line 1:
<!-- page was renamed from PackagingDrafts/UsersAndGroups
This guideline is for packaging cases that require creation of users and groups. 
-->
== 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.
== Basic premise for users ==


To create users and groups in packages, use the following:
In designing these guidelines it was accepted that individual sites will have a need to customize the allocation of UIDs and GIDs to their particular systems.  For instance, if they have both Debian and Fedora installs or if they've already allocated user accounts in the range that we use for system accounts and need to place system accounts elsewhere.  Therefore, the methods that these guidelines advocate had to be adaptable so that local sysadmins could make our packages use the UIDs and GIDs that they desired at their site.
 
The guidelines provide two options: letting each individual system allocate UID and GID values individually or using a "soft static" allocation that attempts to allocate UIDs and GIDs consistently.  In either case, if the username or groupname being created by the package already exists on the system the package will use that instead of creating a new one.  This allows the local system administrator to pre-allocate the UIDs and GIDs for particular usernames and groupnames in order to set them to a particular value for their site.
 
=== Methods of pre-allocating ===
 
There are many ways to pre-allocate the UIDs and GIDs.  Sites that only want to customize the UIDs and GIDs of a few nonessential services may write a script to create the entries with <code>useradd</code> and <code>groupadd</code> and install our package afterwards.
 
Sites that want to pre-allocate accounts that are needed during an unattended kickstart install have trickier problem.  One way for them to accomplish their goals is to create a customized version of the "<code>setup</code>" package with the desired users and groups along with their chosen UID/GID mappings in the <code>/etc/passwd</code>, <code>/etc/shadow</code>, and <code>/etc/group</code> files.  Then they make sure the install transaction uses that package instead of the vanilla distro one (by versioning their setup package higher than ours (for instance, with an epoch) and putting it in a local repo they include when installing or replacing our setup package with their own in a local mirror of the packages that they are installing from).  Since setup is at the top of the dependency tree, it will be installed before any package which needs to use the UIDs and GIDs that are defined in it.
 
{{admon/note|Using LDAP to preallocate|Sites with LDAP or other network authentication systems may want to use those for pre-allocating their system accounts sitewide.  Such sites should make sure their infrastructure is robust and includes suitable local caching of the system accounts.  Without suitable local caching, a computer that becomes disconnected from the network may not be able to start essential services because the computer is unable to resolve a username or groupname to a proper UID or GID.}}
 
=== Known caveat of the pre-allocation strategy ===
 
The practice of using existing users and groups if their symbolic names (usernames and groupnames) already exists on the system lets the system administrator customize the UIDs and GIDs as they please.  However, it has one drawback that system admins should be aware of.  If an unrelated account has already been created that uses those usernames and groupnames the package will make use of those accounts.
 
As an example, say that you are installing the mailman package which wants to create the <code>mailman</code> user and group so that the private mailing list archives can be owned by that user and group on disk.  One of your local users already has the local username <code>mailman</code>.  When the mailman package is installed, it will detect that there is already a <code>mailman</code> user and use that account for owning its private archives.  The local user who owns the mailman account would then be able to read those private archives.
 
At the moment, there is no strategy for the packagers to counteract this.  It is up to the site system administrators to keep track of and remove conflicts for the user and group names used by their users and those used by the packages they are using.
 
== Allocation Strategies ==
 
{{admon/warning|Do not remove users or groups|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 with 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.}}
 
We have two methods for creating users and groups: Dynamic and Soft Static.
 
Any package can use dynamic allocation; it is especially appropriate for packages that use separate identities only for privilege separation and don't create any files owned by that group/user account.  Because of the limited number of soft static UIDs and GIDs available, it is better to use dynamic allocation if in doubt.
 
Soft static allocation ensures that multiple independently installed systems use the same UID and GID values; either UID and GID values allocated by Fedora or values that were optionally pre-allocated by the system administrator.  Don't use soft static allocation unnecessarily as the number of available values is limited.  Soft static allocation is only appropriate for packages where the UID or GID values are shared between computers.  For instance, if the package creates files with the assigned UID or GID that are likely to be shared over NFS.  Soft static allocation '''MUST''' be evaluated by the FPC.  See the paragraph in the [[#Soft_static_allocation| soft static section]] for details the FPC will want.
 
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 <code>groupadd</code> parts of the below recipes.
 
=== Dynamic allocation ===
 
To create users and groups in packages using dynamic allocation, use the following:


<pre>
<pre>
Line 18: Line 50:
</pre>
</pre>


<code>HOMEDIR</code> 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.
=== Soft static allocation ===


User accounts created by packages are rarely used for interactive logons, and should thus generally use <code>/sbin/nologin</code> as the user's shell.
To allocate a UID and/or GID, file a [https://fedorahosted.org/fpc/newticket ticket for the FPC] to evaluate.  If the FPC finds that your package needs a soft static UID or GID, they will assign you one and add an entry documenting it to the [https://git.fedorahosted.org/cgit/setup.git/tree/uidgid /usr/share/doc/setup-*/uidgid] file in the setup package.  Because the number of UIDs and GIDs is limited, you need to justify your package's need for a soft static uid in the FPC ticket.  Explain how the uids and gids are being shared between computers.  If applicable, also explain why the program can't be adapted to use symbolic names (username and groupname) instead.  If a specific UID or GID should be used, please mention it and why (for instance, it is the one used by upstream or the one used by other distributions).  We will try to accommodate on a first-come-first serve basis if the UID/GID is available from within the Fedora system UID/GID range.


We want to invoke <code>groupadd</code> explicitly instead of relying on <code>useradd</code> to create the group for us.  This is because <code>useradd</code> alone would fail if the group it tries to create already existed.  Note: even though the <code>useradd</code> manual page doesn't mention it (as of FC6), <code>-g GROUPNAME</code> appears to imply <code>-n</code>.
To create users and groups in packages, use the following:


The <code>exit 0</code> at the end will result in the <code>%pre</code> 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.
<pre>
 
Requires(pre): shadow-utils
We run <code>getent</code> before <code>groupadd</code> and <code>useradd</code> 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 "<code>setup</code>" 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.
[...]
 
%pre
We run the <code>groupadd</code>/<code>useradd</code> always -- both on initial installs and upgrades -- in <code>%pre</code>.  This is made possible by the <code>getent</code> 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).
getent group GROUPNAME >/dev/null || groupadd -f -g ALLOCATED_GID -r GROUPNAME
 
if ! getent passwd USERNAME >/dev/null ; then
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.
    if ! getent passwd ALLOCATED_UID >/dev/null ; then
      useradd -r -u ALLOCATED_UID -g GROUPNAME -d HOMEDIR -s /sbin/nologin -c "Useful comment about the purpose of this account" USERNAME
    else
      useradd -r -g GROUPNAME -d HOMEDIR -s /sbin/nologin -c "Useful comment about the purpose of this account" USERNAME
    fi
fi
exit 0
</pre>


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 <code>groupadd</code> parts of the above recipe.
=== Values given to useradd and groupadd ===


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.
* <code>HOMEDIR</code> 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.
* <code>USERNAME</code> and <code>GROUPNAME</code> are the symbolic names used by your package.  Be aware that all code in the package should use these names, not the UID or GIDIf this is not possible, please mention it within the ticket so that the FPC can see if this is a different type of problem than we usually encounter.
* <code>ALLOCATED_UID</code> and <code>ALLOCATED_GID</code> are the UID and GID that FPC tells you has been allocated for use by your package.
* User accounts created by packages are rarely used for interactive logons, and should thus generally use <code>/sbin/nologin</code> as the user's shell.


=== Collection of past random notes ===
=== Rationale for some of the implementation choices ===


Moved to PackagingDrafts/UsersAndGroupsThoughts (note that these are not part of this guideline).
* We run <code>getent</code> before <code>groupadd</code> and <code>useradd</code> to check whether the user/group we're about to create already exists and skip the creation if they do.  This is what allows the local system administrators to customize the users and groups beforehand in case they wish to get a predefined static UID/GID mapping for those users.  Similarly, we verify whether the ID values allocated in the "setup" package aren't already allocated by the local system administrators.
* We want to invoke <code>groupadd</code> explicitly instead of relying on <code>useradd</code> to create the group for us.  This is because <code>useradd</code> alone would fail if the group it tries to create already existed.
* We run the <code>groupadd</code>/<code>useradd</code> always -- both on initial installs and upgrades -- in <code>%pre</code>.  This is made possible by the <code>getent</code> 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).
* The <code>exit 0</code> at the end will result in the <code>%pre</code> 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 setting those files owned by root.


[[Category:Packaging guidelines]]
[[Category:Packaging guidelines]]

Revision as of 16:54, 17 April 2013

This guideline is for packaging cases that require creation of users and groups.

Basic premise for users

In designing these guidelines it was accepted that individual sites will have a need to customize the allocation of UIDs and GIDs to their particular systems. For instance, if they have both Debian and Fedora installs or if they've already allocated user accounts in the range that we use for system accounts and need to place system accounts elsewhere. Therefore, the methods that these guidelines advocate had to be adaptable so that local sysadmins could make our packages use the UIDs and GIDs that they desired at their site.

The guidelines provide two options: letting each individual system allocate UID and GID values individually or using a "soft static" allocation that attempts to allocate UIDs and GIDs consistently. In either case, if the username or groupname being created by the package already exists on the system the package will use that instead of creating a new one. This allows the local system administrator to pre-allocate the UIDs and GIDs for particular usernames and groupnames in order to set them to a particular value for their site.

Methods of pre-allocating

There are many ways to pre-allocate the UIDs and GIDs. Sites that only want to customize the UIDs and GIDs of a few nonessential services may write a script to create the entries with useradd and groupadd and install our package afterwards.

Sites that want to pre-allocate accounts that are needed during an unattended kickstart install have trickier problem. One way for them to accomplish their goals is to create a customized version of the "setup" package with the desired users and groups along with their chosen UID/GID mappings in the /etc/passwd, /etc/shadow, and /etc/group files. Then they make sure the install transaction uses that package instead of the vanilla distro one (by versioning their setup package higher than ours (for instance, with an epoch) and putting it in a local repo they include when installing or replacing our setup package with their own in a local mirror of the packages that they are installing from). Since setup is at the top of the dependency tree, it will be installed before any package which needs to use the UIDs and GIDs that are defined in it.

Using LDAP to preallocate
Sites with LDAP or other network authentication systems may want to use those for pre-allocating their system accounts sitewide. Such sites should make sure their infrastructure is robust and includes suitable local caching of the system accounts. Without suitable local caching, a computer that becomes disconnected from the network may not be able to start essential services because the computer is unable to resolve a username or groupname to a proper UID or GID.

Known caveat of the pre-allocation strategy

The practice of using existing users and groups if their symbolic names (usernames and groupnames) already exists on the system lets the system administrator customize the UIDs and GIDs as they please. However, it has one drawback that system admins should be aware of. If an unrelated account has already been created that uses those usernames and groupnames the package will make use of those accounts.

As an example, say that you are installing the mailman package which wants to create the mailman user and group so that the private mailing list archives can be owned by that user and group on disk. One of your local users already has the local username mailman. When the mailman package is installed, it will detect that there is already a mailman user and use that account for owning its private archives. The local user who owns the mailman account would then be able to read those private archives.

At the moment, there is no strategy for the packagers to counteract this. It is up to the site system administrators to keep track of and remove conflicts for the user and group names used by their users and those used by the packages they are using.

Allocation Strategies

Do not remove users or groups
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 with 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.

We have two methods for creating users and groups: Dynamic and Soft Static.

Any package can use dynamic allocation; it is especially appropriate for packages that use separate identities only for privilege separation and don't create any files owned by that group/user account. Because of the limited number of soft static UIDs and GIDs available, it is better to use dynamic allocation if in doubt.

Soft static allocation ensures that multiple independently installed systems use the same UID and GID values; either UID and GID values allocated by Fedora or values that were optionally pre-allocated by the system administrator. Don't use soft static allocation unnecessarily as the number of available values is limited. Soft static allocation is only appropriate for packages where the UID or GID values are shared between computers. For instance, if the package creates files with the assigned UID or GID that are likely to be shared over NFS. Soft static allocation MUST be evaluated by the FPC. See the paragraph in the soft static section for details the FPC will want.

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 below recipes.

Dynamic allocation

To create users and groups in packages using dynamic allocation, 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

Soft static allocation

To allocate a UID and/or GID, file a ticket for the FPC to evaluate. If the FPC finds that your package needs a soft static UID or GID, they will assign you one and add an entry documenting it to the /usr/share/doc/setup-*/uidgid file in the setup package. Because the number of UIDs and GIDs is limited, you need to justify your package's need for a soft static uid in the FPC ticket. Explain how the uids and gids are being shared between computers. If applicable, also explain why the program can't be adapted to use symbolic names (username and groupname) instead. If a specific UID or GID should be used, please mention it and why (for instance, it is the one used by upstream or the one used by other distributions). We will try to accommodate on a first-come-first serve basis if the UID/GID is available from within the Fedora system UID/GID range.

To create users and groups in packages, use the following:

Requires(pre): shadow-utils
[...] 
%pre
getent group GROUPNAME >/dev/null || groupadd -f -g ALLOCATED_GID -r GROUPNAME
if ! getent passwd USERNAME >/dev/null ; then
    if ! getent passwd ALLOCATED_UID >/dev/null ; then
      useradd -r -u ALLOCATED_UID -g GROUPNAME -d HOMEDIR -s /sbin/nologin -c "Useful comment about the purpose of this account" USERNAME
    else
      useradd -r -g GROUPNAME -d HOMEDIR -s /sbin/nologin -c "Useful comment about the purpose of this account" USERNAME
    fi
fi
exit 0

Values given to useradd and groupadd

  • 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.
  • USERNAME and GROUPNAME are the symbolic names used by your package. Be aware that all code in the package should use these names, not the UID or GID. If this is not possible, please mention it within the ticket so that the FPC can see if this is a different type of problem than we usually encounter.
  • ALLOCATED_UID and ALLOCATED_GID are the UID and GID that FPC tells you has been allocated for use by your package.
  • User accounts created by packages are rarely used for interactive logons, and should thus generally use /sbin/nologin as the user's shell.

Rationale for some of the implementation choices

  • We run getent before groupadd and useradd to check whether the user/group we're about to create already exists and skip the creation if they do. This is what allows the local system administrators to customize the users and groups beforehand in case they wish to get a predefined static UID/GID mapping for those users. Similarly, we verify whether the ID values allocated in the "setup" package aren't already allocated by the local system administrators.
  • 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.
  • 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).
  • 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 setting those files owned by root.