OpenLDAP

From Secure Computing Wiki
Jump to: navigation, search

So, at work, we've finally got enough systems and users that we're seriously considering an OpenLDAP server for authentication, as well as for our customer/client contact lists, etc. I've never before successfully rolled out an LDAP system, and I've for certain never rolled one out that does authentication for any systems.

This document aims to describe the installation of OpenLDAP 2.4.7 on a FreeBSD 6.x system. The vast majority of these steps are easily applied to Linux, Unix, and Mac OS X.

Contents

System Overview

As we're big fans of ezjail, we're going to install an LDAP system with one master server, and one slave. All of our email clients will be pointed to the slave for read operations, with that server redirecting any writes to the master server. With version 2.4.x of OpenLDAP, replication is implemented in a couple unique ways. [1] We're going to setup a system with one master and one slave, with all writes directed to the master.

To keep things simpler, I'm only going to cover setting up a single server on this page. For the replication portion, please see OpenLDAP/replication.

Installation

In our setup, we're going to have two OpenLDAP servers (one master, one slave). To begin, we install the following ports:

  • net/openldap-server24
    • enable SASL
    • other defaults should be fine

Configuration

/etc/rc.conf

Now that we have all the ports installed, edit /etc/rc.conf and add the following lines:

slapd_enable="YES"

OpenLDAP Configuration

Now that we have openldap, php5 and apache22 installed, we need to setup our slapd.conf file. The first thing to take into consideration is the function of your directory. In our installation, we're going to use it for an address book and an authentication server. As such, we're going to need the following schemas:

  • core.schema
  • cosine.schema
  • inetorgperson.schema
  • nis.schema

You can look to ldap schemas for more information about the different types.

Our configuration file (/usr/local/etc/openldap/slapd.conf) looks like this, with explanation:

## MASTER LDAP SERVER
# Specify the location of the file to append changes to.

Here, we define our included schemas, as discussed above.

# Global Section
include         /usr/local/etc/openldap/schema/core.schema
include         /usr/local/etc/openldap/schema/cosine.schema
include         /usr/local/etc/openldap/schema/inetorgperson.schema
include         /usr/local/etc/openldap/schema/nis.schema

OpenLDAP uses a bit-based method for determining log level. A value of 296 gives us good verbosity for testing and initial configuration. See the man page for more information on this value.

loglevel        296

Leave these at their default value.

pidfile         /var/run/openldap/slapd.pid
argsfile        /var/run/openldap/slapd.args

The SSHA password hash is default for OpenLDAP. We're going to use this in our setup. 3DES, DES, and MD5 are other valid options.

# Misc Security Settings
password-hash   {SSHA}

We're using the Berkely Database engine, which is defined here. You can also use SQL and others.

# Load dynamic backend modules:
modulepath      /usr/local/libexec/openldap
moduleload      back_bdb

#######################################################################
# BDB database definitions
#######################################################################

database        bdb

Here, we need to define our directory root and our rootdn.

suffix          "dc=example,dc=com"
rootdn          "cn=root,dc=example,dc=com"

For the rootpw, you have a couple options for entering your password. For our demonstration, we're entering a clear-text password. In a production setup, you should run the slappasswd command, and enter your password. Assuming the password is secret, the output from slappasswd would be similar to:

# slappasswd <enter>
New password: secret <enter>  (text is echo off)
Re-enter new password:  secret <enter> (text is echo off)
{SSHA}0H+zTv8o4MR4H43n03eCsvw1luG8LdB7

If we wanted a hashed version stored in our configuration file, we'd enter the text {SSHA}0H+zTv8o4MR4H43n03eCsvw1luG8LdB7 in place of secret below:

# Cleartext passwords, especially for the rootdn, should
# be avoid.  See slappasswd(8) and slapd.conf(5) for details.
# Use of strong authentication encouraged.
rootpw          secret

Create the directory you want your OpenLDAP directory stored in and set the permissions to 0600.

# The database directory MUST exist prior to running slapd AND 
# should only be accessible by the slapd and slap tools.
# Mode 700 recommended.
directory       /var/db/example.com
mode 0600

This section defines the fields we want to index.

# Indices to maintain
index   objectClass     eq
index   cn,sn,mail      eq,sub
index   uidNumber       eq
index   gidNumber       eq

Our configuration is going to use TLS to encrypt the data between systems. We don't want user credentials flying around our network in clear text. See our page on OpenSSL for information on creating a root CA, and the associated certificates.

