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: email@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.
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: firstname.lastname@example.org 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.
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
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
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 are
attribute. To get static groups this attribute value must be set to
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
For a user
email@example.com, this causes Cyrus IMAP to search for group membership with a filter of
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
- Expire the cache with
- 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
user: cyrus-admin time: 1526972872 groups: 0 user: firstname.lastname@example.org 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 email@example.com group:board read-write