Installation d'OpenLDAP, PAM-LDAP, CCREDS et NFS

Procédure validée sur Debian 12.

Présentation du projet

Nous souhaitons créer un serveur central d'authentification et de fichiers sous Debian permettant à des clients Debian de s'y connecter pour l'authentification de leurs utilisateurs. Nous utiliserons CCREDS pour l'authentification des équipements avec mise en cache de l'annuaire (par exemple les ordinateurs portables).

Installation et configuration du serveur OpenLDAP

OpenLDAP est un annuaire informatique qui fonctionne sur le modèle client/serveur. Il contient des informations de n'importe quelle nature qui sont rangées de manière hiérarchique.

Pour bien comprendre le concept, il est souvent comparé aux Pages Jaunes (Yellowpages), où le lecteur recherche un numéro de téléphone particulier: il va d'abord sélectionner la profession, puis la ville, puis le nom de l'entrée pour trouver au final le numéro de téléphone. En pratique, il est utilisé pour enregistrer une grande quantité d'utilisateurs ou de services (parfois des centaines de milliers) dans un réseau informatique. Il permet d'organiser hiérarchiquement les utilisateurs par département, par lieu géographique ou par n'importe quel autre critère.

Source : Wikipedia

Installation des paquets

Sur le serveur, installer les paquets slapd et ldap-utils :

apt install slapd ldap-utils nftables

Configuration de l'annuaire

Afin de configurer l'annuaire, taper :

dpkg-reconfigure slapd

Répondez aux questions comme suit :

Voulez-vous omettre la configuration d'OpenLDAP
Non
Nom de domaine
Votre nom de domaine (exemple : mondomaine.local)
Nom d'entité
Votre nom de domaine (exemple : mondomaine.local)
Mot de passe de l'administrateur
Un mot de passe assez fort
Faut-il supprimer la base de données à la purge du paquet
Comme vous voulez
Faut-il déplacer l'ancienne base de données
Oui

Autoriser le trafic vers le serveur LDAP et en loopback en modifiant le fichier /etc/nftables.conf. Adapter selon les autres services déjà installés :

Pensez à créer une règle pour SSH si vous utilisez ce service pour configurer votre serveur. Ne vous enfermez pas dehors !
#!/usr/sbin/nft -f

flush ruleset

table inet tableinet {
	chain input {
		type filter hook input priority filter; policy drop;
		iifname lo accept
		tcp dport 389 accept
		ct state {established,related} accept
	}
	chain forward {
		type filter hook forward priority filter;
	}
	chain output {
		type filter hook output priority filter;
	}
}

Activer et redémarrer nftables :

systemctl enable nftables.service
systemctl restart nftables.service

Associer le domaine à l'IP 127.0.0.1 dans le fichier /etc/hosts :

127.0.0.1	mondomaine.local

Désactivation du compte anonyme et création du compte en lecture seule

Le compte en lecture seule aura accès au mots de passe des comptes utilisateurs. Créer le fichier lecture.ldif :

dn: cn=lecture,dc=mondomaine,dc=local
objectClass: simpleSecurityObject
objectClass: organizationalRole
cn: lecture
description: Compte lecture seule pour serveurs de messagerie
userPassword: MotDePasseLectureSeule

Créez le fichier anon.ldif :

dn: olcDatabase={1}mdb,cn=config
changetype: modify
replace: olcAccess
olcAccess: to attrs=userPassword by self write by anonymous auth by dn="cn=lecture,dc=mondomaine,dc=local" read by dn="cn=admin,dc=mondomaine,dc=local" write by * none
olcAccess: to dn.base="dc=mondomaine,dc=local" by users read
olcAccess: to * by self write by dn="cn=admin,dc=mondomaine,dc=local" write by * read by anonymous none

Pour activer ce module nécessaire pour la gestion des groupes, créer le fichier memberof.ldif :

dn: cn=module{0},cn=config
changetype: modify
add: olcModuleLoad
olcModuleLoad: memberof.la

