Managing an OpenLDAP system can be difficult if you do not know how to configure your system or where to find the important information you need. In this guide, we’ll demonstrate how to query your OpenLDAP server for crucial information and how to make changes to your running system.
To get started, you should have access to a system with OpenLDAP installed and configured. You can learn how to set up an OpenLDAP server here. You should be familiar with the basic terminology used when working with an LDAP directory service. This guide can be used to get more familiar with these topics.
LDAP systems organize the data they store into hierarchical structures called Directory Information Trees or DITs for short. Starting with version 2.3, the actual configuration for OpenLDAP servers is managed within a special DIT, typically rooted at an entry called cn=config
.
This configuration system is known as OpenLDAP online configuration, or OLC. Unlike the deprecated configuration method, which relied on reading configuration files when the service starts, modifications made to the OLC are immediately implemented and often do not require the service to be restarted.
The OLC system uses standard LDAP methods to authenticate and make modifications. Because of this, management for seasoned LDAP administrators is often seamless, as they can use the same knowledge, skills, and tools that they use to operate the data DITs. However, for those new to LDAP, it can be difficult to get started since you may need to know how to use LDAP tools in order to configure an environment for learning.
This guide will focus on teaching you basic OpenLDAP administration to get past this chicken-and-egg situation so that you can begin learning LDAP and managing your systems.
We will start by talking about a construct called the root DSE, which is the structure that holds all our server’s individual DITs. This is basically an entry used for managing all of the DITs that the server knows about. By starting at this entry, we can query the server to see how it is organized and to find out where to go next.
What Does DSE Stand For?
DSE stands for “DSA specific entry”, which is a management or control entry in an LDAP server. DSA stands for “directory system agent”, which basically means a directory server that implements the LDAP protocol.
To query the root DSE, we must perform a search with a blank (null) search base and with a search scope of “base”. The base search scope means that only the entry given will be returned. Typically, this is used to limit the depth of the search, but when operating on the root DSE, this is required (no information will be returned if any other search scope is selected).
The command we need is this:
- ldapsearch -H ldap:// -x -s base -b "" -LLL "+"
We assume that you’re performing this from the LDAP server itself and that you haven’t set up any access restrictions yet. The results should look similar to this:
dn:
structuralObjectClass: OpenLDAProotDSE
configContext: cn=config
namingContexts: dc=example,dc=com
supportedControl: 2.16.840.1.113730.3.4.18
. . .
supportedLDAPVersion: 3
supportedSASLMechanisms: GS2-IAKERB
supportedSASLMechanisms: GS2-KRB5
supportedSASLMechanisms: SCRAM-SHA-1
supportedSASLMechanisms: GSSAPI
supportedSASLMechanisms: DIGEST-MD5
supportedSASLMechanisms: NTLM
supportedSASLMechanisms: CRAM-MD5
entryDN:
subschemaSubentry: cn=Subschema
We’ve truncated the output a bit. You can see the important meta-data about this LDAP server. We’ll cover what some of these items mean in a bit. For now, we’ll take a look at the command that generated this output.
The -H ldap://
command is used to specify an unencrypted LDAP query on the localhost. The -x
without any authentication information lets the server know you want an anonymous connection. We tell it the search scope and set the search base to null with -s base -b ""
. We suppress some extraneous output with -LLL
. Finally, the "+"
specifies that we want to see the operational attributes that would normally be hidden (this is where we’ll find the information we need).
For our purposes now, we are trying to find out what DITs this particular LDAP server is configured to serve. We can find that as the value of the namingContexts
operational attribute that we can see in the output above.
If this was the only piece of information we wanted, we could construct a better query that would look like this:
- ldapsearch -H ldap:// -x -s base -b "" -LLL "namingContexts"
Here, we’ve called out the exact attribute that we want to know the value of. The base entry of each DIT on the server is available through the namingContexts
attribute. This is an operational attribute that would normally be hidden, but calling it out explicitly allows it to be returned.
This will suppress the other information, giving us clean output that looks like this:
dn:
namingContexts: dc=example,dc=com
We can see that this LDAP server has only one (non-management) DIT which is rooted at an entry with a distinguished name (DN) of dc=example,dc=com
. It’s possible that this would return multiple values if the server is responsible for additional DITs.
The DIT that can be used to configure the OpenLDAP server is not returned by a search for namingContexts
. The root entry of the config DIT is instead stored in a dedicated attribute called configContext
.
To learn the base DN for the configuration DIT, you query this specific attribute, just as we did before:
- ldapsearch -H ldap:// -x -s base -b "" -LLL "configContext"
The result will likely be this:
dn:
configContext: cn=config
The configuration DIT is based at a DN called cn=config
. Since it is likely that this matches your configuration DIT exactly, we’ll use this throughout the guide. Modify the given commands if your configuration DIT is different.
Now that we know the location of the configuration DIT, we can query it to see the current settings. To do this, we actually need to diverge a bit from the format we’ve been using up to this point.
Since this DIT can be used to change the settings of our LDAP system, it has some access controls in place. It is configured, by default, to allow administration for root or sudo
users of the OS.
The command we need looks like this:
- sudo ldapsearch -H ldapi:// -Y EXTERNAL -b "cn=config" -LLL -Q
To make this work, you need to use sudo
before the command and replace the -x
in our previous ldapsearch
commands with -Y EXTERNAL
to indicate that we want to use a SASL authentication method. You also need to change the protocol from ldap://
to ldapi://
to make the request over a Unix socket. This allows OpenLDAP to verify the operating system user, which it needs to evaluate the access control properties. We then use the cn=config
entry as the basis of our search.
The result will be a long list of settings. It may be helpful to pipe it into a pager so that you can easily scroll up and down:
- sudo ldapsearch -H ldapi:// -Y EXTERNAL -b "cn=config" -LLL -Q | less
You can see that there is quite a lot of information, which can be a lot to process. This command printed off the entire configuration tree. To get a better idea of the hierarchy in which the information is organized and stored, let’s just print out the various entry DNs instead:
- sudo ldapsearch -H ldapi:// -Y EXTERNAL -b "cn=config" -LLL -Q dn
This will be a much more manageable list, showing the entry titles (DNs) themselves instead of their entire content:
dn: cn=config
dn: cn=module{0},cn=config
dn: cn=schema,cn=config
dn: cn={0}core,cn=schema,cn=config
dn: cn={1}cosine,cn=schema,cn=config
dn: cn={2}nis,cn=schema,cn=config
dn: cn={3}inetorgperson,cn=schema,cn=config
dn: olcBackend={0}hdb,cn=config
dn: olcDatabase={-1}frontend,cn=config
dn: olcDatabase={0}config,cn=config
dn: olcDatabase={1}hdb,cn=config
These entries represent the configuration hierarchy where different areas of the LDAP system are configured. Let’s take a look at what settings are handled by each of these entries:
The top-level entry contains some global settings that will apply to the entire system (unless overridden in a more specific context). You can see what is stored in this entry by typing:
- sudo ldapsearch -H ldapi:// -Y EXTERNAL -b "cn=config" -LLL -Q -s base
Common items in this section are global authorization settings, log level verbosity settings, a pointer to the process’s PID file location, and information about SASL authentication.
The entries beneath this configure more specific areas of the system. Let’s take a look at the different types of entries you are likely to see.
Now that you have access to the cn=config
DIT, we can find the rootDNs of all of the DITs on the system. A rootDN is basically the administrative entry. We can also find the password (usually hashed) that can be used to log into that account.
To find the rootDN for each of your DITs, type:
- sudo ldapsearch -H ldapi:// -Y EXTERNAL -b "cn=config" "(olcRootDN=*)" olcSuffix olcRootDN olcRootPW -LLL -Q
You will get a printout that looks something like this:
dn: olcDatabase={1}hdb,cn=config
olcSuffix: dc=example,dc=com
olcRootDN: cn=admin,dc=example,dc=com
olcRootPW: {SSHA}AOADkATWBqb0SJVbGhcIAYF+ePzQJmW+
If your system serves multiple DITs, you should see one block for each of them. Here, we can see that our admin entry is cn=admin,dc=example,dc=com
for the DIT based at dc=example,dc=com
. We can also see hashed password.
LDAP schemas define the objectClasses and attributes available to the system. Schemas can be added to the system during runtime to make different object types and attributes available. However, certain properties are built-in to the system itself.
The built-in schema can be found in the cn=schema,cn=config
entry. You can see the schema that is built-in to the LDAP system by typing:
- sudo ldapsearch -H ldapi:// -Y EXTERNAL -b "cn=schema,cn=config" -s base -LLL -Q | less
This will show you the schema that is included in the OpenLDAP system itself. Unlike every other schema, this does not need to be added to the system to be used.
The built-in schema provides a nice jumping off point but it likely won’t have everything you want to use in your entries. You can add additional schema to your system through conventional LDIF methods. These will be available as sub-entries beneath the cn=schema
entry that represents the built-in schema.
Usually, these will be named with a bracketed number followed by the schema name like cn={0}core,cn=schema,cn=config
. The bracketed number represents an index used to determine the order that the schema are read into the system. This is typically done automatically by the system when they are added.
To see just the names of the additional schema loaded onto the system, you can type:
- sudo ldapsearch -H ldapi:// -Y EXTERNAL -b "cn=schema,cn=config" -s one -Q -LLL dn
The output will show the names of the sub-entries. It may look something like this, depending on what’s been loaded onto the system:
dn: cn={0}core,cn=schema,cn=config
dn: cn={1}cosine,cn=schema,cn=config
dn: cn={2}nis,cn=schema,cn=config
dn: cn={3}inetorgperson,cn=schema,cn=config
The schema themselves and the index number assigned may vary. You can see the contents of a specific schema by doing a base search and listing the specific schema you are interested in. For instance, if we wanted to see the cn={3}inetorgperson
schema listed above, we could type:
- sudo ldapsearch -H ldapi:// -Y EXTERNAL -b "cn={3}inetorgperson,cn=schema,cn=config" -s base -LLL -Q | less
If you want to print all of the additional schema, instead type:
- sudo ldapsearch -H ldapi:// -Y EXTERNAL -b "cn=schema,cn=config" -s one -LLL -Q | less
If you want to print out all of the schema, including the built-in schema, use this instead:
- sudo ldapsearch -H ldapi:// -Y EXTERNAL -b "cn=schema,cn=config" -LLL -Q | less
Some other areas of interest in the configuration DIT are modules and the various storage technology settings.
Modules are used to extend the functionality of the OpenLDAP system. These entries are used to point to and load modules in order to use their functionality. The actual configuration is done through other entries.
Entries used to load modules will start with cn=module{#}
where the bracket contains a number in order to order the loading of modules and to differentiate between the various entries.
You can see the modules that are dynamically loaded on the system by typing:
- sudo ldapsearch -H ldapi:// -Y EXTERNAL -b "cn=config" -LLL -Q "objectClass=olcModuleList"
You will see the modules that are currently loaded into the system:
dn: cn=module{0},cn=config
objectClass: olcModuleList
cn: module{0}
olcModulePath: /usr/lib/ldap
olcModuleLoad: {0}back_hdb
This particular example only has a single module which allows us to use the hdb
backend module.
Backend entries are used to specify the storage technology that will actually handle the data storage.
To see which backends are active for your system, type:
- sudo ldapsearch -H ldapi:// -Y EXTERNAL -b "cn=config" -LLL -Q "objectClass=olcBackendConfig"
The result will give you an idea of the storage technology in use. It may look something like this:
dn: olcBackend={0}hdb,cn=config
objectClass: olcBackendConfig
olcBackend: {0}hdb
The actual configuration of these storage systems is done in separate database entries. There should be a database entry for each of the DITs that an OpenLDAP system serves. The attributes available will depend on the backend used for each of the databases.
To see all of the names of database entries on the system, type:
- sudo ldapsearch -H ldapi:// -Y EXTERNAL -b "cn=config" -LLL -Q "olcDatabase=*" dn
You should see the DNs of the database entries:
dn: olcDatabase={-1}frontend,cn=config
dn: olcDatabase={0}config,cn=config
dn: olcDatabase={1}hdb,cn=config
Let’s discuss a bit about what each of these is used for:
olcDatabase={-1}frontend,cn=config
: This entry is used to define the features of the special “frontend” database. This is a pseudo-database used to define global settings that should apply to all other databases (unless overridden).olcDatabase={0}config,cn=config
: This entry is used to define the settings for the cn=config
database that we are now using. Most of the time, this will be mainly access control settings, replication configuration, etc.olcDatabase={1}hdb,cn=config
: This entry defines the settings for a database of the type specified (hdb
in this case). These will typically define access controls, details of how the data will be stored, cached, and buffered, and the root entry and administrative details of the DIT.The numbers in brackets represent an index value. They are mainly created automatically by the system. You will have to substitute the value given to the entry in order to reference it successfully.
You can see the contents of any of these entries by typing:
- sudo ldapsearch -H ldapi:// -Y EXTERNAL -b "entry_to_view" -LLL -Q -s base | less
Use the entry DNs returned from the previous command to populate the entry_to_view
field.
So far, we’ve been working mainly with the cn=config
DIT. The rest of this guide will be applicable to regular DITs as well.
Each entry has operational attributes that act as administrative metadata. These can be accessed in any DIT in order to find out important information about the entry.
To print out all of the operational attributes for an entry, you can specify the special “+” attribute after the entry. For instance, to print out the operational attributes of an entry at dc=example,dc=com
, we could type:
- ldapsearch -H ldap:// -x -s base -b "dc=example,dc=com" -LLL "+"
This will print off all of the operational attributes. It will likely look something like this:
[list operational attributes]
dn: dc=example,dc=com
structuralObjectClass: organization
entryUUID: cdc658a2-8c3c-1034-8645-e30b83a2e38d
creatorsName: cn=admin,dc=example,dc=com
createTimestamp: 20150511151904Z
entryCSN: 20150511151904.220840Z#000000#000#000000
modifiersName: cn=admin,dc=example,dc=com
modifyTimestamp: 20150511151904Z
entryDN: dc=example,dc=com
subschemaSubentry: cn=Subschema
hasSubordinates: TRUE
This can be useful for seeing who modified or created an entry at what time, among other things.
The subschema is a representation of the available classes and attributes. It shows similar information to the schema entries in the cn=config
DIT, with some additional information. This is available through regular, non-configuration DITs, so root access is not required.
To find the subschema for an entry, you can query all of the operational attributes of an entry, as we did above, or you can ask for the specific attribute that defines the subschema for the entry (subschemaSubentry
):
- ldapsearch -H ldap:// -x -s base -b "dc=example,dc=com" -LLL subschemaSubentry
This will print out the subschema entry that is associated with the current entry:
[list subchema entry]
dn: dc=chilidonuts,dc=tk
subschemaSubentry: cn=Subschema
It is common for every entry within a tree to share the same subschema, so you usually will not have to query this for each entry.
To view the contents of the subschema entry, we need to query the subschema entry we found above with a scope of “base”. All of the important information is stored in operational attributes, so we will have to use the special “+” selector again.
The command we need is:
- ldapsearch -H ldap:// -x -s base -b "<^>cn=subschema" -LLL "+" | less
This will print out the entirety of the subschema entry. We can filter based on the type of information we are looking for.
If you want to see the LDAP syntax definitions, you can filter by typing:
- ldapsearch -H ldap:// -x -s base -b "cn=subschema" -LLL ldapSyntaxes | less
If you want to view the definitions that control how searches are processed to match entries, type:
- ldapsearch -H ldap:// -x -s base -b "cn=subschema" -LLL matchingRules | less
To see which items the matching rules can be used to match, type:
- ldapsearch -H ldap:// -x -s base -b "cn=subschema" -LLL matchingRuleUse | less
To view the definitions for the available attribute types, use:
- ldapsearch -H ldap:// -x -s base -b "cn=subschema" -LLL attributeTypes | less
To view the objectClass definitions, type:
- ldapsearch -H ldap:// -x -s base -b "cn=subschema" -LLL objectClasses | less
While operating an OpenLDAP server can seem tricky at first, getting to know the configuration DIT and how to find metadata within the system can help you hit the ground running. Modifying the cn=config
DIT with LDIF files can immediately affect the running system. Also, configuring the system via a DIT allows you to potentially set up remote administration using only LDAP tools. This means that you can separate LDAP administration from server administration.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
There’s a typo in command example under “Displaying the subschema” section: -b “<^>cn=subschema”. The “< ^ >” is clearly a command character that shouldn’t be there.
Amazing article, it really helps to understand the basics of the “new” LDAP configuration/administration.
Following this guide allowed me to perform a better understanding and management of the current ldap servers at my company.
This comment has been deleted
While operating an OpenLDAP server can seem tricky at first… Indeed! I’ve been around linux and open source for 20 years. This tutorial just ended days of frustration for me, so many, many thanks!
I am trying to implement OpenLDAP on RH6 for a client. The RH packaged configuration LDIF files say
# AUTO-GENERATED FILE - DO NOT EDIT!! Use ldapmodify.
Every other tutorial I found talks about modifying the files directly, but I wanted to figure out how to do it withldapmodify
. This tutorial solved it for me.