LDAP

From Wikitech
Jump to: navigation, search

LDAP in Production

There are two separate LDAP installations:

  • dubnium/pollux provide a mirror of the LDAP server operated by OIT. It is used to perform LDAP lookups from the mail servers.
  • seaborgium/serpens provide the LDAP servers predominantly used by labs. In addition they are used for authentication of various services from production (gerrit, servermon, jenkins, icinga, logstash, graphite, phabricator)

Both installations are using openldap. The two servers of each cluster are running in mirror_mode, which provides bi-directional replication of write changes using the syncrepl protocol.

Installing/Configuring the server

Create indexes

After creating the indexes, on each server you need to stop the server, rebuild the indexes, and start the server:

Add a proxy agent

Since we are requiring authentication by default, the clients need a user to do authenticated lookups. We create a proxyagent user for this:

dn: cn=proxyagent,ou=profile,<basedn>
changetype: add
objectclass: top
objectclass: inetorgperson
objectclass: person
sn: agent
givenName: proxy
userpassword: <aPasswordGoesHere>
cn: proxyagent

Installing/Configuring the client manually

Install required packages

apt-get install ldap-utils sudo-ldap libpam-ldap libnss-ldap nss-updatedb libnss-db autofs5 autofs5-ldap nscd

Install the server certificate's CA

  1. Install to /etc/ssl/certs/ldapca.crt
  2. Run:
pushd /etc/ssl/certs
ln -s ldapca.crt $(openssl x509 -hash -noout -in ldapca.crt).0
popd

Configure openldap's ldap.conf

Add the following options to /etc/ldap/ldap.conf:

BASE            <basedn>
URI             ldap://<servername>:389
SSL             start_tls
TLS_CHECKPEER   yes
TLS_REQCERT     demand
TLS_CACERTDIR   /etc/ssl/certs
TLS_CACERTFILE  /etc/ssl/certs/ldapca.crt
TLS_CACERT      /etc/ssl/certs/ldapca.crt
SUDOERS_BASE    ou=sudoers,<basedn>
  • Note: TLS_CACERTDIR is likely ignored, since gnutls doesn't support the directive, but for future compatibility, it should be defined.
  • Note: Though we define the URI as ldap/389, we should always use encryption, so all clients should use StartTLS

Configure libnss's ldap.conf

uri             ldap://<server1>:389 ldap://<server2>:389
base            <basedn>
binddn          cn=proxyagent,ou=profile,<basedn>
bindpw          <proxyagentPasswordInTheClear>
pam_filter      objectclass=posixAccount
nss_base_passwd ou=people,<basedn>
nss_base_shadow ou=people,<basedn>
nss_base_group  ou=group,<basedn>
nss_base_hosts  ou=hosts,<basedn>
nss_base_netgroup     ou=netgroup,<basedn>
tls_checkpeer   yes
tls_cacertfile   /etc/ssl/certs/ldapca.crt
tls_cacertdir   /etc/ssl/certs
ssl             start_tls
pam_password    clear

Configure nss

passwd:         files ldap
group:          files ldap
shadow:         files ldap

hosts:          files dns ldap
networks:       files

protocols:      db files
services:       db files
ethers:         db files
rpc:            db files

netgroup:       ldap
automount:      files ldap
sudoers:        files ldap

The above works for clients with DNS access. For hosts without DNS access, the following line works better for hosts:

hosts:          files ldap dns

Configure pam

common-auth:

# here are the per-package modules (the "Primary" block)
auth    [success=2 default=ignore]      pam_unix.so nullok_secure
auth    [success=1 default=ignore]      pam_ldap.so use_first_pass
# here's the fallback if no module succeeds
auth    requisite                       pam_deny.so
# limit access to specific users
auth    required                        pam_access.so
# prime the stack with a positive return value if there isn't one already;
# this avoids us returning an error just because nothing sets a success code
# since the modules above will each just jump around
auth    required                        pam_permit.so
# and here are more per-package modules (the "Additional" block)
# end of pam-auth-update config

common-account:

# here are the per-package modules (the "Primary" block)
account [success=2 new_authtok_reqd=done default=ignore]        pam_unix.so
account [success=1 default=ignore]      pam_ldap.so
# here's the fallback if no module succeeds
account requisite                       pam_deny.so
# prime the stack with a positive return value if there isn't one already;
# this avoids us returning an error just because nothing sets a success code
# since the modules above will each just jump around
account required                        pam_permit.so
# and here are more per-package modules (the "Additional" block)
# end of pam-auth-update config

common-password:

# here are the per-package modules (the "Primary" block)
password        [success=2 default=ignore]      pam_unix.so obscure sha512
password        [success=1 user_unknown=ignore default=die]     pam_ldap.so try_first_pass
# here's the fallback if no module succeeds
password        requisite                       pam_deny.so
# prime the stack with a positive return value if there isn't one already;
# this avoids us returning an error just because nothing sets a success code
# since the modules above will each just jump around
password        required                        pam_permit.so
# and here are more per-package modules (the "Additional" block)
# end of pam-auth-update config

