Openldap groups: posxigroup vs groupofnames

Title:Openldap groups: posxigroup vs groupofnames
Author:Douglas O’Leary <dkoleary@olearycomputers.com>
Description:Discussion of groups of users in openldap
Date created:05/24/2014
Date updated:12/20/2014
Disclaimer:Standard: Use the information that follows at your own risk. If you screw up a system, don’t blame it on me...

Issue:

There seem to be two main ways to group users in an openldap directory:

  • posixgroup
  • groupofnames

The posixgroup is required to provide the translation between group id numbers and their names:

# ls -ld /home/dkoleary
drwxr-xr-x. 5 dkoleary admin 4096 Apr 27 07:21 /home/dkoleary/

Without that capability, the line would look like:

# ls -ld /home/dkoleary
drwxr-xr-x. 5 dkoleary 110 4096 Apr 27 07:21 /home/dkoleary/

Not nearly as helpful to us humans and probably a show stopper, long term, for the linux system itself.

posixgroup’s member attribute is called memberUID and simply lists the uid of the member. Using this alone, there’s really no solid way to identify the specific distinguised name of the group member.

memberUID: foo

How would you determine which foo that is, if there are multiple people groups for instance.

So, posixgroup is required for gid <=> group name translation..

On the other hand, if you’re using the sssd daemon and want to limit access to systems based on group, you have to use a filter that looks like:

ldap_access_filter = (|(memberof=cn=infra,ou=gon,dc=oci,dc=com)\
(memberOf=cn=dba,ou=gon,dc=oci,dc=com))

Interestingly, that has to be one line - no line breaks, no escaped new lines. I added one for readability only.

That memberof syntax, though, is only used with groupofnames style groups.

So, groupofnames is required.

groupofnames does provide the specific distinguished name of the member so it’s very easy to identify what people belong in this group:

member: uid=foo,ou=users,dc=oci,dc=com

The answer’s easy: add groupofnames objectclass to the posixgroups. And, that’s where the issue comes in. The classes groupofnames and posixgroup are structural and thus, cannot be used in the same group.

So, both group types are required but neither can coexist with the other.

Options:

There are a few options to work around this issue.

  1. Have duplicate group definitions, one posixgroup, one groupofnames. This entails an administrative overhead and a large potential for differences creeping in between the groups. It does work, however, as I’ve proven to myself by doing exactly that. It’s not an optimal solution, though.

  2. Implement the two groups but don’t even try to keep them duplicated. Rather, completely separate the function. The posixgroup groups provide the gid <=> group name translation while the groupofuniqnames specific to a host and perhaps a group named after the host which will then list all the users that have access. This will reduce the complexity of the access filter at the expense of the administrative overhead of maintaining posix groups and access groups. Possible, and possibly even workable, but it’s annoying as that’s what the UNIX groups are for.

  3. Use a dynamic list overlay. I’ve seen one site using this solution. It seemed ... complex. Additionally, each request to identify groups to which a user belongs will kick off a large search of every record in the groups dn which could seriously degrade directory performance, particularly for large directories. Possible, but seemingly not optimal.

  4. Generate a filter for use in the sssd that will search on posixgroups. While theoretically possible, I haven’t been able to come up with such a search. Additionally, it’ll suffer from the same drawback as the dynlist solution. A simple request for groups to which a user belongs will mean a global search of the groups tree. Possible, but not optimal.

  5. Eliminate the need for groupofnames by skipping sssd as the access filter and, instead, rely on pam configurations. This will require updating at least one and possibly several pam related files. Using ssh as the example:

    • Examine the /etc/pam.d/sshd file. For auth, account, and session interfaces, there’s an include for password-auth. Note that this is centos6.5 specific; but, other variants should have something similar.

    • Examine the password-auth file, specifically the account interface as it’s the account attribute that we’re interested in. After running authconfig to enable ldap authentication, it’ll look like:

      account     required      pam_access.so
      account     required      pam_unix.so broken_shadow
      account     sufficient    pam_localuser.so
      account     sufficient    pam_succeed_if.so uid < 500 quiet
      account     [default=bad success=ok user_unknown=ignore] pam_sss.so
      account     required      pam_permit.so
      
    • The trick is to add pam_succeed_if entries for all posixgroups that you want to have access to the system. The last one must be listed as requisite and all other as sufficient. Thusly:

      account     required      pam_access.so
      account     required      pam_unix.so broken_shadow
      account     sufficient    pam_localuser.so
      account     sufficient    pam_succeed_if.so uid < 500 quiet
      account     sufficient    pam_succeed_if.so user ingroup ops
      account     sufficient    pam_succeed_if.so user ingroup dba
      account     requisite     pam_succeed_if.so user ingroup infra
      account     [default=bad success=ok user_unknown=ignore] pam_sss.so
      account     required      pam_permit.so
      
    • The set up above would allow members of the posixgroup ops, dba, and infra access to the system. All others will get denied. Successful and unsuccessful /var/log/secure entries are:

      May 23 22:05:47 client1 sshd[17274]: pam_succeed_if(sshd:account): \
          requirement "user ingroup infra" was met by user "d"
      May 23 22:05:58 client1 sshd[17300]: pam_succeed_if(sshd:account): \
          requirement "user ingroup ops" not met by user "a"
      May 23 22:05:58 client1 sshd[17300]: pam_succeed_if(sshd:account): \
          requirement "user ingroup dba" not met by user "a"
      May 23 22:05:58 client1 sshd[17300]: pam_succeed_if(sshd:account): \
          requirement "user ingroup infra" not met by user "a"
      
    • This has several advantages.

      • It eliminates the mutually exclusive requirement for posixgroup and groupofnames
      • It’s easier to maintain than the ldap_access_filter.
      • It’s significantly easier to read than the ldap_access_filter
      • With the readability is the easier method of identifying which groups have access to a system for audit and security reporting purposes.
  6. Implement rfc2307bis. Option #5 is definitely workable but it also eliminates the functionality that groupofnames groups provides. When deleting users, for instance, an admin should identify the groups to which the user belongs and remove them. Without the memberof functionality, the admin is forced to search all groups in the group dn. Workable, particularly since it’s a reasonably rare event, but not optimal. What if there was a way to combine these two structural classes into one group? Enter rfc2307bis. The directory/linux admin can still maintain access lists outside of sssd for ease of maintenance and use the memberof search to identify posixgroups from which a member needs to be removed prior to deleting him. Seems like the best of both worlds. I’ll be trying that configuration next.

    A major problem with this approach, though, is it has to be done when the directory is first being created as the rfc2307bis pretty much replaces the nis.schema. There are interesting steps to add a schema; but, so far, it seems that it’s still impossible to delete one. So, you can’t add the rfc2307bis schema and delete the nis.schema, particularly if there’s entries in the directory using the nis.schema. Chicken, meet egg. Definitely going into the lessons learned and installation guide....

Summary:

Of those options, the only ones that are really workable, in my opinion, are 2, 5, and 6. I personally will be implementing 5 (and potentially 6) in new environments that I set up as the need to manage different groups for different purposes irks me.

I hope this helps someone as I have yet to see anyone lay it out like this. As long as ldap’s been around, I know I’m not the first person to have run into this issue. While the posixgroup/groupofnames info is available, it’s never, to my knowledge, mentioned in ldap installation guides. It will be in mine as soon as I work out any issues w/rfc2307bis usage.

Doug O’Leary