====== Client sssd (Debian) — login système via LLDAP ======
Dernière mise à jour : juin 2026
État : **validé sur Debian Trixie** — login en ligne ET **hors ligne** fonctionnels. C'est la config de référence à déployer sur les autres portables.
Voir la doc serveur séparée pour LLDAP, le réseau, les UID/GID et le modèle de groupes.
===== Principe =====
sssd interroge LLDAP en LDAPS, résout users/groupes, et **cache les credentials localement** pour permettre le login hors réseau (cache offline éprouvé de sssd).
===== Machine de référence =====
* Portable : lat7400 — Debian Trixie (13)
* Compte de test : ''testldap'' (uid 15000, gid primaire 302/famille)
===== Installation =====
sudo apt install -y sssd sssd-tools libnss-sss libpam-sss libsss-sudo ldb-tools
(''ldb-tools'' fournit ''ldbsearch'', utile pour inspecter le cache.)
===== Certificat CA =====
Copier le CA auto-signé du serveur vers le portable :
sudo mkdir -p /etc/ssl/lldap
sudo scp maitre@192.168.1.9:/mnt/stockage/docker/data/lldap/ca-cert.pem /etc/ssl/lldap/ca-cert.pem
===== Configuration sssd =====
''/etc/sssd/sssd.conf'' — **permissions 600 obligatoires** (sinon sssd refuse de démarrer).
[sssd]
services = nss, pam
domains = beafrancois.fr
[nss]
filter_users = root
filter_groups = root
[pam]
offline_credentials_expiration = 0
[domain/beafrancois.fr]
enumerate = True
id_provider = ldap
auth_provider = ldap
chpass_provider = ldap
access_provider = simple
simple_allow_groups = famille
cache_credentials = True
use_fully_qualified_names = False
ldap_uri = ldaps://auth.beafrancois.fr:6360
ldap_schema = rfc2307bis
ldap_search_base = dc=beafrancois,dc=fr
ldap_default_bind_dn = uid=binduser,ou=people,dc=beafrancois,dc=fr
ldap_default_authtok = MOT_DE_PASSE_BINDUSER
ldap_tls_cacert = /etc/ssl/lldap/ca-cert.pem
ldap_tls_reqcert = demand
# Users (object class réel LLDAP = posixAccount)
ldap_user_search_base = ou=people,dc=beafrancois,dc=fr?subtree?(uidNumber=*)
ldap_user_object_class = posixAccount
ldap_user_name = uid
ldap_user_uid_number = uidNumber
ldap_user_gid_number = gidNumber
ldap_user_home_directory = homeDirectory
# Groupes (object class réel LLDAP = groupOfNames, membres par DN)
ldap_group_search_base = ou=groups,dc=beafrancois,dc=fr?subtree?(gidNumber=*)
ldap_group_object_class = groupOfNames
ldap_group_name = cn
ldap_group_member = member
ldap_group_gid_number = gidNumber
dns_resolver_server_timeout = 500
dns_resolver_op_timeout = 1
dns_resolver_timeout = 2
ldap_opt_timeout = 3
ldap_network_timeout = 2
override_homedir = /home/%u
ldap_user_shell = unixShell
default_shell = /bin/bash
Permissions + activation :
sudo chmod 600 /etc/sssd/sssd.conf
sudo chown root:root /etc/sssd/sssd.conf
sudo sssctl config-check # doit retourner 0 issue
===== Intégration PAM / NSS =====
sudo pam-auth-update
Cocher : **SSS authentication**, **Create home directory on login**, garder **Unix authentication**. **Décocher** tout autre fournisseur d'auth résiduel.
''nsswitch.conf'' : ''libnss-sss'' ajoute ''sss'' automatiquement. Vérifier :
grep -E "^passwd|^group" /etc/nsswitch.conf
# passwd: files systemd sss
# group: files systemd sss
Démarrage :
sudo systemctl enable --now sssd
sudo sssctl domain-status beafrancois.fr # doit afficher Online
===== ⚠️ PIÈGES MAJEURS (vécus, ne pas refaire) =====
==== 1. Mapping object class — LE point critique ====
Les valeurs par défaut de sssd ne correspondent PAS au schéma LLDAP. Valeurs **correctes vérifiées** :
* ''ldap_user_object_class = posixAccount'' (PAS ''person'')
* ''ldap_group_object_class = groupOfNames'' (PAS ''posixGroup'')
* ''ldap_group_member = member'' (LLDAP stocke les membres par **DN**, pas memberUid)
* ''ldap_schema = rfc2307bis'' (obligatoire pour membres par DN)
Un mauvais ''ldap_group_object_class'' = "Autorisation refusée" au login (le groupe ''famille'' n'est pas reconnu, l'access_provider simple refuse).
==== 2. NE PAS utiliser auto_private_groups / groupes privés ====
**Cause de l'échec offline pendant des heures.** Avec ''auto_private_groups = true'' OU des groupes privés portant le même nom que l'utilisateur, sssd génère un conflit MPG (« Group named X already exists in an MPG domain ») : l'**écriture du user dans le cache échoue**, donc pas de credential caché, donc **offline impossible**.
**Solution validée :** groupe primaire **partagé** (''famille'', gid 302) pour tous les users. Pas de groupe privé, pas de ''auto_private_groups''. Le ''gidNumber'' primaire de chaque user pointe vers un groupe **qui existe** (famille).
Règle générale : tout ''gidNumber'' primaire d'un user DOIT correspondre à un groupe existant dans LLDAP, sinon « impossible de trouver le nom pour l'ID de groupe » et l'initgroups offline casse.
==== 3. offline_credentials_expiration dans [pam] ====
Doit être dans la section **[pam]**, pas [domain]. Mal placé, ''sssctl config-check'' le signale et le offline illimité ne s'applique pas. Valeur ''0'' = cache offline **illimité** (exigence : login sans réseau indéfiniment).
==== 4. config_file_version interdit ====
Ne PAS mettre ''config_file_version'' (rejeté par sssctl config-check sur cette version).
==== 5. Reset de cache propre ====
Après tout changement de schéma/groupe, vider **entièrement** le cache (db + memory cache), sssd arrêté :
sudo systemctl stop sssd
sudo rm -f /var/lib/sss/db/cache_beafrancois.fr.ldb /var/lib/sss/db/timestamps_beafrancois.fr.ldb
sudo rm -f /var/lib/sss/mc/*
sudo systemctl start sssd
**⚠️** Ne jamais faire ça si la machine est offline et dépend de sssd (on efface aussi les credentials cachés !).
===== Tests de validation =====
==== En ligne ====
getent passwd testldap # testldap:*:15000:302:...:/home/testldap:/bin/bash
id testldap # uid=15000(testldap) gid=302(famille) groupes=302(famille)
su - testldap # crée le home, donne un shell
ssh testldap@localhost
==== Vérifier que le credential est caché ====
sudo ldbsearch -H /var/lib/sss/db/cache_beafrancois.fr.ldb \
"name=testldap@beafrancois.fr" 2>/dev/null \
| grep -iE "uidNumber|gidNumber|cachedPassword|originalDN"
Doit montrer ''cachedPassword: $6$...'' et ''originalDN: uid=testldap,ou=people,...''.
(Note : le filtre ''(objectClass=user)'' ne marche PAS sur cette version de ldb — utiliser ''name=...''.)
==== Offline (l'objectif) ====
# 1. login en ligne (cache le credential)
su - testldap ; exit
# 2. couper le réseau (wifi off / ethernet débranché)
# 3. login hors ligne
su - testldap
Doit donner un shell **sans réseau**. ✓ Validé.
===== Commandes utilisateur (comportement) =====
==== passwd — FONCTIONNE (en ligne) ====
L'utilisateur change son mot de passe avec ''passwd''. Écrit dans LLDAP (''chpass_provider = ldap''). **Doit être en ligne** (impossible hors réseau). Voir doc serveur pour les détails de propagation du cache.
==== chsh — NE FONCTIONNE PAS ====
''chsh'' échoue sur les comptes LLDAP :
chsh: l'utilisateur 'testldap' n'existe pas dans /etc/passwd
**Limitation de l'outil**, pas de la config : ''chsh'' (util-linux) ne lit/écrit que ''/etc/passwd'' local, il ne passe pas par sssd/NSS. Aucun contournement côté ''chsh''.
Le shell des comptes LLDAP est géré autrement :
* **Actuellement :** ''default_shell = /bin/bash'' dans sssd.conf — shell fixe identique pour tous.
* **Pour des shells par utilisateur :** créer l'attribut ''unixShell'' (ou ''loginShell'') dans le schéma LLDAP, le remplir par user, et l'ajouter au mapping sssd : ''ldap_user_shell = unixShell''. Modifiable alors uniquement par l'admin via l'UI web (pas par l'utilisateur).
==== chfn (gecos / nom complet) ====
Même limitation que ''chsh'' (util-linux, ''/etc/passwd'' local). Le nom complet se gère dans l'UI web LLDAP (''displayName'' / ''cn''), pas par ''chfn''.
===== Purge d'un ancien résolveur d'identité =====
Si un portable a déjà eu un autre résolveur d'identité installé (autre que sssd), le purger avant/après l'installation de sssd, sinon il peut résoudre certains UID en parallèle et entrer en conflit avec sssd :
# désactiver le service de l'ancien résolveur, le cas échéant
sudo systemctl disable --now 2>/dev/null
# retirer son module de /etc/nsswitch.conf (lignes passwd/group)
sudo pam-auth-update # décocher l'ancien fournisseur
Vérifier ensuite que ''/etc/nsswitch.conf'' ne contient plus que ''files systemd sss'' sur les lignes passwd/group.
===== Bascule des vrais comptes (à faire) =====
* UID cibles en plage haute (10000+) — voir doc serveur
* Comptes locaux existants en UID 1000-1003 : leurs homes (''/home/francois'' etc.) appartiennent à l'ancien UID. Après bascule en 10000+, faire un ''chown -R'' du home vers le nouvel UID :
sudo chown -R 10000:302 /home/francois
* Supprimer le compte local SANS ''-r'' (préserve le home) une fois sssd validé :
sudo userdel francois # le home reste
* Procéder **PC par PC**, après validation, en gardant un accès admin local de secours.
===== Sécurité =====
* ''offline_credentials_expiration = 0'' (illimité) répond à l'exigence MAIS : un portable volé jamais reconnecté garde un cache valable indéfiniment. **Chiffrement disque LUKS recommandé** sur les portables.
* Compte bind en lecture seule (''lldap_strict_readonly''), jamais l'admin.
* Auth des serveurs (principal + proxy) : ne PAS passer par sssd — garder compte local + clé SSH (filet de sécurité).
===== Déploiement autres portables =====
* **Debian/Ubuntu** : même procédure (paquets ''sssd sssd-tools libnss-sss libpam-sss libsss-sudo'')
* **Arch** : ''sudo pacman -S sssd'' (+ ''openldap'' pour ldapsearch). Mêmes sssd.conf et pièges.
* Copier le même ''sssd.conf'' (adapter rien sauf si besoin), le CA, faire ''pam-auth-update''.