Vendredi 23 novembre 2018

OpenLDAP

Getting started with OpenLDAP on Debian
LDAP managed mail server with Postfix and Dovecot for multiple domains
Installation d’un serveur mail avec backend OpenLDAP

Installation

L’installation d’OpenLDAP sur Debian est faite à l’aide de la gestion des paquets APT.
root@ldaphost:~# apt install slapd ldap-utils

Pendant l’installation, vous devrez choisir un mot de passe de l’administrateur pour le compte racine LDAP. rhTJH8f97dkS65

Reconfigurer ldap

sudo dpkg-reconfigure slapd
Voulez-vous omettre la configuration d’OpenLDAP ? Non
Nom de domaine : xoyize.xyz
Nom d’entité (« organization ») : yanspm
Mot de passe de l’administrateur : f43z7C9TBwxX3h
Module de base de données à utiliser : HDB
Faut-il supprimer la base de données lors de la purge du paquet ? Non
Faut-il déplacer l’ancienne base de données ? Oui

Ensuite, nous devons redémarrer slapd .
root@ldaphost:~# service slapd restart
Et nous pouvons vérifier si les changements ont pris effet

root@ldaphost:~# netstat -lpn | grep slapd
tcp        0      0 0.0.0.0:389             0.0.0.0:*               LISTEN      3106/slapd          
tcp6       0      0 :::389                  :::*                    LISTEN      3106/slapd          

Comme on peut le voir, slapd écoute les interfaces locales IPv4 et IPv6.

PhpLdapAdmin

Installation
php-ldap
apt install php7.0-ldap #PHP7

Téléchargement
wget -O phpLDAPadmin.tar.gz http://sourceforge.net/projects/phpldapadmin/files/phpldapadmin-php5/1.2.3/phpldapadmin-1.2.3.tgz/download
Décompression
tar xvzf phpLDAPadmin.tar.gz -C .
Déplacer dans le dossier web
mv phpldapadmin-1.2.3 /var/www/phpldapadmin Files owned by root, www-data can just read
chown -R root: /var/www/phpldapadmin
find /var/www/phpldapadmin -type f | xargs sudo chmod 644
find /var/www/phpldapadmin -type d | xargs sudo chmod 755
config.php contains sensitive data, restrict its access
cp /var/www/phpldapadmin/config/config.php.example /var/www/phpldapadmin/config/config.php
chown root:www-data /var/www/phpldapadmin/config/config.php
chmod 640 /var/www/phpldapadmin/config/config.php
Test connexion ldap avec ldapwhoami
ldapwhoami -H ldap:// -x retourne anonymous

Configuration PhpLdapAdmin
sudo nano /var/www/phpldapadmin/config/config.php