Modifiez le fichier /etc/ldap/ldap.conf comme suit :

BASE    dc=mondomaine,dc=local
URI     ldap://mondomaine.local

Éxécutez les scripts LDIF :

ldapadd -x -H ldap://localhost -D "cn=admin,dc=mondomaine,dc=local" -f lecture.ldif -W
ldapmodify -Q -Y EXTERNAL -H ldapi:/// -f anon.ldif
ldapmodify -Q -Y EXTERNAL -H ldapi:/// -f memberof.ldif

Configuration avec SSL/TLS

Pour sécuriser les communications avec votre annuaire, il faut chiffrer les communications entre le serveur et les clients LDAP. Nous allons décrire ici comment créer des certificats auto-signés, mais il est possible d'utiliser des certificats fournis par votre autorité de certification.

Pour cela, nous allons installer OpenSSL :

apt install openssl

Création d'une autorité de certification auto-signée

Nous allons créer l'arborescence qui accueillera les clefs et certificats :

mkdir -p /etc/ssl/openldap/{private,certs}

Créer la clef privée de l'autorité de certification :

openssl genrsa -out /etc/ssl/openldap/private/ca.key 4096

Créer le certificat de l'autorité de certification :

openssl req -new -x509 -days 3650 -key /etc/ssl/openldap/private/ca.key -out /etc/ssl/openldap/certs/ca.crt

Pour créer la clef privée utilisée par le serveur LDAP :

openssl genrsa -out /etc/ssl/openldap/private/openldap.key 4096

Nous allons générer la requête de certificat pour le serveur LDAP. Renseigner le nom de domaine de la machine dans le champ CN :

openssl req -new -key /etc/ssl/openldap/private/openldap.key -out /etc/ssl/openldap/certs/openldap.csr

Signer la demande de certificat avec la clef privée de l'autorité de certification :

openssl x509 -req -CA /etc/ssl/openldap/certs/ca.crt -CAkey /etc/ssl/openldap/private/ca.key -in /etc/ssl/openldap/certs/openldap.csr -out /etc/ssl/openldap/certs/openldap.crt -CAcreateserial

Changer le propriétaire des fichiers générés précédement :

chown -R openldap:openldap /etc/ssl/openldap/

Configuration d'OpenLDAP pour utiliser les certificats

Créer le fichier ssl.ldif :

dn: cn=config
changetype: modify
add: olcTLSCACertificateFile
olcTLSCACertificateFile: /etc/ssl/openldap/certs/ca.crt
-
replace: olcTLSCertificateFile
olcTLSCertificateFile: /etc/ssl/openldap/certs/openldap.crt
-
replace: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: /etc/ssl/openldap/private/openldap.key

Éxécutez le script LDIF :

ldapmodify -Q -Y EXTERNAL -H ldapi:/// -f ssl.ldif

Définir le chemin du certificat de l'autorité de certification dans /etc/ldap/ldap.conf :

URI	ldaps://mondomaine.local
TLS_CACERT	/etc/ssl/openldap/certs/ca.crt

Autoriser le trafic LDAPS en modifiant la ligne suivante dans /etc/default/slapd. Pour n'autoriser que le trafic LDAPS, supprimer le service ldap:/// :

SLAPD_SERVICES="ldap:/// ldaps:/// ldapi:///"

Redémarrer le serveur LDAP :

service slapd restart

Autoriser le trafic vers le serveur en LDAPS et en loopback en modifiant le fichier /etc/nftables.conf. Adapter selon les autres services déjà installés :

#!/usr/sbin/nft -f

flush ruleset

table inet tableinet {
	chain input {
		type filter hook input priority filter; policy drop;
		iifname lo accept
		tcp dport 636 accept
		ct state {established,related} accept
	}
	chain forward {
		type filter hook forward priority filter;
	}
	chain output {
		type filter hook output priority filter;
	}
}

Activer et redémarrer nftables :

systemctl enable nftables.service
systemctl restart nftables.service

