Imported Upstream version 1.6.8p5
[debian/sudo] / README.LDAP
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.
3
4 LDAP philosophy
5 ===============
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.
9
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.
14
15 Definitions
16 ===========
17 Many times the word 'Directory' is used in the document to refer to the LDAP
18 server, structure and contents.
19
20 Many times 'options' are used in this document to refer to sudoer 'defaults'.
21 They are one and the same.
22
23 Design Features
24 ===============
25
26   * Sudo no longer needs to read sudoers in its entirety.  Parsing of
27     /etc/sudoers requires the entire file to be read.  The LDAP feature of sudo
28     uses two (sometimes three) LDAP queries per invocation.  It never reads all
29     the sudoer entries in the LDAP store.  This makes it especially fast and
30     particularly usable in LDAP environments.  The first query is to parse
31     default options (see below).  The second is to match against the username or
32     groups a user belongs to.  (The special ALL tag is matched in this query
33     too.) If no match is made against the username, the third query pulls the
34     entries that match against user netgroups to compare back to the user.
35
36   * Sudo no longer blows up if there is a typo.  Parsing of /etc/sudoers can
37     still blow up when sudo is invoked.  However when using the LDAP feature of
38     sudo, LDAP syntax rules are applied before the data is uploaded into the
39     LDAP server, so proper syntax is always guaranteed!  One can of course still
40     insert a bogus hostname or username, but sudo will not care.
41
42   * Options inside of entries now override global default options.
43     /etc/sudoers allowed for only default options and limited options associated
44     with user/host/command aliases.  The syntax can be difficult for the newbie.
45     The LDAP feature attempts to simplify this and yet still provide maximum
46     flexibility.
47
48     Sudo first looks for an entry called 'cn=default' in the SUDOers container.
49     If found, the multi-valued sudoOption attribute is parsed the same way the
50     global 'Defaults' line in /etc/sudoers is parsed.
51
52     If on the second or third query, a response contains a sudoRole which
53     matches against the user, host, and command, then the matched object is
54     scanned for a additional options to override the top-level defaults.  See
55     the example LDAP content below for more information.
56
57   * Visudo is no longer needed.  Visudo provides locking and syntax checking
58     against the /etc/sudoers file.  Since LDAP updates are atomic, locking is no
59     longer necessary.  Because syntax is checked when the data is inserted into
60     LDAP, the sudoers syntax check becomes unnecessary.
61
62   * Aliases are no longer needed.  User, Host, and Command Aliases were setup
63     to allow simplification and readability of the sudoers files.  Since the
64     LDAP sudoer entry allows multiple values for each of its attributes and
65     since most LDAP browsers are graphical and easy to work with, original
66     aliases are no longer needed.
67
68     If you want to specify lots of users into an entry or want to have similar
69     entries with identical users, then use either groups or user netgroups.
70     Thats what groups and netgroups are for and Sudo handles this well.
71     Alternately, one can just paste them all into the LDAP record.
72
73     If you want to specify lots of hosts into an entry, use netgroups or IP
74     address matches (10.2.3.4/255.255.0.0).  Thats what netgroups are for and
75     Sudo handles this well.  Or just past them all into the LDAP record.
76
77     If you want to specify lots of commands, use directories or wildcards, or
78     just paste them all into LDAP.  That's what it's for.
79
80   * The /etc/sudoers file can be disabled.  Paranoid security administrators
81     can now disallow parsing of any local /etc/sudoers file by an LDAP
82     sudoOption 'ignore_local_sudoers'.  This way all sudoers can be controlled
83     and audited in one place because local entries are not allowed.
84     In fact, if this option is included in the cn=defaults object of LDAP,
85     sudo won't even look for a /etc/sudoers file.
86
87   * The sudo binary compiled with LDAP support should be totally backward
88     compatible and be syntactically and source code equivalent to its non
89     LDAP-enabled build.
90
91
92 Build instructions
93 ==================
94 The most simplest way to build sudo with LDAP support is to include the
95 '--with-ldap' option.  I recommend including the '--with-pam' option on those
96 system with PAM so that if you decide to use LDAP for authentication, you won't
97 need to recompile sudo.
98
99   $ ./configure --with-ldap --with-pam
100
101 If your ldap libraries and headers are in a non standard place, you will need
102 to specify them at configure time.
103
104   $ ./configure --with-ldap=/usr/local/ldapsdk --with-pam
105
106 Sudo is tested against OpenLDAP's implementation.  Other LDAP implementations
107 may require adding '-lldif' to SUDO_LIBS in the Makefile.
108
109 Your Mileage may vary.  Please let Aaron Spangler <aaron@spangler.ods.org>
110 know what combinations worked best for your OS & LDAP Combinations so we can
111 improve sudo.
112
113 More Build Notes:
114 HP-UX 11.23 (gcc3) Galen Johnson <Galen.Johnson@sas.com>
115   CFLAGS="-D__10_10_compat_code" LDFLAGS="-L/opt/ldapux/lib"
116
117 Schema Changes
118 ==============
119 Add the following schema to your LDAP server so that it may contain sudoer
120 content.  In OpenLDAP, simply place this into a new file and 'include' it
121 in your slapd.conf and restart slapd.  For other LDAP servers, provide this
122 to your LDAP Administrator.  Make sure to index the attribute 'sudoUser'.
123
124
125   #
126   #  schema file for sudo
127   #
128
129   attributetype ( 1.3.6.1.4.1.15953.9.1.1
130         NAME 'sudoUser'
131         DESC 'User(s) who may  run sudo'
132         EQUALITY caseExactIA5Match
133         SUBSTR caseExactIA5SubstringsMatch
134         SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
135
136   attributetype ( 1.3.6.1.4.1.15953.9.1.2
137         NAME 'sudoHost'
138         DESC 'Host(s) who may run sudo'
139         EQUALITY caseExactIA5Match
140         SUBSTR caseExactIA5SubstringsMatch
141         SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
142
143   attributetype ( 1.3.6.1.4.1.15953.9.1.3
144         NAME 'sudoCommand'
145         DESC 'Command(s) to be executed by sudo'
146         EQUALITY caseExactIA5Match
147         SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
148
149   attributetype ( 1.3.6.1.4.1.15953.9.1.4
150         NAME 'sudoRunAs'
151         DESC 'User(s) impersonated by sudo'
152         EQUALITY caseExactIA5Match
153         SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
154
155   attributetype ( 1.3.6.1.4.1.15953.9.1.5
156         NAME 'sudoOption'
157         DESC 'Options(s) followed by sudo'
158         EQUALITY caseExactIA5Match
159         SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
160
161   objectclass ( 1.3.6.1.4.1.15953.9.2.1 NAME 'sudoRole' SUP top STRUCTURAL
162         DESC 'Sudoer Entries'
163         MUST ( cn )
164         MAY ( sudoUser $ sudoHost $ sudoCommand $ sudoRunAs $ sudoOption $
165               description )
166         )
167
168   #
169   # Same thing as above, but imports better into SunONE or iPlanet
170   # (remove any leading spaces and save to a seperate file)
171   #
172
173   dn: cn=schema
174   attributeTypes: ( 1.3.6.1.4.1.15953.9.1.1 NAME 'sudoUser' DESC 'User(s) who may  run sudo' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'SUDO' )
175   attributeTypes: ( 1.3.6.1.4.1.15953.9.1.2 NAME 'sudoHost' DESC 'Host(s) who may run sudo' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'SUDO' )
176   attributeTypes: ( 1.3.6.1.4.1.15953.9.1.3 NAME 'sudoCommand' DESC 'Command(s) to be executed by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'SUDO' )
177   attributeTypes: ( 1.3.6.1.4.1.15953.9.1.4 NAME 'sudoRunAs' DESC 'User(s) impersonated by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'SUDO' )
178   attributeTypes: ( 1.3.6.1.4.1.15953.9.1.5 NAME 'sudoOption' DESC 'Options(s) followed by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'SUDO' )
179   objectClasses: ( 1.3.6.1.4.1.15953.9.2.1 NAME 'sudoRole' SUP top STRUCTURAL DESC 'Sudoer Entries' MUST ( cn ) MAY ( sudoUser $ sudoHost $ sudoCommand $ sudoRunAs $ sudoOption $ description ) X-ORIGIN 'SUDO' )
180
181
182
183 Importing /etc/sudoers to LDAP
184 ==============================
185 Importing is a two step process.
186
187 Step 1:
188 Ask your LDAP Administrator where to create the ou=SUDOers container.
189 (An example location is shown below).  Then use the provided script to convert
190 your sudoers file into LDIF format.  The script will also convert any default
191 options.
192
193   # SUDOERS_BASE=ou=SUDOers,dc=example,dc=com
194   # export SUDOERS_BASE
195   # ./sudoers2ldif /etc/sudoers > /tmp/sudoers.ldif
196
197 Step 2:
198 Import into your directory server.  If you are using OpenLDAP, do the following
199 if you are using another directory, provide the LDIF file to your LDAP
200 Administrator.  An example is shown below.
201
202   # ldapadd -f /tmp/sudoers.ldif -h ldapserver \
203   > -D cn=Manager,dc=example,dc=com -W -x
204
205 Example sudoers Entries in LDAP
206 ===============================
207 The equivalent of a sudoer in LDAP is a 'sudoRole'.  It contains sudoUser(s),
208 sudoHost, sudoCommand and optional sudoOption(s) and sudoRunAs(s).
209 <put an example here>
210
211 Managing LDAP entries
212 =====================
213 Doing a one-time bulk load of your ldap entries is fine.  However what if you
214 need to make minor changes on a daily basis?  It doesn't make sense to delete
215 and re-add objects.  (You can, but this is tedious).
216
217 I recommend using any of the following LDAP browsers to administer your SUDOers.
218   * GQ - The gentleman's LDAP client - Open Source - I use this a lot on Linux
219     and since it is Schema aware, I don't need to create a sudoRole template.
220         http://biot.com/gq/
221
222   * LDAP Browser/Editor - by Jarek Gawor - I use this a lot on Windows
223     and Solaris.  It runs anywhere in a Java Virtual Machine including
224     web pages.  You have to make a template from an existing sudoRole entry.
225         http://www.iit.edu/~gawojar/ldap
226         http://www.mcs.anl.gov/~gawor/ldap
227         http://ldapmanager.com
228
229   There are dozens of others, some open source, some free, some not.
230
231
232 Configure your /etc/ldap.conf
233 =============================
234 The /etc/ldap.conf file is meant to be shared between sudo, pam_ldap, nss_ldap
235 and other ldap applications and modules.  IBM Secureway unfortunately uses
236 the same filename but has a different syntax.  If you need to rename where
237 this file is stored, recompile SUDO with the -DLDAP_CONFIG compile option.
238
239 Make sure you sudoers_base matches exactly with the location you specified
240 when you imported the sudoers.  Below is an example /etc/ldap.conf
241
242   # Either specify a uri or host & port
243   #host          ldapserver
244   #port          389
245   #
246   # URI will override host & port settings
247   # but only works with LDAP SDK's that support
248   # ldap_initialize() such as OpenLDAP
249   uri            ldap://ldapserver
250   #uri            ldaps://secureldapserver
251   #
252   # must be set or sudo will ignore LDAP
253   sudoers_base   ou=SUDOers,dc=example,dc=com
254   #
255   # verbose sudoers matching from ldap
256   #sudoers_debug 2
257   #
258   # optional proxy credentials
259   #binddn        <who to search as>
260   #bindpw        <password>
261   #
262   # LDAP Protocol Version defaults to 3
263   #ldap_version 3
264   #
265   # Define if you want to use port 389 and switch to
266   # encryption before the bind credentials are sent
267   #ssl start_tls
268   #
269   # Additional TLS options follow that allow tweaking
270   # of the SSL/TLS connection
271   #
272   #tls_checkpeer yes # verify server SSL certificate
273   #tls_checkpeer no  # ignore server SSL certificate
274   #
275   # If you enable tls_checkpeer, specify either tls_cacertfile
276   # or tls_cacertdir.
277   #
278   #tls_cacertfile /etc/certs/trusted_signers.pem
279   #tls_cacertdir  /etc/certs
280   #
281   # For systems that don't have /dev/random
282   # use this along with PRNGD or EGD.pl to seed the
283   # random number pool to generate cryptographic session keys.
284   #
285   #tls_randfile /etc/egd-pool
286   #
287   # You may restrict which ciphers are used.  Consult your SSL
288   # documentation for which options go here.
289   #
290   #tls_ciphers <cipher-list>
291   #
292   # Sudo can provide a client certificate when communicating to
293   # the LDAP server.
294   # Tips:
295   #   * Enable both lines at the same time.
296   #   * Do not password protect the key file.
297   #   * Ensure the keyfile is only readable by root.
298   #
299   #tls_cert /etc/certs/client_cert.pem
300   #tls_key  /etc/certs/client_key.pem
301   #
302
303 Debugging your LDAP configuration
304 =================================
305 Enable debugging if you believe sudo is not parsing LDAP the way you think it
306 it should.  A value of 1 shows moderate debugging.  A value of 2 shows the
307 results of the matches themselves.  Make sure to set the value back to zero
308 so that other users don't get confused by the debugging messages.  This value
309 is 'sudoers_debug' in the /etc/ldap.conf.
310
311 Parsing Differences between /etc/sudoers and LDAP
312 =================================================
313 There are some subtle differences in the way sudoers is handled once in LDAP.
314 Probably the biggest is that according to the RFC, LDAP's ordering is
315 arbitrary and you cannot expect that Attributes & Entries are returned in
316 any order.  If there are conflicting command rules on an entry, the negative
317 takes precedence.  This is called paranoid behavior (not necessarily the
318 most specific match).
319
320 Here is an example:
321
322   # /etc/sudoers:
323   # Allow all commands except shell
324   johnny  ALL=(root) ALL,!/bin/sh
325   # Always allows all commands because ALL is matched last
326   puddles ALL=(root) !/bin/sh,ALL
327
328   # LDAP equivalent of Johnny
329   # Allows all commands except shell
330   dn: cn=role1,ou=Sudoers,dc=my-domain,dc=com
331   objectClass: sudoRole
332   objectClass: top
333   cn: role1
334   sudoUser: johnny
335   sudoHost: ALL
336   sudoCommand: ALL
337   sudoCommand: !/bin/sh
338
339   # LDAP equivalent of Puddles
340   # Notice that even though ALL comes last, it still behaves like
341   # role1 since the LDAP code assumes the more paranoid configuration
342   dn: cn=role2,ou=Sudoers,dc=my-domain,dc=com
343   objectClass: sudoRole
344   objectClass: top
345   cn: role2
346   sudoUser: puddles
347   sudoHost: ALL
348   sudoCommand: !/bin/sh
349   sudoCommand: ALL
350
351 Another difference is that negations on the Host are User (or Runas) are
352 currently ignorred.  For example, these attributes do not work how they first
353 seem.  If you desperately want this to be changed, contact Aaron Spangler
354 (aaron@spangler.ods.org).
355
356   # does not match all but joe
357   # rather, does not match anyone
358   sudoUser: !joe
359
360   # does not match all but joe
361   # rather, matches everyone including Joe
362   sudoUser: ALL
363   sudoUser: !joe
364
365   # does not match all but web01
366   # rather, matches all hosts including web01
367   sudoHost: ALL
368   sudoHost: !web01
369
370
371 Configure your /etc/nsswitch.conf
372 =================================
373 At the time of this writing, sudo does not consult nsswitch.conf for the
374 search order.  But if it did, it would look like this:
375 This might be implemented in the future.  For now just skip this step.
376
377   sudoers: files ldap