In part 1 we’ve looked at how to install 389 Directory Server and create an instance. While this left us with a fully working LDAP server there are some plugins that greatly increase quality of life and might even be considered essential.
3.1. Attribute Uniqueness
Certain attributes can have duplicate values within a directory. A simple example is a user’s first name which is stored in the
givenName attribute. In a directory with a sufficiently large number of users it’s more likely than not that there are two or more users with the same first name.
But how about a user’s email address? If the
The 389 directory server has a built-in plugin that can guarantee the uniqueness of attributes across the entire directory information tree (DIT) or even just certain subtrees. It can be conveniently configured and enabled through
Let’s say we wanted to guarantee that email addresses are unique across our whole
dc=example,dc=com tree, we would run:
dsconf localhost plugin attr-uniq add "mail attribute uniqueness" --attr-name mail --subtree "dc=example,dc=com" dsconf localhost plugin attr-uniq enable "mail attribute uniqueness"
Other very commonly unique attributes are a user’s ID (
uid), uid number (the integer uniquely identifying a user,
uidNumber) and gid number (the integer uniquely identifying a user’s primary group,
gidNumber). This is not a exhaustive list, of course, and which attributes are unique in a directory may very well depend on the use case. But together with the
dsconf localhost plugin attr-uniq add "mail attribute uniqueness" --attr-name mail --subtree "dc=example,dc=com" dsconf localhost plugin attr-uniq add "uid attribute uniqueness" --attr-name uid --subtree "dc=example,dc=com" dsconf localhost plugin attr-uniq add "uidNumber attribute uniqueness" --attr-name uidNumber --subtree "dc=example,dc=com" dsconf localhost plugin attr-uniq add "gidNumber attribute uniqueness" --attr-name gidNumber --subtree "dc=example,dc=com" dsconf localhost plugin attr-uniq enable "mail attribute uniqueness" dsconf localhost plugin attr-uniq enable "uid attribute uniqueness" dsconf localhost plugin attr-uniq enable "uidNumber attribute uniqueness" dsconf localhost plugin attr-uniq enable "gidNumber attribute uniqueness"
attr-uniq plugin can also ensure uniqueness of values across multiple attributes. That’s called Multi Valued Uniqueness and is done by specifying multiple attribute names:
dsconf localhost plugin attr-uniq add "mail attribute uniqueness" --attr-name mail --attr-name mailAlternateAddress --subtree "dc=example,dc=com"
Note that the 389ds instance has to be restarted in order for the plugin to work (even though it was enabled through
dsctl localhost restart
3.2. Distributed Numeric Assignment
Similarly to manually checking for certain attributes to be unique it’s cumbersome to manually assign and manage
gidNumber attributes. Fortunately this can be automatically handled by the Distributed Numeric Assignment (DNA) plugin.
The plugin settings can be configured through
dsconf localhost plugin dna config "Account IDs" add \ --type gidNumber uidNumber \ --filter "(objectclass=posixAccount)" \ --scope ou=People,dc=example,dc=com \ --next-value 1001 \ --magic-regen -1
The parameters should be quite self-explanatory. Here’s a quick overview anyway:
--type gidNumber uidNumber
the DNA plugin should manage the attributes
uidNumber(from the same range)
it should be limited to
only objects in the specified subtree should be managed
the next value that’s going to be assigned
magic number to tell the DNA plugin that an object’s
uidNumbershould be automatically assigned
After enabling the plugin and restarting the 389ds instance
dsconf localhost plugin dna enable dsctl localhost restart
the DNA plugin will automatically reassign
gidNumber attributes if they’re
# dsidm -b "dc=example,dc=com" localhost user create \ --uid eve \ --cn Eve \ --displayName Eve \ --homeDirectory "/home/eve" \ --uidNumber -1 \ --gidNumber -1 Successfully created eve # ldapsearch -LLL -x -b "dc=example,dc=com" "(uid=eve)" uidNumber gidNumber dn: uid=eve,ou=people,dc=example,dc=com uidNumber: 1001 gidNumber: 1001
You can, however, still specify
gidNumber attributes manually by using a value that’s different from the configured magic number (
-1 in the example above). The magic number itself is arbitrary and doesn’t need to be
-1 at all.
For more details on the DNA plugin have a look at the Redhat Directory Server 11 (RHDS11) Administration Guide or the 389ds documentation, especially when using it in setups that use replication.
There are two ways how group membership of users can be stored. One can either save a list of members in each group object. That’s how it is done traditionally and is described in RFC2307:
Or one can store each group that a given user is a member of in the user object (RFC2307bis):
Querying an LDAP server that uses RFC2307 (sometimes also referred to as posix schema) if a certain user is authorised to access a particular resource is a two-step process: The first query searches for the user object (e.g. a user named Bob) and the second query checks if the user object’s
uid attribute matches one of the entries in the relevant group object (e.g. if the group blog_users has an attribute
memberUID that matches Bob’s uid).
A lot of software supports this, e.g. have a look at Grafana’s LDAP auth module. It has a
search_filter parameter that let’s you query for a particular user and an additional
group_search_filter parameter that filters out users that are not a member of a particular group.
However, that’s not always the case, e.g. postfix or dovecot do not have an additional group filter. The advantage of the RFC2307bis schema is (among other things) that checking user authorisation can be done in a single query, for example:
ldapsearch -LLL -x -b "dc=example,dc=com" \ "(&(uid=eve)(memberOf=cn=cncuser,ou=groups,dc=example,dc=com))" mail dn: uid=eve,ou=people,dc=example,dc=com mail: email@example.com
389ds uses a combination of these two schemas so it stays compatible with both. The memberOf plugin can automatically update a user object’s
memberOf attributes whenever the group membership status is changed. Once again it can be enabled through
dsconf localhost plugin memberof enable dsctl localhost restart
Note that additonally group members will still be listed as multi-valued attributes in the group object (according to the RFC2307 schema). So you can decide depending on the user case wether to use the
memberOf filter or two queries to check if a user is authorised to access your resource.
3.4. Referential Integrity
In general, referential integrity is a property of arbitrary data structures (e.g. an object in OOP, a table in a relational database) meaning that all references to other data structures are vaild. In the context of a directory server it means that an update on one entry in the DIT is correctly reflected in all other entries that reference it.
This is most commonly an issue when removing a user or a group. When a user that’s a member of any group is removed, all corresponding
member attributes of the groups need to be updated as well. Managing this manually would be a nightmare, of course, so thankfully there’s a referential integrity plugin available that takes care of this:
dsconf localhost plugin referential-integrity enable dsctl localhost restart