Tester la connexion :

ldapwhoami -H ldaps://mondomaine.local -x -D "cn=admin,dc=mondomaine,dc=local" -W

Peuplement de l'annuaire

Deux choix s'offrent à nous :

Les deux exemples ci-dessous créent les mêmes objets dans la base LDAP :

Peuplement avec un script LDIF

Voici un script LDIF permettant de créer les éléments. Chaque objet doit être séparé du précédent avec une ligne vide.

Pour générer le hash salé du mot de passe utilisateur, utiliser la commande slappasswd.

Pour cela, créer le fichier peuplement.ldif :

dn: ou=Utilisateurs,dc=mondomaine,dc=local
objectClass: organizationalUnit
ou: Utilisateurs

dn: cn=pdubois,ou=Utilisateurs,dc=mondomaine,dc=local
objectClass: top
objectClass: inetOrgPerson
objectClass: posixAccount
cn: Paul Dubois
userPassword: {SSHA}lIE//AggDjIfUXCR0s/Yox2oi3ddokFP
sn: Dubois
givenname: Paul
uidNumber: 1200
gidNumber: 1200
homeDirectory: /home/pdubois
uid: pdubois
mail: pdubois@mondomaine.local
loginShell: /bin/bash

dn: ou=Groupes,dc=mondomaine,dc=local
objectClass: organizationalUnit
ou: Groupes

dn: cn=admins,ou=Groupes,dc=mondomaine,dc=local
objectClass: top
objectClass: posixGroup
cn: admins
gidNumber: 1100
description: Groupe des administrateurs
memberUid: pdubois

Peupler l'annuaire avec la commande suivante :

ldapadd -x -D "cn=admin,dc=mondomaine,dc=local" -f peuplement.ldif -W

Peuplement avec un script Python

Nous allons ajouter une librairie au serveur :

apt install python3-ldap

Voici le code permettant de se connecter à l'annuaire (remplacer par vos valeurs) :

import ldap,os,hashlib
from base64 import encodebytes as encode
from base64 import decodebytes as decode
import ldap.modlist as modlist

dc="dc=mondomaine,dc=local"

l = ldap.initialize('ldaps://mondomaine.local')
l.simple_bind_s("cn=admin," + dc,"MotDePasseLdap")

Le code permettant d'ajouter les OU (organizational unit) :

dn="ou=Utilisateurs," + dc
attrs = {}
attrs['objectclass'] = [b"organizationalUnit"]
attrs['ou'] = [b"Utilisateurs"]
ldif = modlist.addModlist(attrs)
l.add_s(dn,ldif)

dn="ou=Groupes," + dc
attrs = {}
attrs['objectclass'] = [b"organizationalUnit"]
attrs['ou'] = [b"Groupes"]
ldif = modlist.addModlist(attrs)
l.add_s(dn,ldif)

Voici le code pour hacher le mot de passe :

def makeSecret(password):
	salt = os.urandom(4)
	h = hashlib.sha1(password.encode('utf-8'))
	h.update(salt)
	salted = (encode(h.digest() + salt)[:-1]).decode('utf-8')
	return("{SSHA}" + salted)

Le code permettant d'ajouter un utilisateur :

dn="cn=pdubois,ou=Utilisateurs," + dc
attrs = {}
attrs['objectclass'] = [b"top",b"inetOrgPerson",b"posixAccount"]
attrs['cn'] = [b"Paul Dubois"]
attrs['userPassword'] = makeSecret("MonMotDePasseSuperSecurise").encode('utf-8')
attrs['sn'] = [b"Dubois"]
attrs['givenname'] = [b"Paul"]
attrs['uidNumber'] = [b"1200"]
attrs['gidNumber'] = [b"1200"]
attrs['homeDirectory'] = [b"/home/pdubois"]
attrs['uid'] = [b"pdubois"]
attrs['mail'] = [b"pdubois@mondomaine.local"]
attrs['loginShell'] = [b"/bin/bash"]
ldif = modlist.addModlist(attrs)
l.add_s(dn,ldif)

