{auth, auth1, auth2, … authN}.offbyone.lan, .lair.lan, and .dslab.lan are the authentication servers in use in the BITS universe.
hostname | RAM | disk | swap | OS | Kernel |
---|---|---|---|---|---|
auth1.offbyone.lan | 128MB | 2GB (/) | 128MB | Debian 6.0 “Squeeze” (AMD64) | 2.6.32-5-xen-amd64 |
auth2.offbyone.lan | 128MB | 2GB (/) | 128MB | Debian 6.0 “Squeeze” (AMD64) | 2.6.32-5-xen-amd64 |
auth3.lair.lan | 128MB | 2GB (/) | 128MB | Debian 6.0 “Squeeze” (AMD64) | 2.6.32-5-xen-amd64 |
The Xen config files for one of the auth-class VMs follows:
auth1.offbyone.lan was created by running:
halfadder:~# xen-create-image --hostname=auth1 --mac 00:16:3E:3C:83:50 --role=udev
Its Xen configuration file is as follows:
########################################################################## # LAIR Xen VM configuration file (auth1.offbyone.lan) ########################################################################## ################################################# # Kernel + memory size # bootloader = '/usr/lib/xen-default/bin/pygrub' vcpus = '1' memory = '128' ################################################# # Disk device(s). # root = '/dev/xvda1 ro' disk = [ 'file:/xen/images/auth1.disk,xvda1,w', 'file:/xen/images/auth1.swap,xvda2,w' ] ################################################# # Hostname # name = 'auth1' ################################################# # Networking # dhcp = 'dhcp' vif = [ 'mac=00:16:3E:3C:83:50' ] ################################################# # Behaviour # on_poweroff = 'destroy' on_reboot = 'restart' on_crash = 'restart'
Machine | Interface | IP Address | MAC Address | Other Names |
---|---|---|---|---|
auth.offbyone.lan | eth0 | 10.80.2.8 | N/A | |
auth.lair.lan | eth0 | 10.80.1.8 | N/A | |
auth1.offbyone.lan | eth0 | 10.80.2.9 | 00:16:3E:3C:83:50 | auth1.lair.lan |
auth2.offbyone.lan | eth0 | 10.80.2.10 | 00:16:3E:3C:83:51 | auth2.lair.lan |
auth3.lair.lan | eth0 | 10.80.1.11 | 00:16:3E:42:EE:4A | auth3.offbyone.lan |
The method followed here is derived (and heavily so) from the OpenLDAP provider on Debian Squeeze tutorial at http://www.rjsystems.nl/en/2100-d6-openldap-provider.php … Information here is summarized from that document and adapted to fit the LAIR/BITS environment.
LDAP services are provided via slapd. This used to be configured in a file known as /etc/ldap/slapd.conf, but with Debian Squeeze, the version of OpenLDAP used (2.4.23-7), configuration information is now stored in an LDAP database, and manipulated via the various LDAP command-line tools (think registry).
Because we are also interested in configuring replication and having multiple LDAP servers, these instructions will by default include such instructions.
One immediate benefit of this new structure is that slapd can remain running… we no longer need to shut it down to perform various operations.
To verify correct operation and validate various aspects of operational success, we will start off by installing the following (on all auth machines):
We'll want to install lair-std and lair-vm, and likely eventually lrrd-node, so do the following on both auth's:
all_auth:~# echo "deb http://mirror/lair squeeze main" >> /etc/apt/sources.list all_auth:~# aptitude update ... all_auth:~# swapon /dev/xvda2 all_auth:~# aptitude install lair-std lair-vm ntp ...
All auth-class systems should now be at a good initial state.
lair-std seems to have a bug that prevents proper domain name formatting in /etc/hosts… until this is fixed, be sure to manually check /etc/hosts to ensure that all domain names are set, and properly.
Additionally, to make Debian's slapd install scripts bootstrap with the desired “dc”, we're going to intentionally add an extra domain. As a result, the correct /etc/hosts files on auth1 and auth2 should be as follows:
###LAIRCONF### 127.0.0.1 localhost.localdomain localhost 10.80.2.38 lab46.corning-cc.edu lab46.offbyone.lan lab46.lair.lan lab46 10.80.2.3 nfs.offbyone.lan nfs 10.80.2.9 auth1.lair.bits auth1.offbyone.lan auth1 10.80.2.10 auth2.lair.bits auth2.offbyone.lan auth2 10.80.1.11 auth3.lair.bits auth3.lair.lan auth3
Once slapd is installed and running, we can remove the auth[12].lair.bits phrases.
At this point, to ensure everything is in order, give both systems a reboot.
Since we are going to serve LDAP, we'll now do the following:
all_auth:~# aptitude install slapd ldap-utils ...
There will be a prompt for an administrator password.
As it turns out, there's currently a bug in the OpenLDAP code, as shipped by both Debian and still residing within the vanilla OpenLDAP releases, that causes errors (even affecting the ability for slapd to run) when enabling the chaining functionality, as is the case with LDAP consumers.
For this reason, the Debian packages were manually rebuilt, and a patch applied which resolves this issue. Until the fix is officially provided by the Debian packages, we'll have to rely on these packages instead.
Either rebuild the packages from source (follow the directions in the rjsystems.nl tutorial) or grab an existing copy from other prior efforts.
So instead of installing slapd and ldap-utils above, we'll instead want to do this:
auth_consumer:~# aptitude install libsasl2-2 libltdl7 libperl5.10 libslp1 unixodbc ... auth_consumer:~# dpkg -i ldap-utils_2.4.23-7patched1_amd64.deb libldap-2.4-2_2.4.23-7patched1_amd64.deb slapd_2.4.23-7patched1_amd64.deb ...
Following the installation, we can check to make sure everything is in order. The intent is to use “dc=lair,dc=bits” for our LDAP database, so let's see if our hack to /etc/hosts has paid off:
all_auth:~# slapcat hdb_db_open: database "dc=lair,dc=bits": unclean shutdown detected; attempting recovery. hdb_db_open: database "dc=lair,dc=bits": recovery skipped in read-only mode. Run manual recovery if errors are encountered. dn: dc=lair,dc=bits objectClass: top objectClass: dcObject objectClass: organization o: lair.bits dc: lair structuralObjectClass: organization entryUUID: fadb154e-a654-102f-9d47-4b2dc132a5e2 creatorsName: cn=admin,dc=lair,dc=bits createTimestamp: 20101227223249Z entryCSN: 20101227223249.652609Z#000000#000#000000 modifiersName: cn=admin,dc=lair,dc=bits modifyTimestamp: 20101227223249Z dn: cn=admin,dc=lair,dc=bits objectClass: simpleSecurityObject objectClass: organizationalRole cn: admin description: LDAP administrator userPassword:: e1NTSEF9VG1LV2FDK1QxVkNTSk16MGlCWUQxTnVuOHFkeXdyTEU= structuralObjectClass: organizationalRole entryUUID: fadb71d8-a654-102f-9d48-4b2dc132a5e2 creatorsName: cn=admin,dc=lair,dc=bits createTimestamp: 20101227223249Z entryCSN: 20101227223249.654994Z#000000#000#000000 modifiersName: cn=admin,dc=lair,dc=bits modifyTimestamp: 20101227223249Z all_auth:~#
If you see any “dc=nodomain” or things other than “dc=lair,dc=bits” (or the desired name), then you'll likely want to remove (purge), twiddle settings, and reinstall slapd until this becomes correct.
With further LDAP knowledge and experience, this could likely be fixed with a customized ldif file.
Hook up the rest of the system with our new LDAP service:
BASE dc=lair,dc=bits URI ldap://auth1.offbyone.lan/
BASE dc=lair,dc=bits URI ldap://auth2.offbyone.lan/
Before we go any further, we should remove the hack we put in place to facilitate (trick) the Debian installation scripts into giving us precisely what we want. It would of course been easier had we just used our default domain, but since the LAIR runs 3 different domains, and the long-term intent is to hook up the authentication domains at all BITS endpoints, I opted to adopt the .bits “domain” for authentication services.
So, go and edit /etc/hosts on BOTH auth's, and remove the reference to .lair.bits. The resulting file should look like this:
###LAIRCONF### 127.0.0.1 localhost.localdomain localhost 10.80.2.8 auth.offbyone.lan auth.lair.lan auth 10.80.2.38 lab46.corning-cc.edu lab46.offbyone.lan lab46.lair.lan lab46 10.80.2.3 nfs.offbyone.lan nfs 10.80.2.9 auth1.offbyone.lan auth1 10.80.2.10 auth2.offbyone.lan auth2
To aid in debugging, the rjsystems.nl tutorial has us apply the following changes (I put in a file called olc1.ldif):
# 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
We then apply it as follows:
auth1:~# ldapmodify -QY EXTERNAL -H ldapi:/// -f ~/olc1.ldif modifying entry "cn=config" modifying entry "olcDatabase={1}hdb,cn=config" auth1:~#
Because we're on the machine running the server, we can “get around” the need for authentication to make changes here to cn=config (which would make sense– why would we want to allow modifications to cn=config over the network?).
We'll now push the initial structure we'd like to maintain in our LDAP tree.
To do this, we need the information in an ldif file (see structure.ldif):
dn: ou=people,dc=lair,dc=bits objectClass: organizationalUnit ou: people dn: ou=groups,dc=lair,dc=bits objectClass: organizationalUnit ou: groups dn: ou=hosts,dc=lair,dc=bits objectClass: organizationalUnit ou: hosts
With which we can use ldapadd to place it in our database:
auth1:~# ldapadd -xWD cn=admin,dc=lair,dc=bits -f structure.ldif Enter LDAP Password: <LDAP admin password> adding new entry "ou=people,dc=lair,dc=bits" adding new entry "ou=groups,dc=lair,dc=bits" adding new entry "ou=hosts,dc=lair,dc=bits" auth1:~#
With the database in an amenable format to support our data, we will now transition our existing LDAP user data into the new one.
There are some mild format changes that need to take place, in addition to some additions and deletions of data.
Hopping onto auth (the current LDAP server), we will obtain a copy of the LDAP database as follows:
auth:~# ldapvi --out --discover -D "cn=admin,dc=lair,dc=lan" > ldapdb.ldif --- Login Type M-h for help on key bindings. Filter or DN: cn=admin,dc=lair,dc=lan Password: <LDAP admin password> auth:~#
This will produce a file in the current directory called ldapdb.ldif.
There are some entries in this LDIF that are not needed (due to the fact they already exist in the new LDAP database).
Specifically, we want to remove the following from the top of the file:
dn: dc=lair,dc=lan objectClass: top objectClass: dcObject objectClass: organization o: lair_lan dc: lair dn: cn=admin,dc=lair,dc=lan objectClass: simpleSecurityObject objectClass: organizationalRole cn: admin description: LDAP administrator userPassword: {SSHA}kjsdhfjksdf/sdlfkjsdf+223kKOA dn: ou=People,dc=lair,dc=lan ou: People objectClass: organizationalUnit dn: ou=Group,dc=lair,dc=lan ou: Group objectClass: organizationalUnit
Because we've already defined our distinguished name, admin is there, and we've just added our ou's for people and groups.
So just remove this data.
This will leave us starting with the lair group.
We'll also want to remove the 'replica' object, which was used in the old LDAP replication. We'll be creating a new object to perform this functionality.
So search for and remove the following lines:
dn: cn=replica,dc=lair,dc=bits objectClass: simpleSecurityObject objectClass: organizationalRole cn: replica description: LDAP replicator userPassword: {SSHA}sdjkfhWadsFSdg+hs/a4
Now on to some substitutions (doesn't have to be done on old auth… we can copy our file somewhere and perform the changes):
auth:~# cat ldapdb.ldif | sed 's/dc=lan/dc=bits/g' \ > | sed 's/ou=Group/ou=groups/g' | sed 's/ou=People/ou=people/g' \ # correct our ou's > | sed 's/^objectClass: account/objectClass: top\nobjectClass: person/g' \ # fix objectClasses > | sed 's/^cn: \([a-zA-z]*\) \([a-zA-Z]*\)$/cn: \1\nsn: \2/g' \ # cn/sn fix 1 (first/last) > | sed 's/^cn: \([a-zA-z]*\) \([a-zA-Z]\.\) \([a-zA-Z]*\)$/cn: \1 \2\nsn: \3/g' \ # cn/sn fix 2 (initials) > | sed 's/^cn: \([a-zA-z]*\) \([a-zA-Z]*\) \([a-zA-Z]*\)$/cn: \1\nsn: \2 \3/g' \ # cn/sn fix 3 (3 words) > | sed 's/^objectClass: posixGroup/objectClass: top\nobjectClass: posixGroup/g' \ # fix group objectClasses > | sed '/^shadowLastChange/d' | sed '/^host: /d' > ldapdbnew.ldif # remove unneeded things auth:~#
A few accounts will be pruned by hand (since there are so few of these exceptions that don't warrant a regex).
When done with pruning, be sure the resultant file is copied over to auth1.
Time to add the data to our new database:
auth1:~# ldapadd -cxWD cn=admin,dc=lair,dc=bits -f ~/ldapdbnew.ldif Enter LDAP Password: <LDAP admin password> adding new entry "cn=lair,ou=groups,dc=lair,dc=bits" adding new entry "uid=wedge,ou=people,dc=lair,dc=bits" adding new entry "uid=ian,ou=people,dc=lair,dc=bits" adding new entry "uid=squirrel,ou=people,dc=lair,dc=bits" ... auth:~#
Any errors in the entry, and that account would not be added. Luckily, we can just scan the output of the ldapadd to look for errors, make the appropriate corrections, and run the command again (we'll then get a bunch of “ldap_add: Already exists (68)” messages, but these are harmless) to add the corrected entries.
Once the data is added, we can do some quick checks to ensure it is there and works.
Does 'wedge' exist?
auth1:~# ldapsearch -xLLL uid=wedge dn: uid=wedge,ou=people,dc=lair,dc=bits uid: wedge cn: Matthew sn: Haas objectClass: top objectClass: person objectClass: posixAccount objectClass: shadowAccount loginShell: /bin/bash uidNumber: 1020 gidNumber: 1000 homeDirectory: /home/wedge gecos: Matthew Haas auth1:~#
Check.
Can 'wedge' authenticate and verify its identity?
auth:~# ldapwhoami -xD uid=wedge,ou=people,dc=lair,dc=bits -W Enter LDAP Password: <wedge LDAP password> dn:uid=wedge,ou=people,dc=lair,dc=bits auth1:~#
Also good.
At this point, LDAP (via slapd) should be installed and running.
The method followed here is derived (and heavily so) from the OpenLDAP consumer on Debian Squeeze tutorial at http://www.rjsystems.nl/en/2100-d6-openldap-consumer.php … Information here is summarized from that document and adapted to fit the LAIR/BITS environment.
With a basic slapd database on auth2 and auth3, and a fully functional LDAP server on auth1, we will be moving to configure auth2 and auth3 as an LDAP consumers (slave servers), so we'll have some level of redundancy/availability of LDAP services in the LAIR.
As in our past replicating instantiations, we need an LDAP object to bind as to perform the synchronization activities.
The aim is to have an LDAP consumer in both the offbyone.lan and lair.lan domains, so we'll end up with an auth2 and auth3 VM. For our purposes we'll create objects called auth2repl and auth3repl, which need to be added to the existing LDAP database on auth1.
Its LDIF is as follows:
dn: cn=auth2repl,dc=lair,dc=bits objectClass: simpleSecurityObject objectClass: organizationalRole cn: authrepl description: LDAP auth2 replicator userPassword: chosen_password - dn: cn=auth3repl,dc=lair,dc=bits objectClass: simpleSecurityObject objectClass: organizationalRole cn: authrepl description: LDAP auth3 replicator userPassword: chosen_password
And then to add it to the database (note we're on auth1):
auth1:~# ldapadd -cxWD cn=admin,dc=lair,dc=bits -f ~/authrepl.ldif Enter LDAP Password: <LDAP admin password> adding new entry "cn=auth2repl,dc=lair,dc=bits" adding new entry "cn=auth3repl,dc=lair,dc=bits" auth1:~#
Also as in prior LDAP synchronization attempts, we'll be making use of the syncrepl functionality. The LDIF to provide this functionality is as follows (I put in a file called syncrepl.ldif:
# Remove olcAccess ACL (since it only allows admin to write) dn: olcDatabase={1}hdb,cn=config changetype: modify delete: olcAccess olcAccess: {0}to attrs=userPassword,shadowLastChange by self write by anonymous auth by dn="cn=admin,dc=lair,dc=bits" write by * none - # Add it back in, only also add in the ability for the authrepl object to read data add: olcAccess olcAccess: {0}to attrs=userPassword,shadowLastChange by self write by dn="cn=admin,dc=lair,dc=bits" write by dn="cn=auth2repl,dc=lair,dc=bits" read by dn="cn=auth3repl,dc=lair,dc=bits" read by anonymous auth by * none - # add new indexing option add: olcDbIndex olcDbIndex: entryUUID eq - # avoid verbose logs later through optimization add: olcDbIndex olcDbIndex: uid,uidNumber,gidNumber,memberUid,uniqueMember,objectClass,cn eq - # add another indexing option add: olcDbIndex olcDbIndex: entryCSN eq # enable the syncprov module dn: cn=module{0},cn=config changetype: modify add: olcModuleLoad olcModuleLoad: {1}syncprov # specify syncprov attributes dn: olcOverlay=syncprov,olcDatabase={1}hdb,cn=config changetype: add objectClass: olcOverlayConfig objectClass: olcSyncProvConfig olcOverlay: {0}syncprov olcSpCheckpoint: 100 10 olcSpSessionlog: 100
And then adding it (on auth1):
auth1:~# ldapmodify -QY EXTERNAL -H ldapi:/// -f ~/syncrepl.ldif modifying entry "olcDatabase={1}hdb,cn=config" modifying entry "cn=module{0},cn=config" adding new entry "olcOverlay=syncprov,olcDatabase={1}hdb,cn=config" auth1:~#
Now that auth1 has been configured to be a provider, we now turn to configuring auth2 to act as an LDAP consumer.
We'll need to apply some information to the LDAP database on auth2, the LDIF (replconsume.ldif):
# for debugging purposes, crank up logging on auth2 dn: cn=config changetype: modify replace: olcLogLevel olcLogLevel: stats # remove the current olcAccess {0} ACL dn: olcDatabase={1}hdb,cn=config changetype: modify delete: olcAccess olcAccess: {0}to attrs=userPassword,shadowLastChange by self write by anonymous auth by dn="cn=admin,dc=lair,dc=bits" write by * none - # set the olcAccess {0} ACL add: olcAccess olcAccess: {0}to attrs=userPassword,shadowLastChange by anonymous auth by * none - # remove the {2} olcAccess ACL delete: olcAccess olcAccess: {2}to * by self write by dn="cn=admin,dc=lair,dc=bits" write by * read - # alter the olcAccess ACL add: olcAccess olcAccess: {2}to * by * read - # replace olcRootDN replace: olcRootDN olcRootDN: cn=manager - # remove olcRootPW delete: olcRootPW - # indexing option (by entryCSN) add: olcDbIndex olcDbIndex: entryCSN eq - # indexing option (by entryUUID) add: olcDbIndex olcDbIndex: entryUUID eq - # indexing option (by uid) add: olcDbIndex olcDbIndex: uid eq - # indexing option (by cn) add: olcDbIndex olcDbIndex: cn eq - # indexing option (by ou) add: olcDbIndex olcDbIndex: ou eq - # indexing option (by dc) add: olcDbIndex olcDbIndex: dc eq - # syncrepl definition (who are we synchronizing with) add: olcSyncrepl olcSyncrepl: rid=102 provider="ldap://auth1.offbyone.lan:389/" type=refreshAndPersist retry="60 30 300 +" searchbase="dc=lair,dc=bits" bindmethod=simple binddn="cn=auth2repl,dc=lair,dc=bits" credentials=chosen_password
And add it to the LDAP database on auth2:
auth2:~# ldapmodify -QY EXTERNAL -H ldapi:/// -f ~/replconsume.ldif modifying entry "cn=config" modifying entry "olcDatabase={1}hdb,cn=config" auth2:~#
Because there is default data residing in the LDAP database on auth2, we'll want to clear it out before engaging in full replication activities.
Shut down slapd on auth2, remove the LDAP database, and restart:
auth2:~# /etc/init.d/slapd stop Stopping OpenLDAP: slapd. auth2:~# rm -f /var/lib/ldap/* auth2:~# /etc/init.d/slapd start Starting OpenLDAP: slapd. auth2:~#
After resuming slapd operations, I noticed the following appear in the logs:
Dec 30 18:20:31 auth2 slapd[1232]: do_syncrep2: rid=123 LDAP_RES_SEARCH_RESULT (4) Size limit exceeded Dec 30 18:20:31 auth2 slapd[1232]: do_syncrep2: rid=123 (4) Size limit exceeded Dec 30 18:20:31 auth2 slapd[1232]: do_syncrepl: rid=123 rc -2 retrying (29 retries left)
As it turns out, because we're not binding as an admin user, there are limits applied, and with the full size of the LAIR LDAP database, we easily exceed those default limits.
So what we'll need to do is disable those limits.
The following LDIF file (size.ldif) applied to the LDAP database on auth1 should do the trick:
# fix "Size limit exceeded" message in logs dn: olcDatabase={1}hdb,cn=config changetype: modify add: olcLimits olcLimits: dn.exact="cn=auth2repl,dc=lair,dc=bits" time.soft=unlimited time.hard=unlimited size.soft=unlimited size.hard=unlimited - add: olcLimits olcLimits: dn.exact="cn=auth3repl,dc=lair,dc=bits" time.soft=unlimited time.hard=unlimited size.soft=unlimited size.hard=unlimited
auth1:~# ldapmodify -Y external -H ldapi:/// -f ~/size.ldif SASL/EXTERNAL authentication started SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth SASL SSF: 0 modifying entry "olcDatabase={1}hdb,cn=config" auth1:~#
This appears to have resolved the problem.
Getting a sense of success with the recent LDAP efforts, certain actions should be taken to prepare the way for replication with other BITS peers.
The one big thing that will need to happen is the relocation of LDAP data to a specific directory– /var/lib/ldap/lair for LAIR LDAP, /var/lib/ldap/dslab for DSLAB LDAP, etc.
We'll handle this change on auth2 since it is more expendable in the case of a problem.
First up, the LDIF that will change the location of the LDAP database (dbdir.ldif):
# change where the LDAP database is located dn: olcDatabase={1}hdb,cn=config changetype: modify delete: olcDbDirectory - add: olcDbDirectory olcDbDirectory: /var/lib/ldap/lair
And then, prepping auth2 and actually performing the change:
auth2:~# mkdir /var/lib/ldap/lair /var/lib/ldap/dslab auth2:~# chown openldap:openldap /var/lib/ldap/lair auth2:~# chown openldap:openldap /var/lib/ldap/dslab auth2:~# ldapmodify -Y external -H ldapi:/// -f ~/dbdir.ldif SASL/EXTERNAL authentication started SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth SASL SSF: 0 modifying entry "olcDatabase={1}hdb,cn=config" auth2:~# /etc/init.d/slapd stop Stopping OpenLDAP: slapd. auth2:~# rm -f /var/lib/ldap/* rm: cannot remove `dslab': Is a directory rm: cannot remove `lair': Is a directory auth2:~# /etc/init.d/slapd start Starting OpenLDAP: slapd. auth2:~#
If we now check, /var/lib/ldap/ should be free of LDAP database files, whereas /var/lib/ldap/lair should now be populated with the files (in fact it will have transferred all the data fresh from auth1).
Success!
Right now, replication has established a provider and consumer… they both contain complete replicas of the LAIR LDAP database. But as it is, the provider (auth1) is the only resource that can commit writes, although both can read.
So when the various LAIR LDAP clients are configured, they'll have free selection over either auth1 or auth2, but if they reach auth2 and need to perform a write, we'll need to rig up some functionality so this will succeed.
What we want to rig up are LDAP referrals. Basically, what that will do is forward the write request from auth2 to auth1, enabling the action to go through despite auth2's inability to write.
The beauty is, the end client should notice no difference whether they are communicating with auth2 or auth1… it should just work.
Here is the LDIF (referral.ldif):
# set referral host dn: olcDatabase={1}hdb,cn=config changetype: modify add: olcUpdateref olcUpdateref: "ldap://auth1.offbyone.lan:389/" # load module for referring/chaining dn: cn=module{0},cn=config changetype: modify add: olcModuleLoad olcModuleLoad: {1}back_ldap # configuring chaining, which will force chasing of referrals dn: olcOverlay=chain,olcDatabase={-1}frontend,cn=config changetype: add objectClass: olcOverlayConfig objectClass: olcChainConfig olcOverlay: {0}chain olcChainReturnError: TRUE # more chaining configuration (to enable proxy-like behavior) dn: olcDatabase=ldap,olcOverlay={0}chain,olcDatabase={-1}frontend, cn=config changetype: add objectClass: olcLDAPConfig objectClass: olcChainDatabase olcDatabase: {0}ldap olcDbURI: "ldap://auth1.offbyone.lan:389/" olcDbRebindAsUser: TRUE olcDbIDAssertBind: bindmethod=simple binddn="cn=auth2repl,dc=lair,dc=bits" credentials=chosen_password mode=self
and adding it (we're on auth2):
auth2:~# ldapmodify -QY EXTERNAL -H ldapi:/// -f ~/referral.ldif modifying entry "olcDatabase={1}hdb,cn=config" modifying entry "cn=module{0},cn=config" adding new entry "olcOverlay=chain,olcDatabase={-1}frontend,cn=config" adding new entry "olcDatabase=ldap,olcOverlay={0}chain,olcDatabase={-1}frontend,cn=config" auth2:~#
The last step that needs to take place is to establish the proper authorization on auth1 so that it knows to trust these incoming connections from auth2 (since it'll be using the auth2repl/auth3repl objects).
So, we'll start on auth1… first file up is authorize.ldif:
# Enable ability for authrepl to proxy dn: cn=auth2repl,dc=lair,dc=bits changetype: modify add: authzTo authzTo: {0}dn.regex:^uid=[^,]+,ou=people,dc=lair,dc=bits$ authzTo: {1}dn.exact:cn=admin,dc=lair,dc=bits
And to add it:
auth1:~# ldapmodify -xWD "cn=admin,dc=lair,dc=bits" -f ~/authorize.ldif Enter LDAP Password: modifying entry "cn=auth2repl,dc=lair,dc=bits" auth1:~#
Finally, in a file called policy.ldif, we have the following, which enables acceptance of proxy requests:
# Enable proxy access dn: cn=config changetype: modify add: olcAuthzPolicy olcAuthzPolicy: to
Then to add it:
auth1:~# ldapmodify -QY EXTERNAL -H ldapi:/// -f ~/policy.ldif modifying entry "cn=config" auth1:~#
At this point, proxy access should be working! A write to auth2 should be properly forwarded and processed by auth1.
Due to the various structure changes to the LDAP database, there are some changes required to accomplish client LDAP access in the LAIR.
To facilitate matters, I have updated the lair-ldap package.. doing an “aptitude update” then upgrade or direct install of lair-ldap will bring it in… it is tested and known working with etch, lenny, and squeeze systems.
Here will be a breakdown of the various files and their settings needed to establish proper LDAP client access.
###LAIRCONF### # # $OpenLDAP: pkg/ldap/libraries/libldap/ldap.conf,v 1.9 2000/09/04 19:57:01 kurt Exp $ # # LDAP Defaults # BASE dc=lair,dc=bits URI ldap://auth1 ldap://auth2 ldap://auth3
###LAIRCONF### # # @(#)$Id: ldap.conf,v 1.36 2005/03/23 08:29:59 lukeh Exp $ # # This is the configuration file for the LDAP nameservice # switch library and the LDAP PAM module. # base dc=lair,dc=bits uri ldap://auth1 ldap://auth2 ldap://auth3 ldap_version 3 pam_password exop nss_base_passwd ou=people,dc=lair,dc=bits?one #nss_base_passwd ou=People,dc=dslab,dc=lan?one #nss_base_passwd ou=People,dc=sunyit,dc=lan?one nss_base_shadow ou=people,dc=lair,dc=bits?one #nss_base_shadow ou=People,dc=dslab,dc=lan?one #nss_base_shadow ou=People,dc=sunyit,dc=lan?one nss_base_group ou=groups,dc=lair,dc=bits?one #nss_base_group ou=Group,dc=dslab,dc=lan?one #nss_base_group ou=Group,dc=sunyit,dc=lan?one
###LAIRCONF### # # @(#)$Id: ldap.conf,v 2.47 2006/05/15 08:13:44 lukeh Exp $ # # This is the configuration file for the LDAP nameservice # switch library and the LDAP PAM module. # base dc=lair,dc=bits ldap_version 3 uri ldap://auth1 ldap://auth2 ldap://auth3 bind_policy soft nss_base_passwd ou=people,dc=lair,dc=bits?one #nss_base_passwd ou=People,dc=dslab,dc=lan?one #nss_base_passwd ou=People,dc=sunyit,dc=lan?one nss_base_shadow ou=people,dc=lair,dc=bits?one #nss_base_shadow ou=People,dc=dslab,dc=lan?one #nss_base_shadow ou=People,dc=sunyit,dc=lan?one nss_base_group ou=groups,dc=lair,dc=bits?one #nss_base_group ou=Group,dc=dslab,dc=lan?one #nss_base_group ou=Group,dc=sunyit,dc=lan?one
###LAIRCONF### # # /etc/nsswitch.conf # passwd: files [SUCCESS=return] ldap group: files [SUCCESS=return] ldap shadow: files [SUCCESS=return] ldap hosts: files dns networks: files protocols: files services: files ethers: files rpc: files netgroup: files
###LAIRCONF### # # /etc/pam.d/common-account - authorization settings common to all services # # try password file first, then ldap account [success=2 new_authtok_reqd=done default=ignore] pam_unix.so account [success=1 default=ignore] pam_ldap.so account requisite pam_deny.so account required pam_permit.so
###LAIRCONF### # # /etc/pam.d/common-auth - authentication settings common to all services # # try password file first, then ldap auth [success=2 default=ignore] pam_unix.so nullok_secure try_first_pass auth [success=1 default=ignore] pam_ldap.so use_first_pass auth requisite pam_deny.so auth required pam_permit.so
###LAIRCONF### # # /etc/pam.d/common-password - password-related modules common to all services # # try password files first, then ldap. enforce use of very strong passwords. password [success=2 default=ignore] pam_unix.so obscure sha512 password [success=1 user_unknown=ignore default=die] pam_ldap.so try_first_pass password requisite pam_deny.so password required pam_permit.so
NOTE: if the option use_authtok is present, especially on the line for pam_ldap.so, users will be able to log in, but a failure will take place when a write action to LDAP records occurs, such as in changing passwords. Removal of use_authtok will resolve this problem.
###LAIRCONF### # # /etc/pam.d/common-session - session-related modules common to all services # session [default=1] pam_permit.so session requisite pam_deny.so session required pam_permit.so session required pam_unix.so session optional pam_ldap.so
Prior to this LDAP update, we accomplished access to machines via the host: attribute stored in each user's LDAP entry. This functionality wasn't enabled this time around, so we're resorting to another method.
To control access to the systems, /etc/pam.d/sshd and /etc/security/access.conf are configured:
The default file has everything we need, just uncomment the following line:
account required pam_access.so
Depending on the level of access, we'll want to add a line like the following to this file:
-:ALL EXCEPT root lair:ALL EXCEPT LOCAL
What this line does is exclude access to anyone not root or in the lair group (we can add additional usernames or groups to this list to enable access.
To alter the level or type of information that slapd reports, we adjust the olcLogLevel attribute in the cn=config tree.
This can be done as follows:
auth1:~# ldapmodify -Y external -H ldapi:/// <<EOF dn: cn=config changetype: modify replace: olcLogLevel olcLogLevel: sync none EOF
Where olcLogLevel's old value is replaced with the new (in this case, sync and none).
We actually have a logical OR going on here to report this. The possible logging levels available are:
int | hex and symbol | description |
---|---|---|
0 | (0x0) | logging is disabled |
1 | (0x1 trace) | trace function calls |
2 | (0x2 packets) | debug packet handling |
4 | (0x4 args) | heavy trace debugging (function args) |
8 | (0x8 conns) | connection management |
16 | (0x10 BER) | print out packets sent and received |
32 | (0x20 filter) | search filter processing |
64 | (0x40 config) | configuration file processing |
128 | (0x80 ACL) | access control list processing |
256 | (0x100 stats) | stats log connections/operations/results |
512 | (0x200 stats2) | stats log entries sent |
1024 | (0x400 shell) | print communication with shell backends |
2048 | (0x800 parse) | entry parsing |
16384 | (0x4000 sync) | LDAPSync replication |
32768 | (0x8000 none) | only messages that get logged whatever log level is set |
auth1 was spewing into the logs the following quite often:
Dec 29 09:22:30 auth1 slapd[1236]: <= bdb_equality_candidates: (uidNumber) not indexed Dec 29 09:22:30 auth1 slapd[1236]: <= bdb_equality_candidates: (uidNumber) not indexed Dec 29 09:22:30 auth1 slapd[1236]: <= bdb_equality_candidates: (uidNumber) not indexed Dec 29 09:22:30 auth1 slapd[1236]: <= bdb_equality_candidates: (uidNumber) not indexed Dec 29 09:22:30 auth1 slapd[1236]: <= bdb_equality_candidates: (uidNumber) not indexed Dec 29 09:22:30 auth1 slapd[1236]: <= bdb_equality_candidates: (uidNumber) not indexed Dec 29 09:22:30 auth1 slapd[1236]: <= bdb_equality_candidates: (uidNumber) not indexed Dec 29 09:22:30 auth1 slapd[1236]: <= bdb_equality_candidates: (uidNumber) not indexed Dec 29 09:22:30 auth1 slapd[1236]: <= bdb_equality_candidates: (uidNumber) not indexed
I resolved it by doing the following:
auth1:~# ldapmodify -Y external -H ldapi:/// <<EOF dn: olcDatabase={1}hdb,cn=config changetype: modify replace: olcDbIndex olcDbIndex: uid,uidNumber,gidNumber,memberUid,uniqueMember,objectClass,cn eq EOF
This appeared to immediately resolve the problem.
It will likely be desired to view the settings in place on slapd, especially if we wish to change them, we need to know how to identify what we wish to change.
The following will perform a dump (to STDOUT) of the cn=config database:
auth1:~# slapcat -b cn=config | less
We can then do a search for what it is we are interested in “dn: cn=config”, “dn: olcDatabase={1}hdb,cn=config”, “dn: olcOverlay={0}syncprov,olcDatabase={1}hdb,cn=config”, etc.
At the end of the configuration process, the following packages have been installed on auth{1,2}: