7.2. Setting Up the ServerIf you're like me, you're a lot less interested in LDAP theory than you are in LDAP practice, so let's go ahead and install OpenLDAPwe'll go further with LDAP database design in a minute. (And if you aren't like me, then good for you! But you'll still have to skip ahead a few pages if you want more LDAP theory right this instant.) 7.2.1. Getting and Installing OpenLDAPBeing such a useful and important thing, OpenLDAP is included in most major Linux distributions. Generally, it's split across multiple packages: server daemons in one package, client commands/programs in another, development libraries in still another, etc. You're building an LDAP server, so naturally you'll want to install your distribution's OpenLDAP server package, plus OpenLDAP runtime libraries if they aren't included in the server package.You might be tempted to forego installing the OpenLDAP client commands on your server if there will be no local user accounts on it (i.e., if you expect all LDAP transactions to occur over the network, not locally). However, these client commands are useful for testing and troubleshooting, so I strongly recommend you install them.The specific packages that make up OpenLDAP in Fedora and Red Hat are openldap (OpenLDAP libraries, configuration files, and documentation); openldap-clients (OpenLDAP client software/commands); openldap-servers (OpenLDAP server programs); and openldap-devel (headers and libraries for developers). Although these packages have a number of fairly mundane dependencies (e.g., glibc), there are two required packages in particular that you may not already have installed: cyrus-sasl and cyrus-sasl-md5, which help broker authentication transactions with OpenLDAP.In SUSE, OpenLDAP is provided via the RPMs openldap2-client; openldap2 (which includes both the OpenLDAP libraries and server daemons); and openldap2-devel. As with Red Hat, you'll need to be sure to also install the package cyrus-sasl, located in SUSE's sec1 directory.Note that earlier SUSE distributions (e.g., SUSE 8.0) provided packages for OpenLDAP Versions 1.2 and 2.0. If your version gives you the choice, be sure to install the newer 2.0 packages listed in the previous paragraph (e.g., openldap2 rather than openldap), unless you have a specific reason to run OpenLDAP 1.2.For Debian 3.0 ("Woody"), the equivalent deb packages are libldap2 (OpenLDAP libraries, in Debian's libs directory); slapd (the OpenLDAP server package, found in the net directory); and ldap-utils (OpenLDAP client commands, also found in the net directory). You'll also need libsasl7, from the Debian libs directory.If your distribution of choice doesn't have binary packages for OpenLDAP, if there's a specific feature of the very latest version of OpenLDAP that is lacking in your distribution's OpenLDAP packages, or if you need to customize OpenLDAP at the binary level, you can always compile it yourself from source you've downloaded from the official OpenLDAP web site at http://www.openldap.org. 7.2.2. Configuring and Starting slapdThe main server daemon in OpenLDAP is called slapd, and configuring this program is the first step in getting OpenLDAP working once it's been installed. Its configuration is determined primarily by the file /etc/openldap/slapd.conf.The "OpenLDAP 2.0 Administrator's Guide" at http://www.openldap.org/doc/admin20/guidel has an excellent "Quick-Start" procedure for getting slapd up and running: it's in Section 2, starting at Step 8. (That document also explains directory services and LDAP concepts in more depth than I do in this chapter.) Let's step through this procedure to make sure you get off to a good start. The first thing to do is to edit slapd.conf, an example of which is shown in Example 7-1. As you can see, slapd.conf is a typical Linux configuration file: each line in it consists of a parameter name followed by a value. Example 7-1. Customized part of /etc/openldap/slapd.confdatabase ldbm suffix "dc=wiremonkeys,dc=org" rootdn "cn=ldapguy,dc=wiremonkeys,dc=org" rootpw {SSHA}zRsCkoVvVDXObE3ewn19/Imf3yDoH9XC directory /var/lib/ldap The first parameter shown in Example 7-1, database, specifies what type of database backend to use; usually the best choice here is ldbm, which uses the fast dbm database format, but shell (for custom shell-script backends) and passwd (to use /etc/passwd as the backend) are also valid choices. There may be multiple database definitions, each with its own set of applicable parameters; all the lines in Example 7-1 comprise a single database definition.The next parameter in Example 7-1 is suffix, which determines what queries will match this database definition. Here, the specified suffix is "wiremonkeys.org," expressed in LDAP-speak as a series of domain component (dc) statements, which are parsed from left to right. In other words, if an LDAP client queries our example server in order to obtain information about the distinguished name (dn) cn=bubba,dc=wiremonkeys,dc=org, our server will match that query against this database definition since the dn ends with dc=wiremonkeys,dc=org.The next two entries in Example 7-1 have to do with LDAP database administration: rootdn and rootpw specify the username and password (respectively) that must be supplied by remote (or local) commands that perform administrative actions on the LDAP database. Interestingly, these entries are used only for this purpose: they won't show up in regular LDAP database queries.This addresses the paradox of how to authenticate the actions that are required to populate the authentication (LDAP) database. Later, after you've populated your LDAP database with "real" entity records, you should designate one of them as the administrative account, via slapd.conf access-control lists (ACLs), and delete the rootdn and rootpw entries. During initial setup, however, rootdn and rootpw will suffice.Note that it's a very, very bad idea to store the value of rootpw as cleartext. Instead, you should use the slappasswd command to generate a password hash, like in Example 7-2. Example 7-2. The slappasswd command[root@mydirserver openldap]# slappasswd -h {SSHA} New password: ********* Re-enter new password: ********* {SSHA}16JhhIDajRc1cDwwa1t6o0ske8goj8Od As you can see, slappasswd prompts you for a password and prints that password hashed with the algorithm you specify with the -h flag. Be sure to enclose this value in curly bracketssee the slappasswd(8C) manpage for a list of valid choices. You can copy and paste slappasswd's output directly into slapd.conf, which is precisely what I did to create the rootpw value in Example 7-1.Getting back to Example 7-1, the next parameter in this directory definition is directory. Obviously enough, this specifies which directory on the local filesystem your LDAP directory should be created in. Since /var is the customary place for "growing" files like logs and databases, Example 7-1 shows a value of /var/lib/ldap. This directory must already exist, and you should make sure it's owned by OpenLDAP's user and group (usually ldap and ldap). Its permissions should be set to 0700 (-rwx------).Technically, that's enough to get started: you can try starting slapd via your ldap startup script, most likely /etc/init.d/ldap, though this may vary between distributions. I encourage you to start adding practice entries to your LDAP database using the ldapadd command; the Quick Start procedure I mentioned earlier shows how.Before you begin managing and querying your LDAP database from over the network, however, you'll want to configure and enable TLS encryption. 7.2.3. TLS for Secure LDAP TransactionsBy default, OpenLDAP transactions over networks are conducted in clear text. If you're using OpenLDAP, for example, as a centralized address-book server on a trusted network, that's probably fine. But if you're using it to authenticate users, regardless of whether the networks involved are trusted or not, you really ought to encrypt your LDAP communications so as to protect your users' passwords from eavesdroppers.The LDAP v3 protocol, support for which was introduced in OpenLDAP 2.0, provides encryption in the form of Transport Layer Security (TLS), the same mechanism used by web browsers and Mail Transport Agents (TLS is the successor to SSL, the Secure Sockets Layer protocol). All you'll need to do to take advantage of this is: Create a server certificate on your LDAP server Add a couple more lines to /etc/openldap/slapd.conf. Optionally, tweak slapd's startup flags. To generate a server certificate, you'll need OpenSSL. This should already be present on your system, since binary OpenLDAP packages depend on OpenSSL.What sort of certificate you should use on your LDAP server is actually a fairly subtle question: will the server need a certificate that has been signed by some other Certificate Authority such as Thawte or Verisign (i.e., will your LDAP clients need to see an externally verifiable certificate when connecting to your server)? Or will your organization be its own Certificate Authority? If so, will the LDAP server also act as your local CA, issuing and signing both its own and other hosts' and users' certificates?If your needs match any of those scenarios, you'll need to do a bit more work than I'm going to describe here. Suffice it to say that the certificate slapd uses can't have a password associated with it (i.e., its key can't be DES-encrypted), so a self-signed certificate, while technically a CA certificate, shouldn't be used as an actual CA certificate (i.e., for signing other certificates). If you want to use your LDAP server as a "real" CA, you'll need to create two keys, a password-protected CA key and a password-free slapd key. Vincent Danen's article "Using OpenLDAP for Authentication" (http://www.mandrakesecure.net/en/docs/ldap-auth.php) discusses this.For many if not most readers, it will be enough to create a self-generated TLS-only certificate to be used by slapd and slapd alone. If you don't care about being a Certificate Authority and you don't need your LDAP clients to be able to verify the server certificate's authenticity via some third party, you can create your certificate like this (Example 7-3). Example 7-3. Generating a self-signed X.509 certificate and keybash-$> openssl req -new -x509 -nodes -out slapdcert.pem -keyout slapdkey.pem -days 365 Using configuration from /usr/share/ssl/openssl.cnf Generating a 1024 bit RSA private key ....++++++ .........++++++ writing new private key to 'slapdkey.pem' ----- You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [GB]:US State or Province Name (full name) [Berkshire]:Minnesota Locality Name (eg, city) [Newbury]:St. Paul Organization Name (eg, company) [My Company Ltd]:wiremonkeys Organizational Unit Name (eg, section) []: Common Name (eg, your name or your server's hostname) []:cornelius.wiremonkeys.org Email Address []:ldapguy@wiremonkeys.org Example 7-3 is deceptively long, but it involved only one command: the openssl command at the beginning. In this command line, I told OpenSSL to generate a new X.509 certificate, without password protection, with the certificate (public key) stored in the current working directory in the file slapdcert.pem and with the private key stored in the file slapdkey.pem, with a lifetime of 365 days.After issuing this command, I was prompted for "Distinguished Name" information for the new certificate and key. For OpenLDAP's purposes, the most important field here was the "Common Name": this must be set to your LDAP server's DNS namei.e., the name your LDAP clients will see associated with this certificate. If your LDAP server's IP address, for example, reverse-resolves to bonzo.lamemoviesfromthepast.com but its server certificate shows a CN of bonzo.lm.com, LDAP clients will reject the certificate and will therefore be unable to negotiate TLS connections (with very unpredictable results, depending on your client software).Once you've got certificate and key files, copy them into /etc/openldap (if you weren't in that directory already when you created them). Make sure that both of these are owned by ldap (or whatever user your Linux distribution runs slapd as; Red Hat and SUSE use ldap) and that your key file has very strict permissions, e.g., -r-------- (your certificate file may, however, be world-readable, since this contains a public key).
key, then on every client system that makes LDAPS queries (LDAPS means LDAP secure) against your server, you'll need to add this line to /etc/openldap/ldap.conf: TLS_REQCERT a llow You'll also need this line in your server's /etc/openldap/ldap.conf file if other processes on the LDAP server make LDAPS queries (i.e., to ldaps://localhost).If instead of using a self-signed certificate, you used a CA to sign your LDAP server certificate, then you'll need to copy your CA certificate to each client system and specify the CA certificate's location in the client's ldap.conf file, via either the TLS_CACERT or TLS_CACERTDIR variable. See the ldap.conf(5) manpage for more details.Naturally, it isn't enough to have certificate/key files in place; you need to tell slapd to use them. As with most other slapd configurations, this happens in /etc/openldap/slapd.conf.Example 7-4 shows the sample slapd.conf entries from Example 7-1, plus three additional ones: TLSCipherSuite, TLSCertificateFile, and TLSCertificateKeyFile. Example 7-4. Customized Part of /etc/openldap/slapd.confdatabase ldbm suffix "dc=wiremonkeys,dc=org" rootdn "cn=ldapguy,dc=wiremonkeys,dc=org" rootpw {SSHA}zRsCkoVvVDXObE3ewn19/Imf3yDoH9XC directory /var/lib/ldap TLSCipherSuite HIGH:MEDIUM:+SSLv2 TLSCertificateFile /etc/openldap/slapdcert.pem TLSCertificateKeyFile /etc/openldap/slapdkey.pem TLSCipherSuite specifies a list of OpenSSL ciphers from which slapd will choose when negotiating TLS connections, in decreasing order of preference. To see which ciphers are supported by your local OpenSSL installation, issue this command: openssl ciphers -v ALL In addition to those specific ciphers, you can use any of the wildcards supported by OpenSSL, which allow you to specify multiple ciphers with a single word. For example, in Example 7-4, TLSCipherSuite is set to HIGH:MEDIUM:+SSLv2; as it happens, HIGH, MEDIUM, and +SSLv2 are all wildcards.HIGH means "all ciphers using key lengths greater than 128 bits"; MEDIUM is short for "all ciphers using key lengths equal to 128 bits"' and +SSLv2 means "all ciphers specified in the SSL protocol, Version 2, regardless of key strength." For a complete explanation of OpenSSL ciphers, including all supported wildcards, see the ciphers(1) manpage.TLSCertificateFile and TLSCertificateKeyFile are more obvious: they specify the paths to your certificate file and private-key file, respectively. If both certificate and key are combined in a single file, you can specify the same path for both parameters (but see my note on the previous page). 7.2.4. slapd Startup Options for TLSOkay, we've done everything we need (on the server end) for TLS encryption to work. There's only one remaining detail to consider: should we force the use of TLS for all LDAP requests from the network, or keep it optional?By default, slapd will listen for LDAP connections on TCP port 389 and will accept either cleartext or TLS-encrypted connections on that port. However, if you're using LDAP for authentication, you probably don't want to make TLS optional. A better approach in that case is to have slapd listen for cleartext-only LDAP connections on TCP 389 on the loopback interface only, and have slapd listen for TLS-enabled (ldaps) connections on TCP 636 (the standard port for ldaps) for all other local addresses.This behavior is controlled by slapd's startup option -h, which you can use to specify the various LDAP URLs slapd will respond to. For example: slapd -h ldap://127.0.0.1/ ldaps:/// tells slapd to listen on the loopback address (127.0.0.1) for ldap connections to the default ldap port (TCP 389), and to listen on all local addresses for ldaps connections to the default ldaps port (TCP 636).If you run Red Hat 7.3 or later, this is actually the default behavior: /etc/init.d/ldap checks /etc/openldap/slapd.conf for TLS configuration information, and if it finds it, sets the -h option exactly like the one in the previous paragraph's example. If you run SUSE 8.1 or later, you can achieve the same thing by editing /etc/sysconfig/openldap such that the value for OPENLDAP_START_LDAPS is yes, and then editing /etc/init.d/openldap to set the value for SLAPD_URLS to ldap://127.0.0.1 (this variable is defined early in the script, with a default value of ldap:///).Other Linux distributions may have different ways of passing startup options like -h to slapd, but hopefully by now you get the idea and can figure out how to make slapd's listening-ports work the way you want them to. 7.2.5. TestingSo, does our TLS-enabled LDAP server actually work? A quick local test will tell us. First, start LDAP: /etc/init.d/ldap start Next, use the ldapsearch command to do a simple query via loopback: ldapsearch -x -H ldaps://localhost/ -b 'dc=wiremonkeys,dc=org' '(objectclass=*)' (Naturally, your own LDAP server will have a different base DN from dc=wiremonkeys,dc=org.) If you prefer, you can run that last command from a remote host, specifying the LDAP server's name or IP address in place of localhost in the -h option.If the LDAP server returns a dump of the LDAP database (which is actually empty at this point), followed by the string result: 0 Success, then your test has succeeded! Depending on which version of OpenLDAP your server is running, a nonzero result may also mean success, if you haven't yet added your organization entry (see "Creating Your First LDAP Record" later in this chapter). 7.2.6. LDAP SchemaYou're almost ready to start populating the LDAP database. On the one hand, tools such as gq and ldapbrowser can greatly reduce the ugliness and toil of LDAP data entry and administration. But to get to the point where these tools can be used, you first have to settle on a combination of LDAP schemas, and this is where things can get unpleasant.For purposes of this discussion, there are two types of LDAP data that matter: attributes and object classes. Attributes are the things that make up a record: a user's phone number, email address, nicknames, etc. are all attributes. You can use as many or as few attributes in your LDAP database as you like; you can even invent your own. But for a record to contain a given attribute, that record must be associated with the proper object class.An object class describes the type of record you're trying to build: it defines which attributes are mandatory for each record and which attributes are optional. "Oh," you might think, "that's easy, then: I just need to choose an object class that provides the group of attributes I want to store for my users and associate each user record with that object class!" If you thought that, you'd only be partly right. In practice, you'll probably want to use attributes from a variety of object classes. "Well, fine," you think, "I'll just specify multiple object classes in each user record, and get my full complement of attributes à la carte. Whatever." Right again, but again there's more to it than that: chances are, the object classes that provide the attributes you need are spread across a number of schema files (these are text files, each containing a list of attributes and the object classes that reference them). So even before you can begin composing your user records, each containing a stack of object class statements and a bigger stack of attribute settings, you'll need to first make sure /etc/openldap/slapd.conf contains include statements for all the schema files you need (usually present in /etc/openldap/schema).For example, suppose that since we're going to use our sample LDAP server for authentication, we want to make sure that no matter what, we're able to specify the attributes userid and userPassword. Doing a quick grep of the files in /etc/openldap/schema shows that uid appears in the file inetorgperson.schema in the MAY list (of allowed attributes) for the object class inetOrgPerson.This has two ramifications. First, /etc/openldap/slapd.conf will need to contain this line: include /etc/openldap/schema/inetorgperson.schema Second, whenever I create a user record, I'll need to make sure that there is an objectclass: inetOrgPerson statement present. 7.2.7. Creating Your First LDAP RecordSo, how do you create LDAP records? Ideally, via the GUI of your choice. (I've mentioned gq, which is a standard package in many distros; another excellent tool is ldapbrowser, available at http://www.iit.edu/~gawojar/ldap/) Initially, however, you'll probably want to add at least your organizational entry manually, by creating an LDIF file and writing it to the database via the ldapadd command.An LDIF file is a text file containing a list of attribute/object-class declarations, one per line: Example 7-5 shows a simple one. Example 7-5. A simple LDIF filedn: dc=wiremonkeys,dc=org objectclass: top objectclass: dcObject objectclass: organization dc: wiremonkeys o: Wiremonkeys of St. Paul In Example 7-5, we're defining the organization wiremonkeys.org: we specify its Distinguished Name, we associate it with the object classes top, dcObject, and organization, and finally we specify the organization's unique domain component (wiremonkeys) and name (Wiremonkeys of St. Paul).To write this record to the database, we issue this command: ldapadd -x -H ldaps://localhost/ -D "cn=ldapguy,dc=wiremonkeys,dc=org" -W \ -f wiremonkeys_init.ldif As with most openldap commands, -x specifies simple password authentication, -H specifies the LDAP server's URL, -D specifies the DN of the administrator account, and -W causes the administrator's password to be prompted for. The -f option specifies the path to our LDIF file.Confused yet? I've packed a lot of information into this section, but our LDAP server is very nearly done. |