Le code permettant d'ajouter un groupe :

dn="cn=admins,ou=Groupes," + dc
attrs = {}
attrs['objectclass'] = [b"top",b"posixGroup"]
attrs['cn'] = [b"admins"]
attrs['gidNumber'] = [b"1100"]
attrs['description'] = [b"Groupe des administrateurs"]
attrs['memberUid'] = [b"pdubois"]
ldif = modlist.addModlist(attrs)
l.add_s(dn,ldif)

Tester le peuplement du LDAP :

print(l.search_s(dc,ldap.SCOPE_SUBTREE,'(cn=pdubois)',['dn','objectclass','userPassword']))

Configurer un annuaire LDAP multi-domaines

Pour créer plusieurs bases dans un annuaire LDAP, créer un fichier creation-db.ldif décrivant les autres domaines. Voici un exemple créant deux bases supplémentaires :

dn: olcDatabase={2}mdb,cn=config	# Incrémenter le nombre à chaque nouvelle base
changetype: add
objectClass: olcDatabaseConfig
objectClass: olcMdbConfig
olcDatabase: mdb
olcDbMaxSize: 1073741824
olcDbCheckpoint: 512 30
olcLastMod: TRUE
olcSuffix: dc=mondeuxiemedomaine,dc=local
olcDbDirectory: /var/lib/ldap-mondeuxiemedomaine-local	# Le répertoire où sera stockée la base
olcRootDN: cn=admin,dc=mondeuxiemedomaine,dc=local
olcRootPW: {SSHA}wpGpcAKFTpUTBigFzIs2T2dwlhz3KRaZ	# Le mot de passe admin obtenu avec slappasswd
olcDbIndex: objectClass eq
olcDbIndex: cn,uid eq
olcDbIndex: uidNumber,gidNumber eq
olcDbIndex: member,memberUid eq
olcAccess: to attrs=userPassword by self write by anonymous auth by * none
olcAccess: to attrs=shadowLastChange by self write by * read
olcAccess: to * by * read

dn: olcDatabase={3}mdb,cn=config
changetype: add
objectClass: olcDatabaseConfig
objectClass: olcMdbConfig
olcDatabase: mdb
olcDbMaxSize: 1073741824
olcDbCheckpoint: 512 30
olcLastMod: TRUE
olcSuffix: dc=montroisiemedomaine,dc=local
olcDbDirectory: /var/lib/ldap-montroisiemedomaine-local
olcRootDN: cn=admin,dc=montroisiemedomaine,dc=local
olcRootPW: {SSHA}wpGpcAKFTpUTBigFzIs2T2dwlhz3KRaZ
olcDbIndex: objectClass eq
olcDbIndex: cn,uid eq
olcDbIndex: uidNumber,gidNumber eq
olcDbIndex: member,memberUid eq
olcAccess: to attrs=userPassword by self write by anonymous auth by * none
olcAccess: to attrs=shadowLastChange by self write by * read
olcAccess: to * by * read

Appliquer les changements :

ldapmodify -Y EXTERNAL -H ldapi:/// -f creation-db.ldif

Configuration du client LDAP

Le serveur LDAP peut également être client de lui-même pour l'authentification.

Sur les clients, installer les paquets suivants :

apt install libpam-ldapd libnss-ldapd nscd

Réponder aux questions comme suit :

L'URI du serveur LDAP
ldaps://mondomaine.local
Base de recherche du serveur LDAP
ou=Utilisateurs,dc=mondomaine,dc=local
Contrôle du certificat SSL du serveur
Autoriser
Service de nom à configurer
group, shadow et passwd

Paramétrer le compte en lecture seule dans le fichier /etc/nslcd.conf :

binddn cn=lecture,dc=mondomaine,dc=local
bindpw MotDePasseLectureSeule

Finaliser la configuration en entrant :

pam-auth-update

