1 This file explains how to use the optional LDAP functionality of SUDO to
2 store /etc/sudoers information. This feature is distinct from LDAP passwords.
6 As times change and servers become cheap, an enterprise can easily have 500+
7 UNIX servers. Using LDAP to synchronize Users, Groups, Hosts, Mounts, and
8 others across an enterprise can greatly reduce the administrative overhead.
10 Sudo in the past has only used a single local configuration file /etc/sudoers.
11 Some have attempted to workaround this by synchronizing changes via
12 RCS/CVS/RSYNC/RDIST/RCP/SCP and even NFS. Many have asked for a Hesiod, NIS,
13 or LDAP patch for sudo, so here is my attempt at LDAP'izing sudo.
15 For information on OpenLDAP, please see http://www.openldap.org/.
19 Many times the word 'Directory' is used in the document to refer to the LDAP
20 server, structure and contents.
22 Many times 'options' are used in this document to refer to sudoer 'defaults'.
23 They are one and the same.
28 * Sudo no longer needs to read sudoers in its entirety. Parsing of
29 /etc/sudoers requires the entire file to be read. The LDAP feature of sudo
30 uses two (sometimes three) LDAP queries per invocation. It never reads all
31 the sudoer entries in the LDAP store. This makes it especially fast and
32 particularly usable in LDAP environments. The first query is to parse
33 default options (see below). The second is to match against the username or
34 groups a user belongs to. (The special ALL tag is matched in this query
35 too.) If no match is made against the username, the third query pulls the
36 entries that match against user netgroups to compare back to the user.
38 * Sudo no longer blows up if there is a typo. Parsing of /etc/sudoers can
39 still blow up when sudo is invoked. However when using the LDAP feature of
40 sudo, LDAP syntax rules are applied before the data is uploaded into the
41 LDAP server, so proper syntax is always guaranteed! One can of course still
42 insert a bogus hostname or username, but sudo will not care.
44 * Options inside of entries now override global default options.
45 /etc/sudoers allowed for only default options and limited options associated
46 with user/host/command aliases. The syntax can be difficult for the newbie.
47 The LDAP feature attempts to simplify this and yet still provide maximum
50 Sudo first looks for an entry called 'cn=default' in the SUDOers container.
51 If found, the multi-valued sudoOption attribute is parsed the same way the
52 global 'Defaults' line in /etc/sudoers is parsed.
54 If on the second or third query, a response contains a sudoRole which
55 matches against the user, host, and command, then the matched object is
56 scanned for a additional options to override the top-level defaults. See
57 the example LDAP content below for more information.
59 * Visudo is no longer needed. Visudo provides locking and syntax checking
60 against the /etc/sudoers file. Since LDAP updates are atomic, locking is no
61 longer necessary. Because syntax is checked when the data is inserted into
62 LDAP, the sudoers syntax check becomes unnecessary.
64 * Aliases are no longer needed. User, Host, and Command Aliases were setup
65 to allow simplification and readability of the sudoers files. Since the
66 LDAP sudoer entry allows multiple values for each of its attributes and
67 since most LDAP browsers are graphical and easy to work with, original
68 aliases are no longer needed.
70 If you want to specify lots of users into an entry or want to have similar
71 entries with identical users, then use either groups or user netgroups.
72 Thats what groups and netgroups are for and Sudo handles this well.
73 Alternately, one can just paste them all into the LDAP record.
75 If you want to specify lots of hosts into an entry, use netgroups or IP
76 address matches (10.2.3.4/255.255.0.0). Thats what netgroups are for and
77 Sudo handles this well. Or just past them all into the LDAP record.
79 If you want to specify lots of commands, use directories or wildcards, or
80 just paste them all into LDAP. That's what it's for.
82 * The /etc/sudoers file can be disabled. Paranoid security administrators
83 can now disallow parsing of any local /etc/sudoers file by an LDAP
84 sudoOption 'ignore_local_sudoers'. This way all sudoers can be controlled
85 and audited in one place because local entries are not allowed.
86 In fact, if this option is included in the cn=defaults object of LDAP,
87 sudo won't even look for a /etc/sudoers file.
89 * The sudo binary compiled with LDAP support should be totally backward
90 compatible and be syntactically and source code equivalent to its non
96 The most simplest way to build sudo with LDAP support is to include the
99 $ ./configure --with-ldap
101 If your ldap libraries and headers are in a non-standard place, you will need
102 to specify them at configure time. E.g.
104 $ ./configure --with-ldap=/usr/local/ldapsdk
106 Sudo is developed using OpenLDAP. Other LDAP implementations may
107 require adding '-lldif' to SUDO_LIBS in the Makefile.
109 Your Mileage may vary. Please let the sudo workers mailing list
110 <sudo-workers@sudo.ws> know what combinations worked best for your
111 OS and LDAP Combinations so we can improve sudo.
114 HP-UX 11.23 (gcc3) Galen Johnson <Galen.Johnson@sas.com>
115 CFLAGS="-D__10_10_compat_code" LDFLAGS="-L/opt/ldapux/lib"
119 Add the appropriate schema to your LDAP server so that it may contain
122 For OpenLDAP, simply copy schema.OpenLDAP to the schema directory
123 (e.g. /etc/openldap/schema) and 'include' it in your slapd.conf and
124 restart slapd. For other LDAP servers, provide this to your LDAP
125 Administrator. Make sure to index the attribute 'sudoUser'.
127 For netscape-derived LDAP servers such as SunONE, iPlanet or Fedora
128 Directory, use the schema.iPlanet file.
130 Importing /etc/sudoers to LDAP
131 ==============================
132 Importing is a two step process.
135 Ask your LDAP Administrator where to create the ou=SUDOers container.
137 For instance, if using OpenLDAP:
139 dn: ou=SUDOers,dc=example,dc=com
141 objectClass: organizationalUnit
144 (An example location is shown below). Then use the provided script to convert
145 your sudoers file into LDIF format. The script will also convert any default
148 # SUDOERS_BASE=ou=SUDOers,dc=example,dc=com
149 # export SUDOERS_BASE
150 # ./sudoers2ldif /etc/sudoers > /tmp/sudoers.ldif
153 Import into your directory server. If you are using OpenLDAP, do the following
154 if you are using another directory, provide the LDIF file to your LDAP
155 Administrator. An example is shown below.
157 # ldapadd -f /tmp/sudoers.ldif -h ldapserver \
158 > -D cn=Manager,dc=example,dc=com -W -x
160 Example sudoers Entries in LDAP
161 ===============================
162 The equivalent of a sudoer in LDAP is a 'sudoRole'. It contains sudoUser(s),
163 sudoHost, sudoCommand and optional sudoOption(s) and sudoRunAs(s).
165 The following example allows users in group wheel to run any
166 command on any host through sudo:
168 dn: cn=%wheel,ou=SUDOers,dc=example,dc=com
170 objectClass: sudoRole
176 Managing LDAP entries
177 =====================
178 Doing a one-time bulk load of your ldap entries is fine. However what if you
179 need to make minor changes on a daily basis? It doesn't make sense to delete
180 and re-add objects. (You can, but this is tedious).
182 I recommend using any of the following LDAP browsers to administer your SUDOers.
183 * GQ - The gentleman's LDAP client - Open Source - I use this a lot on Linux
184 and since it is Schema aware, I don't need to create a sudoRole template.
187 * LDAP Browser/Editor - by Jarek Gawor - I use this a lot on Windows
188 and Solaris. It runs anywhere in a Java Virtual Machine including
189 web pages. You have to make a template from an existing sudoRole entry.
190 http://www.iit.edu/~gawojar/ldap
191 http://www.mcs.anl.gov/~gawor/ldap
192 http://ldapmanager.com
194 * Apache Directory Studio - Open Source - an Eclipse-based LDAP
195 development platform. Includes an LDAP browser, and LDIF editor,
196 a schema editor and more.
197 http://directory.apache.org/studio
199 There are dozens of others, some Open Source, some free, some not.
202 Configure your /etc/ldap.conf
203 =============================
204 The /etc/ldap.conf file is meant to be shared between sudo, pam_ldap, nss_ldap
205 and other ldap applications and modules. IBM Secureway unfortunately uses
206 the same filename but has a different syntax. If you need to rename where
207 this file is stored, re-run configure with the --with-ldap-conf-file=filename
210 Make sure you sudoers_base matches exactly with the location you specified
211 when you imported the sudoers. Below is an example /etc/ldap.conf
213 # Either specify one or more URIs or one or more host:port pairs.
214 # If neither is specified sudo will default to localhost, port 389.
217 #host ldapserver1 ldapserver2:390
219 # Default port if host is specified without one, defaults to 389.
222 # URI will override the host and port settings.
223 uri ldap://ldapserver
224 #uri ldaps://secureldapserver
225 #uri ldaps://secureldapserver ldap://ldapserver
227 # must be set or sudo will ignore LDAP
228 sudoers_base ou=SUDOers,dc=example,dc=com
230 # verbose sudoers matching from ldap
233 # optional proxy credentials
234 #binddn <who to search as>
236 #rootbinddn <who to search as, uses /etc/ldap.passwd for bindpw>
238 # LDAP protocol version, defaults to 3
241 # Define if you want to use an encrypted LDAP connection.
242 # Typically, you must also set the port to 636 (ldaps).
245 # Define if you want to use port 389 and switch to
246 # encryption before the bind credentials are sent.
247 # Only supported by LDAP servers that support the start_tls
248 # extension such as OpenLDAP.
251 # Additional TLS options follow that allow tweaking of the
252 # SSL/TLS connection. Only supported when using OpenLDAP.
254 #tls_checkpeer yes # verify server SSL certificate
255 #tls_checkpeer no # ignore server SSL certificate
257 # If you enable tls_checkpeer, specify either tls_cacertfile
258 # or tls_cacertdir. Only supported when using OpenLDAP.
260 #tls_cacertfile /etc/certs/trusted_signers.pem
261 #tls_cacertdir /etc/certs
263 # For systems that don't have /dev/random
264 # use this along with PRNGD or EGD.pl to seed the
265 # random number pool to generate cryptographic session keys.
266 # Only supported when using OpenLDAP.
268 #tls_randfile /etc/egd-pool
270 # You may restrict which ciphers are used. Consult your SSL
271 # documentation for which options go here.
272 # Only supported when using OpenLDAP.
274 #tls_ciphers <cipher-list>
276 # Sudo can provide a client certificate when communicating to
279 # * Enable both lines at the same time.
280 # * Do not password protect the key file.
281 # * Ensure the keyfile is only readable by root.
284 #tls_cert /etc/certs/client_cert.pem
285 #tls_key /etc/certs/client_key.pem
287 # For SunONE or iPlanet LDAP, the file specified by tls_cert may
288 # contain CA certs and/or the client's cert. If the client's
289 # cert is included, tls_key should be specified as well.
290 # For backward compatibility, sslpath may be used in place of tls_cert.
291 #tls_cert /var/ldap/cert7.db
292 #tls_key /var/ldap/key3.db
294 Debugging your LDAP configuration
295 =================================
296 Enable debugging if you believe sudo is not parsing LDAP the way you think it
297 it should. A value of 1 shows moderate debugging. A value of 2 shows the
298 results of the matches themselves. Make sure to set the value back to zero
299 so that other users don't get confused by the debugging messages. This value
300 is 'sudoers_debug' in the /etc/ldap.conf.
302 Parsing Differences between /etc/sudoers and LDAP
303 =================================================
304 There are some subtle differences in the way sudoers is handled once in LDAP.
305 Probably the biggest is that according to the RFC, LDAP's ordering is
306 arbitrary and you cannot expect that Attributes & Entries are returned in
307 any order. If there are conflicting command rules on an entry, the negative
308 takes precedence. This is called paranoid behavior (not necessarily the
309 most specific match).
314 # Allow all commands except shell
315 johnny ALL=(root) ALL,!/bin/sh
316 # Always allows all commands because ALL is matched last
317 puddles ALL=(root) !/bin/sh,ALL
319 # LDAP equivalent of Johnny
320 # Allows all commands except shell
321 dn: cn=role1,ou=Sudoers,dc=my-domain,dc=com
322 objectClass: sudoRole
328 sudoCommand: !/bin/sh
330 # LDAP equivalent of Puddles
331 # Notice that even though ALL comes last, it still behaves like
332 # role1 since the LDAP code assumes the more paranoid configuration
333 dn: cn=role2,ou=Sudoers,dc=my-domain,dc=com
334 objectClass: sudoRole
339 sudoCommand: !/bin/sh
342 Another difference is that negations on the Host, User or Runas are
343 currently ignorred. For example, these attributes do not work how they first
344 seem. If you desperately want this to be changed, contact Aaron Spangler
345 (aaron@spangler.ods.org).
347 # does not match all but joe
348 # rather, does not match anyone
351 # does not match all but joe
352 # rather, matches everyone including Joe
356 # does not match all but web01
357 # rather, matches all hosts including web01