Mise en place d'OpenLDAP avec Proxmox
Dans cet article, nous allons voir comment installer et configurer OpenLDAP sous Proxmox. Nous allons dans un premier temps mettre en place le serveur avant de nous pencher sur la configuration du client. Notre architecture est la suivante :
- 1 instance Proxmox (PM1) contenant un conteneur exécutant le serveur OpenLDAP (serveur).
- 1 instance Proxmox (PM2), cliente OpenLDAP.
- 1 domaine
lab.loc
.
Commençons par l’installation et la configuration du serveur.
Installer le serveur
L’installation du serveur passe par la création du conteneur qui va héberger le serveur OpenLDAP sur PM1. À partir de la console de l’hyperviseur, nous pouvons donc télécharger une image Linux (Debian) pour conteneur. La commande suivante permet de créer un nouveau conteneur sur l’hyperviseur.
1
bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/ct/debian.sh)"
Installer et configurer l’annuaire
Maintenant que le serveur est en place, nous pouvons installer le service LDAP.
slapd
Installer
slapd
est le processus réseau qui attend les requêtes des clients de l’annuaire pour lire ou écrire dans la base de données de cet annuaire. Une bonne pratique est de créer un utilisateur openldap
, qui va faire tourner slapd
et gérer le dossier /var/lib/ldap
, qui répertorie les fichiers composant la base de données.
1
2
3
useradd openldap
mkdir /var/lib/ldap
chown openldap:openldap /var/lib/ldap
Une fois l’utilisateur ajouté, nous pouvons installer slapd
.
1
apt-get -y install slapd
Configurer
Nous allons maintenant configurer slapd
, en renseignant les informations dont le service a besoin pour s’exécuter.
1
dpkg-reconfigure slapd
Les menus ncurses apparaissent alors, et nous pouvons renseigner successivement :
No
, pour configurerslapd
.lab.loc
, pour fixer la racine de l’annuaire (= domaine DNS).lab.loc
, pour fixer l’attributorganization
de la racine.<mdp>
, pour le mot de passe de l’administrateur de l’annuaire.MDB
, pour le moteur de base de données.Non
, pour limiter la purge.Yes
, pour sauvegarder la base de données actuelle.
Nous démarrons et activons ensuite slapd
, de manière à ce qu’il s’exécute, même après redémarrage.
1
2
systemctl start slapd
systemctl enable slapd
Tester
Nous vérifions que le service écoute sur le port 389.
1
ss -laputn | grep slapd
S’il apparaît, nous vérifions ensuite que slapd
est lancé avec les bons arguments :
1
cat /var/run/slapd/slapd.args
-h ldap:/// ldapi:///
, pour accepter les connexions en clair et en local à la machine.-g openldap -u openldap
, qui définissent l’identité sous laquelle tourne le processus.-F /etc/ldap/slapd.d
, qui donne l’emplacement de la configuration deslapd
.
Si tout est bon, nous pouvons requêter l’annuaire.
1
2
apt-get install -y ldap-utils
ldapsearch -x -H ldap://<hostname>.lab.loc -b 'dc=lab,dc=loc -W -D 'cn=admin,dc=lab,dc=loc'
<hostname>
est le nom de l’hôte contenu dans /etc/hostname
ou retourné par la commande hostname
. Pour la suite, nous utiliserons serveur
.
L’option -D
permet de préciser le compte à utiliser pour se connecter à slapd
.
L’option -W
permet de faire demander le mot de passe interactivement.
Peupler l’annuaire
Maintenant que le service est installé, nous allons pouvoir définir la structure de notre annuaire et l’appliquer.
Définir de l’arborescence
Tout d’abord, il faut avoir une idée claire de l’arborescence à créer pour son annuaire. Nous partirons sur le modèle standard suivant.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
dc=lab,dc=loc
├── ou=people ← utilisateurs
│ ├── uid=root
│ ├── uid=pnom
│ ├── uid=qnom
│ └── ...
├── ou=groups ← groupes
│ ├── cn=admins
│ ├── cn=readonly
│ ├── cn=vmusers
│ ├── cn=vmadmins
│ └── ...
└── ou=system ← compte de service
└── cn=binduser
Créer l’arborescence
Ajouter des OU
Nous créons d’abord les OU à partir du fichier LDIF suivant.
1
2
3
4
5
6
7
8
9
10
11
dn: ou=people,dc=lab,dc=loc
objectClass: organizationalUnit
ou: people
dn: ou=groups,dc=lab,dc=loc
objectClass: organizationalUnit
ou: groups
dn: ou=system,dc=lab,dc=loc
objectClass: organizationalUnit
ou: system
Nous les ajoutons ensuite à l’annuaire, en utilisant ce fichier.
1
ldapadd -x -H ldap://serveur.lab.loc -D 'cn=admin,dc=lab,dc=loc' -f ou.ldif -W
Ajouter des utilisateurs
Ajoutons maintenant un compte, en suivant la même méthode.
1
2
3
4
5
6
7
dn: uid=pnom,ou=people,dc=lab,dc=loc
uid: pnom
sn: pnom
cn: pnom
objectClass: inetOrgPerson
objectClass: top
userPassword: {SSHA}XXXXXXXXXXXXXXXXXXXXXXXX
La configuration présentée ici est la configuration minimale. Des attributs supplémentaires comme
objectClass: posixAccount
ouobjectClass: shadowAccount
peuvent être ajoutés.
Il faut remplacer {SSHA}XXXXXXXXXXXXXXXXXXXXXXXX
par la sortie de la commande slappasswd
.
L’utilisateur est ensuite ajouté à l’annuaire par la commande suivante.
1
ldapadd -x -H ldap://serveur.lab.loc -D 'cn=admin,dc=lab,dc=loc' -f users.ldif -W
Il est possible de vérifier que l’ajout ait fonctionné.
1
ldapsearch -x -H ldap://serveur.lab.loc -b 'dc=lab,dc=loc'
Les entrées ajoutées devraient apparaître.
Ajouter des groupes
Nous pouvons maintenant ajouter des groupes, toujours en utilisant des fichiers LDIF.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
dn: cn=admins,ou=groups,dc=lab,dc=loc
objectClass: top
objectClass: groupOfNames
cn: vmadmins
member: uid=root,ou=people,dc=lab,dc=loc
dn: cn=vmusers,ou=groups,dc=lab,dc=loc
objectClass: top
objectClass: groupOfNames
cn: vmadmins
member: uid=pnom,ou=people,dc=lab,dc=loc
dn: cn=readonly,ou=groups,dc=lab,dc=loc
objectClass: top
objectClass: groupOfNames
cn: readonly
memberUid: uid=binduser,ou=system,dc=lab,dc=loc
dn: cn=vmadmins,ou=groups,dc=lab,dc=loc
objectClass: top
objectClass: groupOfNames
cn: vmadmins
member: uid=pnom,ou=people,dc=lab,dc=loc
La configuration présentée ici est la configuration minimale. Des attributs supplémentaires comme
objectClass: posixGroup
ouobjectClass: shadowGroup
peuvent être ajoutés.
Dans ce cas, l’attribution des utilisateurs aux groupes se fait par la correspondance entre lesgidNumber
renseignés dans les définitions du groupe et de l’utilisateur (groupe principal) et par la correspondance entre lememberUid
de la définition du groupe et leuid
de la définition de l’utilisateur (groupe secondaire).
Pour rappel, un groupe primaire est le groupe par défaut de l’utilisateur qui apparaît par exemple lors de la création de fichiers. Un groupe secondaire permet à l’utilisateur d’avoir des droits additionnels.
L’ajout d’un compte utilisateur (non technique) à un groupe peut se faire comme suit (groupe secondaire).
1
2
3
4
dn: cn=vmusers,ou=groups,dc=lab,dc=loc
changetype: modify
add: member
member: uid=qnom,ou=people,dc=lab,dc=loc
Ajouter des comptes techniques
Comme les comptes techniques ne sont pas amenés à se connecter en utilisant l’annuaire, leur configuration diffère.
1
2
3
4
5
6
dn: cn=binduser,ou=system,dc=lab,dc=loc
objectClass: simpleSecurityObject
objectClass: organizationalRole
cn: binduser
description: LDAP Bind Account
userPassword: {SSHA}XXXXXXXXXXXXXXXXXXXXXXXX
Le rôle du compte binduser
est de permettre aux clients d’interroger l’annuaire pour vérifier et synchroniser les informations. Il est donc lecteur et n’a pas vocation à modifier l’annuaire.
Modifier ou supprimer des entrées
Il peut arriver qu’une entrée soit ajoutée par erreur à l’annuaire. Heureusement, il est possible de la modifier ou de la supprimer.
Supprimer
Commençons par le plus simple : supprimer une entrée.
Nous utilisons pour cela la commande ldapdelete
et un compte ayant les droits pour supprimer un objet, identifié par son DN (OU, utilisateur, groupe etc.).
1
ldapdelete -x -D "cn=admin,dc=lab,dc=loc" -W "ou=users,dc=lab,dc=loc"
Avant de pouvoir supprimer un conteneur, il faut en supprimer tout le contenu.
Modifier
Pour modifier une entrée, on crée d’abord un nouveau fichier LDIF de la forme suivante.
1
2
3
4
dn: uid=pnom,ou=people,dc=lab,dc=loc
changetype: modify
replace: cn
cn: prom
Ensuite, on applique les changements avec la commande ldapmodify
, un compte ayant les droits de modification de l’annuaire et le nouveau fichier créé.
1
ldapmodify -x -D "cn=admin,dc=lab,dc=loc" -W -f modify.ldif
Pour modifier le dn
, c’est un peu différent. Il faut d’abord modifier le rdn
avec la commande ldapmodrdn
.
1
ldapmodrdn -x -D "cn=admin,dc=lab,dc=loc" -W "cn=admins,ou=groups,dc=lab,dc=loc" "cn=nouveau"
Puis modifier les autres champs qui dépendent de ce rdn
, comme cn
via un fichier LDIF.
1
2
3
4
dn: cn=admins-LDAP,ou=groups,dc=lab,dc=loc
changetype: modify
replace: cn
cn: nouveau
Et enfin appliquer les changements via la commande ldapmodify
.
1
ldapmodify -x -D "cn=admin,dc=lab,dc=loc" -W -f rdn_modif.ldif
Sécuriser avec SSL
SSL permet d’ajouter la confidentialité à la connexion, par un chiffrement.
Générer un certificat SSL
Nous créons d’abord un répertoire spécifique, dans lequel nous rangerons notre certificat.
1
mkdir /etc/ldap/ssl && cd /etc/ldap/ssl
Puis nous générons le certificat.
1
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 3650 -nodes
Les fichiers générés :
key.pem
, est la clé privée.cert.pem
, est le certificat contenant la clé publique et fait office de CA, comme le certificat est auto-signé.
Pendant le création, nous renseignons surtout le champs Common Name, avec serveur.lab.loc
.
Nous adaptons ensuite les propriétaires et droits des fichiers.
1
2
3
chown openldap:openldap /etc/ldap/ssl/cert.pem
chown openldap:openldap /etc/ldap/ssl/key.pem
chmod 400 /etc/ldap/ssl/key.pem
Reconfigurer slapd
Nous allons modifier les entrées de la racine cn=config
pour y renseigner les chemins vers les fichiers générés. Nous utilisons pour cela un fichier LDIF.
1
2
3
4
5
6
7
8
9
10
dn: cn=config
changetype: modify
replace: olcTLSCACertificateFile
olcTLSCACertificateFile: /etc/ldap/ssl/cert.pem
-
replace: olcTLSCertificateFile
olcTLSCertificateFile: /etc/ldap/ssl/cert.pem
-
replace: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: /etc/ldap/ssl/key.pem
Nous appliquons ensuite les changements par ldapi
, comme aucun compte administrateur n’a été créé pour la racine cn=config
.
1
ldapmodify -Y EXTERNAL -H ldapi:/// -f cert.ldif
-Y EXTERNAL
remplace-x
, pour permettre l’authentification via UID plutôt que par un compte de l’annuaire (simple bind).-H ldapi:///
pointe vers la socket UNIX gérée parslapd
.
Enfin, il nous reste à modifier le fichier de configuration /etc/default/slapd
pour y ajouter ldaps:///
dans le ligne SLAPD_SERVICES="ldap:/// ldapi:/// ldaps:///"
.
Nous pouvons maintenant redémarrer slapd
avant de tester la nouvelle configuration.
1
2
systemctl restart slapd
ss -laputn -A inet | grep slapd
Si le port 636 est en écoute, en plus du port 389, la configuration a bien été prise en compte.
Configurer le client
Notre client est donc un hyperviseur Proxmox et notre objectif est de synchroniser son authentification avec les données de l’annuaire.
Ajouter un Realm
Il faut d’abord ajouter un Realm au Datacenter Proxmox, sous Datacenter > Permissions > Realms > Add, en renseignant les informations nécessaires à la connexion au serveur LDAP, et en particulier les éléments suivants :
User classes
:inetOrgPerson
Group classes
:groupOfNames
User Filter
:(objectClass=inetOrgPerson)
Group Filter
:(objectClass=groupOfNames)
Ces paramètres correspondent à ceux choisis lors de la définition de notre arborescence et de ses objets. Nous prendrons pour notre realm, le nom LDAP
.
Une fois le Realm ajouté, il est possible de synchroniser l’annuaire via le bouton Sync
. De cette manière, les utilisateurs, groupes et appartenance des utilisateurs aux groupes sont ajoutés automatiquement.
Il reste toutefois possible de le faire manuellement.
Déclarer des utilisateurs manuellement
Il est possible d’ajouter des utilisateurs LDAP manuellement dans Proxmox soit par l’interface graphique, soit en ligne de commandes.
1
pveum user add root@LDAP
Et pour le supprimer.
1
pveum user del root@LDAP
Déclarer des groupes manuellement
Il est également possible d’ajouter des groupes manuellement.
1
pveum groupadd admins
Et pour le supprimer.
1
pveum groupdel admins
L’interface graphique est plus permissive ici, puisqu’elle permet par exemple les majuscules dans les noms des groupes.
Ajouter un utilisateur à un groupe manuellement
Il ne reste maintenant plus qu’à ajouter l’utilisateur au groupe, dont les droits sont déjà définis.
1
pveum usermod root@LDAP -group admins
Sur l’interface graphique, au moment de créer l’utilisateur, il est possible de lui assigner un groupe directement. Il est également possible d’éditer cette valeur.
Attribuer des droits
L’attribution automatique des droits n’est en revanche pas possible par synchronisation, elle doit être faite manuellement.
Par utilisateur
Il est possible d’assigner les droits par utilisateur en fonction de ce qu’il seront autorisés à faire sur l’hyperviseur.
1
pveum aclmod / -user root@LDAP -role Administrator
Par groupe
Il est aussi possible d’attribuer des droits Proxmox aux groupes LDAP synchronisés, dont les utilisateurs membres vont hériter.
1
pveum aclmod / -group admins@LDAP -role Administrator
/
définit le périmètre sur lequel ces droits s’appliquent. Il peut être restreint (par exemple,/vms
)
Et pour supprimer le rôle associé au groupe donné.
1
pveum acldel / -group admins@ldap -role Administrator
Bonne pratique : restriction des droits du binduser
Le compte binduser
, qui n’est utile que pour synchroniser l’annuaire et le Proxmox peut avoir des droits restreints en lecture seule sur l’annuaire.
Pour restreindre ses droits, il faut d’abord déterminer si la configuration d’OpenLDAP est statique ou dynamique.
Pour cela, regardons si le fichier /etc/ldap/slapd.conf
existe. Si oui, il s’agit d’une configuration statique.
Pour s’assurer que la configuration est dynamique, regardons le retour de la commande suivante.
1
ldapsearch -Q -LLL -Y EXTERNAL -H ldapi:/// -b cn=config dn
Si la ligne dn: cn=config
est retournée, alors il s’agit d’une configuration dynamique.
Configuration statique
Dans la section access
du /etc/ldap/slapd.conf
, ajoutons ou remplaçons les lignes suivantes.
1
2
3
access to dn.subtree="dc=lab,dc=loc"
by dn.exact="cn=binduser,ou=system,dc=lab,dc=loc" read
by * none
Configuration dynamique
Nous créons un nouveau fichier LDIF pour modifier les ACL en place par défaut.
1
2
3
4
5
6
dn: olcDatabase={1}mdb,cn=config
changetype: modify
replace: olcAccess
olcAccess: to dn.subtree="dc=lab,dc=loc"
by dn.exact="cn=binduser,ou=system,dc=lab,dc=loc" read
by * none
Puis nous l’appliquons.
1
ldapmodify -Y EXTERNAL -H ldapi:/// -f binduser-acl.ldif
Si l’erreur suivante apparaît, nous devrons redéfinir l’ensemble de l’ACL.
1
ldapmodify: wrong attributeType at line 4, entry "olcDatabase={1}mdb,cn=config"
Pour commencer, récupérons la sous-partie des ACL qui nous intéresse.
1
ldapsearch -Q -Y EXTERNAL -H ldapi:/// -b cn=config '(olcAccess=*)' olcAccess`, section `# {1}mdb, config
Et inscrivons-la, en plus de notre entrée, dans un fichier LDIF.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
dn: olcDatabase={1}mdb,cn=config
changetype: modify
replace: olcAccess
olcAccess: {0}to attrs=userPassword
by self write
by anonymous auth
by * none
olcAccess: {1}to attrs=shadowLastChange
by self write
by * read
olcAccess: {2}to dn.subtree="dc=lab,dc=loc"
by dn.exact="cn=binduser,ou=system,dc=lab,dc=loc" read
by * none
olcAccess: {3}to *
by * read
Puis appliquons-la avec la méthode habituelle.
1
ldapmodify -Y EXTERNAL -H ldapi:/// -f binduser-acl.ldif
Nous pouvons ensuite vérifier que la modification ait bien été prise en compte.
1
slapcat -n 0 | grep olcAccess
Références
Description | Lien |
---|---|
Installation et configuration du client et SSL | https://connect.ed-diamond.com/Linux-Pratique/lp-115/installation-et-configuration-d-un-annuaire-openldap |