Rechercher Ctrl W $servers->setValue(‘server’,’name’
$servers->setValue('server','name','xoyize LDAP Server'); Rechercher Ctrl W $servers->setValue(‘server’,’base’,array(‘’))
$servers->setValue('server','base',array('dc=xoyize,dc=xyz'));
Hide the warnings for invalid objectClasses/attributes in templates.
$config->custom->appearance['hide_template_warning'] = true;

Configuration Vhost NGINX
sudo nano /etc/nginx/conf.d/xoyize.xyz.d/phpldapadmin.conf

location /phpldap {
  alias /var/www/phpldapadmin ;
  index index.php;
  try_files $uri $uri/ index.php;
        location ~ \.php$ {
           fastcgi_split_path_info ^(.+\.php)(/.+)$;
           fastcgi_pass unix:/run/php/php7.0-fpm.sock;    # PHP7.0 
           fastcgi_index index.php;
           include fastcgi_params;
	   fastcgi_param SCRIPT_FILENAME $request_filename;
        }
}

Vérifier et relancer le service sudo nginx -t
sudo systemctl restart nginx

Connexion https://xoyize.xyz/phpldap/ cn=admin,dc=xoyize,dc=xyz mot-de-passe
cn=admin,dc=xoyize,dc=xyz WLgG39zx52

Configuration LDAP StartTLS

Bien que nous ayons crypté notre interface Web, les clients LDAP externes se connectent toujours au serveur et transmettent des informations en texte brut.
Utilisons nos certificats SSL Let’s Encrypt pour ajouter un cryptage à notre serveur LDAP.
Configuration de Slapd pour offrir des connexions sécurisées

Enfin, nous devons configurer slapd pour utiliser ces certificats et ces clés.
Pour ce faire, nous mettons toutes nos modifications de configuration dans un fichier LDIF (format d’échange de données LDAP)
puis chargeons les modifications dans notre serveur LDAP avec la commande ldapmodify.

sudo -s
mkdir /etc/ldap/tls/
# copy the files
cp /root/.acme.sh/xoyize.xyz/xoyize.xyz.cer /etc/ldap/tls/slapd-xoyize-cert.pem
cp /root/.acme.sh/xoyize.xyz/fullchain.cer /etc/ldap/tls/slapd-xoyize-fullchain.pem
cp /root/.acme.sh/xoyize.xyz/xoyize.xyz.key /etc/ldap/tls/slapd-xoyize-key.pem
chown -R openldap:openldap /etc/ldap/tls/
chmod 101 /etc/ldap/tls/
chmod 400 /etc/ldap/tls/*
chmod 404 /etc/ldap/tls/slapd-xoyize-cert.pem

ATTENTION: Le fichier /etc/ldap/ldap.conf doit contenir une référence TLS_CACERT

Now you need to tell slapd where it will find the files by setting the accordant attributes in cn=config.

slapd_config_TLS_enable.ldif

dn: cn=config changetype: modify add: olcTLSCACertificateFile olcTLSCACertificateFile: /etc/ldap/tls/slapd-xoyize-cert.pem - add: olcTLSCertificateFile olcTLSCertificateFile: /etc/ldap/tls/slapd-xoyize-fullchain.pem - add: olcTLSCertificateKeyFile olcTLSCertificateKeyFile: /etc/ldap/tls/slapd-xoyize-key.pem

root@ldaphost:~# ldapmodify -Q -Y EXTERNAL -H ldapi:/// -f slapd_config_TLS_enable.ldif

OpenLDAP configuration

Depuis OpenLDAP 2.3, la configuration du comportement de slapd est stockée dans l’arborescence d’informations du répertoire (DIT). À mon avis, cela rend la configuration beaucoup plus obscure que de simplement éditer un fichier de configuration, mais comme la configuration de l’ancien fichier slapd.conf est obsolète et ne sera pas prise en charge dans les versions futures, nous devons nous en occuper.

Modifier la configuration

Pour modifier la configuration de votre installation slapd, vous devez modifier les attributs de l’arbre de répertoires cn=config. Cela peut être réalisé en utilisant n’importe quel outil standard pour la communication et la manipulation avec LDAP comme ldapmodify ou des outils graphiques comme jxeplorer ou phpldapadmin. Dans la configuration par défaut appliquée lors de l’installation de slapd, seul l’utilisateur root local de la machine est autorisé à accéder au cn=config DIT.

Pour appliquer les modifications à la configuration active, vous pouvez créer des fichiers LDIF décrivant la modification et les envoyer dans l’arborescence cn=config en utilisant ldapmodify.
Pour définir le loglevel de slapd, vous pouvez créer le fichier suivant
slapd_config_loglevel.ldif

dn: cn=config
changetype: modify
add: olcLogLevel
olcLogLevel: none stats config conns

Et utiliser ldapmodify pour appliquer les modifications.

root@ldaphost:~# ldapmodify -Q -Y EXTERNAL -H ldapi:/// -f slapd_config_loglevel.ldif

Configure suffix and create basic DIT objects

One of the very first things you might want to configure is the olcSuffix attribute of your directory database. Usually this is choosen to reflect the domain name of the slapd running host. For example, if the server runs on a host thats domain name is ldap.example.com, the olcSuffix attribute is set to dc=example,dc=com.

If you are lucky the suffix got set correctly during installation of slapd and you don’t have to configure it yourself. To check what suffix was set you can either check for the olcSuffix attribute in olcDatabase={1}mdb,cn=config or ask your LDAP server which baseDNs it provides.

To figure this out, run the following command on your server.

user@ldaphost:~$ ldapsearch -LLL -x -H ldapi:/// -b “” -s base namingcontexts

If you get something like

dn: namingContexts: dc=your,dc=domain,dc=com

(of course reflecting your domain name instead) you are just fine and can proceed with further configuration. If you get something that doesn’t match your domain name (e.g. dc=nodomain) you have to set it up yourself.

To change the suffix of your database, you first have to modify the olcSuffix and olcRootDN attributes to match your domain name.

slapd_config_suffix.ldif

dn: olcDatabase={1}mdb,cn=config
changetype: modify
replace: olcSuffix
olcSuffix: dc=your,dc=domain,dc=com
-
replace: olcRootDN
olcRootDN: cn=admin,dc=your,dc=domain,dc=com

root@ldaphost:~# ldapmodify -Q -Y EXTERNAL -H ldapi:/// -f slapd_config_suffix.ldif

After that you have to create the top element of the directory tree (dc=your,dc=domain,dc=com) and the object for the LDAP adminstrator account (cn=admin,dc=your,dc=domain,dc=com).

slapd_setup_basic.ldif

dn: dc=your,dc=domain,dc=com
changetype: add
objectClass: top
objectClass: dcObject
objectClass: organization
o: Example Organisation name
dc: your

dn: cn=admin,dc=your,dc=domain,dc=com
changetype: add
objectClass: simpleSecurityObject
objectClass: organizationalRole
cn: admin
description: LDAP administrator
userPassword:

To create these objects, you have to use the databases root account and to enter your LDAP admin password as specified during installation.

user@ldaphost:~$ ldapmodify -x -W -D cn=admin,dc=your,dc=domain,dc=com -H ldapi:/// -f slapd_setup_basic.ldif

Allow configuration via simple authentication over TCP

While for basic configurations of slapd the usage of LDIF files and the hosts root account is necessary, it might be more convinient to connect to the cn=config DIT using graphical tools like jxeplorer or phpldapadmin to browse and modify the configuration comfortably. These tools connect to slapd via TCP and usually make use of the simple authentication method. To allow configuration over TCP connections, we have to add a olcRootPW attribute to the olcDatabase=config,cn=config entry. The password is provided in a hashed manner. You can either reuse the hash you retrieved from your current configuration (See attribute olcRootPW in olcDatabase={1}mdb,cn=config) and use one password for managing both configuration and information database, or you generate a new hash choosing a seperate password (advised) by using the slappasswd command.

user@ldaphost:~$ slappasswd New password: Re-enter new password: {SSHA}x8dz1b+GDsUM9jeqz81xQhoEvTQLf07/

To add the password to the cn=config database you have to create a LDIF file which describes the changes that will be made to the database.

slapd_setup_config_rootPW.ldif

dn: olcDatabase={0}config,cn=config
changetype: modify
add: olcRootPW
olcRootPW: {SSHA}x8dz1b+GDsUM9jeqz81xQhoEvTQLf07/

To apply the changes to your slapd run

root@ldaphost:~# ldapmodify -Q -Y EXTERNAL -H ldapi:/// -f slapd_setup_config_rootPW.ldif

and check if the password got added correctly:

root@ldaphost:~# ldapsearch -LLL -Q -Y EXTERNAL -H ldapi:/// -b ‘olcDatabase={0}config,cn=config’ dn: olcDatabase={0}config,cn=config objectClass: olcDatabaseConfig olcDatabase: {0}config olcAccess: {0}to * by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external ,cn=auth manage by * break olcRootDN: cn=admin,cn=config olcRootPW: {SSHA}x8dz1b+GDsUM9jeqz81xQhoEvTQLf07/

You should now be able to see and edit your configuration using the cn=admin,cn=config user and your password with simple authentication (-x) over TCP (ldap://localhost:389).

user@ldaphost:~$ ldapsearch -LLL -x -W -D cn=admin,cn=config -H ldap://localhost:389 -b cn=config Enter LDAP Password: dn: cn=config …

WARNING: Before connecting to your LDAP server over TCP trough the internet read the next section on how to secure the connection between you and your server to prevent sniffing of your passwords and intrusion to your slapd. Securing the connection

Before connecting to your LDAP server over TCP from outsite (your local workspace) you should ensure that the connection established over the network (usually the internet) between your workstation and your LDAP server is encrypted so that an eavesdropper can’t sniff the content of your LDAP communication, which, for example, might contain your root password.

If you have SSH access to the slapd running server you can setup an encrypted tunnel from your local machine to slapd by doing something like

you@workstation:~$ ssh -L 10389:localhost:389 ldap.example.com

which will open port 10389 on your workstation to which you can connect with any ldap client like ldapsearch.

you@workstation:~$ ldapsearch -x -H ldap://localhost:10389 -b dc=ldap,dc=example,dc=com

While this is a good way of securing your connection if you are the only one connecting to your slapd from the outsite world it is not sustainable to make your directory reachable for other services running on different hosts or for users without SSH access to this particular machine. For these purposes it’s better to secure the connection by TLS.

To setup TLS support you need to provide three files.

The certification authority certificate (CA.pem)
The actual TLS key used for encryption (device.key)
The certificate for your TLS key (device.crt), signed with the key belonging to the CA certificate

Here is a quick walkthrough to generate these files on your own. This will leave you with a certificate valid for one year. Important when generating the device certificate (device.crt) is to set the common name (CN) to the domain name that will be used to contact the ldap server (e.g. ldap.example.com). Otherwise, the connection will be refused with TLS: hostname does not match CN in peer certificate. You could also use a certificate signed by an official certificate authority like Let’s Encrypt.

root@ldaphost:~# openssl genrsa -out CA.key 8192 && chmod 400 CA.key root@ldaphost:~# openssl req -new -x509 -nodes -key CA.key -days 3650 -out CA.pem root@ldaphost:~# openssl genrsa -out device.key 4096 && chmod 400 device.key root@ldaphost:~# openssl req -new -key device.key -out device.csr root@ldaphost:~# openssl x509 -req -in device.csr -CA CA.pem -CAkey CA.key -CAcreateserial -out device.crt -days 365

If you got all necessary files generated, you can store them in /etc/ldap/tls/. Keep in mind that at least the key (device.key) contains sensitive data that needs to be protected from being read by anyone else than the slapd process. This can easily be achieved by changing the file’s owner to the slapd running user openldap and giving read permissions to only the owner of the file.

root@ldaphost:~# mkdir /etc/ldap/tls/ root@ldaphost:~# cp CA.pem device.key device.crt /etc/ldap/tls/ root@ldaphost:~# chown -R openldap:openldap /etc/ldap/tls/ root@ldaphost:~# chmod 101 /etc/ldap/tls/ root@ldaphost:~# chmod 400 /etc/ldap/tls/* root@ldaphost:~# chmod 404 /etc/ldap/tls/CA.pem

Now you need to tell slapd where it will find the files by setting the accordant attributes in cn=config.

slapd_config_TLS_enable.ldif

dn: cn=config
changetype: modify
add: olcTLSCACertificateFile
olcTLSCACertificateFile: /etc/ldap/tls/CA.pem
-
add: olcTLSCertificateFile
olcTLSCertificateFile: /etc/ldap/tls/device.crt
-
add: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: /etc/ldap/tls/device.key

root@ldaphost:~# ldapmodify -Q -Y EXTERNAL -H ldapi:/// -f slapd_config_TLS_enable.ldif

If you run into trouble setting these attributes, it might help to restart the slapd deamon (service slapd restart).

Before testing the TLS configuration with ldapsearch on your ldap server the TLS_CACERT directive has to be set in /etc/ldap/ldap.conf to point to the CA certificate used by the slapd. This needs to be done on any host that needs to connect to your LDAP server using TLS. This means that you also need to copy the CA.pem to each clients /etc/ldap/tls/CA.pem and configure /etc/ldap/ldap.conf accordingly.

ldap.conf

TLS_CACERT /etc/ldap/tls/CA.pem

To test whether TLS support works try to run a ldapsearch with parameter -ZZ. Make sure to use the hostname you specified in the CN attribute of your TLS certificate.

user@ldaphost:~$ ldapsearch -LLL -x -H ldap://ldap.example.com -b dc=ldap,dc=example,dc=com -ZZ

If this works without any errors, also try to connect to the configuration database cn=config using TLS.

user@ldaphost:~$ ldapsearch -LLL -x -W -D cn=admin,cn=config -H ldap://ldap.example.com -b cn=config -ZZ Enter LDAP Password: dn: cn=config …

If you get an error like ldap_start_tls: Can’t contact LDAP server (-1) this might indicate a wrong configuration of your DNS setup (domain does not point to your local interface). Try to add the line 127.0.0.1 ldap.example.com (and ::1 ldap.example.com when using IPv6) to your /etc/hosts file and try again. Tightening TLS

When the basic TLS setup works, you also might want to set the olcTLSCipherSuite to define what cypher suites and protocols will be used within the connection. There is no general recommendation for this parameter, since a lot of things must be taken into consideration. If you control the clients connecting to your server as well, you can come up with a more secure and strict configuration. If you have to support a lot of different and maybe outdated clients, a more relaxed configuration might be necessary.

Since in Debian slapd was built against GnuTLS it is not possible to use OpenSSL cypher lists. Instead a GnuTLS Priority string has to be used. Take some time to read through the following links to decide for a string that suits your environment.

GnuTLS Priority string reference
RHEL 7 dokumentation, chapter 4.11, Hardening TLS Configuration
BetterCrypto.org "Applied Crypto Hardening"

The string can be applied to your configuration with this LDIF

slapd_config_TLS_cyphersuite.ldif

dn:cn=config
changetype:modify
add:olcTLSCipherSuite
olcTLSCipherSuite: SECURE256:-VERS-TLS-ALL:+VERS-TLS1.2:-RSA:-DHE-DSS:-CAMELLIA-128-CBC:-CAMELLIA-256-CBC:-SHA1

After configuring the cypher suits, test again if you can contact your databases. If you get errors concerning TLS, relax your configuration and test again.

Unfortunately, it is not possible to use the olcTLSEphemeralDHParamFile parameter to use your own Diffie-Hellman group when slapd got linked against GnuTLS as done in Debian. This is a pity, since it makes hardening the LDAP Server against the Logjam attack impossible.

To enable this feature in Debian you need to build slapd against OpenSSL by yourself. Enforce TLS connections

The next step is to forbid any unencrypted communication to slapd and enforce the usage of TLS. Before doing so, it is very important to have TLS set up correctly and tested whether you can read and edit the cn=config DIT over TLS (using -ZZ). Otherwise, you will lock yourself out from configuration.

If everything works as expected, you can set the olcSecurity attribute to tls=n, where n is the minimum key length in bits required in any key used during communication. tls=1 means that any key length would be fine, as long as encryption happens. If you configured the olcTLSCypherSuite parameter, the key length used will result out of that configuration, and tls=1 will be a sufficient configuration.

If you didn’t set the olcTLSCypherSuite parameter, you at least might want to set a propper value here. A good key length might be something like 128 bits or higher.

slapd_config_TLS_enforce.ldif

dn: cn=config
changetype: modify
add: olcSecurity
olcSecurity: tls=128

Note: Be aware that the key length is just one of many many different factors that makes up the security chain of your encryption. The best way to tighten your TLS configuration is still to select propper cypher suites and configure them in olcTLSCypherSuite as decribed in the section before.

Warning: When configuring the key length too high, you might run into trouble and lock yourself out of your directory if the key length specified is not supported by client or server. To avoid this situation it is a good idea to first set the considered value only for the database of your data and not for the cn=config database and test if it works.

slap_config_TLS_enforce_test192.ldif

dn: olcDatabase={1}mdb,cn=config
changetype: modify
add: olcSecurity
olcSecurity: tls=192

Then test if you can connect to the directory

user@ldaphost~: ldapsearch -LLL -x -H ldap://your.domain.com -b dc=your,dc=domain,dc=com -ZZ Confidentiality required (13) Additional information: stronger TLS confidentiality required

If you get stronger TLS confidentiality required the key length used is too long, and you have to decrese it until the test succeeds.

slap_config_TLS_enforce_test128.ldif

dn: olcDatabase={1}mdb,cn=config
changetype: modify
replace: olcSecurity
olcSecurity: tls=128

If you got a working key length, delete the olcSecurity attribute from the olcDatabase={1}mdb,cn=config object and add it to the cn=config object as described at the beginning of this section to apply it to all databases.

slapd_config_TLS_enforce_test_delete.ldif

dn: olcDatabase={1}mdb,cn=config
changetype: modify
delete: olcSecurity

Now check whether it is still possible to communicate with slapd unencrypted by skipping the -ZZ parameter.

ldapsearch -LLL -x -H ldap://your.domain.com -b dc=your,dc=domain,dc=com ldap_bind: Confidentiality required (13) additional info: TLS confidentiality required

try to do the same with cn=config

user@ldaphost:~$ ldapsearch -LLL -x -W -D cn=admin,cn=config -H ldap://ldap.example.com -b cn=config Enter LDAP Password: ldap_bind: Confidentiality required (13) additional info: TLS confidentiality required

If you get TLS confidentiality required in both cases slapd will not accept unencrypted communication anymore. Manage ACLs

Before opening your LDAP server to the public (if necessary anyway) you should review the ACLs given in the default configuration whether they fit your needs.

To retrieve the given ACLs run

user@ldaphost:~$ ldapsearch -LLL -x -W -D cn=admin,cn=config -ZZ -H ldap://ldap.example.com -b cn=config ‘(olcAccess=*)’ olcAccess Enter LDAP Password: dn: olcDatabase={-1}frontend,cn=config olcAccess: {0}to * by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manage by * break olcAccess: {1}to dn.exact=”” by * read olcAccess: {2}to dn.base=”cn=Subschema” by * read

dn: olcDatabase={0}config,cn=config olcAccess: {0}to * by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manage by * break

dn: olcDatabase={1}mdb,cn=config olcAccess: {0}to attrs=userPassword,shadowLastChange by self write by anonymous auth by * none olcAccess: {1}to dn.base=”” by * read olcAccess: {2}to * by * read

Since the order of ACLs matters during their evaluation, it is important to insert them into the right place. The {n} prefix in the olcAccess attribute defines the position of the ACL. If you, for example insert an new ACL at index {1}, it will be placed below the ACL indexed {0}, and the old {1} will get indexed {2} and all subsequent ACLs will be renumbered accordingly.

When deleting an entry you can just refer to the index of the ACL.

slapd_acl_delete_1.ldif

dn: olcDatabase={1}mdb,cn=config
changetype:modify
delete: olcAccess
olcAccess: {1}

To replace an ACL

slapd_acl_replace_1.ldif

dn: olcDatabase={1}mdb,cn=config
changetype: modify
delete: olcAccess
olcAccess: {1}

dn: olcDatabase={1}mdb,cn=config
changetype: modify
add: olcAccess
olcAccess: {1} to <what> by <who> <access>

Since the ACLs needed highly depend on the purpose of your slapd installation there is no common recommendation. Please refer to section 8 of the OpenLDAP Administrator’s Guide and have a look at the OpenLDAP Faq-O-Matic to figure out what suits your needs.

The default configuration above allows unauthenticated users to read the whole DIT, the baseDN and schemes provided by the server. Authentication is allowed against objects providing the userPassword attribute and authenticated users are allowed to change their own userPassword and shadowLastChange attributes.

A basic ACL to start could be to replace all by * with by users in the default ACL to prevent reading the DIT by unauthenticated users.

slapd_config_ACL_basic.ldif

dn: olcDatabase={-1}frontend,cn=config
olcAccess: {0}to * by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external
 ,cn=auth manage by * break
olcAccess: {1}to dn.exact="" by users read
olcAccess: {2}to dn.base="cn=Subschema" by users read

dn: olcDatabase={0}config,cn=config
olcAccess: {0}to * by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external
 ,cn=auth manage by * break

dn: olcDatabase={1}mdb,cn=config
olcAccess: {0}to attrs=userPassword,shadowLastChange by self write by anonymou
 s auth by * none
olcAccess: {1}to dn.base="" by users read
olcAccess: {2}to * by users read

Grand Opening

When you are done with your setup, you can edit /etc/default/slapd to make the slapd listen to the global interfaces.

/etc/default/slapd

SLAPD_SERVICES="ldap:///"

root@ldaphost:~# service slapd restart root@ldaphost:~# netstat -lpn | grep slapd tcp 0 0 0.0.0.0:389 0.0.0.0:* LISTEN 654/slapd
tcp6 0 0 :::389 :::* LISTEN 654/slapd