On vous demandera quels modules activer, ajouter LDAP Authentication et Create home directory on login et valider.

Définir l'URI du serveur LDAP le chemin du certificat de l'autorité de certification dans /etc/ldap/ldap.conf :

URI	ldaps://mondomaine.local
TLS_CACERT	/etc/ssl/openldap/certs/ca.crt

Pour ajouter un groupe parmi les administrateurs du client (sudoers), ajouter au fichier /etc/sudoers avant la directive @includedir :

%admins ALL=(root) ALL

Permettre l'association des groupes LDAP aux droits sudo en ajoutant la ligne suivante au fichier /etc/nsswitch.conf :

sudoers:        ldap files

Redémarrer les services nscd et nslcd :

service nscd restart
service nslcd restart

Tester le bon fonctionnement avec getent :

getent passwd
getent group

Pour un client graphique, configurer LightDM en ajoutant ce qui suit au fichier de configuration /etc/lightdm/lightdm.conf :

[Seat:*]
allow-guest=false
greeter-hide-users=true
greeter-show-manual-login=true

Configuration pour un usage hors ligne (ordinateur portable)

Installer le module PAM CCREDS :

apt install libpam-ccreds

Nous allons allonger la durée du cache NSS. Pour cela, modifier le fichier /etc/nscd.conf pour augmenter la durée du cache à 30 jours :

positive-time-to-live   passwd          2592000
positive-time-to-live   group           2592000

Redémarrer les services nscd et nslcd :

service nscd restart
service nslcd restart

Une première connexion avec le réseau connecté est nécessaire pour mettre en cache les identifiants.

Vous pouvez vérifier le cache des identifiants avec la commande suivante :

cc_dump

Installation et configuration du serveur NFS

Network File System (ou 'NFS', système de fichiers en réseau) est à l'origine un protocole développé par Sun Microsystems en 1984 qui permet à un ordinateur d'accéder à des fichiers via un réseau. Il fait partie de la couche application du modèle OSI et utilise le protocole RPC.

Ce système de fichiers en réseau permet de partager des données principalement entre systèmes UNIX. Des versions existent pour Macintosh ou Microsoft Windows.

NFS est compatible avec IPv6 sur la plupart des systèmes.

Source : Wikipedia

Installation des paquets

Sur le serveur, installer le paquet nfs-kernel-server :

apt-get install nfs-kernel-server

Configurer le serveur NFS

Définir le port d'écoute du serveur NFS en éditant la ligne suivante dans le fichier /etc/default/nfs-kernel-server :

RPCMOUNTDOPTS="--manage-gids -p 892"

Éditer le fichier /etc/exports :

/home/	192.168.1.0/24(rw,sync)

Redémarrer le service NFS pour prendre en compte de vos modifications :

service nfs-kernel-server restart

Autoriser le trafic vers le serveur LDAP et en loopback en modifiant le fichier /etc/nftables.conf. Adapter selon les autres services déjà installés :

Pensez à créer une règle pour SSH si vous utilisez ce service pour configurer votre serveur. Ne vous enfermez pas dehors !
#!/usr/sbin/nft -f

flush ruleset

table inet tableinet {
	chain input {
		type filter hook input priority filter; policy drop;
		iifname lo accept
		tcp dport 2049 accept
		tcp dport 111 accept
		tcp dport 892 accept
		udp dport 2049 accept
		udp dport 111 accept
		udp dport 1194 accept
		udp sport 1194 accept
		ct state {established,related} accept
	}
	chain forward {
		type filter hook forward priority filter;
	}
	chain output {
		type filter hook output priority filter;
	}
}

Activer et redémarrer nftables :

systemctl enable nftables.service
systemctl restart nftables.service

Configurer le client NFS

Nous allons installer le module NFS sur le client :

apt-get install nfs-common

Puis effectuons le point de montage. Pour cela, éditer le fichier /etc/fstab et y ajouter la ligne suivante :

192.168.1.100:/home/    /home   nfs     defaults      0       0