Basic Configuration of OpenLDAP

After getting a basic understanding of OpenLDAP (perhaps using my other article The Basics of OpenLDAP) and LDAP systems in general, we can spend a few minutes analyzing OpenLDAP configuration and modification, at a very high level. The previous article shows where the configuration is stored, but it is all accessible and modifiable via the ldapsearch command as well, and that’s what we’ll be using for this article.

Using the EXTERNAL SASL mechanism

Using ldapsearch with the -Y and -H options allows us to use EXTERNAL as the SASL authentication mechanism. You need to use this to make configuration changes to the slapd configuration as the root user. You can use sudo to do this, or $ sudo su - to get an administrator shell. One of the reasons that you should do all of your testing on a virtual machine is that you can easily get sudo access to the box, and this tutorial is going to require it. Describing these mechanisms in detail is beyond the scope of the current article, but what you really need to understand is that using this mechanism is by default the only way that you can do modifications with the default install of OpenLDAP that I am playing with, and it is very reasonable.

With the super user prompt, we can view all of the configuration options using the following command:

$ ldapsearch -Y EXTERNAL -H ldapi:/// -b cn=config
# extended LDIF
#
# LDAPv3
# base  with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#

# config
dn: cn=config
objectClass: olcGlobal
cn: config
olcArgsFile: /var/run/slapd/slapd.args
olcLogLevel: none
olcPidFile: /var/run/slapd/slapd.pid
olcToolThreads: 1

# module{0}, config
dn: cn=module{0},cn=config
objectClass: olcModuleList
cn: module{0}
olcModulePath: /usr/lib/ldap
olcModuleLoad: {0}back_hdb

# schema, config
dn: cn=schema,cn=config
objectClass: olcSchemaConfig
cn: schema
...

And a bunch more, obviously. All of the files that I mentioned in the previous article under the directory /etc/ldap/slapd.d/ will have their contents listed here, and any modifications and additions to configuration will be added to that directory as well. This is wisely protected and can only be viewed as the root user from the ldap server by default, and I would strongly recommend that you keep it that way. The segment that makes it work this way is the following:

dn: olcDatabase={0}config,cn=config
objectClass: olcDatabaseConfig
olcDatabase: {0}config
olcAccess: {0}to * by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external
 ,cn=auth manage by * break

Note the olcAccess. It basically says that a user with the group id and user id of 0 (root), matched using EXTERNAL SASL on localhost (peercred, see Unix Domain Socket on Wikipedia, and the article On Peercred for some more information). You could expand this permission without giving a user root access by adding a new olcAccess line to this entry with the gidNumber and uidNumber of another user. For instance, my user, ‘psalcido’, on the box has the uid/gid of 1000/1000 (/etc/passwd). I’m going to give my local user access via an ldapmodify command as root, and test that access. First, I copy out the data from the entry into a file for modification:

# ldapsearch -Y EXTERNAL -H ldapi:/// \
   -b cn=config "(olcDatabase={0}config)" -LLL \
   > /tmp/ldap_database_config.ldif

Using my preferred editor, I modified the resulting file with the changetype and new olcAccess line:

dn: olcDatabase={0}config,cn=config
changetype: modify
add: olcAccess
olcAccess: {1}to * by dn.exact=gidNumber=1000+uidNumber=1000,cn=peercred,cn=external,cn=auth manage by * break

A rather key aside here, I went ahead and paused my virtual machine and took a snapshot before I ran this so that if I broke anything, I could revert to what everything was before I started pushing these modifications. This could save you a lot of time and effort and testing. Now I need to run the file using ldapmodify against the configuration database with the following command:

# ldapmodify -r -Y EXTERNAL -H ldapi:/// -f /tmp/ldap_database_config.ldif

Now run the ldapsearch command again for the database configuration:

# ldapsearch -Y EXTERNAL -H ldapi:/// \ -b cn=config "(olcDatabase={0}config)" -LLL
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
dn: olcDatabase={0}config,cn=config
objectClass: olcDatabaseConfig
olcDatabase: {0}config
olcAccess: {0}to * by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external
 ,cn=auth manage by * break
olcAccess: {1}to * by dn.exact=gidNumber=1000+uidNumber=1000,cn=peercred,cn=ex
 ternal,cn=auth manage by * break

And now I test it as the user psalcido to demonstrate that the changes worked:

psalcido$ ldapsearch -Y EXTERNAL -H ldapi:/// \
>    -b cn=config "(olcDatabase={0}config)" -LLL
...

And all of the output that I expect is produced. Now I can manage the databases as the user psalcido rather than the user root. If you want to avoid giving sudo access to new users, this is an excellent option.

Adding a new database

Creating a new database should also be relatively simple, but will require some system administration as well as some application level administration in openldap. The first new database that I’ll create will use HDB again, for simplicity, and it will have a new base and administrative user. It will need a new directory to store the HDB files that will be used for storage. The easiest way to do this is to make a copy of the current database configuration and run some modifications. we get a new ldif file with the following command:

$ ldapsearch -Y EXTERNAL -H ldapi:/// \
   -b cn=config -LLL "(olcDatabase={1}hdb)" \
   > /tmp/new_database.ldif

Now we need to modify this file into the following:

# New DN for this object, {2}hdb, is set.
dn: olcDatabase={2}hdb,cn=config
# This is an hdb database configuration.
objectClass: olcDatabaseConfig
objectClass: olcHdbConfig
# The database is again, {2}hdb, not {1} hdb as before.
olcDatabase: {2}hdb
# Changed the directory to a new database directory.
olcDbDirectory: /var/lib/ldap-newdb/
# changed the base dcObject from home to newdb.
olcSuffix: dc=newdb,dc=paulsalcido,dc=local
# Once again, home to newdb for the admin user.
olcAccess: {0}to attrs=userPassword,shadowLastChange by self write by anonymous auth by dn="cn=admin,dc=newdb,dc=paulsalcido,dc=local" write by * none
olcAccess: {1}to dn.base="" by * read
# Once again, home to newdb for the admin user.
olcAccess: {2}to * by self write by dn="cn=admin,dc=newdb,dc=paulsalcido,dc=local" write by * read
olcLastMod: TRUE
olcRootDN: cn=admin,dc=newdb,dc=paulsalcido,dc=local
# You can create a new password with slappass if you need to.  This is same.
olcRootPW: # Put a password here!
olcDbCheckpoint: 512 30
olcDbConfig: {0}set_cachesize 0 2097152 0
olcDbConfig: {1}set_lk_max_objects 1500
olcDbConfig: {2}set_lk_max_locks 1500
olcDbConfig: {3}set_lk_max_lockers 1500
olcDbIndex: objectClass eq

If you try to run this now, you will get an error:

$ ldapadd -r -Y EXTERNAL -H ldapi:/// -f /tmp/new_database.ldif
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
adding new entry "olcDatabase={2}hdb,cn=config"
ldap_add: Other (e.g., implementation specific) error (80)
        additional info: olcDbDirectory: value #0: invalid path: No such file or directory

This is because the directory /var/lib/ldap-newdb/ does not exist. We can create it with:

$ sudo mkdir /var/lib/ldap-newdb/
$ sudo chown openldap:openldap /var/lib/ldap-newdb/

There is a distinct possibility that if you try to run this now, you will get the following error:

# ldapadd -r -Y EXTERNAL -H ldapi:/// -f /tmp/new_database.ldif
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
adding new entry "olcDatabase={2}hdb,cn=config"
ldap_add: Other (e.g., implementation specific) error (80)
        additional info: olcDbDirectory: value #0: invalid path: Permission denied

This is actually an ‘apparmor’ issue. App Armor is a Linux application that limits the access from certain applications to certain directories. In this case, we need to expand the permissions, which I will do without too much description, but perhaps with some luck I’ll come back to later. Modify the file /etc/apparmor.d/usr.sbin.slapd with the following lines (I list the three lines before so that context is included:


  # the databases and logs
  /var/lib/ldap/ r,
  /var/lib/ldap/** rwk,

  # The new database location
  /var/lib/ldap-newdb/ r,
  /var/lib/ldap-newdb/** rwk,

Run sudo service apparmor reload and try to run the file again:

root@redmine-automation:/etc/apparmor.d# ldapadd -r -Y EXTERNAL -H ldapi:/// -f /tmp/new_database.ldif
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
adding new entry "olcDatabase={2}hdb,cn=config"

And your new database should be connected. You could start by searching the new database for values, but unlike the default one, this one is completely empty. By entering a new top level dcObject/organization, it should be possible to demonstrate it’s use. I create a new file /tmp/newbase.ldif:

dn: dc=newdb,dc=paulsalcido,dc=local
objectClass: top
objectClass: dcObject
objectClass: organization
o: Paul Salcido New Database Org
dc: newdb

And I use ldapadd to add the new entry to the database:

$ ldapadd -D "cn=admin,dc=newdb,dc=paulsalcido,dc=local" \
  -W -f /tmp/newbase.ldif

Now the database should be able to be populated with additional objects. Test the new object using the search:

$ ldapsearch -D "" -b "dc=newdb,dc=paulsalcido,dc=local"

Adding new schemas to the Database

Sometimes the default four schemas are not enough, and you need to either add new schemas or create your own, applying new schemas to the database can be a huge benefit. This final section will describe adding new schemas. With our current knowledge, this should actually be relatively easy, as all you’ll need to do is run a file against the cn=config database using a peercred user that has access to the database (in my case, root or user 1000 on the local machine: psalcido). We can find the installed schemas using the command:

$ ldapsearch -Y EXTERNAL -H ldapi:/// -b "cn=config" \
  "objectClass=olcSchemaConfig" dn cn
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
# extended LDIF
#
# LDAPv3
# base  with scope subtree
# filter: objectClass=olcSchemaConfig
# requesting: dn cn 
#

# schema, config
dn: cn=schema,cn=config
cn: schema

# {0}core, schema, config
dn: cn={0}core,cn=schema,cn=config
cn: {0}core

# {1}cosine, schema, config
dn: cn={1}cosine,cn=schema,cn=config
cn: {1}cosine

# {2}nis, schema, config
dn: cn={2}nis,cn=schema,cn=config
cn: {2}nis

# {3}inetorgperson, schema, config
dn: cn={3}inetorgperson,cn=schema,cn=config
cn: {3}inetorgperson

# search result
search: 2
result: 0 Success

# numResponses: 6
# numEntries: 5

We will apply the misc schema available under /etc/ldap/schema/. This can be done with the following command:

$ ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/ldap/schema/misc.ldif

And now the configuration addition is complete. You can also convert schema files (misc.schema) into ldif files using the slapcat command, but that is beyond the scope of this tutorial. For more on schemas and what they do, please see the first blog post The Basics of OpenLDAP, which covers a few things about them.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: