191 lines
8.9 KiB
Markdown
191 lines
8.9 KiB
Markdown
PAM et pam-auth-update
|
|
----------------------
|
|
|
|
L'authentification par mot de passe est gérée par le profil `common-auth`.
|
|
Ce profil n'est pas utilisé directement, il est inclus depuis les profils
|
|
de service présents dans `/etc/pam.d`.
|
|
|
|
Le contenu de ce profil commun est généré automatiquement par la commande
|
|
`pam-auth-update` pour tous les modules PAM qui livrent une définition dans
|
|
`/usr/share/pam-configs`. Cette commande peut être invoquée en mode interactif
|
|
(menu curses) ou en ligne de commande, éventuellement depuis un script de
|
|
paquet `postinst`. Voir [pam-auth-update(8)] pour les détails.
|
|
|
|
Les fichiers de définition dans `/usr/share/pam-configs` contiennent des
|
|
fragments de profil PAM, et aussi des méta-données qui sont utilisées
|
|
pendant l'exécution de `pam-auth-update`. La propriété la plus intéressante
|
|
est `Priority`: elle détermine l'ordre d'apparition du module dans la
|
|
liste du menu curses et dans le fichier `common-auth`. Les modules sont
|
|
classés par ordre de priorité décroissante. Voir [PAMConfigFrameworkSpec].
|
|
|
|
Extrait d'un `common-auth` généré avec les définitions `krb5`, `unix` et `ccreds`:
|
|
```
|
|
# here are the per-package modules (the "Primary" block)
|
|
auth [success=4 default=ignore] pam_krb5.so minimum_uid=1000
|
|
auth [success=3 default=ignore] pam_unix.so nullok_secure try_first_pass
|
|
auth [success=2 default=ignore] pam_ccreds.so minimum_uid=1000 action=validate use_first_pass
|
|
auth [default=ignore] pam_ccreds.so minimum_uid=1000 action=update
|
|
# here's the fallback if no module succeeds
|
|
auth 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
|
|
auth required pam_permit.so
|
|
```
|
|
|
|
Les modules sont testés dans l'ordre d'apparition: d'abord `krb5`, si
|
|
l'authentification Kerberos échoue on passe à `unix`, si l'authentification
|
|
avec mot de passe local échoue on passe à `ccreds`, etc.
|
|
|
|
Important: l'option `success=N` est une instruction de saut: si le module concerné
|
|
authentifie l'utilisateur, alors les N modules suivants seront sautés, ce n'est pas
|
|
la peine de les invoquer. Autrement dit, si `pam_krb5` réussit, on passe directement
|
|
à `pam_permit`. Voir [pam.conf(5)] pour les détails sur les options.
|
|
|
|
|
|
Mise en place de `pam_sss`
|
|
--------------------------
|
|
|
|
Après avoir configuré SSSD, on active le profil `sss` avec `pam-auth-update`:
|
|
```
|
|
# pam-auth-update --remove krb5 --enable sss
|
|
```
|
|
|
|
Et là, c'est le drame : à l'ouverture de session, l'utilisateur n'obtient pas
|
|
de ticket Kerberos :-( alors que la machine est bien connectée au réseau.
|
|
Dans les logs, on a:
|
|
```
|
|
pam_unix(gdm-password:session): session opened for user meyd7400 by (uid=0)
|
|
```
|
|
C'est le module `unix` qui a authentifié l'utilisateur.
|
|
|
|
Sur une autre machine, où (par chance) le mot de passe local est différent
|
|
du mot de passe AD, le comportement est différent, le TGT est bien obtenu
|
|
à l'ouverture de session en utilisant le mot de passe AD.
|
|
Dans les logs, on a maintenant:
|
|
```
|
|
pam_unix(gdm-password:auth): authentication failure; logname= uid=0 euid=0 tty=/dev/tty1 ruser= rhost= user=meyd7400
|
|
pam_sss(gdm-password:auth): authentication success; logname= uid=0 euid=0 tty=/dev/tty1 ruser= rhost= user=meyd7400
|
|
[...]
|
|
pam_unix(gdm-password:session): session opened for user meyd7400 by (uid=0)
|
|
```
|
|
Le module `unix` a échoué (normal) et le module `sss` a réussit.
|
|
|
|
Pour comprendre ce comportement, il faut regarder dans le profil `common-auth`,
|
|
qui contient maintenant ceci:
|
|
|
|
```
|
|
# here are the per-package modules (the "Primary" block)
|
|
auth [success=4 default=ignore] pam_unix.so nullok_secure
|
|
auth [success=3 default=ignore] pam_sss.so use_first_pass
|
|
auth [success=2 default=ignore] pam_ccreds.so minimum_uid=1000 action=validate use_first_pass
|
|
auth [default=ignore] pam_ccreds.so minimum_uid=1000 action=update
|
|
```
|
|
|
|
Le module `unix` est placé en premier, donc il réussit toujours quand le
|
|
mot de passe local est synchronisé avec le mot de passe AD, et alors le
|
|
module `sss` n'est pas appelé à cause de l'option `success`, cf plus haut.
|
|
|
|
Si le module `sss` était placé en premier, comme l'était `krb5`,
|
|
alors on aurait eu le résultat attendu. Mais il est placé en second par
|
|
`pam-auth-update`, parce que sa priorité (128) est inférieure à celle de
|
|
`unix` (256).
|
|
|
|
|
|
Le module `pam_sss` en premier
|
|
------------------------------
|
|
|
|
D'apres [PAMConfigFrameworkSpec], le module `pam_sss` devrait avoir une
|
|
priorité supérieure ou égale à 512, puisqu'il s'agit d'un profil
|
|
qui "authenticates against a central network service, with rules to
|
|
exclude administrative/system accounts". Or sa priorité définie dans
|
|
`/usr/share/pam-configs/sss` est 128 ... pourquoi ?
|
|
|
|
Une réponse possible: le module `pam_sss` ne prend pas en compte l'option
|
|
PAM classique `minimum_uid` comme le font `pam_krb5` et `pam_ccreds`, il
|
|
utilise pour faire la même chose une propriéte `min_id` à définir dans
|
|
le fichier de configuration `sssd.conf`. Comme la règle d'exclusion n'est
|
|
pas explicitement dans la configuration PAM, ca pourrait expliquer le
|
|
choix d'une priorité inférieure.
|
|
|
|
=> chercher dans le bugtracker ?
|
|
|
|
On dirait vraiment que `pam_sss` est conçu et configuré pour des
|
|
utilisateurs qui sont enregistrés dans un LDAP et pas en local (dans ce
|
|
cas ça marche direct). Moi je veux bien, c'est parfait pour un poste
|
|
fixe qui est toujours connecté au réseau, mais que se passe-t'il avec
|
|
un laptop déconnecté, si on n'a pas de mot de passe local ?
|
|
|
|
On pourrait envisager de désactiver le profil `pam_unix`, comme cela il
|
|
ne reste que `pam_sss` et le problème disparait, mais je soupçonne qu'il
|
|
va y avoir des effets de bord ;-)
|
|
|
|
Pour passer `pam_sss` en premier, il faut augmenter sa priorité. On peut
|
|
faire cela en modifiant le fichier `/usr/share/pam-configs/sss` à la
|
|
volée depuis le `postinst` avec `sed`, mais c'est très moche, et cela ne
|
|
résiste pas à une mise à jour du paquet `libpam-sss`, il faudrait mettre
|
|
en place un `trigger` ou mieux encore un `divert` ... ça reste du bricolage.
|
|
|
|
Autre solution, plus propre:
|
|
- ajouter un fichier `/usr/share/pam-configs/sss-first`, copie de `sss`
|
|
- modifier sa propriété `Name` et augmenter la valeur de `Priority`
|
|
- rajouter une propriété `Conflicts: sss`
|
|
- dans le `postinst`, activer `sss-first` et désactiver `sss`
|
|
|
|
Important: ne pas utiliser --force dans les scripts, seulement --package
|
|
Important: bien verifier uid >= 1000 et users interdits.
|
|
|
|
Note: les deux profils `sss` et `sss-first` sont en conflit, mais leur
|
|
propriété `Default` vaut `yes`, ce qui a une conséquence particulière
|
|
: quand on lance `pam-auth-update` une première fois en mode interactif,
|
|
sans avoir exécuté la configuration automatique via le `postinst`, alors
|
|
les deux profils sont sélectionnés dans le dialogue `debconf`. Si on
|
|
valide à ce moment, le dialogue se plaint qu'il y a conflit, et refuse de
|
|
valider la sélection. Il faut modifier et choisir l'un ou l'autre. Ensuite,
|
|
le dialogue se souvient du choix qui a été fait.
|
|
|
|
Reste à faire
|
|
-------------
|
|
|
|
Avec le module `pam_sss` en premier, on a le comportement attendu,
|
|
le problème de l'obtention du TGT Kerberos à l'ouverture de session
|
|
est résolu.
|
|
|
|
Néanmoins, il doit bien y avoir une raison explicite pour que `pam_sss`
|
|
ne soit pas prioritaire dans la configuration par défaut Debian/Ubuntu,
|
|
la "réponse possible" ci-dessus n'est qu'une supposition de ma part, tant
|
|
que je n'aurais pas trouvé l'explication dans une documenation officielle
|
|
il restera un doute sur la méthode ci-dessus.
|
|
|
|
Question subsidiaire a résoudre: comment changer le mot de passe local ?
|
|
Précédemment, avec `pam_krb5`, la méthode consistait à d'abord désactiver
|
|
Kerberos via `pam-auth-update`, changer le mot de passe avec `passwd`, puis
|
|
rétablir Kerberos. On peut faire la même chose maintenant, mais c'est plus
|
|
délicat, on a deux entrées dans le menu curses : "SSSD (first)" et "SSSD",
|
|
c'est la première qu'il faut rétablir, pas la deuxième...
|
|
A creuser:
|
|
|
|
- un script pour automatiser les différentes étapes du changement de
|
|
mot de passe local
|
|
- désactiver le changement de mot de passe AD dans la configuration PAM,
|
|
via la définition de `sss-first`, puisque de toute façon ce n'est pas
|
|
une bonne méthode (desynchro AD/Gassi), il faut passer par le site
|
|
"Mot de passe attitude".
|
|
|
|
Pour éviter les confusions, il faudrait renommer la définition `sss-first`
|
|
en `yourdev`, ça serait plus explicite.
|
|
|
|
Références
|
|
----------
|
|
|
|
- [pam.conf(5)]
|
|
- [pam-auth-update(8)]
|
|
- [PAMConfigFrameworkSpec]
|
|
|
|
[PAMConfigFrameworkSpec]: https://wiki.ubuntu.com/PAMConfigFrameworkSpec
|
|
[pam.conf(5)]: https://manpages.debian.org/bullseye/libpam-runtime/pam.conf.5.en.html
|
|
[pam-auth-update(8)]: https://manpages.debian.org/bullseye/libpam-runtime/pam-auth-update.8.en.html
|
|
|
|
|
|
|