1 I'm using [LDAP][] ([RFC 4510][rfc4510]) to maintain a centralized
2 address book at home. Here are my setup notes, mostly following
3 Gentoo's [LDAP howto][howto].
5 Install [OpenLDAP][] with the `ldap` USE flag enabled:
9 If you get complaints about a `cyrus-sasl` ↔ `openldap` dependency
10 cycle, you should temporarily (or permanently) disable the `ldap` USE
11 flag for `cyrus-sasl`:
13 # echo 'dev-libs/cyrus-sasl -ldap' > /etc/portage/package.use/ldap
14 # -ldap" emerge -av1 cyrus-sasl
17 Generate an administrative password:
21 Re-enter new password:
22 {SSHA}EzP6I82DZRnW+ou6lyiXHGxSpSOw2XO4
24 Configure the `slapd` LDAP server. Here is a very minimal
25 configuration, read the [OpenLDAP Admin Guide][admin] for details:
27 # emacs /etc/openldap/slapd.conf
28 # cat /etc/openldap/slapd.conf
29 include /etc/openldap/schema/core.schema
30 include /etc/openldap/schema/cosine.schema
31 include /etc/openldap/schema/inetorgperson.schema
32 pidfile /var/run/openldap/slapd.pid
33 argsfile /var/run/openldap/slapd.args
35 suffix "dc=example,dc=com"
37 rootdn "cn=Manager,dc=example,dc=com"
38 rootpw {SSHA}EzP6I82DZRnW+ou6lyiXHGxSpSOw2XO4
39 directory /var/lib/openldap-data
42 Note that [inetorgperson][] is huge, but it's standardized. I think
43 it's better to pick a big standard right off, than to outgrow
44 something smaller and need to migrate.
46 Gentoo creates the default database directory for you, so you can
47 ignore warnings about needing to create it yourself.
49 Configure LDAP client access. Again, read the docs for details on
50 adapting this to your particular situation:
52 # emacs /etc/openldap/ldap.conf
53 $ cat /etc/openldap/ldap.conf
54 BASE dc=example,dc=com
55 URI ldap://ldapserver.example.com
57 You can edit '/etc/conf.d/slapd' if you want command line options
58 passed to `slapd` when the service starts, but the defaults looked
63 # /etc/init.d/slapd start
65 Add it to your default runlevel:
67 # eselect rc add /etc/init.d/slapd default
71 $ ldapsearch -x -b '' -s base '(objectclass=*)'
73 Build a hierarchy in your database (this will depend on your
74 organizational structure):
76 $ emacs /tmp/people.ldif
77 $ cat /tmp/people.ldif
80 dn: dc=example, dc=com
82 objectClass: organization
86 dn: ou=people, dc=example,dc=com
87 objectClass: organizationalUnit
89 description: All people in organisation
91 dn: cn=Manager, dc=example,dc=com
92 objectClass: organizationalRole
94 description: Directory Manager
95 $ ldapadd -D "cn=Manager,dc=example,dc=com" -xW -f /tmp/people.ldif
101 If you currently keep your addresses in [abook][], you can export them
104 $ abook --convert --infile ~/.abook/addressbook --outformat ldif \
105 | abook-ldif-cleanup.py --basedn 'ou=people,dc=example,dc=com' > dump.ldif
107 where [[abook-ldif-cleanup.py]] does some compatibility processing
108 using the [python-ldap][] module.
110 Add the people to your LDAP database:
112 $ ldapadd -D "cn=Manager,dc=example,dc=com" -xW -f dump.ldif
114 To check if that worked, you can list all the entries in your
117 $ ldapsearch -x -b 'dc=example,dc=com' '(objectclass=*)'
119 Then remove the temporary files:
126 Ok, we've put lots of people into the `people` OU, but what if we want
127 to assign them to another department? We can use aliases ([RFC
128 4512][rfc4512]), the symlinks of the LDAP world. To see how this
129 works, lets create a test OU to play with:
131 $ emacs /tmp/test.ldif
134 dn: ou=test, dc=example,dc=com
135 objectClass: organizationalUnit
137 $ ldapadd -D "cn=Manager,dc=example,dc=com" -xW -f /tmp/test.ldif
140 Now assign one of your people to that group:
142 $ emacs /tmp/alias.ldif
143 $ cat /tmp/alias.ldif
145 dn: cn=Jane Doe, ou=test,dc=example,dc=com
147 aliasedObjectName: cn=Jane Doe, ou=people,dc=example,dc=com
148 $ ldapadd -D "cn=Manager,dc=example,dc=com" -xW -f /tmp/alias.ldif
151 The `extensibleObject` class allows us to add the DN field, without it
154 $ ldapadd -D "cn=Manager,dc=example,dc=com" -xW -f /tmp/alias.ldif
156 adding new entry "cn=Jane Doe, ou=test,dc=example,dc=com"
157 ldap_add: Object class violation (65)
158 additional info: attribute 'cn' not allowed
160 You can search for all entries (including aliases) with
162 $ ldapsearch -x -b 'ou=test, dc=example,dc=com' '(objectclass=*)'
164 dn: cn=Jane Doe,ou=test,dc=example,dc=com
166 objectClass: extensibleObject
167 aliasedObjectName:: Y249TWljaGVsIFZhbGxpw6hyZXMsb3U9cGVvcGxlLGRjPXRyZW1pbHksZGM9dXM=
170 You can control dereferencing with the `-a` option:
172 $ ldapsearch -x -a always -b 'ou=test, dc=example,dc=com' '(objectclass=*)'
174 dn: cn=Jane Doe,ou=people,dc=example,dc=com
179 Once you've played around, you can remove the `test` OU and its
182 $ ldapdelete -D "cn=Manager,dc=example,dc=com" -xW -r ou=test,dc=example,dc=com
187 There are a number of tools to make it easier to manage LDAP
188 databases. Command line junkies will probably like [shelldap][]:
190 $ shelldap --server ldapserver.example.com
196 dn: cn=Manager,dc=example,dc=com
197 objectClass: organizationalRole
203 Shelldap's `edit` command spawns your `EDITOR` on a temporary file
204 populated by the entry you're editing. You can either alter the entry
205 as you see fit, or try something fancier in [LDIF][].
210 If you use the [[Mutt]] email client (or just want a simple way to
211 query email addresses from the command line) there are a [number of
212 scripts][mutts] available. Pick whichever sounds most appealing to
213 you. I wrote up [[mutt-ldap.py]], which lets you configuration the
214 connection details via a config file (`~/.mutt-ldap.rc`) rather than
215 editing the script itself. Usage details are available in the
221 You can configure Apple's [Address Book][aab] to search an LDAP
222 directory. See [[Humanizing_OS_X]] for details.
227 It took me a bit of work to get [SSL/TLS][] working with my
228 [[GnuTLS]]-linked OpenLDAP. First, you'll probably need to generate
229 new SSL/TLS keys (`/etc/openldap/ssl/*`) with [certtool][] (see
230 [[X.509_certificates]]). Then add the following lines to
231 `/etc/openldap/slapd.conf`:
233 TLSCipherSuite NORMAL
234 TLSCACertificateFile /etc/openldap/ssl/ca.crt
235 TLSCertificateFile /etc/openldap/ssl/ldap.crt
236 TLSCertificateKeyFile /etc/openldap/ssl/ldap.key
237 TLSVerifyClient never
239 Where `ca.crt`, `ldap.crt`, and `ldap.key` are your new CA,
240 certificate, and private key. If you want to disable unencrypted
241 connections completely, remove the `ldap://` entry from your `slapd`
242 command line by editing (on Gentoo) `/etc/conf.d/slapd` so it has
244 OPTS="-h 'ldaps:// ldapi://%2fvar%2frun%2fopenldap%2fslapd.sock'"
246 Now you should be able to restart `slapd` so it will use the new
249 Have clients running on your server use the local socket by editing
250 `/etc/openldap/ldap.conf` to set:
252 URI ldapi://%2fvar%2frun%2fopenldap%2fslapd.sock
254 Test your server setup by running (on the server)
256 $ ldapsearch -x -b '' -s base '(objectclass=*)'
258 Copy your CA over to any client machines (I put it in
259 `/etc/openldap/ssl/ldapserver.crt`), and set them up with the
260 following two lines in `/etc/openldap/ldap.conf`:
262 URI ldaps://ldapserver.example.com
263 TLS_CACERT /etc/openldap/ssl/ldapserver.crt
265 Test your client setup by running (on the client)
267 $ ldapsearch -x -b '' -s base '(objectclass=*)'
269 You can configure `shelldap` with the following lines in
272 server: ldaps://ldapserver.example.com
274 tls_cacert: /etc/openldap/ssl/ldapserver.crt
276 You can configure `mutt-ldap.py` with the following lines in
285 I wanted to mirror my home LDAP info on my public Ubuntu server.
286 Here's a quick rundown of the Ubuntu setup. Install OpenLDAP:
288 $ sudo apt-get install slapd ldap-utils
290 Don't serve in the clear:
292 $ cat /etc/default/slapd
294 SLAPD_SERVICES="ldaps:/// ldapi:///"
297 Avoid `Unrecognized database type (hdb)` by loading the `hdb` backend
298 module before declaring `hdb` databases:
300 $ sudo cat /etc/ldap/slapd.conf
306 Convert the old school `slapd.conf` to the new [slapd.d][]:
308 $ sudo mv slapd.d{,.bak}
310 $ sudo slaptest -f slapd.conf -F slapd.d
312 hdb_db_open: database "dc=example,dc=com": db_open(/var/lib/slapd/id2entry.bdb) failed: No such file or directory (2).
314 slap_startup failed (test would succeed using the -u switch)
316 $ sudo chown -R openldap.openldap slapd.d
318 Don't worry about that `db_open` error, the conversion to `slapd.d`
319 will have completed successfully.
321 Set permissions on the database directory (note that the databases
322 should be under `/var/lib/ldap` to match Ubuntu's default apparmor
323 config. Otherwise you'll see `invalid path: Permission denied` errors
324 when `slapd` tries to initialize the databaes).
326 $ sudo chown openldap.openldap /var/lib/ldap/
327 $ sudo chmod 750 /var/lib/ldap/
329 Configure your clients
331 $ cat /etc/ldap/ldap.conf
332 BASE dc=example,dc=com
333 URI ldaps://example.com
334 TLS_CACERT /etc/ldap/ssl/ldapserver.crt
336 Start `slapd` and add it to your default runlevel:
338 $ sudo /etc/init.d/slapd start
339 $ sudo update-rc.d slapd defaults
341 Finally, import your directory data. Dump the data on your master
344 master$ sudo slapcat -b 'dc=example,dc=com' > database.ldif
346 Load the data on your slave:
348 $ sudo /etc/init.d/slapd stop
349 $ sudo slapadd -l database.ldif
350 $ sudo /etc/init.d/slapd start
355 There's a [good overview][schema] of schema and objectclasses by Brian
356 Jones on O'Reilly. If you want to use inetOrgPerson but also include
357 the countryName attribute, ...
359 [LDAP]: http://en.wikipedia.org/wiki/LDAP
360 [rfc4510]: http://tools.ietf.org/html/rfc4510
361 [howto]: http://www.gentoo.org/doc/en/ldap-howto.xml
362 [OpenLDAP]: http://www.openldap.org/
363 [admin]: http://www.openldap.org/doc/admin/
364 [inetorgperson]: http://www.apps.ietf.org/rfc/rfc2798.html
365 [abook]: http://abook.sourceforge.net/
366 [LDIF]: http://en.wikipedia.org/wiki/LDAP_Data_Interchange_Format
367 [python-ldap]: http://www.python-ldap.org/
368 [rfc4512]: http://tools.ietf.org/html/rfc4512
369 [shelldap]: http://projects.martini.nu/shelldap/
370 [mutts]: http://wiki.mutt.org/?QueryCommand
371 [aab]: http://support.apple.com/kb/ht2486
372 [SSL/TLS]: http://en.wikipedia.org/wiki/Transport_Layer_Security
373 [certtool]:http://www.gnu.org/software/gnutls/manual/html_node/Invoking-certtool.html#Invoking-certtool
374 [slapd.d]: http://www.openldap.org/doc/admin24/slapdconf2.html
375 [schema]: http://www.oreillynet.com/pub/a/sysadmin/2006/11/09/demystifying-ldap-data.html