By default, Kolab ships with a configuration that lets Cyrus IMAP use LDAP roles as permission groups for IMAP folders. This article describes the configuration necessary to change a default Kolab deployment to use distribution groups instead of LDAP roles.
About Roles and Groups in LDAP
For as far as users and permissions are concerned, a role in LDAP is an object type attribute that is associated with the user’s entry directly. As such, they scale tremendously well. They are typically not used for email addresses, but for permissions.
The distribution groups we speak of are individual LDAP object entries where members are stored as a list in a multi-valued attribute. The following is an example entry for a distribution list for board members:
dn: cn=Board of Directors,ou=Groups,dc=example,dc=com cn: Board of Directors objectClass: top objectClass: groupofuniquenames mail: board@example.com uniqueMember: uid=john.doe,ou=People,dc=example,dc=com uniqueMember: uid=jane.doe,ou=People,dc=example,dc=com
Groups come in different forms and shapes, and it is important to understand that ultimately, IMAP will require an attribute value of the group that adheres to valid syntax requirements. Therefore, the type of groups that IMAP can use as permission groups are limited to distribution groups only; these groups have an email address.
The uniqueMember
attribute hold members of the group. In Kolab terminology this is a static distribution group, because members are defined statically, and new members need to be added manually. A different approach is a dynamic group. In this case members are defined as an LDAP filter, which is used every time a list of group members is needed. The same distribution group for board members would look as follows:
dn: cn=Board of Directors,ou=Groups,dc=example,dc=com cn: Board of Directors memberURL: ldap://localhost/ou=People,dc=example,dc=com??sub?(nsrole=board-member) mail: board@example.com objectClass: top objectClass: groupofurls objectClass: kolabgroupofuniquenames
As you can see, the memberURL is the filter definition that describes where and how to find group individual members. Both these groups are traditional way of defining groups.
Roles
The other approach is to list groups the user is member of in user definition object. In other words user object holds information about which groups does the user belongs to. This is the opposite approach to traditional groups.
In 389 Directory server roles are defined in special attribute nsroledn
. The value of that attribute should be a DN of defined role. Role definitions can be found with ldapsearch query filter "(|(objectclass=ldapsubentry)(objectclass=nsroledefinition))"
and the example, Kolab adds a kolab-admin
role by default, that has all of the day-to-day permissions necessary to add/modify/delete users, groups and so forth:
dn: cn=kolab-admin,dc=example,dc=com objectClass: top objectClass: ldapsubentry objectClass: nsroledefinition objectClass: nssimpleroledefinition objectClass: nsmanagedroledefinition description: Kolab Administrator cn: kolab-admin
To list the roles a user is assigned to you need to query for nsrole
attribute. That is a read-only special attribute, which is automatically created for a user after a valid nsroledn
attribute is added. To query for nsrole
or nsroledn
attributes you need to specifically list these attributes as requested search result attributes because these are special attributes, and special attributes are not shown by a regular search of LDAP when not specifically requested.
Kolab and Groups
Kolab supports all types of LDAP groups, however a mail distribution group can be either static or dynamic traditional groups. If those distribution groups are to be used as permission groups, this does not align with default Cyrus IMAP ptloader configuration. The actual purpose of this article is to show how to reconfigure Cyrus IMAP to use the same traditional groups. This maybe be important when you need to set permissions for group when sharing a folder.
Kolab’s Default Cyrus IMAP Configuration
Kolab configures Cyrus IMAP with the following configuration snippet;
ldap_group_base: dc=example,dc=com ldap_group_filter: (&(cn=%u)(objectclass=ldapsubentry)(objectclass=nsroledefinition)) ldap_group_scope: one ldap_member_method: attribute ldap_member_attribute: nsrole
This can be read as follows — using LDAP group method attribute
look for nsrole
attribute of the logged in user. The list of nsrole
values is the groups the user belongs to. ldap_group_filter
is used to get the list of available permission groups (roles).
Re-configure Cyrus IMAP
So to setup distribution groups as permission groups in Cyrus IMAP, change the following options in /etc/imapd.conf
ldap_group_base: ou=Groups,dc=example,dc=com ldap_group_filter: (&(mail=%U)(objectclass=kolabgroupofuniquenames)) ldap_group_scope: one ldap_member_base: ou=Groups,dc=example,dc=com ldap_member_method: filter ldap_member_attribute: uid ldap_member_filter: uniqueMember=%D ldap_size_limit: 0
A bit of explanation:
ldap_member_method
– group type definitions. Allowed values arefilter
andattribute
. To get static groups this attribute value must be set tofilter
.ldap_member_base
– This setting controls where to look for groups the user is member of.ldap_member_attribute
– that is a attribute which holds group identifier, a group name.ldap_member_filter
– attribute with instructions how to construct LDAP filter, group membership query filter.
These are the main 4 Cyrus IMAP configuration parameters controlling how to get group membership from LDAP.
In this particular case we have configured that Cyrus IMAP ptloader should use filter
group membership query method and look for group membership under ldap_member_base: ou=Groups,dc=example,dc=com
with the ldap filter ldap_member_filter: uniqueMember=%D
.
For a user john.doe@example.org
, this causes Cyrus IMAP to search for group membership with a filter of (uniquemember=uid=doe,ou=People,dc=example,dc=org)
.
Cyrus IMAP Group Membership Caches
This section re-iterates how to obtain, validate, review and expire the Cyrus IMAP group membership caches;
- Examine the cache with
/usr/lib/cyrus-imapd/ptdump
, - Expire the cache with
/usr/lib/cyrus-imapd/ptexpire -E0
, - Login with a user that is a member of a distribution group that is used as a permission group, and examine the cache.
Some example output of ptdump
;
user: cyrus-admin time: 1526972872 groups: 0 user: john.doe@example.com time: 1526972871 groups: 1 group:board
That is pretty self explanatory and it does represent the LDAP group definitions in Cyrus.
Now, when you need to share a specific folder to group, you can use a command similar to the following;
# kolab sam shared/board@example.com group:board read-write