Linux System Administration |
Home | Tech | Linux | Links | Consulting |
|
OpenLDAP consumer with MIT Kerberos V on Debian lenny
This page describes how to set up an OpenLDAP consumer server (syncrepl) with MIT Kerberos V support for authentication and encryption. It depends on a previously installed OpenLDAP provider server, ldapks1.example.com, which also includes Kerberos support, as well as two Kerberos servers, kdc1.example.com and kdc2.example.com − a master and a slave. At least the master KDC will be necessary for this exercise, but it may be more interesting to use the slave. It is assumed that the reader is familiar with the concepts involved in the installation and configuration of an OpenLDAP consumer server. However, as opposed to that configuration, this OpenLDAP system will only store Unix user account information for authorization; the task of authentication will be performed by Kerberos, with all username and password combinations being stored in a Kerberos database. In this example, OpenLDAP is installed on a host running Debian 5.0 (lenny). If followed properly, the step-by-step process should produce a slave server with a copy of the DIT from the provider. But before the actual OpenLDAP installation process can begin, it will first be necessary to install the operating system on a new host called ldapks2.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. After the initial installation of the operating system, make sure these packages are installed on the system as well: ~# apt-get install ntp ntpdate nmap Afterwards, edit /etc/ntp.conf so that the machine synchronizes to a common NTP server (preferably a local one) and edit /etc/default/ntpdate to use the same host also. Now the installation of the new server can begin. 1. Kerberos client install First, run the following command to test if the MIT Kerberos V server installed previously is available on the network: ~# nmap kdc1.example.com This should be among the results: PORT STATE SERVICE 749/tcp open kerberos-adm 754/tcp open krb_prop If there is a problem, fix it first. If not, continue by installing these three packages: ~# apt-get install krb5-{config,user} libpam-krb5 A total of four packages are installed as a result, including one dependency: krb5-config 1.22 Configuration files for Kerberos Version 5 krb5-user 1.6.dfsg.4~beta1-5lenny2 Basic programs to authenticate using MIT Kerberos libkadm55 1.6.dfsg.4~beta1-5lenny2 MIT Kerberos administration runtime libraries libpam-krb5 3.11-4 PAM module for MIT Kerberos During the installation, the krb5-config package will automatically have the default realm set to EXAMPLE.COM, but a few questions have to be answered for it as well: Kerberos servers for your realm: kdc1.example.com kdc2.example.com Administrative server for your Kerberos realm: krb.example.com These settings, along with the default realm, are saved in /etc/krb5.conf. 2. Realm config file Edit the Kerberos realm configuration file, /etc/krb5.conf. This file is initially created by the Debian installer and contains information about the realms of a number of famous institutions, but none of that is necessary in this case. Instead, replace its contents with this: [libdefaults] default_realm = EXAMPLE.COM forwardable = true proxiable = true [realms] EXAMPLE.COM = { kdc = kdc1.example.com kdc = kdc2.example.com admin_server = krb.example.com } [domain_realm] .example.com = EXAMPLE.COM example.com = EXAMPLE.COM See this section for a more detailed explanation of this file. Regarding the list of KDCs that are specified here, it is often recommended to use a predetermined set of DNS hostname aliases (CNAME records) to refer to the Kerberos servers on a network. However, it is also possible to omit the mention of any KDCs here and instead rely on the relatively new SRV DNS resource record type. See the article DNS discovery for MIT Kerberos V for information on how to do that. 3. Service princ & keytab Use kadmin to create a Kerberos principal for the LDAP service and a matching keytab file by issuing a few commands: ~# kadmin -p admin Authenticating as principal admin with password. Password for admin@EXAMPLE.COM: Lampropeltis kadmin: addprinc -randkey ldap/ldapks2.example.com WARNING: no policy specified for ldap/ldapks2.example.com@EXAMPLE.COM; defaulting to no policy Principal "ldap/ldapks2.example.com@EXAMPLE.COM" created. kadmin: ktadd ldap/ldapks2.example.com Entry for principal ldap/ldapks2.example.com with kvno 3, encryption type AES-256 CTS mode with 96-bit SHA-1 HMAC added to keytab WRFILE:/etc/krb5.keytab. Entry for principal ldap/ldapks2.example.com with kvno 3, encryption type ArcFour with HMAC/md5 added to keytab WRFILE:/etc/krb5.keytab. Entry for principal ldap/ldapks2.example.com with kvno 3, encryption type Triple DES cbc mode with HMAC/sha1 added to keytab WRFILE:/etc/krb5.keytab. Entry for principal ldap/ldapks2.example.com with kvno 3, encryption type DES cbc mode with CRC-32 added to keytab WRFILE:/etc/krb5.keytab. kadmin: q ~# _ The -randkey switch is used because a machine cannot enter a password. To list the keys in /etc/krb5.keytab, use the klist -ke command. A host (or service) principal and a keytab file should be created for and saved on all of the various client machines that are part of a Kerberos realm. 4. OpenLDAP install Before starting the install process, run the following command to test if the previously installed OpenLDAP provider server is actually available on the network: ~# nmap ldapks1.example.com This should be among the results: PORT STATE SERVICE 389/tcp open ldap If there is a problem, fix it first. Otherwise, install these two packages: ~# apt-get install slapd ldap-utils A total of ten packages are installed as a result, including eight dependencies: ldap-utils 2.4.11-1+lenny1 OpenLDAP utilities libdb4.2 4.2.52+dfsg-5 Berkeley v4.2 Database Libraries [runtime] libltdl3 1.5.26-4+lenny1 A system independent dlopen wrapper for GNU libtool libperl5.10 5.10.0-19lenny2 Shared Perl library libsasl2-modules 2.1.22.dfsg1-23+lenny1 Cyrus SASL - pluggable authentication modules libslp1 1.2.1-7.5 OpenSLP libraries odbcinst1debian1 2.2.11-16 Support library and helper program for accessing odbc ini file psmisc 22.6-1 Utilities that use the proc filesystem slapd 2.4.11-1+lenny1 OpenLDAP server (slapd) unixodbc 2.2.11-16 ODBC tools libraries During the install process, an administrator password will be requested for slapd. Use piscivorus: Administrator password: contortrix Confirm password: contortrix Run the following command to test if the new OpenLDAP server is actually running: ~# nmap ldapks2.example.com This should be among the results: PORT STATE SERVICE 389/tcp open ldap Perform a quick test by generating an LDIF dump of the contents of a the database: ~# slapcat dn: dc=example,dc=com objectClass: top objectClass: dcObject objectClass: organization o: example.com dc: example structuralObjectClass: organization entryUUID: 99e8f32e-942a-102e-82c5-a92153394a8a creatorsName: createTimestamp: 20100113005909Z entryCSN: 20100113005909.540613Z#000000#000#000000 modifiersName: modifyTimestamp: 20100113005909Z dn: cn=admin,dc=example,dc=com objectClass: simpleSecurityObject objectClass: organizationalRole cn: admin description: LDAP administrator userPassword:: e2NyeXB0fVA1d2NsRmgyNm5RcW8= structuralObjectClass: organizationalRole entryUUID: 99e9aeb8-942a-102e-82c6-a92153394a8a creatorsName: createTimestamp: 20100113005909Z entryCSN: 20100113005909.545578Z#000000#000#000000 modifiersName: modifyTimestamp: 20100113005909Z ~# _ Edit /etc/ldap/slapd.conf and comment out the logging option, which will return it to its default value (256): #loglevel "none" 5. ldap.conf Edit /etc/ldap/ldap.conf and use these two lines: BASE dc=example,dc=com URI ldap://ldapks2.example.com/ This configuration file is used to set system-wide defaults for LDAP clients. 6. Syncprov Switch over to the provider server, ldapks1.example.com, to make some changes there. Start by installing a package that will prevent a replication error from appearing in the syslog: root@ldapks1:~# apt-get install sasl2-bin A total of two packages are installed as a result, including one dependency: db4.6-util 4.6.21-11 Berkeley v4.6 Database Utilities sasl2-bin 2.1.22.dfsg1-23+lenny1 Cyrus SASL - administration programs for SASL users database The installation also warns that saslauthd requires some tending to before it will start up automatically, but that can be ignored. All that is important here is that the install process creates a small database file, /etc/sasldb2, that slapd needs to have write access to so that certain error messages will not be generated. Next, make sure that the sasl group has access to the file: root@ldapks1:~# chgrp sasl /etc/sasldb2 Then edit /etc/group and add openldap to the sasl group: sasl:x:45:openldap Then edit /etc/ldap/slapd.conf and make several changes to it. First, add these four lines to the end of the first database section to load, activate and configure the Sync Provider overlay: access to * by users read by * none moduleload syncprov overlay syncprov syncprov-checkpoint 100 10 syncprov-sessionlog 100 Also, add three new eq index entries: index objectClass eq index uid eq index entryUUID eq index entryCSN eq See this section for an explanation of the last two sets of modifications. Having committed these changes to the slapd.conf file on ldapks1, it becomes necessary to reindex the database. Since it is best to run the appropriate command as the openldap user, first make this possible by altering the following line (that may not have the same UID and GID numbers) in the /etc/passwd file: openldap:x:105:107:OpenLDAP Server Account,,,:/var/lib/ldap:/bin/sh Now stop the LDAP service, regenerate the database indices as the openldap user, and restart the LDAP service: root@ldapks1:~# /etc/init.d/slapd stop Stopping OpenLDAP: slapd. root@ldapks1:~# su -c /usr/sbin/slapindex openldap root@ldapks1:~# /etc/init.d/slapd start Starting OpenLDAP: slapd. root@ldapks1:~# _ 7. Kstart Return to ldapks2. To keep its copy of the database in sync, the consumer must contact the provider and authenticate itself just like any other client. It has previously been shown how to do this with a simple bind and a password, but in this case Kerberos will be used to take care of both slapd consumer authentication to the provider and encryption of the entire replication process. To make this possible, an initial Kerberos ticket (a TGT) must be obtained automatically on behalf of the openldap user, which owns the slapd process, and it must be renewed regularly. One way to do this is to run kinit -k with a cron job, but a better solution is to use a modified version of kinit, called k5start. Install it with: ~# apt-get install kstart This is the only package that gets installed as a result: kstart 3.14-1 Kerberos kinit supporting AFS and ticket refreshing To configure it, just add this line to the end of the /etc/inittab file to start running k5start in the background soon after the system boots up: KS:2345:respawn:/usr/bin/k5start -U -f /etc/krb5.keytab -K 10 -l 24h -k /tmp/krb5cc_105 -o openldap This must be written as a single line (without the backslash)! A number of options have been used for this command:
After saving this modification to /etc/inittab, start k5start for the first time by forcing init to reload its configuration file: ~# kill -HUP 1 A new ticket cache file, /tmp/krb5cc_105, should be created almost immediately as a consequence. 8. sasldb2 Install a package, the sole purpose of which is to prevent a certain error from appearing in the syslog: ~# apt-get install sasl2-bin A total of two packages are installed as a result, including one dependency: db4.6-util 4.6.21-11 Berkeley v4.6 Database Utilities sasl2-bin 2.1.22.dfsg1-23+lenny1 Cyrus SASL - administration programs for SASL users database The sasldb2 database file is installed here for the same reasons as on ldapks1. Begin by making sure that the sasl group has access to the file: ~# chgrp sasl /etc/sasldb2 Then edit /etc/group and add openldap to the sasl group: sasl:x:45:openldap 9. Slapd kerberization This step is about kerberizing OpenLDAP. A number of requirements have already been met, but there is more. First, install this one package: ~# apt-get install libsasl2-modules-gssapi-mit Only one package is installed as a result with no dependencies: libsasl2-modules-gssapi-mit 2.1.22.dfsg1-23+lenny1 Cyrus SASL - pluggable authentication modules (GSSAPI) First, change the permissions and ownership of the Kerberos service keytab file to allow slapd to read it: ~# chmod 640 /etc/krb5.keytab ~# chown root.openldap /etc/krb5.keytab ~# _ Next, three different files must be modified. First, edit /etc/default/slapd and uncomment a line near the end that exports as a variable the location of the Kerberos system keytab file: export KRB5_KTNAME=/etc/krb5.keytab Edit /etc/ldap/ldap.conf and add the following line, which specifies the authentication mechanism, to the end of the file: SASL_MECH GSSAPI Then, edit /etc/ldap/slapd.conf and add these lines to the end of the Global section (before any database definitions): tool-threads 1 authz-regexp uid=([^,]+),cn=example.com,cn=gssapi,cn=auth uid=$1,ou=people,dc=example,dc=com sasl-realm EXAMPLE.COM This authz-regexp statement is exactly the same as on the provider server, ldapks1. 10. Syncrepl Continue to edit /etc/ldap/slapd.conf, this time to enable the replication process. Start by adding an entry for a hard-coded root user, which is necessary for replication: # rootdn "cn=admin,dc=example,dc=com" rootdn "cn=manager" It does not matter that the rootdn is not part of the DIT; just as long as it exists and is unique within the same system of replicating servers. Next, add three new eq index entries: index objectClass eq index uid eq index entryUUID eq index entryCSN eq The first eq index will facilitate searches for uid entries, which will also speed up the login process, while the other two eq indexes will accelerate the replication process. Modify the ACLs by eliminating the lines with admin from the three existing directives, as well as those that give clients access to passwords, so that they look like this: access to attrs=userPassword,shadowLastChange by * none access to dn.base="" by * read access to * by users read by * none It is pointless to add the same access directives here as on the provider to allow clients to write, since all database replicas are strictly read-only. If clients attempt to write to it anyway, they will be given a referral (URL) to the provider before these ACLs are ever encountered. Then add this replication stanza to the end of the first database section: access to * by users read by * none syncrepl rid=123 provider=ldap://ldapks.example.com:389/ type=refreshAndPersist retry="60 30 300 +" searchbase="dc=example,dc=com" bindmethod=sasl saslmech=gssapi With the refreshAndPersist replication strategy, any changes made to the provider database are immediately sent to the consumer. Note that the provider's alias, ldapks, is used here, so if the OpenLDAP provider is ever moved to a different host, only the alias will need to be changed. Alternatively, in case a more bandwidth-friendly solution is desired, the refreshOnly replication strategy can be used instead: syncrepl rid=123 provider=ldap://ldapks.example.com:389/ type=refreshOnly interval=00:00:05:00 searchbase="dc=example,dc=com" bindmethod=sasl saslmech=gssapi Usually, complete replication of the provider's copy of the OpenLDAP database is only possible if specific access rules are added to the provider's slapd.conf to ensure that each consumer server has read access to everything. However, in this case it is currently unnecessary to change the provider's ACLs, because other than a few unnecessary passwords, all users have complete access to the DIT anyway. 11. Referrals Still editing /etc/ldap/slapd.conf, add a referral to the end of the file, below the syncrepl stanza, to inform clients where to find the provider when they need to make changes to the LDAP database: bindmethod=sasl saslmech=gssapi updateref ldap://ldapks.example.com:389/ Finally, since some LDAP clients do not understand referrals, implement the chain overlay to allow slapd to chase referrals on behalf of such clients by adding the following lines to the end of the global section of slapd.conf, before any database definitions: sasl-realm EXAMPLE.COM moduleload back_ldap overlay chain chain-uri ldap://ldapks.example.com:389/ chain-rebind-as-user TRUE chain-idassert-bind bindmethod=sasl saslmech=gssapi mode=self chain-return-error TRUE Having saved all of the previous changes to /etc/slapd.conf, stop the LDAP service, delete the now-redundant local database, and restart the service. This will cause the consumer to synchronize its database with the provider for the first time: ~# /etc/init.d/slapd stop Stopping OpenLDAP: slapd. ~# rm /var/lib/ldap/* ~# /etc/init.d/slapd start Starting OpenLDAP: slapd. ~# _ If the original copy of the local database is not deleted, its one existing entry, the domain component, will not be replaced with that of the provider, even though the rest of the DIT will be synchronized. If everything has worked as expected, it should be possible to run the slapcat command on both the consumer and the provider and verify that, in both cases, the entire output in exactly the same. 12. Authentication test Run some tests. First try a simple unauthenticated (-x) LDAP query: ~# ldapsearch -x -LLL dn: dc=example,dc=com objectClass: top objectClass: dcObject objectClass: organization o: example.com dc: example dn: ou=people,dc=example,dc=com objectClass: organizationalUnit ou: people dn: ou=groups,dc=example,dc=com objectClass: organizationalUnit ou: groups ~# _ This should work without any problems (and verify that the initial replication has been successful). However, the authenticated version of this query will give an error: ~# ldapsearch -LLL SASL/GSSAPI authentication started ldap_sasl_interactive_bind_s: Local error (-2) ~# _ The solution is to first acquire a Kerberos ticket for the admin user (password Lampropeltis): ~# kinit admin Password for admin@EXAMPLE.COM: Lampropeltis ~# _ A verification of the ticket should show a success: ~# klist -5 Ticket cache: FILE:/tmp/krb5cc_0 Default principal: admin@EXAMPLE.COM Valid starting Expires Service principal 01/13/10 03:54:36 01/14/10 03:54:18 krbtgt/EXAMPLE.COM@EXAMPLE.COM ~# _ Now the authenticated version of the query should also work: ~# ldapsearch -LLL SASL/GSSAPI authentication started SASL username: admin@EXAMPLE.COM SASL SSF: 56 SASL data security layer installed. dn: dc=example,dc=com objectClass: top objectClass: dcObject objectClass: organization o: example.com dc: example dn: ou=people,dc=example,dc=com objectClass: organizationalUnit ou: people dn: ou=groups,dc=example,dc=com objectClass: organizationalUnit ou: groups ~# _ 13. Proxy authorization Before the chaining configuration added in step 11 will work, more changes first have to be made to the OpenLDAP provider server, ldapks1.example.com. What is required is something called SASL proxy authorization. With this mechanism it is possible to allow an authenticated user, such as the consumer server in this example, to assume the identity of other users and use that to relay their write requests on to the provider server. The ability to assume another user's identity is important, as it would otherwise not be possible to enforce existing access rules. A number of changes are needed to enable proxy authorization. First, a new LDAP object must be created that corresponds to the consumer user's Kerberos identity and includes an authzTo attribute that will allow it to act as an authorization proxy for certain users. A new organizational unit will also be created in which the new consumer server object will reside. Second, an extra authz-regexp directive will then be added to slapd.conf to add an additional search for users in the new origanizational unit. Third and last, an authz-policy directive will be added to the slapd.conf file. The new LDAP object to represent ldapks2 is required because of the need to authorize it to act as a proxy entity. At the moment it is only able to replicate with ldapks1 thanks to Kerberos authentication, but without an LDAP object to represent it as well, any form of LDAP authorization will not be possible. An examination of /var/log/syslog on ldapks1 will show that, when ldapks2 binds for the purpose of replication, its LDAP identity is currently part of ou=people: BIND authcid="ldap/ldapks2.example.com" \ authzid="ldap/ldapks2.example.com" BIND dn="uid=ldap/ldapks2.example.com,ou=people,dc=example,dc=com" \ mech=GSSAPI sasl_ssf=56 ssf=56 This must be changed. On ldapks1, start by creating an LDIF file, called ~/ldapks2.ldif, with the following contents: dn: ou=consumers,dc=example,dc=com objectClass: organizationalUnit ou: consumers dn: cn=ldapks2,ou=consumers,dc=example,dc=com cn: ldapks2 objectClass: simpleSecurityObject objectClass: organizationalRole description: LDAP server2 replicator authzTo: dn.regex:^uid=[^,]+,ou=people,dc=example,dc=com$ userPassword: {CRYPT}* This will create and origanizational unit and an organizationalRole object. Note the last two attributes: authzTo is a source rule that determines which user identities it is allowed to assume; in this case its value is a regular expression that matches all uid objects in the ou=people,dc=example,dc=com container. The userPassword attribute, on the other hand, is only included because it is required for organizationalRole objects, but since it is not actually necessary here, an invalid hash is used for its value. To actually add these new objects, authenticate as the administrative user and add them to the database using the following commands: root@ldapks1:~# kinit admin Password for admin@EXAMPLE.COM: Lampropeltis root@ldapks1:~# ldapadd -f ~/ldapks2.ldif adding new entry "ou=consumers,dc=example,dc=com" adding new entry "cn=ldapks2,ou=consumers,dc=example,dc=com" root@ldapks1:~# _ Next, edit /etc/ldap/slapd.conf and add an additional authz-regexp statement: authz-regexp uid=ldap/([^/\.]+).example.com,cn=example.com,cn=gssapi,cn=auth cn=$1,ou=consumers,dc=example,dc=com authz-regex uid=([^,]+),cn=example.com,cn=gssapi,cn=auth uid=$1,ou=people,dc=example,dc=com This new authz-regexp statement, inserted above the existing one, will only match GSSAPI-format names involving Kerberos service principals for the LDAP protocol. After that, the second authz-regexp statement will map all other GSSAPI names to the ou=people organizational unit just as it did as before. Then, add this line to the end of the slapd.conf Global section: sasl-realm EXAMPLE.COM authz-policy to This statement enables proxy authorization using rules associated with the authzTo attribute of the authentication DN (in this case cn=ldapks2). Without this, the authzTo attribute that was added to the cn=ldapks2 object would be ignored. Last, still editing /etc/ldap/slapd.conf, change the following ACL as indicated: access to attrs=userPassword,shadowLastChange by dn.one="ou=consumers,dc=example,dc=com" read by * none This will ensure that all entries in ou=consumers, including ldapks2, will have full access to the DIT. Having made these changes to /etc/slapd.conf, save them and restart the LDAP service: root@ldapks1:~# /etc/init.d/slapd restart Stopping OpenLDAP: slapd. Starting OpenLDAP: slapd. root@ldapks1:~# _ Because of the changes to the ACLs on ldaks1, switch back to ldapks2 now and force it to rebuild its database from scratch once more: ~# /etc/init.d/slapd stop Stopping OpenLDAP: slapd. ~# rm /var/lib/ldap/* ~# /etc/init.d/slapd start Starting OpenLDAP: slapd. ~# _ 14. Proxy auth test This last step will test whether the newly added proxy authorization actually works. This is easily done on the consumer server, as admin, using the ldapadd command. If it works, the newly added entries will become immediately available on the consumer server (assuming refreshAndPersist replication is used). First, create a file, called ~/ccolumbus.ldif, to add a new user account, based on an existing Kerberos account by the same name, and add this information to it: dn: cn=ccolumbus,ou=groups,dc=example,dc=com cn: ccolumbus gidNumber: 20001 objectClass: top objectClass: posixGroup dn: uid=ccolumbus,ou=people,dc=example,dc=com uid: ccolumbus uidNumber: 20001 gidNumber: 20001 cn: Christopher sn: Columbus objectClass: top objectClass: person objectClass: posixAccount objectClass: shadowAccount loginShell: /bin/bash homeDirectory: /home/ccolumbus userPassword: {CRYPT}* Authenticate first if necessary: ~# kinit admin Password for admin@EXAMPLE.COM: Lampropeltis ~# _ Then add the new user: ~# ldapadd -f ccolumbus.ldif SASL/GSSAPI authentication started SASL username: admin@EXAMPLE.COM SASL SSF: 56 SASL data security layer installed. adding new entry "cn=ccolumbus,ou=groups,dc=example,dc=com" adding new entry "uid=ccolumbus,ou=people,dc=example,dc=com" ~# _ Obviously, this is what success looks like. Consequently, the following entries should be seen in the /var/log/syslog file on ldapks1 as evidence of the proxy event that just transpired: PROXYAUTHZ dn="uid=admin,ou=people,dc=example,dc=com" ADD dn="cn=ccolumbus,ou=groups,dc=example,dc=com" RESULT tag=105 err=0 text= PROXYAUTHZ dn="uid=admin,ou=people,dc=example,dc=com" ADD dn="uid=ccolumbus,ou=people,dc=example,dc=com" RESULT tag=105 err=0 text= Further examination of the syslog on ldapks1 should also show that whenever ldapks2 is restarted, its replication process binds to the provider with the new LDAP name created for it in step 13: BIND authcid="ldap/ldapks2.example.com@EXAMPLE.COM" \ authzid="ldap/ldapks2.example.com@EXAMPLE.COM" BIND dn="cn=ldapks2,ou=consumers,dc=example,dc=com" mech=GSSAPI \ sasl_ssf=56 ssf=56 15. See also
16. Further reading
17. 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. |