TLSCipherSuite HIGH:MEDIUM:+SSLv2
TLSCACertificateFile /usr/local/etc/openldap/ca.crt
TLSCertificateFile /usr/local/etc/openldap/client.crt
TLSCertificateKeyFile /usr/local/etc/openldap/client.key

TLSVerifyClient demand

Access control lists are what defines what each authenticated or anonymous user is able to do within the directory. These should go at the end of the configuration file. Here, we have two access control lists. The first ACL states that access to the userPassword attribute, within ou=people,dc=example,dc=com is only writable by the owner, is available for authentication by anyone, and is writable by ou=admins,ou=staff,ou=people,dc=example,dc=com. The second ACL states that all fields a readable by anyone, including anonymous users.

## ACLs
#

# Restrict userPassword to be used for authentication only,
# but allow users to update their own password.
access to dn.children="ou=people,dc=example,dc=com"
 attrs=userPassword
 by self write
 by * auth
 by dn.children="ou=admin,ou=staff,ou=people,dc=example,dc=com" write

# Read access to the world.
access to *
 by * read

The completed file, without comments, looks so:

## MASTER LDAP SERVER

# Global Section
include         /usr/local/etc/openldap/schema/core.schema
include         /usr/local/etc/openldap/schema/cosine.schema
include         /usr/local/etc/openldap/schema/inetorgperson.schema
include         /usr/local/etc/openldap/schema/nis.schema

loglevel        296

pidfile         /var/run/openldap/slapd.pid
argsfile        /var/run/openldap/slapd.args

# Misc Security Settings
password-hash   {SSHA}

# Load dynamic backend modules:
modulepath      /usr/local/libexec/openldap
moduleload      back_bdb

#######################################################################
# BDB database definitions
#######################################################################

database        bdb

suffix          "dc=example,dc=com"
rootdn          "cn=root,dc=example,dc=com"

# Cleartext passwords, especially for the rootdn, should
# be avoid.  See slappasswd(8) and slapd.conf(5) for details.
# Use of strong authentication encouraged.
rootpw          secret

# The database directory MUST exist prior to running slapd AND 
# should only be accessible by the slapd and slap tools.
# Mode 700 recommended.
directory       /var/db/example.com
mode 0600

# Indices to maintain
index   objectClass     eq
index   cn,sn,mail      eq,sub
index   uidNumber       eq
index   gidNumber       eq

TLSCipherSuite HIGH:MEDIUM:+SSLv2
TLSCACertificateFile /usr/local/etc/openldap/ca.crt
TLSCertificateFile /usr/local/etc/openldap/client.crt
TLSCertificateKeyFile /usr/local/etc/openldap/client.key

TLCVerifyClient demand

## ACLs
#

# Restrict userPassword to be used for authentication only,
# but allow users to update their own password.
access to dn.children="ou=people,dc=example,dc=com"
 attrs=userPassword
 by self write
 by * auth
 by dn.children="ou=admin,ou=staff,ou=people,dc=example,dc=com" write

# Read access to the world.
access to *
 by * read

Once we've got this file saved, create the directory you referenced for the database store, set permissions to 0600 and chown to your openldap users (ldap/ldap if you installed OpenLDAP from ports). Lastly, go ahead and try to start slapd from it's rc.d script:

# /usr/local/etc/rc.d/slapd start

Check that it's running (sockstat | grep slapd is my method). If you do not see slapd listed as running, check your log files for any errors. If you've followed my directions up to this point, you should be good to go. At this point, stop slapd with the following command:

# /usr/local/etc/rc.d/slapd stop

Slapd can't be running for our initial load of the database.

Initial Database Load

Our initial database load is going to define the structure of our directory tree. The following text should be saved somewhere as initial.ldif. I'm not going to describe it in detail, as this is supposed to be a quick how-to.

Our tree is going to follow the following structure:

Example.com OpenLDAP Tree Structure
## Build the root node.
dn: dc=example,dc=com
dc: example
objectClass: dcObject
objectClass: organizationalUnit
ou: Example

## Build the people ou.
dn: ou=people,dc=example,dc=com
ou: people
objectClass: organizationalUnit

### Build the staff/people ou.
dn: ou=staff,ou=people,dc=example,dc=com
ou: staff
objectClass: organizationalUnit

#### Build the admin/staff/people ou.
dn: ou=admin,ou=staff,ou=people,dc=example,dc=com
ou: admin
objectClass: organizationalUnit

