Activité Authentification LDAP sous Linux
Consigne
- Avant de commencer l’activité :
- Lire la mise en situation, prendre connaissance des objectifs, du résultat attendu, et des ressources à disposition.
- Lire une première fois en entier la section Mise en route.
- Effectuez le travail décrit dans la section Mise en route et effectuez les tâches demandées dans la section Tâches.
Mise en situation
Votre équipe est chargée de centraliser l’authentification des utilisateur·rice·s sur les serveurs Linux et les applications Web. Après une phase d’analyse, il a été décidé de mettre en place un système d’annuaire à haute disponibilité avec OpenLDAP. Actuellement, le système d’annuaire se compose d’un unique serveur. Vous devez maintenant configurer l’authentification d’un système Linux pour utiliser le système d’annuaire. Les données de l’annuaire doivent être utilisées lors d’une connexion locale (login), lors d’une élévation de privilège avec la commande « sudo », et lors d’une connexion ssh. En outre, l’authentification par mot de passe n’est pas autorisée pour les connexions ssh. L’annuaire doit donc être en mesure de fournir les clés publiques de l’utilisateur·rice.
Objectifs
À la fin de ce travail, en ayant accès au web, vous devez :
- Connaître la manière dont les utilisateur·rice·s, les groupes et les mots de passe sont stocké par défaut dans un système Linux (fichier
/etc/passwd
,/etc/group
, et/etc/shadow
) - Connaître, dans les grandes lignes, le principe du sélecteur de service de noms (naming service switch ou NSS) sous Linux.
- Connaître, dans les grandes lignes, le principe des modules d’authentification (pluggable authentication module ou PAM) sous Linux.
- Être capable d’installer les modules
libnss-ldapd
etlibpam-ldapd
, et le daemonnslcd
sous Debian/Ubuntu. - Connaître des commandes qui utilisent le PAM (
login
,sudo
,ssh
, etc.) - Être capable d’expliquer comment fonctionne l’authentification par clé publique avec SSH.
- Être capable d’expliquer ce qui distingue une clé publique SSH d’un certificat de clé publique TLS.
- Être capable d’expliquer les différents moyens dont dispose le daemon
sshd
pour localiser les clés publiques. - Être capable d’écrire un script qui permet d’obtenir la clé publique d’un·e utilisateur·rice.
- Être capable d’expliquer à quoi sert la commande
sudo
. - Être capable d’expliquer comment la commande
sudo
détermine ce que l’utilisateur·rice peut faire. - Connaître l’importance de contrôler l’accès à certains attributs de l’annuaire.
Résultat attendu
- Un rapport qui comprend :
- Une marche à suivre permettant l’installation et la configuration de OpenLDAP.
- Les réponses aux questions
- Une machine virtuelle Linux (Ubuntu server 22.04) avec OpenLDAP configuré.
Ressources
Documents:
Matériel:
- Un serveur Linux avec Ubuntu server 22.04 :
- le nom complet est
svr-m159-$NUM-01.lab.epai-ict.ch
($NUM est le numéro de la machine sur deux chiffres). - le nom d’utilisateur·rice est
admin
- le numéro de la machine et le mot de passe sont les mêmes que pour l’activité précédente
- le nom complet est
Mise en route
Installation des outils OpenLDAP
Dans cette activité vous devez configurer une nouvelle machine Linux : svr-m159-##-01.lab.epai-ict.ch
où ## est le numéro à deux chiffres de vos machines. Connectez-vous en SSH à cette machine, et, si vous le souhaitez, copier votre clé publique sur cette machine. Le mot de passe est celui qui se trouve sur la fiche que vous avez reçue au début du module.
Lorsque l’on travaille avec un serveur LDAP, il est utile d’avoir à disposition les commandes utilitaires de OpenLDAP, en particulier la commande ldapsearch
. Ces commandes se trouvent dans le paquet ldap-utils
que vous pouvez installer avec la commande suivante:
1
sudo apt install -y ldap-utils
Vérification de l’accessibilité et du fonctionnement du serveur LDAP
Lors de l’activité précédente, vous avez installé un serveur d’annuaire sur la machine svr-m159-##-ldap-01.lab.epai-ict.ch
. Avant de commencer cette nouvelle activité, assurons-nous que ce serveur fonctionne correctement et qu’il est accessible depuis la machine Linux que vous devez configurer. Pour cela, assurez-vous d’être connecté à la machine Linux que vous devez configurer (svr-m159-##-01
) et lancez la commande suivante:
1
2
3
4
ldapsearch -H ldaps://svr-m159-$NUM-ldap-01.lab.epai-ict.ch \
-LLL -x -b dc=lab,dc=epai-ict,dc=ch \
'(|(objectclass=posixAccount)(objectclass=posixGroup))' \
uid cn uidNumber gidNumber userPassword
Si la commande fonctionne, vous devriez voir apparaître les groupes et les comptes POSIX qui se trouvent dans l’annuaire. Si la commande ne fonctionne pas, ouvrez une nouvelle fenêtre de terminal, connectez-vous au serveur d’annuaire et reprenez l’activité précédente.
Assurez-vous ensuite que l’opération bind de l’annuaire fonctionne. Pour cela, effectuez la même recherche que précédemment, mais avec l’utilisateur bornetj
, en exécutant la commande ci-dessous. Lorsque le système vous le demande, saisissez le mot de passe que vous avez défini pour ce compte.
1
2
3
4
5
ldapsearch -H ldaps://svr-m159-$NUM-ldap-01.lab.epai-ict.ch \
-D uid=bornetj,ou=People,dc=lab,dc=epai-ict,dc=ch -W \
-LLL -x -b dc=lab,dc=epai-ict,dc=ch \
'(|(objectclass=posixAccount)(objectclass=posixGroup))' \
uid cn uidNumber gidNumber userPassword
Si l’opération bind fonctionne, la commande devrait renvoyer le même résultat que la précédente. Si ce n’est pas le cas, assurez-vous que le compte de l’utilisateur bornetj
existe et que le mot de passe est correct. Au besoin, supprimez et recréez les comptes d’utilisateur·rice. Il est essentiel que de pouvoir utiliser l’opération bind, car c’est grâce à cette opération que l’annuaire peut authentifier les utilisateur·rice·s.
Tâche
Authentification sous Linux
Sous Linux, le processus d’authentification repose essentiellement sur deux sous-systèmes :
- NSS : sélecteur de service de nom (name service switch)
- PAM : modules d’authentification enfichables (pluggable authentication modules)
Le NSS est un système modulaire qui contrôle l’assemblage des différentes bases de données de l’OS en mémoire et expose une interface de programmation unifiée pour l’accès à ces données. Grâce à ce système, les applications ne dépendent pas de la manière dont ces informations sont stockées (fichier, base de données, annuaire, etc.), et ne sont pas impactées en cas de changement dans la manière de les stocker.
Parmi les bases données prises en charge par le NSS, on trouve notamment:
- passwd : base de données des utilisateur·rice·s
- group : base de données des groupes
- shadow: base de données des mots de passe
- hosts : base de données des hôtes du réseau
Pour ce travail, nous utiliserons les trois premières. La configuration du NSS se trouve dans le fichier /etc/nsswitch.conf
.
Le PAM est également un système modulaire qui permet d’ajouter des mécanismes d’authentification. Par défaut, Linux utilise une authentification par mot de passe. Le module pam_unix
qui l’implémente utilise le NSS pour vérifier que l’utilisateur·rice possède bien un compte et, le cas échéant, pour obtenir l’empreinte de son mot de passe. Le nom de l’utilisateur·rice se trouve dans la base de données passwd et l’empreinte du mot de passe, dans la base de données shadow. Par défaut, les données de passwd se trouvent dans le fichier /etc/passwd
qui peut être lu par tout le monde, et les données de shadow se trouvent dans le fichier /etc/shadow
qui n’est lisible que par root
. D’autres mécanismes d’authentification tel que Kerberos peuvent être mis-en-œuvre.
Connectez-vous en SSH à votre machine Linux svr-m159-##-01.lab.epai-ict.ch
et répondez aux questions ci-après.
Questions:
- Affichez le contenu du fichier
/etc/nssswitch.conf
et décrivez les trois premières lignes (relever ces trois lignes dans votre rapport) ? - Affichez le contenu des fichiers
/etc/passwd
et/etc/shadow
, relevez les lignes qui concernent l’utilisateur·riceadmin
et décrivez-les. - Comment sont stockés les mots de passe dans
/etc/shadow
? - Existe-t-il plusieurs manières de chiffrer les mots de passe dans le fichier
/etc/shadow
? Si oui, comment sait-on de quelle manière ils sont chiffrés ? - Affichez le contenu du fichier
/etc/pam.d/common-auth
. Quel module PAM est configuré dans le «”Primary” block» ? Comment ce module authentifie-t-il les utilisateur·rice·s ? - Nommez trois commandes qui permettent d’authentifier un utilisateur en utilisant le PAM.
Authentification Linux avec LDAP
La tâche qui nous a été confiée est la centralisation des comptes d’utilisateur·rice·s dans un système d’annuaire. Pour cela, nous avons besoin d’installer deux bibliothèques et un daemon. La première bibliothèque, libnss_ldap.so.2
, est un module pour le NSS qui permet de récupérer les informations des utilisateur·rice·s dans le système d’annuaire. La seconde, pam_ldap.so
, est un module pour le PAM qui permet d’authentifier l’utilisateur·rice·s avec une opération de bind du protocole LDAP. Les deux modules utilisent le daemon nslcd
pour effectuer des requêtes LDAP.
Dans Ubuntu, les deux bibliothèques et le daemon peuvent être installés avec les paquets suivants:
- libnss-ldapd : récupérer des utilisateur·rice·s et des groupes dans l’annuaire.
- libpam-ldapd : authentifie un·e utilisateur·rice·avec une opération bind.
- nslcd : daemon qui effectue des requêtes LDAP pour des processus locaux.
Connectez-vous en SSH à votre serveur svr-m159-$NUM-01.lab.epai-ict.ch
(Attention, ce n’est pas le serveur LDAP!) et lancez la commande suivante pour lancer l’installation.
1
sudo apt -y install libnss-ldapd libpam-ldapd nslcd
Lorsque le système vous y invite, saisissez l’URI du serveur LDAP: ldaps://svr-m159-##-ldap-01.lab.epai-ict.ch
(Attention: n’oubliez pas le ldaps et de changer ## par le numéro de vos serveurs), puis le DN de la base : dc=lab,dc=epai-ict,dc=ch
et enfin, sélectionnez les bases de données passwd
et group
. Les deux premières informations (URI et base DN) sont stockées dans le fichier /etc/nslcd.conf
. La troisième se trouve dans le fichier de configuration du NSS (/etc/nsswitch.conf
).
Vous devriez maintenant être en mesure de vous authentifier sur cette machine en utilisant les utilisateur·rice·s de l’annuaire. Assurons-nous que tout fonctionne. Lancez la commande sudo -i login
, puis saisissez le nom d’utilisateur bornetj
et le mot de passe que vous avez défini pour cet utilisateur.
Si tout fonctionne correctement, vous devriez être connecté avec l’utilisateur bornetj
, mais avec un avertissement qui vous informe que le système n’a pas pu trouver de répertoire personnel pour cet utilisateur et que, à défaut, c’est la racine qui est affectée à la variable HOME (No directory, logging in with HOME=/
). Pour corriger ce problème, nous pouvons ajouter un module PAM pour créer le répertoire personnel (home directory) au login. Terminez la session de bornetj
avec la commande exit
et lancez la commande ci-dessous pour ouvrir le fichier de configuration de session du système PAM.
1
sudo vi /etc/pam.d/common-session
Ajouter la ligne ci-après immédiatement après le commentaire # and here are more per-package modules (the "Additional" block)
:
1
session required pam_mkhomedir.so skel=/etc/skel/ umask=0022
Après modification, le fichier de configuration doit avoir le contenu suivant:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#
# /etc/pam.d/common-session - session-related modules common to all services
#
# This file is included from other service-specific PAM config files,
# and should contain a list of modules that define tasks to be performed
# at the start and end of interactive sessions.
#
# As of pam 1.0.1-6, this file is managed by pam-auth-update by default.
# To take advantage of this, it is recommended that you configure any
# local modules either before or after the default block, and use
# pam-auth-update to manage selection of other modules. See
# pam-auth-update(8) for details.
# 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
# The pam_umask module will set the umask according to the system default in
# /etc/login.defs and user settings, solving the problem of different
# umask settings with different shells, display managers, remote sessions etc.
# See "man pam_umask".
session optional pam_umask.so
# and here are more per-package modules (the "Additional" block)
session required pam_mkhomedir.so skel=/etc/skel/ umask=0022
session required pam_unix.so
session [success=ok default=ignore] pam_ldap.so minimum_uid=1000
session optional pam_systemd.so
# end of pam-auth-update config
Lancez une nouvelle fois la commande sudo -i login
pour ouvrir une session avec l’utilisateur bornetj
et assurez-vous que vous être dans son répertoire personnel (/home/bornetj
) avec la commande pwd
. Vous pouvez également essayer la commande sudo -u bornetj -i
.
Questions:
- Affichez le contenu du fichier
/etc/nssswitch.conf
et décrivez les trois premières lignes (relever ces trois lignes dans votre rapport) ? Qu’est-ce qui a changé ? - Si vous avez bien suivi les instructions, seules les bases de données
passwd
etgroup
sont configurées pour utiliserldap
. Comme la base de donnéesshadow
est seulement locale, le système Linux ne peut pas utiliser les mots de passe qui se trouvent dans l’annuaire. Comment les mots de passe des utilisateur·rice·s de l’annuaire sont-ils vérifiés ? - Est-ce qu’un utilisateur peut modifier son mot de passe avec la commande Linux
passwd
? Essayez et vérifiez que l’attributuserPassword
de l’utilisateur est effectivement modifié.
Authentification SSH par clé publique avec LDAP
Lors d’une connexion SSH, l’authentification par mot de passe est gérée par le PAM. Nous pouvons donc également utiliser les comptes d’utilisateur·rice de l’annuaire pour nous connecter avec SSH. Vous pouvez vous en assurer, ouvrez une nouvelle fenêtre de terminal et créez une connexion ssh avec la commande ssh bornetj@svr-m159-##-01.lab.epai-ict.ch
.
En revanche, l’authentification par clé publique est gérée directement par le daemon sshd
. Il n’utilise ni le PAM ni le NSS pour obtenir la liste des clés publiques autorisées (authorized keys). Par défaut, il trouve cette liste dans le fichier .ssh/authorized_keys
, mais il est également possible de définir une commande qui doit renvoyer une clé en fonction d’un nom d’utilisateur·rice passé en paramètre.
Commençons par implémenter cette commande à l’aide d’un script bash. Connectez-vous avec SSH à la machine svr-m159-##-01.lab.epai-ict.ch
avec le compte admin
. Créez ensuite un script nommé fetchSSHKeysFromLDAP
avec le code ci-dessous, puis modifiez les permissions du fichier pour le rendre exécutable. N’oubliez pas de changer ## par le numéro de votre serveur sur deux chiffres.
1
2
3
4
5
6
7
#! /bin/bash
ldapsearch -x -H ldaps://svr-m159-##-ldap-01.lab.epai-ict.ch \
-b dc=lab,dc=epai-ict,dc=ch \
'(&(objectClass=ldapPublicKey)(uid='"$1"'))' \
'sshPublicKey' | \
sed -n '/^ /{H;d};/sshPublicKey:/x;$g;s/\n *//g;s/sshPublicKey: //gp'
Nous pouvons maintenant tester le script en l’exécutant avec la commande suivante:
1
./fetchSSHKeysFromLDAP bornetj
Si la commande fonctionne, vous devez voir la valeur de l’attribut sshPublicKey
du compte d’utilisateur bornetj
. Si la clé ne s’affiche pas, utiliser la commande ldapsearch pour vérifier la valeur de l’attribut. Au besoin, reprenez l’activité précédente.
Lorsque le script fonctionne, copiez le fichier fetchSSHKeysFromLDAP
dans le répertoire /usr/local/bin
et modifiez le propriétaire et les permissions de la manière suivante:
1
2
3
sudo cp ./fetchSSHKeysFromLDAP /usr/local/bin/.
sudo chown root:root /usr/local/bin/fetchSSHKeysFromLDAP
sudo chmod 755 /usr/local/bin/fetchSSHKeysFromLDAP
Lorsque le script fonctionne, nous pouvons modifier le fichier de configuration du daemon sshd
. Ouvrez le fichier /etc/ssh/sshd_config
et cherchez le commentaire #AuthorizedKeysCommand none
. Immédiatement après, ajoutez les lignes suivantes:
1
2
AuthorizedKeysCommand /usr/local/bin/fetchSSHKeysFromLDAP
AuthorizedKeysCommandUser nobody
Vous devriez, maintenant, être en mesure d’ouvrir une session SSH avec un·e utilisateur·rice de l’annuaire (p. ex. bornetj
) sans avoir à saisir de mot de passe.
Questions:
- Expliquez dans les grandes lignes comment fonctionne l’authentification par clé publique avec SSH.
- Quel rôle joue le PAM dans l’authentification par clé publique avec SSH ?
- Expliquez comment le daemon
sshd
peut récupérer la clé publique de l’utilisateur·rice dans un serveur d’annuaire. - Expliquez en détail le fonctionnement du script de la figure 11. En particulier, traduisez en français le filtre LDAP et expliquez ce que fait la commande sed.
Configuration du sudo
Il nous reste encore à nous occuper de la commande sudo. Cette commande utilise le PAM pour l’authentification, et le NSS pour obtenir les règles qui permettent de déterminer ce qu’un utilisateur peut faire avec cette commande. Par défaut, ces règles sont définies dans le fichier de configuration /etc/sudoers
. En installant le paquet sudo-ldap
, le NSS peut également rechercher les règles du sudo dans un serveur d’annuaire.
Commençons par installer le paquet en exécutant la commande suivante:
1
sudo apt install -y sudo-ldap
Après l’installation, le fichier /etc/nsswitch.conf
a déjà été modifié et son contenu devrait être semblable à la figure ci-dessous.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# /etc/nsswitch.conf
#
# Example configuration of GNU Name Service Switch functionality.
# If you have the `glibc-doc-reference' and `info' packages installed, try:
# `info libc "Name Service Switch"' for information about this file.
passwd: files systemd
group: files systemd
shadow: files
gshadow: files
hosts: files dns
networks: files
protocols: db files
services: db files
ethers: db files
rpc: db files
netgroup: nis
sudoers: files ldap
La dernière ligne indique que les règles sont recherchées d’abord dans le fichier /etc/sudoers
, puis dans le serveur d’annuaire. Toutefois, nous n’avons pas encore indiqué au système comment trouver ces informations dans le notre serveur LDAP. Pour cela, nous devons modifier le fichier /etc/ldap.conf
. La figure ci-après montre ce à quoi devrait ressembler votre fichier de configuration. Attention: n’oubliez pas de changer ## par le numéro de vos machines.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#
# LDAP Defaults
#
# See ldap.conf(5) for details
# This file should be world readable but not world writable.
BASE dc=lab,dc=epai-ict,dc=ch
URI ldaps://svr-m159-##-ldap-01.lab.epai-ict.ch
# The amount of time, in seconds, to wait while trying to connect to
# an LDAP server.
bind_timelimit 30
#
# The amount of time, in seconds, to wait while performing an LDAP query.
timelimit 30
#
# Must be set or sudo will ignore LDAP; may be specified multiple times.
sudoers_base ou=sudoers,dc=lab,dc=epai-ict,dc=ch
#
# verbose sudoers matching from ldap
sudoers_debug 0
#
# Enable support for time-based entries in sudoers.
sudoers_timed yes
#SIZELIMIT 12
#TIMELIMIT 15
#DEREF never
# TLS certificates (needed for GnuTLS)
TLS_CACERT /etc/ssl/certs/ca-certificates.crt
Pour finir, il reste à définir les règles dans le serveur d’annuaire. Pour cela, nous devons ajouter une unité d’organisation sudoers
et des objets de type sudoRole
dans notre serveur d’annuaire. La figure ci-après contient la description LDIF de ces objets. Ajoutez ces objets à l’aide de la commande ldapadd
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
dn: ou=sudoers,dc=lab,dc=epai-ict,dc=ch
objectClass: organizationalUnit
ou: sudoers
dn: cn=%it-service,ou=sudoers,dc=lab,dc=epai-ict,dc=ch
objectClass: sudoRole
objectClass: top
cn: %it-service
sudoCommand: ALL
sudoHost: ALL
sudoRunAsUser: ALL
sudoUser: %it-serviceI
sudoOption: !authenticate
sudoOrder: 2
dn: cn=defaults,ou=sudoers,dc=lab,dc=epai-ict,dc=ch
objectClass: sudoRole
objectClass: top
cn: defaults
sudoOption: env_reset
sudoOption: mail_badpass
sudoOption: secure_path=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin
sudoOrder: 1
Si tout est en ordre, vous devriez pouvoir utiliser la commande sudo
sans avoir à saisir de mot de passe avec l’utilisateur bornetj
.
Questions:
- Comment la commande sudo obtient-elle les règles qui permettent de déterminer ce qu’un utilisateur peut faire avec cette commande ? Est-ce que la commande lit directement ces règles dans des fichiers?
- À quoi fait référence
sudoers_base
dans le fichierldap.conf
? - Expliquez l’option
mail_badpass
et!authenticate
. - Expliquez à quoi correspond le caractère
%
dans la valeur de l’attributsudoUser
dans l’une des règles ? - Expliquez à quoi correspond l’attribut
sudoOrder
?
Contrôle d’accès aux données sensible de l’annuaire
Pour finir, nous devons encore nous assurer que l’accès aux attributs qui contiennent des informations sensibles est contrôlé. L’attribut le plus sensible est userPassword
. Le mot de passe est bien sûr chiffré, mais s’il est accessible par tout le monde, une personne malveillante pourrait, par exemple, mener une attaque par dictionnaire. L’attribut userPassword
ne doit donc être visible et modifiable que par son ou sa propriétaire et par l’opération bind pour l’authentification. L’attribut sshPublicKey
peut être visible par tout le monde (c’est une clé publique), mais doit pouvoir être modifié que par l’utilisateur·rice lui ou elle-même ou l’administrateur. Les autres attributs sont visibles par tous, mais ne sont modifiables que par l’administrateur.
1
2
3
4
5
6
7
8
9
10
11
12
dn: olcDatabase={1}mdb,cn=config
changetype: modify
delete: olcAccess
-
add: olcAccess
olcAccess: to attrs=userPassword by self write by anonymous auth by * none
-
add: olcAccess
olcAccess: to attrs=sshPublickey by self write by * read
-
add: olcAccess
olcAccess: to * by * read
Pour vérifier la configuration, afficher une première fois le contenu de l’annuaire (avec ldapsearch
) de manière anonyme. Il ne devrait pas y avoir d’attribut userPassword
visible. Afficher une seconde fois le contenu avec l’utilisateur bornetj
(option -D uid=bornetj,ou=People,dc=lab,dc=epai-ict,dc=ch
). Cette fois, le mot de passe de bornetj
devrait être visible.
Questions:
- Expliquer pourquoi il est nécessaire de restreindre l’accès à l’attribut
userPassword
. - Expliquer en détail ce que dit la règle
olcAccess: to attrs=userPassword by self write by anonymous auth by * none
- Assurez-vous que la commande Linux
passwd
fonctionne toujours. - Utilisez la commande
ldapmodify
pour remplacer la valeur de l’attributsshPublicKey
d’un·e utilisateur·rice (p. ex.uid=bornetj,ou=People,dc=lab,dc=epai-ict,dc=ch
), une fois en utilisant l’option-D
avec l’administrateur (-D cn=admin,dc=lab,dc=epai-ict,dc=ch
) et une fois en utilisant l’option-D
avec l’utilisateur·rice lui ou elle-même (p. ex.-D uid=bornetj,ou=People,dc=lab,dc=epai-ict,dc=ch
).