[BACK]Return to README.LDAP CVS log [TXT][DIR] Up to [local] / src / usr.bin / sudo

Annotation of src/usr.bin/sudo/README.LDAP, Revision 1.2

1.1       millert     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:
1.2     ! millert    15: For information on OpenLDAP, please see http://www.openldap.org/.
        !            16:
1.1       millert    17: Definitions
                     18: ===========
                     19: Many times the word 'Directory' is used in the document to refer to the LDAP
                     20: server, structure and contents.
                     21:
                     22: Many times 'options' are used in this document to refer to sudoer 'defaults'.
                     23: They are one and the same.
                     24:
                     25: Design Features
                     26: ===============
                     27:
                     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.
                     37:
                     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.
                     43:
                     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
                     48:     flexibility.
                     49:
                     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.
                     53:
                     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.
                     58:
                     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.
                     63:
                     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.
                     69:
                     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.
                     74:
                     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.
                     78:
                     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.
                     81:
                     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.
                     88:
                     89:   * The sudo binary compiled with LDAP support should be totally backward
                     90:     compatible and be syntactically and source code equivalent to its non
                     91:     LDAP-enabled build.
                     92:
                     93:
                     94: Build instructions
                     95: ==================
                     96: The most simplest way to build sudo with LDAP support is to include the
1.2     ! millert    97: '--with-ldap' option.
1.1       millert    98:
1.2     ! millert    99:   $ ./configure --with-ldap
1.1       millert   100:
1.2     ! millert   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.
1.1       millert   103:
1.2     ! millert   104:   $ ./configure --with-ldap=/usr/local/ldapsdk
1.1       millert   105:
1.2     ! millert   106: Sudo is developed using OpenLDAP.  Other LDAP implementations may
        !           107: require adding '-lldif' to SUDO_LIBS in the Makefile.
1.1       millert   108:
1.2     ! millert   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.
1.1       millert   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: ==============
1.2     ! millert   119: Add the appropriate schema to your LDAP server so that it may contain
        !           120: sudoers content.
1.1       millert   121:
1.2     ! millert   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'.
1.1       millert   126:
1.2     ! millert   127: For the SunONE or iPlanet LDAP server, use the schema.iPlanet file.
1.1       millert   128:
                    129: Importing /etc/sudoers to LDAP
                    130: ==============================
                    131: Importing is a two step process.
                    132:
                    133: Step 1:
                    134: Ask your LDAP Administrator where to create the ou=SUDOers container.
1.2     ! millert   135:
        !           136: For instance, if using OpenLDAP:
        !           137:
        !           138:   dn: ou=SUDOers,dc=example,dc=com
        !           139:   objectClass: top
        !           140:   objectClass: organizationalUnit
        !           141:   ou: SUDOers
        !           142:
1.1       millert   143: (An example location is shown below).  Then use the provided script to convert
                    144: your sudoers file into LDIF format.  The script will also convert any default
                    145: options.
                    146:
                    147:   # SUDOERS_BASE=ou=SUDOers,dc=example,dc=com
                    148:   # export SUDOERS_BASE
                    149:   # ./sudoers2ldif /etc/sudoers > /tmp/sudoers.ldif
                    150:
                    151: Step 2:
                    152: Import into your directory server.  If you are using OpenLDAP, do the following
                    153: if you are using another directory, provide the LDIF file to your LDAP
                    154: Administrator.  An example is shown below.
                    155:
                    156:   # ldapadd -f /tmp/sudoers.ldif -h ldapserver \
                    157:   > -D cn=Manager,dc=example,dc=com -W -x
                    158:
                    159: Example sudoers Entries in LDAP
                    160: ===============================
                    161: The equivalent of a sudoer in LDAP is a 'sudoRole'.  It contains sudoUser(s),
                    162: sudoHost, sudoCommand and optional sudoOption(s) and sudoRunAs(s).
                    163: <put an example here>
                    164:
                    165: Managing LDAP entries
                    166: =====================
                    167: Doing a one-time bulk load of your ldap entries is fine.  However what if you
                    168: need to make minor changes on a daily basis?  It doesn't make sense to delete
                    169: and re-add objects.  (You can, but this is tedious).
                    170:
                    171: I recommend using any of the following LDAP browsers to administer your SUDOers.
                    172:   * GQ - The gentleman's LDAP client - Open Source - I use this a lot on Linux
                    173:     and since it is Schema aware, I don't need to create a sudoRole template.
                    174:        http://biot.com/gq/
                    175:
                    176:   * LDAP Browser/Editor - by Jarek Gawor - I use this a lot on Windows
                    177:     and Solaris.  It runs anywhere in a Java Virtual Machine including
                    178:     web pages.  You have to make a template from an existing sudoRole entry.
                    179:        http://www.iit.edu/~gawojar/ldap
                    180:        http://www.mcs.anl.gov/~gawor/ldap
                    181:        http://ldapmanager.com
                    182:
                    183:   There are dozens of others, some open source, some free, some not.
                    184:
                    185:
                    186: Configure your /etc/ldap.conf
                    187: =============================
                    188: The /etc/ldap.conf file is meant to be shared between sudo, pam_ldap, nss_ldap
                    189: and other ldap applications and modules.  IBM Secureway unfortunately uses
                    190: the same filename but has a different syntax.  If you need to rename where
                    191: this file is stored, recompile SUDO with the -DLDAP_CONFIG compile option.
                    192:
                    193: Make sure you sudoers_base matches exactly with the location you specified
                    194: when you imported the sudoers.  Below is an example /etc/ldap.conf
                    195:
                    196:   # Either specify a uri or host & port
                    197:   #host          ldapserver
                    198:   #port          389
                    199:   #
                    200:   # URI will override host & port settings
                    201:   # but only works with LDAP SDK's that support
                    202:   # ldap_initialize() such as OpenLDAP
                    203:   uri            ldap://ldapserver
                    204:   #uri            ldaps://secureldapserver
                    205:   #
                    206:   # must be set or sudo will ignore LDAP
                    207:   sudoers_base   ou=SUDOers,dc=example,dc=com
                    208:   #
                    209:   # verbose sudoers matching from ldap
                    210:   #sudoers_debug 2
                    211:   #
                    212:   # optional proxy credentials
                    213:   #binddn        <who to search as>
                    214:   #bindpw        <password>
