Hi,
I wrote a design document for the work tracked in
https://pagure.io/SSSD/sssd/issue/3822
which is about a ‘hybrid’ MPG mode where the private group would be generated only for
users who do not have a gidNumber set explicitly:
https://pagure.io/SSSD/docs/pull-request/72
For your convenience, the document in the RST format is also pasted below:
Hybrid Private Groups for LDAP and AD domains
=============================================
Related ticket(s):
------------------
https://pagure.io/SSSD/sssd/issue/3822
Problem statement
-----------------
This change will augment the ``auto_private_groups`` option which currently
is a boolean option with a third mode that would, for users who do have
the ``gidNumber`` attribute set return the original group, but for users who
have no ``gidNumber,`` autogenerate a user-private group.
Use cases
---------
This change is mostly useful for backwards compatibility in environments that
used to manually set a ``gidNumber`` and need to retain the same primary
GID number, but for newly added user, autogenerate the user private group
from the ``uidNumber.`` Please see the "How to test" section for an example.
Overview of the solution
------------------------
Internally, this hybrid domain would work as a MPG domain, so as if
``auto_private_groups`` was set true. The difference would be when
returning the entries. In the hybrid model, if the user being returned
had an original GID, this original GID would be used. Otherwise, a primary
group generated from the UID would be returned.
Care must be taken in the getgrnam and getgrgid calls to not return the
autogenerated group if requested for a user who also has the originalGID set.
Implementation details
----------------------
As said above, for the most part, the hybrid domain would work in a similar
manner as a domain that had ``auto_private_groups=true`` set in the config
file. This means, that the ``uidNumber`` and ``gidNumber`` attributes in
the sysdb cache are always set to the same value, but in case the original
entry in LDAP did have a gidNumber stored, that original value is also
stored in the cache using the ``origPrimaryGroupGidNumber`` attribute.
The purpose of this attribute is to be able to return the original
primary GID as a supplemetary group so that any resources owned by this
ID are still accessible to the user.
We will take advantage of this attribute when returning the user object
during ``getpwnam`` (keep in mind that ``struct passwd`` that the
``getpwnam`` call returns also contains the primary GID number), initgroups
and also for a special case during the ``getgrgid`` and ``getgrnam`` calls.
During the getpwnam call, the code will check whether the user being returned
has the ``origPrimaryGroupGidNumber`` or not. If it does, its value would
be returned as the GID number, otherwise the ``gidNumber`` attribute would
be used. A similar logic will be implemented in the initgroups call, with
the additional caveat that if the ``origPrimaryGroupGidNumber`` exists,
it wouldn't be returned as another secondary group.
For group requests in a domain where the user private groups are completely
managed, SSSD would search the whole combined user and group space and
return group objects based on user objects in the cache. The hybrid domain
must behave a little differently here. When a request for a user-private
group comes, the ``getgr*`` call in a hybrid domain should first try
to search group objects only. If there is no match, then also the user
objects need to be searched, but only those user objects that have no
``origPrimaryGroupGidNumber`` set can be returned as a private groups.
Reusing the example above, ``getgrnam("hybriduser")`` would return a group
object inferred from the user object, but ``getgrnam("posixuser")`` would
not return anything.
Configuration changes
---------------------
Since we are adding a new option value to the existing
``auto_private_groups`` call, the option must internally be converted from
boolean to a string with three possible values. We would retain ``true``
and ``false`` for backwards compatibility but add a third option value
``hybrid.``
How To Test
-----------
Considering these two partial LDIFs::
cn=posixuser,dc=example,dc=com
uidNumber: 1234
gidNumber: 5678
cn: posixuser
gecos: posix user
homeDirectory: /home/posixuser
loginShell: /bin/sh
cn=hybriduser,dc=example,dc=com
uidNumber: 2345
cn: hybriduser
# note: no gidNumber attribute
gecos: hybrid user
homeDirectory: /home/hybriduser
loginShell: /bin/sh
The getpwnam output for these two users would be::
$ getent passwd posixuser
posixuser:*:1234:5678:posix user:/home/posixuser:/bin/sh
$ getent passwd hybriduser
hybriduser:*:2345:2345:hybrid user:/home/hybriduser:/bin/sh