J’ai récemment eu l’occasion de dépanner des implémentations WSS/MOSS présentant des problèmes relatifs au people picker (sélecteur de personnes).
Je dois reconnaître que les documentations existantes sont assez pauvres et que d’autres messages postés sur des blogs sont peu clairs à mes yeux. J’ai donc décidé de synthétiser un document sur le comportement et la configuration du people picker, lorsqu’il se repose sur Active Directory/l’authentification intégrée de Windows (Integrated Windows Authentication – IWA). Notes : ce qui s’applique ici à IWA s’applique également aux authentifications basique, digest et à l’authentification s’appuyant sur un certificat client : ce qui importe c’est qu’Active Directory (AD) soit l’entité de référence pour l’authentification.
Il est donc primordial de comprendre comment AD, les domaines, les forêts et les relations d’approbations se comportent afin de faire fonctionner le people picker correctement (retourne le résultat effectivement attendu), rapidement (ne prend pas des plombes pour retourner le résultat) et de manière fiable (son comportement est prévisible et ne varie pas dans le temps). Je suis souvent surpris par le fait que très peu de spécialistes Sharepoint connaissent réellement les mécanismes internes de Windows et d’AD, conduisant très souvent à une configuration incorrect du people picker.
Comment ça marche, avec la configuration par défaut
Le people picker est une interface SharePoint en charge d’interroger différentes entités sur les identités ou les groupes afin de leurs accorder des permissions dans l’application SharePoint. Il est implémenté dans le cadre du rôle Web Font End (WFE), ce qui signifie que si vous l’utilisez, le WFE auquel vous vous connectez tentera de contacter AD afin de retourner les éléments correspondants aux critères de votre requête. Voici, pas à pas, comment cela fonctionne du point de vue d’AD/Windows :
- Un utilisateur soumet une requête au people picker
- Le WFE exécute une requête DNS afin de localiser un contrôleur de domaine (DC) configuré en tant que serveur de catalogue global (Global Catalog – GC). Il y a en fait 2 requêtes DNS possibles :
- La première requête contient le nom du site Active Directory dans lequel se trouve le serveur afin de localiser un contrôleur de domaine qui réside dans le même site ou qui le « couvre » (il ne se trouve pas dans le même site mais est configuré en tant que candidat pour recevoir des requêtes venant de ce site). Si cette requête réussit, il n’y en a pas de seconde.
- Si elle échoue et que le service DNS rapporte qu’un tel site n’existe pas, une deuxième requête sera envoyée sans aucune référence au site du serveur.
- Avec l’adresse IP d’un contrôleur de domaine en main, SharePoint initiera une connexion d’un port local aléatoire vers le port distant 3268 (Global Catalog LDAP en TCP) du contrôleur de domaine sélectionné. La première connexion, qui est anonyme, rapportera à SharePoint des informations complémentaires à propos du contrôleur de domaine qu’il a contacté. Cela inclut diverses informations LDAP, ses fonctionnalités exactes, ainsi que les mécanismes d’authentification qu’il supporte. Ce point d’entrée est connu en tant que « racine » (« root ») ou « rootDSE ».
- Une fois que SharePoint sait comment « parler » à Active Directory, il exécutera une requête dont une partie des paramètres est basée sur les entrées de l’utilisateur. Cette requête est en fait régie de manière programmée dans l’espace de noms System.DirectoryService. Puisque la requête se fait auprès du service de catalogue global, elle ne peut se servir que d’une partie des attributs d’AD (connue sous le nom de « partial attribute set », ensemble d'attributs partiel). La liste des attributs exacts dépend de la version de Windows des contrôleurs de domaine et de la présence d’extensions du schéma (MS Exchange, OCS ou personnalisées …). Si AD nécessite une authentification, ce qui est le cas par défaut, SharePoint s’authentifiera dans le contexte du pool d’applications sous lequel tourne l’application Web SharePoint. Cela peut être Local System ou Network Service (alors DOMAIN\NOMDUSERVEUR$ sera utilisé) ou un utilisateur spécifié.
- SharePoint affiche le résultat à l’utilisateur
La requête, telle qu’enregistrée dans le code:
- (&(objectCategory=person)(objectClass=user)(!(userAccountControl:1.2.840.113556.1.4.803:=2))(|(name={0}*)(displayName={0}*)(cn={0}*)(mail={0}*)(sn={0}*)(SamAccountName={1}*)(proxyAddresses=SMTP:{0})(proxyAddresses=sip:{0}){2}))", "(&(objectCategory=person)(objectClass=user)(!(userAccountControl:1.2.840.113556.1.4.803:=2))(|(name={0})(displayName={0})(cn={0})(mail={0})(samAccountName={0})(proxyAddresses=SMTP:{0})(proxyAddresses=sip:{0})))", "(&(objectCategory=person)(objectClass=user)(!(userAccountControl:1.2.840.113556.1.4.803:=2))(|(mail={0})(proxyAddresses=SMTP:{0})))"), new SearchParameter("(&(objectCategory=group)(|(name={0}*)(displayname={0}*)(cn={0}*)(SamAccountName={1}*)(mail={0}*)(proxyAddresses=SMTP:{0}){2}))", "(&(objectCategory=group)(|(name={0})(displayname={0})(SamAccountName={0})(mail={0})(proxyAddresses=SMTP:{0})))", "(&(objectCategory=group)(|(mail={0})(cn={0})(proxyAddresses=SMTP:{0})))"), new SearchParameter("(&(objectCategory=group)(groupType:1.2.840.113556.1.4.803:=2147483648)(|(name={0}*)(displayname={0}*)(cn={0}*)(SamAccountName={1}*){2}))", "(&(objectCategory=group)(groupType:1.2.840.113556.1.4.803:=2147483648)(|(name={0})(displayName={0})(cn={0})(samAccountName={0})))
Les critères de la requête en clair :
- Un utilisateur ou un groupe
- Si c’est un utilisateur, au moins un des attributs suivants doit commencer par ce que l’utilisateur a entré comme information : name, displayName, cn, mail, sn, SamAccountName, proxyAddresses (avec SMTP ou sip)
- Si c’est un utilisateur, il ne doit pas être désactivé
- Si c’est un groupe, au moins un des attributs suivants doit commencer par ce que l’utilisateur a entré comme information : name, displayName, cn, sAMAccountName
- Si c’est un groupe, cela doit être un groupe de sécurité (domaine local, global, universel), pas un groupe de distribution
Les attributs suivants seront retournés pour chaque enregistrement trouvé :
- objectSID
- mail
- displayName
- title
- department
- proxyAddresses
- cn
- samAccountName
- groupType
- userAccountControl
- distinguishedName
Et finalement, les contrôles serveurs suivants seront spécifiés :
- LDAP_PAGED_RESULT_OID_STRING: découpe le résultat en pages et affiche 20 résultats par page
- LDAP_SERVER_DOMAIN_SCOPE_OID: ordonne au DC de ne pas générer de référence de continuation LDAP en réponse à une opération de recherche
Points clés :
- Par défaut, SharePoint n’a connaissance que de la forêt AD à laquelle le serveur appartient
- SharePoint utilise les enregistrements DNS « DC locator » pour localiser un DC faisant tourner le service de catalogue global
- Il émet des requêtes en utilisant un dialecte pseudo-LDAP contre le service de catalogue global en utilisant l’espace de noms System.DirectoryService
- Il n’y a pas de « security trimming » en soi. Les requêtes retournent les résultats en se basant sur ce que le pool d’application IIS est autorisé à voir, pas l’identité de l’utilisateur
Toujours obscur à mes yeux :
- Dans le cas ( pas par défaut, et non recommandé) où le pool d’application IIS tourne dans le contexte d’un utilisateur d’un autre domaine, quel domaine contrôleur de quel domaine sera utilisé ?
Interroger des forêts ou domaines additionnels
Dans cette section, je couvrirai la configuration la plus fréquente : le serveur SharePoint appartient à une forêt et/ou domaine qui a une relation d’approbation bidirectionnelle (2-way trust) établie avec une autre forêt ou domaine. Les comptes des utilisateurs accédant à SharePoint appartiennent donc à ces domaines approuvés puisque l’approbation est bidirectionnelle , l’identité du pool d’application IIS est aussi capable de s’authentifier face à ces domaines approuvés.
Afin d’ordonner à SharePoint d’interroger ces domaines ou forêts approuvés, la commande « STSADM.exe –o setproperty –pn peoplepicker -searchadforest » doit être utilisée. Mais il semblerait que de nombreuses personnes sont désorientées, pour de bonnes raisons, quant à la syntaxe exacte des paramètres à passer.
Vous devez premièrement collecter les informations suivantes :
- Voulez-vous interroger une forêt (dans ce cas vous aurez besoin d’une relation d’approbatiopn entre deux forêts) ou un domaine (dans ce cas une relation externe d’approbation est suffisante)
- Quel est le nom DNS de la forêt que vous voulez interroger (ainsi que le nom DNS de son domaine racine)
Suivant les informations collectées ci-dessus, vous pourrez alors assembler les paramètres correctement. Les configurations de chaque forêt ou domaine à interroger doivent être séparées par un point-virgule et à l’intérieur de la configuration, le premier mot doit être « forest: » ou « domain: » et il doit être suivipar un nom DNS valide. Exemple :
- STSADM.exe -o setproperty -pn peoplepicker–searchadforests –pv “forest:dune.local;domain:carthag.local;domain:tuono.local”
Points clés:
- Le processus “DC Locator » utilisé avec la configuration standard est toujours applicable MAIS s’étend au-delà des limites de la forêt locale. Cela signifie que les serveurs SharePoint doivent être capables de résoudre les noms des contrôleurs de domaine des forêts/domaines distants (enregistrement SRV et A)
- Aussi, les sites Active Directory doivent être nommés de manière identique dans chaque forêt, sinon SharePoint peut ne pas sélectionner le contrôleur de domaine “le plus proche”.
- Si vous utilisez l’ “authentification sélective” ou le “filtrage des SID” afin de restreindre l’authentification à travers les relations d’approbation, vous devez vous assurer que l’identité du pool d’application IIS est autorisée à s’authentifier face au domaine/à la forêt distant qu’il interroge.
- Il va de soi que s’il y a des firewalls entre SharePoint et le domaine/la forêt distant(e), ils doivent être configurés de manière adéquate.
- Comme il a été dit précédemment, si l’argument “forest” est spécifié, une relation d’approbation entre deux forêts doit être mise en place.
- Si vous désirez toujours interroger la forêt/le domaine auquel SharePoint appartient, vous devrez le spécifier également comme paramètre
- Si c’est une forêt que vous interrogez, il est inutile de déclarer tous ou une partie des domaines enfants de manière séparée, ils seront de toute façon interrogés.
- Si “forest” est spécifié, le service de catalogue global sera utilisé pour réaliser la requête.
Si “domain” est spécifié, le service LDAP sera alors utilisé.
Le catalogue global (“Global Catalog”, GC en abrégé) peut interroger tous les objets à l’intérieur d’une forêt mais ne connaît qu’une partie limitée de leurs attributs alors que LDAP connaît tous les attributs mais est limité au domaine ciblé.
- Ne pas oublier d’exécuter IISRESET sur chaque serveur SharePoint où la configuration doit être appliquée
Toujours obscur à mes yeux :
- Je suis persuadé que les requêtes contre chaque forêt/domaine ne sont pas executées en parallèle, du moins pas la partie DNS
La configuration avec une relation d’approbation unidirectionnelle (one-way trust)
Cette configuration est identique à la précédente, excepté le fait que des crédentiels alternatifs doivent être spécifiés, dû au fait que l’identité du pool d’application IIS n’est pas capable de authentifier face à la forêt/domaine distant à cause la limitation définie par la relation d’approbation unidirectionnelle. Ces crédentiels doivent provenir du domaine/de la forêt interrogée ou d’un domaine approuvé, tant qu’ils sont autorisés à s’authentifier et que la connexion à distance ne leur est pas refusée.
La tâche la plus difficile consiste à appliquer la configuration
Premièrement, une clé doit être générée afin d’encrypter/de décrypter les crédentiels alternatifs à utiliser. Pour ce faire, vous devez exécuter la commande suivante sur chaque serveur SharePoint où le people picker sera utilisé (raccourci: faites-le sur chaque serveur!):
- STSADM.exe -o setapppassword -password MYPASSWORD
où MYPASSWORD est la clé -> il va de soi qu’il est préférable d’utiliser une clé la plus complexe possible. Cependant, elle n’est pas soumise à la stratégie de mots de passe de Windows.
Deuxièmement, vous devez fournir la liste de forêts/domaines à interroger ainsi que les crédentiels pour le faire. Chaque bloc est séparé par un point-virgule et chaque élément dans les blocs est séparé par une virgule.
Exemple:
- STSADM.exe -o setproperty -pn peoplepicker–searchadforests –pv “forest:dune.local,DUNE\PAULA,MotDePasseDePaulA;domain:carthag.local,CARTHAG\Gurney, MotDePasseDeGurney;domain:tuono.local,TUONO\SHANIA, MotDePasseDeShania”
Points clés:
- Assurez-vous d’avoir des crédentiels valides pour chaque forêt/domaine
- Assurez-vous que chaque élément de la forêt/domaine est correctement structuré
- Ne pas oublier d’exécuter IISRESET sur chaque serveur SharePoint où la configuration doit être appliquée
Astuces de dépannage
Outils utiles
- L’outil de commande NTLTEST (fait partie des outils de support de Windows Serveur 2003, ou inclus dans Windows Serveur 2008)
- L’outil de capture réseau Wireshark
- LDP.exe, simple client LDAP (fait partie des outils de support de Windows Serveur 2003, ou inclus dans Windows Serveur 2008)
- Console Active Directory Utilisateurs et Ordinateurs (AD Users and computers - ADUC)
- ADInsight de MS Sysinsternals (malheureusement pas toujours totalement fiable)
Approche globale
Le moyen le plus direct de retracer le comportement du people picker est de prendre une capture réseau lors d’une recherche réalisée à partir de l’interface graphique Web, en prenant soin de vider la cache DNS (ipconfig /flushdns). Prenez cette capture depuis le Web front-end que vous visez et filtrez les résultats comme suit:
Appliquez un filtre d’affichage afin de ne visualier que les requêtes DNS; vous devriez voir des requêtes semblables à ceci:
Si vous tentez d’interroger un domaine: _ldap._tcp.Site-Name._sites.domain.local: type SRV, class IN (premières tentatives, afin de localiser un DC du même site) ou _ldap._tcp.domain.local: type SRV, class IN (n’importe quel DC du domaine, indifféremment du site)
Si vous tentez d’interroger une forêt, vous devriez voir _gc au lieu de _ldap
Si vous ne voyez pas ces requêtes DNS ou si vous les voyez mais qu’elles échouent, assurez-vous que les serveurs SharePoint sont capable de résoudre les noms des domaines distants et qu’ils sont configurés avec les serveurs DNS corrects, éventuellement accompagnés de suffixes DNS additionnels.
Une fois que la résolution de noms fonctionne correctement, retournez à votre capture et assurez-vous de trouver LDAP (port 389) ou GC (identique à LDAP mais utilisant le port 3268).
Pour chaque forêt ou domaine, vous devez apercevoir un “bindrequest” et sa réponse réussie, suivi d’un “searchrequest” et de sa réponse réussie également. Plongez-vous dans la requête afin d’en retrouver les détails, et plus particulièrement le filtre et les conditions appliquées.
Détermination du site AD du serveur
Exécutez la commande suivante: “NLTEST /dsgetsite”. Cela devrait retourner le site AD auquel le serveur SharePoint appartient. Si ce n’est pas le cas, vous avez de sérieux problèmes de configuration AD ;-)
Détermination d’un DC pour un domaine donné
Exécutez la commande suivante: “NLTEST /dsgetdc:mydomain.local”
Analysez le résultat et vérifiez la liste des flags retournée. Si elle comporte les éléments suivants, vous avez tout bon:
- CLOSE_SITE= le DC est dans le même site AD que le serveur SharePoint ou “couvre” ce site
- LDAP: le DC est un serveur LDAP (tous les DCs le sont, mais doivent l’annoncer)
- GC: le DC est également serveur de catalogue global (Tous les DCs ne sont PAS GC, mais ceux qui le sont doivent également l’annoncer)
Note: les autres informations renvoyées par cette commande peuvent également être utiles pour le dépannage, telles que le nom du DC, son adresse IP, …
Simple test de connexion LDAP
- Sur le serveur SharePoint, démarrer ldp.exe
- Allez dans le menu “Connection” et cliquer sur “Connect”. Entrez l’adresse IP ou le nom du DC distant. Vous devriez tester avec un FQDN (“nom de domaine totalement qualifié”) afin de tester la résolution DNS également.
Sélectionnez le port 389 pour LDAP ou 3268 pour GC
Si cela fonctionne, cela devrait renvoyer une liste d’information relative au server.
- Répétez ce test pour chaque DC face auquel SharePoint pourrait éventuellement réaliser une requête
Tester les crédentiels pour se connecter au domaine distant en utilisant LDAP (en particulier dans le cas du scénario utilisant la relation d’approbation unidirectionnelle)
Si les tests précédents fonctionnent, procédez à celui-ci:
- Retournez dans le menu “Connection” et cliquez ensuite sur “Bind”. Entrez alors les crédentiels du domaine distant (incluant le nom de domaine dans la 3e textbox)
- Si cela échoue, vous obtiendrez un message tel que le suivant:
res = ldap_bind_s(ld, NULL, &NtAuthIdentity, 1158); // v.3
{NtAuthIdentity: User=’myuser’; Pwd= <unavailable>; domain = ‘mydomain’.}
Error <49>: ldap_bind_s() failed: Invalid Credentials.
- Si cela fonctionne, cela rapportera
res = ldap_bind_s(ld, NULL, &NtAuthIdentity, 1158); // v.3
{NtAuthIdentity: User=’myuser’; Pwd= <unavailable>; domain = ‘mydomain’.}
Authenticated as dn:’myuser’.
Eléments perturbants le plus la fiabilité et/ou les performances du people picker
- Plus il y a de domaines/forêts à interroger, plus la requête prendra du temps à délivrer les résultats
- Processus de résolution de noms problématique: afin de résoudre les enregistrements “DC locator”, Windows épuisera toutes les méthodes de résolution de nom possibles, du DNS au broadcast.. Et ceci pour chaque forêt/domaine déclaré
- Un DC qui ne fournit pas de réponse accroît considérablement la lenteur du processus
- Configuration de sites AD non optimisée/inconsistante: la détermination du site est un facteur clé; cela permet de s’assurer que SharePoint interroge toujours le DC le plus proche
- Equipement réseau ou de sécurité empêchant le trafic TCP: depuis la carte réseau défaillante jusqu’au firewall, tout ce qui génére des retransmissions TCP ou force les connexions à se terminer
- La charge d’Active Directory/du DC ou les paramètres de sécurité du DC (permettant d’empêcher les attaques de type DoS)
- Si un filtre personnalisé est utilisé: filtre mal construit
Assurez-vous que la complexité des critères reste raisonnable, que seuls les attributs indexés sont recherchés et que bien sûr, seuls les attributs faisant parties du “partial attribute set” sont utilisés dans le cas d’une requête GC
Informations Additionnelles (en anglais)
Et après?
Dans des articles suivants, je couvrirai:
- Possibilités additionnelles de filtrage des recherches LDAP
- Configurations détaillées pour chaque scénario
- Comment le people picker est reliés à l’authentification et à l’importation du profil (exclusivement MOSS)
- Conseils pour optimiser le people picker dans différents scénarios
Marc
(traduit de l’anglais par Anthony)