common-session:

# here are the per-package modules (the "Primary" block)
session [default=1]                     pam_permit.so
# here's the fallback if no module succeeds
session requisite                       pam_deny.so
# prime the stack with a positive return value if there isn't one already;
# this avoids us returning an error just because nothing sets a success code
# since the modules above will each just jump around
session required                        pam_permit.so
# and here are more per-package modules (the "Additional" block)
session required        pam_unix.so
session optional                        pam_ldap.so
# end of pam-auth-update config

common-session-noninteractive:

# here are the per-package modules (the "Primary" block)
session [default=1]                     pam_permit.so
# here's the fallback if no module succeeds
session requisite                       pam_deny.so
# prime the stack with a positive return value if there isn't one already;
# this avoids us returning an error just because nothing sets a success code
# since the modules above will each just jump around
session required                        pam_permit.so
# and here are more per-package modules (the "Additional" block)
session required        pam_unix.so
session optional                        pam_ldap.so
# end of pam-auth-update config

Configure autofs

Configure /etc/autofs_ldap_auth.conf

Autofs's ldap configuration needs to be set to require tls, and authentication, and to use SASL PLAIN authentication with a DN and password. The following configuration provides that:

<?xml version="1.0" ?>
<autofs_ldap_sasl_conf
        usetls="yes"
        tlsrequired="yes"
        authrequired="yes"
        authtype="PLAIN"
        user="dn:cn=proxyagent,ou=profile,<basedn>"
        secret="<proxyagentPassword>"
/>

Be sure to fill in <basedn> and <proxyagentPassword> with real values.

Configuring overrides

nsswitch.conf is configured to use files, then ldap. It is possible, but not necessary to do this per map. It is required to do this at least for auto.master. If we want to pull all maps from ldap, the only line needed in /etc/auto.master is:

+auto.master

The above line tells automount to pull its maps from whichever service is configured in nss after files. If you wish to override LDAP, you can place entries above the + line. You can override individual entries for individual maps by doing something like the following:

  • In auto.master:
/data    /etc/auto.data
+auto.master
  • In auto.data:
overridenentry    <server>:/export
+auto.data

The above would still pull all auto.data entries, but would override the specific entry "overrideentry".

Configure sudo

sudo is configured via the nsswitch. As long as the sudo-ldap package is installed, and nsswitch.conf has ldap listed for sudoers, it will automatically pull from ldap.

Troubleshooting

Where to find logs

All LDAP server logs can be found here:


Corrupt nscd cache

The nscd cache is a bdb database, and can (rarely) become corrupt when a system shuts down uncleanly. You can forcibly clear the cache by doing the following:

/etc/init.d/nscd stop
rm -f /var/cache/nscd/*
/etc/init.d/nscd start

Invalid nscd cache

To purge an invalid cache, you can do the following:

nscd -i <database>

Where <database> is passwd, group, or services.

Debugging sudo-ldap

Sudo will print ldap debugging information, if you add the following to /etc/ldap/ldap.conf:

SUDOERS_DEBUG 2

Debugging autofs

Autofs will print debugging information to /var/log/syslog, if you add the following to /etc/default/autofs:

LOGGING="debug"

Common LDAP administrative actions

This shows you how to do user administration on LDAP. You need access to terbium, and should be either a root or a member of the group ldap-admins. We shall use the wonderful ldapvi program, not invented by us but maintained by a real upstream, to do these tasks.

Add a user to a group

ldapvi -b ou=groups cn=$groupname

This brings up an editor with all information about the group, including its list of members. You can add a member by adding the following line to the end of the editor:

member: uid=$shellname,ou=people,dc=wikimedia,dc=org

Then save and exit your editor (<ESC>:wq in vim), you'll be asked if you want to save these LDAP changes. Press y and enter to confirm, or q and enter to cancel

Remove a user from a group

ldapvi -b ou=groups cn=$groupname

This brings up an editor with all information about the group, including its list of members. You can find the member you want to remove (Press /$shellname to search in vim), remove that line entirely, and then exit and save.

Finding the shell name of a user

ldapsearch -x -b ou=people,dc=wikimedia,dc=org cn=$wikitechUserName

The shell username will be listed as 'uid', which is also in the DN.

Editing info about a user

If you want to change details about a user (for a rename, or a ssh key change or password reset), you can do

ldapvi -b ou=people cn=$shellusername

Then you can change all the info you want to and save to persist.

Changing the password of a user

To change the password of a user (as root, without knowing their current password):

sudo ldappasswd -H ldap://ldap-eqiad.wikimedia.org -x -D "cn=admin,dc=wikimedia,dc=org" -W -S "uid=<USER>,ou=people,dc=wikimedia,dc=org"

You will first be asked twice for a NEW password and then once for the admin password. You can find the admin password in pwstore.

See Also