### Build the users/staff/people ou.
dn: ou=users,ou=staff,ou=people,dc=example,dc=com
ou: users
objectClass: organizationalUnit

## Build the contacts/people ou.
dn: ou=contacts,ou=people,dc=example,dc=com
ou: contacts
objectClass: organizationalUnit

## Build the group/people ou.
dn: ou=group,ou=people,dc=example,dc=com
ou: group
objectClass: organizationalUnit

## Build the services ou.
dn: ou=services,dc=example,dc=com
ou: services
objectClass: organizationalUnit

## Build the hosts ou.
dn: ou=hosts,dc=example,dc=com
ou: hosts
objectClass: organizationalUnit

As was mentioned in the last section, slapd cannot be running for this initial load. That being said, run the following command, assuming the above configuration has been named ~/initial.ldif:

# slapadd -v -l ~/initial.ldif <enter>
bdb_db_open: warning - no DB_CONFIG file found in directory /var/db/example.com: (2).
Expect poor performance for suffix "dc=example,dc=com".
added: "dc=example,dc=com" (00000001)
added: "ou=people,dc=example,dc=com" (00000002)
added: "ou=staff,ou=people,dc=example,dc=com" (00000003)
added: "ou=admin,ou=staff,ou=people,dc=example,dc=com" (00000004)
added: "ou=users,ou=staff,ou=people,dc=example,dc=com" (00000005)
added: "ou=contacts,ou=people,dc=example,dc=com" (00000006)
added: "ou=group,ou=people,dc=example,dc=com" (00000007)
added: "ou=services,dc=example,dc=com" (00000008)
added: "ou=hosts,dc=example,dc=com" (00000009)

If you got the error above that I did, you need to copy the file DB_CONFIG from /usr/local/etc/openldap/DB_CONFIG.example to the directory for your LDAP database. In our case, the following command will resolve this error:

# cp /usr/local/etc/openldap/DB_CONFIG.example /var/db/example.com/DB_CONFIG

This document doesn't discuss the purpose or use for this file. Please see OpenLDAP/DB_CONFIG for more information.

If you did the above as the root user, we need to chmod all of the files within the database directory to the ldap user. On my FreeBSD system, I would execute the following command:

# chown -R ldap:ldap /var/db/example.com

You can now start the slapd daemon:

# /usr/local/etc/rc.d/slapd start

Check your /var/log/all.log for any errors. If there aren't any errors, congratulations, you've got a running LDAP server! Now, we just need to add data. Also, from this point you should be able to log in via the phpldapadmin scripts on the web server we also configured. When asked for the username and password, use the entries you put in the slapd.conf file earlier. In our case, our user name would be cn=root,dc=example,dc=com and our password would be secret.

Adding Records

Once we have our core schema loaded, and the primary structure of our directory, we can add entries via a couple methods. While I'll briefly discuss adding LDAP entries via the phpldapadmin interface, my concentration is going to be with manual adds with text LDIF files.

Manual Adds

Manually adding an entry to your OpenLDAP directory is done by first creating an LDIF file with the entry data. Our example database has two purposes on our network.

  1. Server Authentication
  2. Company Address Book

LDIF File

First, we'll add an entry for the address book. I created a file called user.ldif containing the following information:

## Test ldif for ecrist user
dn: cn=Eric F Crist,ou=admin,ou=staff,ou=people,dc=example,dc=com
cn: Eric F Crist
sn: Crist
mail: ecrist@foobeans.com
mail: ecrist@secure-computing.net
labeledURI: http://www.secure-computing.net
departmentNumber: IT
telephoneNumber: (411) 555-1212
mobile: (411) 555-0411
objectClass: inetOrgPerson

As you'll note, the format closely follows that of our initial database import. Also, you'll note that we can have more than one mail, phone, etc. Again, specific discussion of the various schema is beyond the scope of this document. You can have more than one entry per file, simply separate the two with an empty line.

Import

Since we started our LDAP server earlier, we're going to use the ldapadd program to add this entry to our database. Assuming your file name is user.ldif, as mine is above, running the following command should import your new entries into your database:

# ldapadd -D "cn=root,dc=example,dc=com" -w <password> -x -a -f user.ldif
adding new entry "cn=Eric F Crist,ou=admin,ou=staff,ou=people,dc=example,dc=com"

#

Related Topics

References

Personal tools
Namespaces

Variants
Actions
Miscellaneous
Operating Systems
Toolbox