[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.1

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:
        !            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