Last-Updated: 12/02/2022
Introduction
Think about the traditional Unix user, password and group definitions:
- they are stored as flat file databases (i.e. text files in which one line is one record) in /etc/passwd, /etc/shadow and /etc/group
- they are simple text files, therefore …
- … we can modify them with a text editor (e.g. vi, emacs).
But with LDAP:
- they are stored in a hierarchical database, known in LDAP parlance as a Directory Information Tree (DIT) under /var/lib/ldap
- we are not concerned with how the data is encoded, therefore …
- … we may only modify the database with commands that do understand how the data is encoded, or rather, with commands (ldapadd, ldapmodify, ldapdelete) that communicate with the program (slapd) that does understand how the data is encoded.
DITs are identified by their base Distinguished Name (DN). The base DN is something you decide for yourself, but typically it is the ‘dc’-prefixed and comma-separated list of labels in the fully qualified domain name of an organisation. For example, my LDAP server is orzo.pasta.net and my home network’s domain is pasta.net, so my base DN should probably be ‘dc=pasta,dc=net’. That particular base DN is referenced in all the commands below, so remember to adjust to suit your own requirements!
The entries in the DIT are identified using their Relative Distinguished Name (RDN) followed by the parent entry’s DN; e.g. ‘ou=Users,dc=pasta.dc=net’.
Many entries in the DIT (e.g. ‘ou=Users,dc=pasta.dc=net’, ‘ou=Groups,dc=pasta.dc=net’) are created to act as containers for other entries (‘cn=fred,ou=Users,dc=pasta.dc=net’, ‘cn=bert,ou=Users,dc=pasta.dc=net’), allowing like entries to be grouped together.
LDAP configuration data (e.g. the LDAP admin’s password, which SASL authentication mechanisms to allow, the name of the DIT) can be stored in one of two ways:
- in files under /etc/ldap/slapd.d/ and are managed by editing these files and then restarting the LDAP daemon (slapd), or
- in a separate DIT called the Runtime Configuration (RTC) DIT (typically with base DN set to ‘cn=config’) and are managed (like the regular DIT) by using commands (e.g. ldapadd, ldapmodify).
While the first option looks like it might be easier to manage, the second option seems to be what most people are using now, so I will use the second option. We will refer to the two DITs as the regular DIT and the RTC DIT. (There is an additional third DIT called ‘frontend’; see section 5.2.5.1 of this document for details.)
There are various vendor-specific conventions regarding the names of OUs within the regular DIT (e.g. some put user records under a ‘People’ node, others put them under a ‘Users’ node). There are no fixed rules except that:
- you need to be consistent
- you will need to tell LDAP clients (e.g. the passwd program) where in the DIT the data they read/write is stored.
In this document I will store:
- all user entries under ‘ou=Users’
- all associated group entries under ‘ou=Groups’
- all associated automounter entries under ‘ou=admin,ou=automounter’ (which seems to be what the automounter is configured to expect by default)
This document is heavily based on the work of others; see the links at the bottom of the page for details.
This document was written for Debian 11, which uses LDAP server version 2.4.57, so remember to adjust to suit your own requirements!
Basic server installation
- Install the LDAP server and tools without being asked any questions by running:
DEBIAN_FRONTEND=noninteractive apt -y install slapd ldap-utils
(We skip the questions because otherwise it would have asked only a subset of the questions we want to answer! The full list will be answered shortly.)
- Check the name of the RTC DIT by running:
ldapsearch -H ldap:// -x -s base -b "" -LLL "configContext"
(Probably that reports that the configuration DIT is called ‘cn=config’.)
- Check the name of the regular DIT by running:
ldapsearch -Y EXTERNAL -H ldapi:/// -s base -b "" -LLL "namingContexts"
and if that reports nothing or something other than ‘dc=pasta,dc=net’ then answer the above-avoided questions plus some more by running:
dpkg-reconfigure slapd
answering the questions as follows:
- omit OpenLDAP server configuration: accept the default (i.e. the server configuration will be completed).
- DNS domain name: accept the default
- Organization name: accept the default (the same as the DNS domain name)
- set the password for the LDAP administrator (actually, I think this means: set the password for the administrator of the regular DIT)
- database backend to use: accept the default (MDB)
- remove database when slapd is purged: accept the default (no)
- move the old database: accept the default (yes)
- Note that, if the base DN was correct (which it might well be and was in my case) then this means we have not set a password for the LDAP administrator yet.
- Test as follows:
- Run:
orzo# ldapwhoami -x anonymous orzo#
and verify the output is as shown. (It reports ‘anonymous’ as root has not been properly authenticated when using this command.)
- Attempt the same command using SASL authentication, just pressing ENTER when prompted for a password:
orzo# ldapwhoami -U admin SASL/DIGEST-MD5 authentication started Please enter your password: ldap_sasl_interactive_bind_s: Invalid credentials (49) additional info: SASL(-13): user not found: no secret in database orzo#
- Note, as described here, that:
Some documentation and examples in the wild assume the existence of the entry cn=admin,cn=config in the RTC DIT and use this as the root Distinguished Name (DN). However, the default installation does not create any RootDN/RootPW entries in the RTC DIT. You must use the EXTERNAL mechanism to bind and manage the RTC DIT in the default installation. To manage the RTC DIT with tools such as slapadd or ldapmodify, bind with -Y EXTERNAL -H ldapi:///:
#test if OpenLDAP/slapd is running correctly: sudo ldapsearch -Y EXTERNAL -H ldapi:/// -b cn=config
- Note that that means we do not have to set a password for the LDAP administrator in order to be secure.
- So from here on:
- commands accessing the RTC DIT will use options to bind (i.e. to authenticate oneself, possibly specifying the ID of an entry in the DIT and the credentials stored in that entry)
-Y EXTERNAL -H ldapi:///
(the first option selects the SASL authentication mechanism that authenticates the user with UID==0 and GID==0; the second option means to connect over the Unix socket /var/run/ldap) - commands accessing the regular DIT will use options to bind
-x -D cn=admin,dc=pasta,dc=net -W
(the first option selects simple/non-SASL authentication, which requires specifying the ID of an entry in the DIT and the credentials stored in that entry; the second option specifies the ID of the entry in the DIT; the third options forces the password to be prompted for, rather than requiring it to be specified on the command line).
- commands accessing the RTC DIT will use options to bind (i.e. to authenticate oneself, possibly specifying the ID of an entry in the DIT and the credentials stored in that entry)
- So now attempt that
ldapwhoami
command again, but this time using SASL authentication over the Unix socket channel:ziti# ldapwhoami -Y EXTERNAL -H ldapi:/// SASL/EXTERNAL authentication started SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth SASL SSF: 0 dn:gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth ziti#
- Run:
- Reset the LDAP administrator’s password as described below.
Nicer management tools
While ldapadd, ldapdelete, ldapmodify are sufficient (and required for most of this procedure), there are nicer tools available. This section installs a couple of them.
- To install, configure and test shelldap:
- Run:
apt -y install shelldap
- Create ~/.shelldap.rc containing:
server: localhost binddn: cn=admin,dc=pasta,dc=net bindpass: <admin-password-in-plaintext> basedn: dc=pasta,dc=net tls: no
- Run shelldap and verify the output as below:
orzo# shelldap ~ > ls - cn=admin ~ > exit orzo#
- Run:
- To install, configure and test ldap-ui:
- Use
shelldap
to ensure that the cn=admin,dc=pasta,dc=net entry in the DIT has the following attributes:objectClass: uidObject uid: admin
(While
shelldap
seems happy without these attributes, ldap-ui will not be.) - Run:
apt -y install libsasl2-dev python-dev libldap2-dev libssl-dev python3-venv python3-ldap python3-pip mkdir -p /usr/local/opt cd /usr/local/opt git clone https://github.com/dnknth/ldap-ui.git cd ldap-ui make
- Press CTRL-C to exit.
- Run:
export LDAP_URL=ldap://localhost/ export BASE_DN=dc=pasta,dc=net /usr/local/opt/ldap-ui/.venv3/bin/hypercorn -b 0.0.0.0:5000 -c file:/usr/local/opt/ldap-ui/settings.py app:app &
(Note LDAP_URL and BASE_DN could be propagated into the environment of this one process, but the commands for setting up ldap-ui more permanently, a little bit further down this sub-procedure, rely on them being more widely scoped.)
- Login as user ‘admin’ (not ‘cn=admin,dc=pasta,dc=net’) with the admin’s password.
- Press CTRL-C to exit.
- To configure ldap-ui to start at boot time, run:
sed -e "s@/opt/@/usr/local/opt/@g" etc/ldap-ui.service \ -e "s@^Environment.*@Environment=LDAP_URL=$LDAP_URL BASE_DN=$BASE_DN@" \ -e 's/127\.0\.0\.1/0.0.0.0/' \ > /etc/systemd/system/ldap-ui.service systemctl daemon-reload systemctl start ldap-ui systemctl enable ldap-ui
- Use
Expanding the structure
Before we add users, groups, automount details, we need to add the containers (e.g. ‘ou=Users’) to accomodate them. You may wish to archive the LDIF files you import or create.
- You might wan to save a list of the currently known schemas:
ldapsearch -o ldif-wrap=no -H ldap://localhost/ -x -s base -b "cn=subschema" objectclasses | \ sed -nr "s/.* NAME '([^']+)'.*/\\1/p" | sort > before-schemas
- If autofs support is required then:
- As per instructions here, define the automountMap object class by running:
wget -qO classes-autofs.ldif https://launchpadlibrarian.net/55451730/autofs.ldif ldapadd -Y EXTERNAL -H ldapi:/// -f classes-autofs.ldif
Note that:
- In case the LDIF files disappears from that location, here is a copy:
dn: cn=autofs,cn=schema,cn=config objectClass: olcSchemaConfig cn: autofs olcAttributeTypes: {0}( 1.3.6.1.1.1.1.25 NAME 'automountInformation' DESC 'Inf ormation used by the autofs automounter' EQUALITY caseExactIA5Match SYNTAX 1. 3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) olcObjectClasses: {0}( 1.3.6.1.1.1.1.13 NAME 'automount' DESC 'An entry in an automounter map' SUP top STRUCTURAL MUST ( cn $ automountInformation $ object class ) MAY description ) olcObjectClasses: {1}( 1.3.6.1.4.1.2312.4.2.2 NAME 'automountMap' DESC 'An gro up of related automount objects' SUP top STRUCTURAL MUST ou )
(It is correct that words are split in the middle at the end of some lines.)
- The object class can also be defined by installing the autofs-ldap package but that pulls in a lot of dependencies, including autofs, which is probably not wanted on the LDAP server.
- In case the LDIF files disappears from that location, here is a copy:
- Create structure-autofs.ldif containing
dn: ou=automount,dc=pasta,dc=net ou: automount objectClass: top objectClass: organizationalUnit
- If you want to store the auto.master map itself in LDAP (I do not!) then add this to the same file (with a blank line separating it from any existing content in the file):
dn: ou=auto.master,ou=automount,dc=pasta,dc=net ou: auto.master objectClass: top objectClass: automountMap
- If you want to store the auto.home map in LDAP (I do!) then add this to the same file (with a blank line separating it from any existing content in the file):
dn: ou=auto.home,ou=automount,dc=pasta,dc=net ou: auto.home objectClass: top objectClass: automountMap
- If you want to store the auto.staging map in LDAP (I do!) then add this to the same file (with a blank line separating it from any existing content in the file):
dn: ou=auto.staging,ou=automount,dc=pasta,dc=net ou: auto.staging objectClass: top objectClass: automountMap
- Run:
ldapadd -x -D cn=admin,dc=pasta,dc=net -W -f structure-autofs.ldif
- As per instructions here, define the automountMap object class by running:
- Create structure-users.ldif containing:
dn: ou=Users,dc=pasta,dc=net objectClass: organizationalUnit ou: Users dn: ou=Groups,dc=pasta,dc=net objectClass: organizationalUnit ou: Group
- Run:
ldapadd -x -D cn=admin,dc=pasta,dc=net -W -f structure-users.ldif
SASL authentication
Note that this procedure appears to work but it does not! As soon as ldappasswd
is run then the password reverts from plaintext to SSHA. Since plaintext is not secure anyway (root can see users’ passwords) then I won’t use SASL, but will try LDAP over SSL instead. I.e. I did not do this!
- Create a file entries-config-sasl.ldif containing:
dn: cn=config changetype: modify add: olcAuthzRegexp olcAuthzRegexp: uid=([^,]*),cn=digest-md5,cn=auth ldap:///dc=pasta,dc=net??sub?(uid=$1)
Note the use of a regular expression to help locate crendentials. This way it doesn’t matter if users info is stored unde ou=Users, ou=People or whatever.
- Apply this change by running:
ldapmodify -Y EXTERNAL -H ldapi:/// -f entries-config-sasl.ldif
- To test SASL authentication:
- Create a file entries-users-test.ldif containing:
dn: uid=test,ou=Users,dc=pasta,dc=net objectClass: account objectClass: posixAccount cn: test gidNumber: 1000 homeDirectory: /home/test uid: test uidNumber: 1000 userPassword: opensesame
- Apply the change by running:
ldapadd -x -D cn=admin,dc=pasta,dc=net -W -f entries-users-test.ldif
- Check if SASL authentication is now working for that single user by running:
ldapwhoami -U test
and checking the looks like this:
SASL/DIGEST-MD5 authentication started Please enter your password: SASL username: test SASL SSF: 128 SASL data security layer installed. dn:uid=test,ou=users,dc=pasta,dc=net
- Delete the test user again:
ldapdelete -x -D cn=admin,dc=pasta,dc=net -W uid=test,ou=Users,dc=pasta,dc=net
- Create a file entries-users-test.ldif containing:
Let’s Encrypt certificate
Beware that replacing an LDAP server will be more complicated since we don’t want to break the certificate chain for the old server.
- Ensure that the front-end webserver to does not forward requests that it receives over https to the mail server (it is not needed).
- Ensure that the front-end webserver forwards requests that it receives over http to the LDAP server, with a configuration something like this:
<VirtualHost *:80> ServerName ldap.pasta.freemyip.com ServerAdmin webmaster@dont-use-this-address CustomLog /var/log/apache2/ldap.pasta.freemyip.com.pasta.freemyip.com/ldap.pasta.freemyip.com.pasta.freemyip.com-access.log combined2 ErrorLog /var/log/apache2/ldap.pasta.freemyip.com.pasta.freemyip.com/ldap.pasta.freemyip.com.pasta.freemyip.com-error.log LogLevel warn ServerSignature Off <Location /> ProxyPass http://ldap.pasta.net/ ProxyPassReverse http://ldap.pasta.net/ </Location> </VirtualHost>
- On the DNS server, update the CNAME record and RPZ for ‘ldap.pasta.freemyip.com’ to point to the new LDAP server.
- On the LDAP server install and run certbot as follows:
apt -y install certbot certbot certonly --standalone -d <public-dns-name> # e.g. ldap.pasta.freemyip.com
(The option
--standalone
will – whenever requesting/renewing a certificate – start a standalone internal webserver to allow letsencrypt.org authenticate the renewal request; /etc/cron.d/certbot will respect this option when it is used to initially request the certificate.) - Locate the certificate and key generated by certbot:
find /etc/letsencrypt/live/ -name fullchain.pem -o -name privkey.pem -o -name cert.pem
LDAP over SSL
- Set some environment variables:
FQDN=<fully-qualified-domain-name> # e.g. FQDN=ldap.pasta.freemyip.com
- Edit /etc/default/slapd and set:
SLAPD_SERVICES="ldap:/// ldapi:/// ldaps:///"
- Run:
systemctl restart slapd
- Check that slapd is now listening on port 636, as shown in this output:
orzo# netstat -plutn | grep slapd tcp 0 0 0.0.0.0:636 0.0.0.0:* LISTEN 3913/slapd tcp 0 0 0.0.0.0:389 0.0.0.0:* LISTEN 3913/slapd orzo#
- Copy the LetsEncrypt certificate files to where the slapd process can read them:
mkdir /etc/ldap/certs cd /etc/letsencrypt/live/$FQDN for FILE in *.pem; do cp $FILE /etc/ldap/certs/$FQDN.$FILE done chown -R openldap:openldap /etc/ldap/certs
- Create entries-config-cert1.ldif containing:
dn: cn=config changetype: modify replace: olcTLSCACertificateFile olcTLSCACertificateFile: /etc/ldap/certs/FQDN.fullchain.pem
- Create entries-config-cert2.ldif containing:
dn: cn=config changetype: modify replace: olcTLSCertificateKeyFile olcTLSCertificateKeyFile: /etc/ldap/certs/FQDN.privkey.pem
- Create entries-config-cert3.ldif containing:
dn: cn=config changetype: modify replace: olcTLSCertificateFile olcTLSCertificateFile: /etc/ldap/certs/FQDN.cert.pem
- Make the necessary substitutions in those files:
sed -i "s/FQDN/$FQDN/g" entries-config-cert*.ldif
- Run:
ldapsearch -o ldif-wrap=no -Y EXTERNAL -H ldapi:/// -z 0 -b "cn=config" "(objectclass=*)" > before ldapmodify -Y EXTERNAL -H ldapi:/// -f entries-config-cert1.ldif ldapmodify -Y EXTERNAL -H ldapi:/// -f entries-config-cert2.ldif ldapmodify -Y EXTERNAL -H ldapi:/// -f entries-config-cert3.ldif ldapsearch -o ldif-wrap=no -Y EXTERNAL -H ldapi:/// -z 0 -b "cn=config" "(objectclass=*)" > after diff before after
You should expect the diff command to show lines have been added. (This may seem a stupid wau to do this, but putting all three stanzas in one file generally doesn’t work and this way facilitates reordering most easily. See the many questions on Stackexchange regarding this.)
- Test by running:
orzo# ldapwhoami -H ldaps://ldap.pasta.freemyip.com/ -x -D "cn=admin,dc=pasta,dc=net" -W Enter LDAP Password: dn:cn=admin,dc=pasta,dc=net orzo#
- Note that the host name in the LDAP URL must agree with the CN for which the certificate was issued; here is a command showing what happens when it doesn’t:
orzo# ldapwhoami -H ldaps://ldap.pasta.net/ -x -D "cn=admin,dc=pasta,dc=net" -W -d-1 Enter LDAP Password: ... TLS: hostname (ldap.pasta.net) does not match common name in certificate (ldap.pasta.freemyip.com). TLS: can't connect: (unknown error code). ldap_err2string ldap_sasl_bind(SIMPLE): Can't contact LDAP server (-1) orzo#
- Note the procedure is enough to make LDAP over SSL work … until the certificate gets renewed! At that point the copy of the certificate files in /etc/ldap is out of date with respect to those in /etc/letsencrypt! To address that we need a simple plugin.
- Create a script to instruct slapd to reload its configuration when the Let’s Encrypt certificate gets renewed:
{ echo '#!/bin/sh' echo "FQDN=$FQDN" echo 'cp /etc/letsencrypt/live/$FQDN/fullchain.pem /etc/ldap/certs/$FQDN.fullchain.pem' echo 'cp /etc/letsencrypt/live/$FQDN/privkey.pem /etc/ldap/certs/$FQDN.privkey.pem' echo 'cp /etc/letsencrypt/live/$FQDN/privkey.pem /etc/ldap/certs/$FQDN.chain.pem' echo 'cp /etc/letsencrypt/live/$FQDN/privkey.pem /etc/ldap/certs/$FQDN.cert.pem' echo 'chown openldap:openldap /etc/ldap/certs/$FQDN.fullchain.pem' echo 'chown openldap:openldap /etc/ldap/certs/$FQDN.privkey.pem' echo 'chown openldap:openldap /etc/ldap/certs/$FQDN.chain.pem' echo 'chown openldap:openldap /etc/ldap/certs/$FQDN.cert.pem' echo 'systemctl restart slapd' } > /etc/letsencrypt/renewal-hooks/deploy/slapd chmod 755 /etc/letsencrypt/renewal-hooks/deploy/slapd
- Edit ~/.shelldap.rc and adjust
server
andtls
.
Adding real entries
- If you want to add an entry to auto.staging for the mailserver to automount the mail directory, using a symlink pointing from /var/mail to /staging/mail (I did but not any more) then create entries-autofs-mail.ldif containing:
dn: cn=mail,ou=auto.staging,ou=automount,dc=pasta,dc=net cn: mail objectClass: top objectClass: automount automountInformation: -nordirplus,noatime,nodiratime,nfsvers=3,nolock,proto=tcp filer-on-storage-net.pasta.net,filer-on-public-net.pasta.net:/vol/small/mail
and run:
ldapadd -x -D cn=admin,dc=pasta,dc=net -W -f entries-autofs-mail.ldif
- If you want to add an entry to auto.staging for any machine to automount /pub, using a symlink pointing from /pub to /staging/pub (I do) then create entries-autofs-pub.ldif containing:
dn: cn=pub,ou=auto.staging,ou=automount,dc=pasta,dc=net cn: pub objectClass: top objectClass: automount automountInformation: -nordirplus,noatime,nodiratime,nfsvers=3,nolock,proto=tcp filer-on-storage-net.pasta.net,filer-on-public-net.pasta.net:/vol/pub
and run:
ldapadd -x -D cn=admin,dc=pasta,dc=net -W -f entries-autofs-pub.ldif
Creating a normal user
- Create entries-users-alexis.ldif containing:
dn: cn=alexis,ou=Groups,dc=pasta,dc=net objectClass: posixGroup cn: alexis gidNumber: 1000 description: Group account dn: uid=alexis,ou=Users,dc=pasta,dc=net objectClass: account objectClass: posixAccount cn: alexis uid: alexis uidNumber: 1000 gidNumber: 1000 homeDirectory: /home/alexis loginShell: /bin/bash gecos: Alexis Huxley description: User account
which is deliberately missing the userPassword attribute.
- If using the automounter (I do!) then add this to the same file (with a blank line separating it from any existing content in the file):
dn: cn=alexis,ou=auto.home,ou=automount,dc=pasta,dc=net cn: alexis objectClass: top objectClass: automount automountInformation: -nordirplus,noatime,nodiratime,nfsvers=3,nolock,proto=tcp filer-on-storage-net.pasta.net,filer-on-public-net.pasta.net:/vol/home/alexis
- Create the user by running:
ldapadd -x -D cn=admin,dc=pasta,dc=net -W -f entries-users-alexis.ldif
- Set the user’s password by running:
ldappasswd -x -D cn=admin,dc=pasta,dc=net -W -S "uid=alexis,ou=Users,dc=pasta,dc=net"
- Repeat for other users.
Client configuration
Note that pcms takes care of this for me!
- Run:
apt-get install libnss-ldapd nslcd libldap-common
(libnss-ldapd and nslcd are required for programs that consult nssswitch.conf, e.g. ‘getent’, ‘id’; libldap-common is required for programs that consult /etc/ldap/ldap.conf and then contact the LDAP server directly, e.g. ldapsearch).
- At the ‘Configuring nslcd’ window, when prompted ‘LDAP server URI’, enter ‘ldap://<ldap-server-ip-address>/’.
- At the ‘Configuring nslcd’ window, when prompted ‘LDAP server search base’, enter the correct search base as set earlier (e.g. ‘dc=pasta,dc=net’)
- At the ‘Configuring libnss-ldapd’, when prompted ‘Name services to configure’, enable passwd, group and shadow services.
- Test by running:
getent passwd alexis
Resetting the LDAP administrator’s password
- Log in to the LDAP server.
- Set the password for the RTC DIT as follows:
- Get the LDIF-formatted entry specifying the current password, as in this example:
orzo# ldapsearch -H ldapi:// -LLL -Q -Y EXTERNAL -b "cn=config" "(olcRootDN=*)" dn olcRootDN olcRootPW dn: olcDatabase={0}config,cn=config olcRootDN: cn=admin,cn=config dn: olcDatabase={1}mdb,cn=config olcRootDN: cn=admin,dc=pasta,dc=net olcRootPW: {SSHA}YYYYYYYYYYYYYYYYYYYYYYYYYY orzo#
and note:
- the use of
-H ldapi:// -Y EXTERNAL
to communicate over a channel that obviates the need to provide credentials in order to authenticate oneself - the hash type used to store the old password, which in this case is
{SSHA}
- the database format, which in this case is
mdb
.
- the use of
- Use slappasswd, possibly with the
-h
option to use the same hash type as before, to generate the hash of the new password, e.g.:ziti# slappasswd -h '{SSHA}' New password: Re-enter new password: {SSHA}ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ ziti#
- Create a new LDIF file called entries-config-admin-passwd.ldif containing:
dn: olcDatabase={1}<database-format-e.g.-mdb>,cn=config changetype: modify replace: olcRootPW olcRootPW: <hashed-password-including-hash-type-prefix-as-reported-by-slappasswd-above>
- Apply this by running:
ldapmodify -H ldapi:// -Y EXTERNAL -f entries-config-admin-passwd.ldif
- Get the LDIF-formatted entry specifying the current password, as in this example:
- How to the password for the regular DIT, depends on whether you are modifying the entry (because you did run
dpkg-reconfigure slapd
above, which will have created the entry for you) or creating the entry (because you did not rundpkg-reconfigure
slapd above). If you are modifying the entry then:- Create entries-admin-passwd.ldif containing:
dn: cn=admin,dc=pasta,dc=net changetype: modify replace: userPassword userPassword: <hashed-password-including-hash-type-prefix-as-reported-by-slappasswd-above>
- Apply this by running:
ldapmodify -H ldap:// -x -D "cn=admin,dc=pasta,dc=net" -W -f entries-admin-passwd.ldif
using simple/non-SASL authentication (
-x
) using the RTC password just set above.
and if you are adding the entry then:
- Create entries-admin-passwd.ldif containing:
dn: cn=admin,dc=pasta,dc=net objectClass: simpleSecurityObject objectClass: organizationalRole cn: admin description: LDAP administrator userPassword: <hashed-password-including-hash-type-prefix-as-reported-by-slappasswd-above>
- Apply this by running::
ldapadd -H ldap:// -x -D "cn=admin,dc=pasta,dc=net" -W -f entries-admin-passwd.ldif
using simple/non-SASL authentication (
-x
) using the RTC password just set above.
- Create entries-admin-passwd.ldif containing:
- Test that you can authenticate yourself as admin against the admin’s entry in the regular DIT:
orzo# ldapwhoami -W -x -D cn=admin,dc=pasta,dc=net Enter LDAP Password: dn:cn=admin,dc=pasta,dc=net orzo#
Determining which SASL authentication mechanisms are enabled
- Run:
ldapsearch -LLL -H ldapi:// -Y EXTERNAL -D dc=pasta,dc=net -s base -b "" "(objectclass=*)" supportedSASLMechanisms
(This is taken from here.)
- For reasons I don’t yet understand the following command gives different results:
ldapsearch -LLL -x -s base -b "" "(objectclass=*)" supportedSASLMechanisms
(This is based on something taken from here.)
ldapscripts
We deliberately use only ldapadd, ldapdelete and ldapmodify as these should work everywhere and keep the software stack to a minimum, but there is a package that will allow some shortcuts, especially for creating groups and users. I do not use it!
- Run:
apt-get install ldapscripts
- Edit /etc/ldapscripts/ldapscripts.conf and set the following, being sure to ignore the Debian-specific ways of doing things:
SERVER="ldap://localhost" SUFFIX="dc=pasta,dc=net" GSUFFIX="ou=Groups" USUFFIX="ou=Users" MSUFFIX="ou=Machines" SASL_AUTH="" BINDDN="cn=admin,dc=pasta,dc=net" PASSWORDGEN="<ask>"
(That’s a literal ‘<‘ and ‘>’.)
- Run:
echo -n '<the-ldap-password-you-set-earlier>' > /etc/ldapscripts/ldapscripts.passwd chmod 600 /etc/ldapscripts/ldapscripts.passwd
- Test by running:
lsldap
List contents of DITs
- To list the whole contents of the regular DIT run
ldapsearch -z 0 -W \ -b "dc=pasta,dc=net" \ -D "cn=admin,dc=pasta,dc=net" \ "(objectclass=*)"
- To list the whole contents of the RTC DIT run:
ldapsearch -W -Y EXTERNAL -H ldapi:/// -z 0 \ -b "cn=config" \ "(objectclass=*)"
Backing up and restoring DITs
Stuff for me to investigate further
- chsh probably doesn’t work
- force changing password see https://serverfault.com/questions/255603/ldap-force-user-to-change-password
See also
- Computing
- Securing openLDAP SASL authentication
- OpenLDAPServer at help.ubuntu.com
- How To Configure OpenLDAP and Perform Administrative LDAP Tasks at digitalocean.com
-
How To Change Account Passwords on an OpenLDAP Server at digitalocean.com
- AutofsLDAP at help.ubuntu.com
- Use ppolicy_hash_cleartext to keep OpenLDAP from storing and returning plain text passwords (includes a section on decoding the base64-encoded passwords returned by ldapsearch)