Linux System Administration |
Home | Tech | Linux | Links | Consulting |
|
OpenLDAP provider on Debian squeeze
Back in the mid 1980s, before the Internet and its TCP/IP protocol suite became popular, two standards organizations, the ITU-T (then known as the CCITT) and the ISO, were busy developing their own standards for network communications. They had already produced the OSI Transport service, which was an advance in network communications, and also X.400; a collection of data communication standards for what was basically an e-mail service. However, more standards needed to be defined before any of this could be used as part of a global communications system. The two organizations were looking for solutions. The ITU-T was hoping to develop a white pages service that would return either people's phone numbers or X.400 O/R addresses, while the ISO mostly wanted a name server service for OSI applications. Not wanting to duplicate each other's efforts, they decided to pool their resources. Together they produced a set of networking standards in 1988, called X.500, for what was described as a directory service. X.500 is an elaborate collection of protocols, specifications and definitions centered around the concept of a single, distributed, replicated, global Directory Information Tree (DIT), capable of storing all kinds of information that would be accessible via the Directory Access Protocol (DAP). The whole system would take off as soon as organizations everywhere started to publish their own directory information, or subsets thereof, in the global DIT. Unfortunately, this never happened, perhaps because most organizations considered their own directory information to be too valuable, or too confidential, to be made available to the world at large in the form of an X.500 directory sub-tree. However, the concept of a private DIT, and a DAP with which to access it, was regarded as worthy enough in its own right. It just needed to be simplified somewhat. To this end, the Lightweight Directory Access Protocol (LDAP) was defined in 1993 (RFC-1487), giving clients access to an X.500-based DIT via TCP/IP without incurring the costly resource requirements associated with the X.500 DAP. The third and current version of LDAP was published in 1997 (RFC-2251), with a technical specification (RFC-3377) following in 2002. First released 1998, OpenLDAP is the popular open source implementation of LDAP. With it, anyone can create their own DIT and, unfettered by vendor limitations, decide for themselves what to use it for. All kinds of information can be stored in it − anything from host configuration data to names and addresses − and accessed from anywhere using the many different LDAP-compatible applications. A DIT is a hierarchically organized collection of entries, each identified by a Distinguished Name (DN); a unique, comma-separated list of components that provide the path to an entry, or object, from the top of the tree. For example, the DN of the root of a DIT for Example Corp. could be dc=example,dc=com, while the DN of someone employed there might be cn=JoeSmith,ou=People,dc=example,dc=com. The Relative Distinguished Name (RDN) of this entry is cn=JoeSmith. Notice how each DN consists of multiple key=value pairs. The keys in these example DNs stand for Common Name (cn), Organizational Unit (ou) and Domain Component (dc). All LDAP entries are typed, meaning that each DN belongs to an objectClass that identifies the type of information it represents. In turn, each entry consists of multiple attributes that also consist of key=value pairs, each of which is defined by a certain attributeType. These objectClasses and attributeTypes are defined in schema files. This allows an LDAP administrator to decide which schema files to include, based on the needs of the applications that will be using the DIT. In this example, OpenLDAP is installed on a host running Debian 6.0 (squeeze). If followed properly, the step-by-step process should produce a provider server with a new DIT. Actually, OpenLDAP used to refer to master and slave servers, but this has been depricated in favor of, respectively, provider and consumer servers, since the differences between them are not as distinct as they once were. This is because some consumers may now also act as providers for other LDAP hosts. Before the actual OpenLDAP installation process can begin, it will first be necessary to install Debian squeeze on a new host called ldaps1.example.com. A DNS server must also be available on the network with a zone file to which forward and reverse mappings can be added for this host, as well as an alias for it called ldaps.example.com. After the initial installation of the operating system, make sure these packages are installed on the system as well: ~# apt-get install ssh nmap Now the installation process for the OpenLDAP provider server can begin: 1. Package installation On the new host, ldaps1.example.com, start by installing these two packages: ~# apt-get install slapd ldap-utils A total of eight packages are installed as a result, including six dependencies: ldap-utils 2.4.23-7 OpenLDAP utilities libltdl7 2.2.6b-2 A system independent dlopen wrapper for GNU libtool libperl5.10 5.10.1-16 shared Perl library libslp1 1.2.1-7.8 OpenSLP libraries odbcinst 2.2.14p2-1 Helper program for accessing odbc ini files odbcinst1debian2 2.2.14p2-1 Support library for accessing odbc ini files slapd 2.4.23-7 OpenLDAP server (slapd) unixodbc 2.2.14p2-1 ODBC tools libraries During the install process, an administrator password will be requested for slapd. Use piscivorus: Administrator password: piscivorus Confirm password: piscivorus Run the following command to test if the OpenLDAP server is actually running: ~# nmap -p 389 localhost Starting Nmap 5.00 ( http://nmap.org ) at 2010-10-27 15:05 CEST Warning: Hostname localhost resolves to 2 IPs. Using 127.0.0.1. Interesting ports on localhost (127.0.0.1): PORT STATE SERVICE 389/tcp open ldap Nmap done: 1 IP address (1 host up) scanned in 0.08 seconds ~# _ The ldap service is made available on port 389 by the Standalone LDAP Daemon (slapd). Note that the state of the port is open. To be sure, the LDAP v3 technical specification (RFC-3377) does not mention anything about a backend solution in which to store the database; it is only a description of the network protocol itself. The daemon, slapd, the way it stores its data and the various utilities it comes with are all unique to OpenLDAP. Perform a quick test by generating an LDAP Data Interchange Format (LDIF) dump of the contents of a the database: ~# slapcat hdb_db_open: database "dc=example,dc=com": unclean shutdown detected; attempting recovery. hdb_db_open: database "dc=example,dc=com": recovery skipped in read-only mode. Run manual recovery if errors are encountered. dn: dc=example,dc=com objectClass: top objectClass: dcObject objectClass: organization o: example.com dc: example structuralObjectClass: organization entryUUID: 6c2b7ba6-7614-102f-8dca-2b8c20077bc5 creatorsName: cn=admin,dc=example,dc=com createTimestamp: 20101027124946Z entryCSN: 20101027124946.661291Z#000000#000#000000 modifiersName: cn=admin,dc=example,dc=com modifyTimestamp: 20101027124946Z dn: cn=admin,dc=example,dc=com objectClass: simpleSecurityObject objectClass: organizationalRole cn: admin description: LDAP administrator userPassword:: e1NTSEF9NUxZQ0hMd2E4OHgzQzE4d29xeEVkSWFqZVpsWndBT1U= structuralObjectClass: organizationalRole entryUUID: 6c2bfc66-7614-102f-8dcb-2b8c20077bc5 creatorsName: cn=admin,dc=example,dc=com createTimestamp: 20101027124946Z entryCSN: 20101027124946.664624Z#000000#000#000000 modifiersName: cn=admin,dc=example,dc=com modifyTimestamp: 20101027124946Z ~# _ If the output looks something like the above, continue with the next step. 2. ldap.conf Edit /etc/ldap/ldap.conf and add these two lines to the end of the file: BASE dc=example,dc=com URI ldap://ldaps1.example.com/ This configuration file is used to set system-wide defaults for LDAP clients. 3. cn=config As of OpenLDAP 2.4.23-3, the slapd runtime configuration is fully LDAP-enabled and the default is to manage it using the standard LDAP operations with data in LDIF. The old slapd.conf format is still supported, but since that file must now be converted to the new slapd-config format to allow runtime changes to be saved, it seems likely that the developers will eventually phase it out. Therefore, this article will focus only on the new configuration method, the main advantage of which is that any changes made are immediately active, so it is no longer necessary to restart slapd after making configuration changes. The new configuration format uses a slapd backend database that is found in the /etc/ldap/slapd.d/ directory. The configuration is stored as a special LDAP directory with a predefined schema and DIT, the root of which is called cn=config. To get an idea of what this database looks like, run this command: ~# slapcat -b cn=config This generates an LDIF dump of the contents of the cn=config directory. Much of it consists of schema information. The LDAP configuration directives are attributes of the directory entries (objects) and most them start with the prefix "olc" (OpenLDAP Configuration). Also, some of the objects have names with numbers between curly brackets. This is to compensate for the fact that LDAP databases do not store their contents in any particular order; they are inherently unordered. The numbers constitute a numeric index to ensure a consistent order in the configuration database and thereby preserve all ordering dependencies. The index numbers, however, are generated automatically in the order they are created and usually do not have to be provided. In this step of the installation process, a few general-purpose modifications will be made to two entries in the runtime DIT: to the cn=config object, which is the root of the configuration directory and contains attributes that are global directives, and to the olcDatabase={1}hdb entry, which is the database definition. To see what they look like at the moment, the attributes of both of these objects can be listed with a single command (see RFC-4515): ~# ldapsearch -LLLQY EXTERNAL -H ldapi:/// -b cn=config \ "(|(cn=config)(olcDatabase={1}hdb))" dn: cn=config objectClass: olcGlobal cn: config olcArgsFile: /var/run/slapd/slapd.args olcLogLevel: none olcPidFile: /var/run/slapd/slapd.pid olcToolThreads: 1 dn: olcDatabase={1}hdb,cn=config objectClass: olcDatabaseConfig objectClass: olcHdbConfig olcDatabase: {1}hdb olcDbDirectory: /var/lib/ldap olcSuffix: dc=example,dc=com olcAccess: {0}to attrs=userPassword,shadowLastChange by self write by anonymou s auth by dn="cn=admin,dc=example,dc=com" write by * none olcAccess: {1}to dn.base="" by * read olcAccess: {2}to * by self write by dn="cn=admin,dc=example,dc=com" write by * read olcLastMod: TRUE olcRootDN: cn=admin,dc=example,dc=com olcRootPW: {SSHA}ABsCG0bmPL8aRFVEU4NK6zYiU6QvVyPK 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 ~# _ The -L option used here causes the results to be displayed in LDAP Data Interchange Format (LDIF). A second -L will disable comments, and a third one will prevent the LDIF version from being printed. The default is to use extended LDIF. Five changes will be made to the cn=config DIT:
To make both of the above changes to the cn=config DIT, first create an LDIF file, called ~/olc-mod1.ldif, with the following contents: # 1. dn: cn=config changetype: modify replace: olcLogLevel olcLogLevel: stats # 2.1. dn: olcDatabase={1}hdb,cn=config changetype: modify add: olcDbIndex olcDbIndex: uid eq - # 2.2. add: olcDbIndex olcDbIndex: cn eq - # 2.3. add: olcDbIndex olcDbIndex: ou eq - # 2.4. add: olcDbIndex olcDbIndex: dc eq NB: According to the LDIF specification (RFC-2849), lines containing only a "-" character act as a separator between modifications that apply to the same directory entry. Empty lines separate tasks involving different directory entries. Lines that start with a "#" character are considered comments and are ignored. Apply both of the above changes with this single command: ~# ldapmodify -QY EXTERNAL -H ldapi:/// -f ~/olc-mod1.ldif modifying entry "cn=config" modifying entry "olcDatabase={1}hdb,cn=config" ~# _ Repeat the previous ldapsearch command to verify that the changes have been applied. Also, check /var/log/syslog for slapd log output. 4. Basic tree Create a basic tree structure. First create a file, ~/tree.ldif, with the following contents: dn: ou=people,dc=example,dc=com ou: people objectClass: organizationalUnit dn: ou=groups,dc=example,dc=com ou: groups objectClass: organizationalUnit Add this information to the LDAP database with the ldapadd command: ~# ldapadd -cxWD cn=admin,dc=example,dc=com -f ~/tree.ldif Enter LDAP Password: piscivorus adding new entry "ou=people,dc=example,dc=com" adding new entry "ou=groups,dc=example,dc=com" ~# _ Five different options are used for this ldapadd command:
Perform a test. Run an ldapsearch with an anonymous bind (no DN specified) to check that the new organizational units have indeed been added to the database. Check that the output looks like the following and does not contain any obvious errors: ~# ldapsearch -xLLL dn: dc=example,dc=com objectClass: top objectClass: dcObject objectClass: organization o: example.com dc: example dn: cn=admin,dc=example,dc=com objectClass: simpleSecurityObject objectClass: organizationalRole cn: admin description: LDAP administrator dn: ou=people,dc=example,dc=com ou: people objectClass: organizationalUnit dn: ou=groups,dc=example,dc=com ou: groups objectClass: organizationalUnit ~# _ 5. User account Create a new user account, called ccolumbus. First create a file, ~/ccolumbus.ldif, with the following contents: dn: cn=ccolumbus,ou=groups,dc=example,dc=com cn: ccolumbus gidNumber: 20000 objectClass: top objectClass: posixGroup dn: uid=ccolumbus,ou=people,dc=example,dc=com uid: ccolumbus uidNumber: 20000 gidNumber: 20000 cn: Christopher sn: Columbus objectClass: top objectClass: person objectClass: posixAccount objectClass: shadowAccount loginShell: /bin/bash homeDirectory: /home/ccolumbus userPassword: NewWorld Add this information to the DIT with the ldapadd command: ~# ldapadd -cxWD cn=admin,dc=example,dc=com -f ~/ccolumbus.ldif Enter LDAP Password: piscivorus adding new entry "cn=ccolumbus,ou=groups,dc=example,dc=com" adding new entry "uid=ccolumbus,ou=people,dc=example,dc=com" ~# _ Run an ldapsearch for the new ccolumbus entry to check if the response seems reasonable and does not contain any errors. The output should look like this: ~# ldapsearch -xLLL uid=ccolumbus dn: uid=ccolumbus,ou=people,dc=example,dc=com uid: ccolumbus uidNumber: 20000 gidNumber: 20000 cn: Christopher sn: Columbus objectClass: top objectClass: person objectClass: posixAccount objectClass: shadowAccount loginShell: /bin/bash homeDirectory: /home/ccolumbus ~# _ It is possible to test authentication for an LDAP account with the ldapwhoami command: ~# ldapwhoami -xD uid=ccolumbus,ou=people,dc=example,dc=com -w NewWorld dn:uid=ccolumbus,ou=people,dc=example,dc=com ~$ _ This is also an example of a password that is specified on the command line using the -w option. Anyway, when using only simple authentication, if no DN is given to bind to and no password is included, the binding will be anonymous: ~# ldapwhoami -x anonymous ~# _ The same applies to ldapsearch when using simple authentication. In all such cases the principle is the same: authentication and authorization must take place before any such single commands are processed. 6. See also
7. Further reading
8. Sources
Last modified: 2017-08-02, 17:50
©2003-2020 RJ Systems. Permission is granted to copy, distribute and/or modify the content of this page under the terms of the OpenContent License, version 1.0. |