1.2     ! millert   215:   #rootbinddn    <who to search as, uses /etc/ldap.passwd for bindpw>
1.1       millert   216:   #
                    217:   # LDAP Protocol Version defaults to 3
                    218:   #ldap_version 3
                    219:   #
                    220:   # Define if you want to use port 389 and switch to
                    221:   # encryption before the bind credentials are sent
                    222:   #ssl start_tls
                    223:   #
                    224:   # Additional TLS options follow that allow tweaking
                    225:   # of the SSL/TLS connection
                    226:   #
                    227:   #tls_checkpeer yes # verify server SSL certificate
                    228:   #tls_checkpeer no  # ignore server SSL certificate
                    229:   #
                    230:   # If you enable tls_checkpeer, specify either tls_cacertfile
                    231:   # or tls_cacertdir.
                    232:   #
                    233:   #tls_cacertfile /etc/certs/trusted_signers.pem
                    234:   #tls_cacertdir  /etc/certs
                    235:   #
                    236:   # For systems that don't have /dev/random
                    237:   # use this along with PRNGD or EGD.pl to seed the
                    238:   # random number pool to generate cryptographic session keys.
                    239:   #
                    240:   #tls_randfile /etc/egd-pool
                    241:   #
                    242:   # You may restrict which ciphers are used.  Consult your SSL
                    243:   # documentation for which options go here.
                    244:   #
                    245:   #tls_ciphers <cipher-list>
                    246:   #
                    247:   # Sudo can provide a client certificate when communicating to
                    248:   # the LDAP server.
                    249:   # Tips:
                    250:   #   * Enable both lines at the same time.
                    251:   #   * Do not password protect the key file.
                    252:   #   * Ensure the keyfile is only readable by root.
                    253:   #
                    254:   #tls_cert /etc/certs/client_cert.pem
                    255:   #tls_key  /etc/certs/client_key.pem
                    256:   #
                    257:
                    258: Debugging your LDAP configuration
                    259: =================================
                    260: Enable debugging if you believe sudo is not parsing LDAP the way you think it
                    261: it should.  A value of 1 shows moderate debugging.  A value of 2 shows the
                    262: results of the matches themselves.  Make sure to set the value back to zero
                    263: so that other users don't get confused by the debugging messages.  This value
                    264: is 'sudoers_debug' in the /etc/ldap.conf.
                    265:
                    266: Parsing Differences between /etc/sudoers and LDAP
                    267: =================================================
                    268: There are some subtle differences in the way sudoers is handled once in LDAP.
                    269: Probably the biggest is that according to the RFC, LDAP's ordering is
                    270: arbitrary and you cannot expect that Attributes & Entries are returned in
                    271: any order.  If there are conflicting command rules on an entry, the negative
                    272: takes precedence.  This is called paranoid behavior (not necessarily the
                    273: most specific match).
                    274:
                    275: Here is an example:
                    276:
                    277:   # /etc/sudoers:
                    278:   # Allow all commands except shell
                    279:   johnny  ALL=(root) ALL,!/bin/sh
                    280:   # Always allows all commands because ALL is matched last
                    281:   puddles ALL=(root) !/bin/sh,ALL
                    282:
                    283:   # LDAP equivalent of Johnny
                    284:   # Allows all commands except shell
                    285:   dn: cn=role1,ou=Sudoers,dc=my-domain,dc=com
                    286:   objectClass: sudoRole
                    287:   objectClass: top
                    288:   cn: role1
                    289:   sudoUser: johnny
                    290:   sudoHost: ALL
                    291:   sudoCommand: ALL
                    292:   sudoCommand: !/bin/sh
                    293:
                    294:   # LDAP equivalent of Puddles
                    295:   # Notice that even though ALL comes last, it still behaves like
                    296:   # role1 since the LDAP code assumes the more paranoid configuration
                    297:   dn: cn=role2,ou=Sudoers,dc=my-domain,dc=com
                    298:   objectClass: sudoRole
                    299:   objectClass: top
                    300:   cn: role2
                    301:   sudoUser: puddles
                    302:   sudoHost: ALL
                    303:   sudoCommand: !/bin/sh
                    304:   sudoCommand: ALL
                    305:
1.2     ! millert   306: Another difference is that negations on the Host, User or Runas are
1.1       millert   307: currently ignorred.  For example, these attributes do not work how they first
                    308: seem.  If you desperately want this to be changed, contact Aaron Spangler
                    309: (aaron@spangler.ods.org).
                    310:
                    311:   # does not match all but joe
                    312:   # rather, does not match anyone
                    313:   sudoUser: !joe
                    314:
                    315:   # does not match all but joe
                    316:   # rather, matches everyone including Joe
                    317:   sudoUser: ALL
                    318:   sudoUser: !joe
                    319:
                    320:   # does not match all but web01
                    321:   # rather, matches all hosts including web01
                    322:   sudoHost: ALL
                    323:   sudoHost: !web01
                    324:
                    325:
                    326: Configure your /etc/nsswitch.conf
                    327: =================================
                    328: At the time of this writing, sudo does not consult nsswitch.conf for the
                    329: search order.  But if it did, it would look like this:
                    330: This might be implemented in the future.  For now just skip this step.
                    331:
                    332:   sudoers: files ldap