It is crucial within a networked environment to keep important information structured and quickly available. Data chaos does not only loom when using the Internet. The search for important data in the company network can just as quickly grow disproportionately. “What is the extension number of colleague XY? What is his e-mail address?” This problem is solved by a directory service that, like the common yellow pages, keeps information available in a well-structured, quickly searchable form.
In the ideal case, a central server keeps the data in a directory and distributes it to all clients using a certain protocol. The data is structured in a way that a wide range of applications can access them. That way, it is not necessary for every single calendar tool and e-mail client to keep its own database — a central repository can be accessed instead. This notably reduces the administration effort for the concerned information. The use of an open and standardized protocol like LDAP ensures that as many different client applications as possible can access such information.
A directory in this context is a type of database optimized for quick and effective reading and searching:
To make numerous (concurrent) reading accesses possible, the writing access is limited to a small number of updates by the administrator. Conventional databases are optimized for accepting the largest possible data volume in a short time.
Because writing accesses can only be executed in a restricted fashion, a directory service is employed for administering mostly unchanging, static information. Data in a conventional database typically changes very often (dynamic data). Phone numbers in a company directory do not change nearly as often as, for instance, the figures administered in accounting.
When static data is administered, updates of the existing data sets are very rare. When working with dynamic data, especially when data sets like bank accounts or accounting are concerned, the consistency of the data is of primary importance. If an amount should be subtracted from one place to be added to another, both operations must happen concurrently, within a transaction, to ensure the balance over the whole data stock. Databases support such transactions. Directories do not. Short-term inconsistencies of the data are quite acceptable in directories.
The design of a directory service like LDAP is not laid out to support complex update or query mechanisms. All applications accessing this service should gain access quickly and easily.
Many directory services have previously existed and still exist both in Unix and outside it. Novell NDS, Microsoft ADS, Banyan's Street Talk, and the OSI standard X.500 are just a few examples. LDAP was originally planned as a lean flavor of the DAP, the Directory Access Protocol, which was developed for accessing X.500. The X.500 standard regulates the hierarchical organization of directory entries.
LDAP is relieved of a few functions of the DAP. Without having to miss the X.500 entry hierarchy you profit from LDAP's cross-platform capabilities and save resources. and can be employed, The use of TCP/IP makes it substantially easier to establish interfaces between a docking application and the LDAP service.
LDAP, meanwhile, has evolved and is increasingly employed as a stand-alone solution without X.500 support. LDAP supports referrals with LDAPv3 (the protocol version in package openldap2), making it possible to realize distributed databases. The usage of SASL (Simple Authentication and Security Layer) is also new.
LDAP is not limited to querying data from X.500 servers, as it was originally planned. There is an open source server slapd, which can store object information in a local database. There is also an extension called slurpd, which is responsible for replicating multiple LDAP servers.
The openldap2 package consists of:
A stand-alone LDAPv3 server that administers object information in a BerkeleyDB-based database.
This program enables the replication of modifications to data on the local LDAP server to other LDAP servers installed on the network.
slapcat, slapadd, slapindex
The Unix system administrator traditionally uses the NIS service for name resolution and data distribution in a network. The configuration data contained in the files in /etc and the directories group, hosts, mail, netgroup, networks, passwd, printcap, protocols, rpc, and services are distributed by clients all over the network. These files can be maintained without major effort because they are simple text files. The handling of larger amounts of data, however, becomes increasingly difficult due to nonexistent structuring. NIS is only designed for Unix platforms, which makes its employment as a central data administrator in a heterogeneous network impossible.
Unlike NIS, the LDAP service is not restricted to pure Unix networks. Windows servers (from 2000) support LDAP as a directory service. Novell also offers an LDAP service. Application tasks mentioned above are additionally supported in non-Unix systems.
The LDAP principle can be applied to any data structure that should be centrally administered. A few application examples are:
Employment as a replacement for the NIS service.
Mail routing (postfix, sendmail).
Address books for mail clients like Mozilla, Evolution, and Outlook.
Administration of zone descriptions for a BIND9 name server.
This list can be extended because LDAP is extensible as opposed to NIS. The clearly-defined hierarchical structure of the data greatly helps the administration of very large amounts of data, because it can be searched better.
An LDAP directory has a tree structure. All entries (called objects) of the directory have a defined position within this hierarchy. This hierarchy is called the directory information tree or, for short, DIT. The complete path to the desired entry, which unambiguously identifies it, is called distinguished name or DN. The single nodes along the path to this entry are called relative distinguished name or RDN. Objects can generally be assigned to one of two possible types:
These objects can themselves contain other objects. Such object classes are root (the root element of the directory tree, which does not really exist), c (country), ou (organizational unit), and dc (domain component). This model is comparable to the directories (folders) in a file system.
These objects sit at the end of a branch and have no subordinate objects. Examples are person, InetOrgPerson, or groupofNames.
The top of the directory hierarchy has a root element root. This can contain c (country), dc (domain component), or o (organization) as subordinate elements. The relations within an LDAP directory tree become more evident in the following example, shown in Figure 14.4. “Structure of an LDAP Directory”.
The complete diagram comprises a fictional directory information tree. The entries on three levels are depicted. Each entry corresponds to one box in the picture. The complete, valid distinguished name for the fictional SUSE employee Geeko Linux, in this case, is cn=Geeko Linux,ou=doc,dc=suse,dc=de. It is composed by adding the RDN cn=Geeko Linux to the DN of the preceding entry ou=doc,dc=suse,dc=de.
The global determination of which types of objects should be stored in the DIT is done following a scheme. The type of an object is determined by the object class. The object class determines what attributes the concerned object must or can be assigned. A scheme, therefore, must contain definitions of all object classes and attributes used in the desired application scenario. There are a few common schemes (see RFC 2252 and 2256). It is, however, possible to create custom schemes or to use multiple schemes complementing each other if this is required by the environment in which the LDAP server should operate.
Table 14.9. “Commonly Used Object Classes and Attributes” offers a small overview of the object classes from core.schema and inetorgperson.schema used in the example, including required attributes and valid attribute values.
Table 14.9. Commonly Used Object Classes and Attributes
|Object Class||Meaning||Example Entry||Compulsory Attributes|
|dcObject||domainComponent (name components of the domain)||suse||dc|
|organizationalUnit||organizationalUnit (organizational unit)||doc||ou|
|inetOrgPerson||inetOrgPerson (person-related data for the intranet or Internet)||Geeko Linux||sn and cn|
Example 14.17. “Excerpt from schema.core (line numbering for explanatory reasons)” shows an excerpt from a scheme directive with explanations offering some understanding of the new schemes.
Example 14.17. Excerpt from schema.core (line numbering for explanatory reasons)
#1 attributetype ( 18.104.22.168 NAME ( 'ou' 'organizationalUnitName' ) #2 DESC 'RFC2256: organizational unit this object belongs to' #3 SUP name ) ... #4 objectclass ( 22.214.171.124 NAME 'organizationalUnit' #5 DESC 'RFC2256: an organizational unit' #6 SUP top STRUCTURAL #7 MUST ou #8 MAY ( userPassword $ searchGuide $ seeAlso $ businessCategory $ x121Address $ registeredAddress $ destinationIndicator $ preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $ telephoneNumber $ internationaliSDNNumber $ facsimileTelephoneNumber $ street $ postOfficeBox $ postalCode $ postalAddress $ physicalDeliveryOfficeName $ st $ l $ description) ) ...
The attribute type organizationalUnitName and the corresponding object class organizationalUnit serve as an example here. Line 1 features the name of the attribute, its unique OID (object identifier) (numerical), and the abbreviation of the attribute.
Line 2 gives brief description of the attribute with DESC. The corresponding RFC on which the definition is based is also mentioned here. SUP in line 3 indicates a superordinate attribute type to which this attribute belongs.
The definition of the object class organizationalUnit begins in line 4, like in the definition of the attribute, with an OID and the name of the object class. Line 5 features a brief description of the object class. Line 6 with its entry SUP top indicates that this object class is not subordinate to another object class. Line 7, starting with MUST, lists all attribute types that must be used in conjunction with an object of the type organizationalUnit. Line 8 starting with MAY lists all attribute types that are allowed to be used in conjunction with this object class.
A very good introduction in the use of schemes can be found in the documentation of OpenLDAP. When installed, find it in /usr/share/doc/packages/openldap2/admin-guide/index.html.
Your installed system contains a complete configuration file for your LDAP server at /etc/openldap/slapd.conf. The single entries are briefly described here and necessary adjustments are explained. Entries prefixed with a hash prefix (#) are inactive. This comment character must be removed to activate them.
Example 14.18. slapd.conf: Include Directive for Schemes
include /etc/openldap/schema/core.schema include /etc/openldap/schema/inetorgperson.schema
This first directive in slapd.conf, shown in Example 14.18. “slapd.conf: Include Directive for Schemes”, specifies the scheme by which the LDAP directory is organized. The entry core.schema is compulsory. Additionally required schemes are appended to this directive (inetorgperson.schema has been added here as an example). More available schemes can be found in the directory /etc/openldap/schema. For replacing NIS with an analogous LDAP service, include the two schemes rfc2307.schema and cosine.schema. Information can be found in the included OpenLDAP documentation.
Example 14.19. slapd.conf: pidfile and argsfile
pidfile /var/run/slapd.pid argsfile /var/run/slapd.args
These two files contain the PID (process ID) and some of the arguments with which the slapd process is started. There is no need for modifications here.
Example 14.20. slapd.conf: Access Control
# Sample Access Control # Allow read access of root DSE # Allow self write access # Allow authenticated users read access # Allow anonymous users to authenticate # access to dn="" by * read access to * by self write by users read by anonymous auth # # if no access controls are present, the default is: # Allow read by all # # rootdn can always write!
Example 14.20. “slapd.conf: Access Control” is the excerpt from slapd.conf that regulates the access permissions for the LDAP directory on the server. The settings made here in the global section of slapd.conf are valid as long as no custom access rules are declared in the database-specific section. These would overwrite the global declarations. As presented here, all users have read access to the directory, but only the administrator (rootdn) can write into this directory. Access control regulation in LDAP is a highly complex process. The following tips can help:
Every access rule has the following structure:
access to <what> by <who> <access>
what is a placeholder for the object or attribute to which access is granted. Individual directory branches can explicitly be protected with separate rules. It is also possible to process whole regions of the directory tree with one rule by using regular expressions. slapd evaluates all rules in the order in which they are listed in the configuration file. More general rules should be listed after more specific ones — the first rule slapd regards as valid is evaluated and all following entries are ignored.
who determines who should be granted access to the areas determined with what. Regular expressions may be used. slapd again aborts the evaluation of who after the first match so more specific rules should be listed before the more general ones. The entries shown in Table 14.10. “User Groups and Their Access Grants” are possible.
access specifies the type of access. It is distinguished from the options listed below in Table 14.11. “Types of Access”.
Table 14.11. Types of Access
|Tag||Scope of Access|
|auth||for contacting the server|
|compare||to objects for comparison access|
|search||for the employment of search filters|
slapd compares the access right requested by the client with those granted in slapd.conf. The client is granted access if the rules allow a higher or equal right than the requested one. If the client requests higher rights than those declared in the rules, it is denied access.
Example 14.21. “slapd.conf: Example for Access Control” shows a simple example for a simple access control that can be arbitrarily developed using regular expressions.
Example 14.21. slapd.conf: Example for Access Control
access to dn.regex="ou=([^,]+),dc=suse,dc=de" by cn=administrator,ou=$1,dc=suse,dc=de write by user read by * none
This rule declares that only its respective administrator has write access to an individual ou entry. All other authenticated users have read access and the rest of the world has no access.
|Establishing Access Rules|
If there is no access to rule or no matching by who directive, access is denied. Only explicitly declared access rights are granted. If no rules are declared at all, the default principle is write access for the administrator and read access for the rest of the world.
Apart from the possibility to administer access permissions with the central server configuration file (slapd.conf), there is ACI, access control information. ACI allows storage of the access information for individual objects within the LDAP tree. This type of access control is not yet common and is still considered experimental by the developers. Refer to http://www.openldap.org/faq/data/cache/758.html for information.
Example 14.22. slapd.conf: Database-Specific Directives
database ldbm suffix "dc=suse,dc=de" rootdn "cn=admin,dc=suse,dc=de" # Cleartext passwords, especially for the rootdn, should # be avoided. 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/tools. Mode 700 recommended. directory /var/lib/ldap # Indices to maintain index objectClass eq
The type of database, LDBM in this case, is determined in the first line of this section (see Example 14.22. “slapd.conf: Database-Specific Directives”). The second line determines, with suffix, for which portion of the LDAP tree this server should be responsible. The following rootdn determines who owns administrator rights to this server. The user declared here does not need to have an LDAP entry or exist as regular user. The administrator password is set with rootpw. Instead of using secret here, it is possible to enter the hash of the administrator password created by slappasswd. The directory directive indicates the directory (in the file system) where the database directories are stored on the server. The last directive, index objectClass eq, results in the maintenance of an index over all object classes. Attributes for which users search most often can be added here according to experience. Custom Access rules defined here for the database are used instead of the global Access rules.
Once the LDAP server is fully configured and all desired entries have been made according to the pattern described below in Section 14.7.4. “Data Handling in the LDAP Directory”, start the LDAP server as root by entering rcldap start. To stop the server manually, enter the command rcldap stop. Request the status of the running LDAP server with rcldap status.
The YaST runlevel editor, described in Section 13.5. “The YaST Runlevel Editor”, can be used to have the server started and stopped automatically on boot and halt of the system. It is also possible to create the corresponding links to the starting and stopping scripts with the insserv command from a command prompt as described in Section 13.4.1. “Adding init Scripts”.
OpenLDAP offers a series of tools for the administration of data in the LDAP directory. The four most important tools for adding to, deleting from, searching through, and modifying the data stock are briefly explained below.
Once the configuration of your LDAP server in /etc/openldap/lsapd.conf is correct and ready to go, meaning that it features appropriate entries for suffix, directory, rootdn, rootpw, and index, proceed to entering records. OpenLDAP offers the ldapadd command for this task. If possible, add the objects to the database in bundles for practical reasons. LDAP is able to process the LDIF format (LDAP Data Interchange Format) to accomplish this. An LDIF file is a simple text file that can contain an arbitrary number of pairs of attribute and value. Refer to the schema files declared in slapd.conf for the available object classes and attributes. The LDIF file for creating a rough framework for the example in Figure 14.4. “Structure of an LDAP Directory” would look like that in File 14.23. “Example for an LDIF File”.
Example 14.23. Example for an LDIF File
# The SuSE Organization dn: dc=suse,dc=de objectClass: dcObject objectClass: organization o: SuSE AG dc: suse # The organizational unit development (devel) dn: ou=devel,dc=suse,dc=de objectClass: organizationalUnit ou: devel # The organizational unit documentation (doc) dn: ou=doc,dc=suse,dc=de objectClass: organizationalUnit ou: doc # The organizational unit internal IT (it) dn: ou=it,dc=suse,dc=de objectClass: organizationalUnit ou: it
|Encoding of LDIF Files|
LDAP works with UTF-8 (Unicode). Umlauts therefore must be encoded correctly. Use an editor that supports UTF-8 (such as Kate or recent versions of Emacs). Otherwise, it would be necessary to avoid umlauts and other special characters or to use recode to recode the input to UTF-8.
The file is saved with the .ldif suffix and is passed to the server with the following command:
ldapadd -x -D <dn of the administrator> -W -f <file>.ldif
The first option -x switches off the authentication with SASL in this case. The -D switch declares the user that calls the operation. The valid DN of the administrator is entered here just like it has been configured in slapd.conf. In the current example, this would be cn=admin,dc=suse,dc=de. The switch -W circumvents entering the password on the command line (in clear text) and activates a separate password requesting prompt. This password was previously determined in slapd.conf with rootpw. The -f switch passes the file name. See the details of running ldapadd in Example 14.24. “ldapadd with example.ldif”.
Example 14.24. ldapadd with example.ldif
ldapadd -x -D cn=admin,dc=suse,dc=de -W -f example.ldif Enter LDAP password: adding new entry "dc=suse,dc=de" adding new entry "ou=devel,dc=suse,dc=de" adding new entry "ou=doc,dc=suse,dc=de" adding new entry "ou=it,dc=suse,dc=de"
The user data of the individual colleagues can be prepared in separate LDIF files. The following example, shown in Example 14.25. “LDIF Data for Tux”, adds the colleague Tux to the new LDAP directory.
Example 14.25. LDIF Data for Tux
# coworker Tux dn: cn=Tux Linux,ou=devel,dc=suse,dc=de objectClass: inetOrgPerson cn: Tux Linux givenName: Tux sn: Linux mail: email@example.com uid: tux telephoneNumber: +49 1234 567-8
An LDIF file can contain an arbitrary number of objects. It is possible to pass entire directory branches to the server at once or only parts of it as shown in the example of individual objects. If it is necessary to modify some data relatively often, a fine subdivision of single objects is recommended.
The tool ldapmodify is provided for modifying the data stock. The easiest way to do this is to modify the corresponding LDIF file then pass this modified file to the LDAP server. To change the telephone number of colleague Tux from +49 1234 567-8 to +49 1234 567-10, the LDIF file must be edited like in Example 14.26. “Modified LDIF File tux.ldif”.
Example 14.26. Modified LDIF File tux.ldif
# coworker Tux dn: cn=Tux Linux,ou=devel,dc=suse,dc=de changetype: modify replace: telephoneNumber telephoneNumber: +49 1234 567-10
Import the modified file into the LDAP directory with the following command:
ldapmodify -x -D cn=admin,dc=suse,dc=de -W -f tux.ldif
Alternatively, pass the attributes to change directly to ldapmodify. The procedure for this is described below:
Start ldapmodify and enter your password:
ldapmodify -x -D cn=admin,dc=suse,dc=de -W Enter LDAP password:
Enter the changes while carefully complying with the syntax in the order it is presented below:
dn: cn=Tux Linux,ou=devel,dc=suse,dc=de changetype: modify replace: telephoneNumber telephoneNumber: +49 1234 567-10
Read detailed information about ldapmodify and its syntax in its corresponding man page.
OpenLDAP provides, with ldapsearch, a command line tool for searching data within an LDAP directory and reading data from it. A simple query would have the following syntax:
ldapsearch -x -b dc=suse,dc=de "(objectClass=*)"
The option -b determines the search base — the section of the tree within which the search should be performed. In the current case, this is dc=suse,dc=de. To perform a more finely-grained search in specific subsections of the LDAP directory (for instance, only within the devel department), pass this section to ldapsearch with -b. The -x switch requests the activation of simple authentication. (objectClass=*) declares that all objects contained in the directory should be read. This command option can be used after the creation of a new directory tree to verify that all entries have been recorded correctly and the server responds as desired. More information about the use of ldapsearch can be found in the corresponding man page (man ldapsearch).
Delete unwanted entries with ldapdelete. The syntax is similar to that of the commands described above. To delete, for example, the complete entry for Tux Linux, issue the following command:
ldapdelete -x -D cn=admin,dc=suse,dc=de -W cn=Tux \ Linux,ou=devel,dc=suse,dc=de
More complex subjects, like SASL configuration or establishment of a replicating LDAP server that distributes the workload among multiple slaves, were intentionally not included in this chapter. Detailed information about both subjects can be found in the OpenLDAP 2.1 Administrator's Guide (see below for references).
The web site of the OpenLDAP project offers exhaustive documentation for beginning and advanced LDAP users:
A very rich question and answer collection concerning installation, configuration, and employment of OpenLDAP. http://www.openldap.org/faq/data/cache/1.html.
Brief step-by-step instructions for installing your first LDAP server.
http://www.openldap.org/doc/admin21/quickstart.html or on an installed system in /usr/share/doc/packages/openldap2/admin-guide/quickstart.html
A detailed introduction to all important aspects of LDAP configuration, including access controls and encryption. http://www.openldap.org/doc/admin21/ or on an installed system in /usr/share/doc/packages/openldap2/admin-guide/index.html
The following redbooks from IBM exist regarding the subject of LDAP:
A detailed general introduction to the basic principles of LDAP: http://www.redbooks.ibm.com/redbooks/pdfs/sg244986.pdf.
The target audience consists of administrators of IBM SecureWay Directory. However, important general information about LDAP is also contained here: http://www.redbooks.ibm.com/redbooks/pdfs/sg245110.pdf.
Printed literature about LDAP:
Howes, Smith, and Good: Understanding and Deploying LDAP Directory Services. Addison-Wesley, 2. Aufl., 2003. (ISBN 0-672-32316-8)
Hodges: LDAP System Administration. O'Reilly & Associates, 2003. (ISBN 1-56592-491-6)
The ultimate reference material for the subject of LDAP is the corresponding RFCs (request for comments), 2251 to 2256.