pluginsGLPI / formcreator

GLPI Plugin Formcreator (DOWNLOAD : https://github.com/pluginsGLPI/formcreator/releases)
http://www.teclib-edition.com
GNU General Public License v3.0
172 stars 125 forks source link

Connexion LDAP #1137

Open EC2311 opened 5 years ago

EC2311 commented 5 years ago

Bonjour

je suis avec GLPI 9.2.3 et formCreator 2.6.4

j'arrive à importer des utilisateurs et des groupes AD. OK

Lorsque je cree un formulaire avec un composant lié LDAP, le resultat est toujours 'Aucun resultat' : je prends la meme structure de filtre que celui declaré dans le LDAP GLPI.

Pourquoi ? Quelle serait le type de filtre à renseigner ? attribut (AD/LDAP?)

D'avance merci

btry commented 5 years ago

Bonjour

Avez-vous spécifié un attribut ?

image

Si vous choisissez l'attribut Common Name, vous devriez voir vos utilisateurs.

EC2311 commented 5 years ago

Voici le champ et le filtre : image et coté LDAP (authentification) image image

EC2311 commented 5 years ago

En regardant via Ldap, je ne vois pas de champs commonName. par contre display name existe. Seulement pas dans les attributs disponibles?

btry commented 5 years ago

Ine faut pas regarder la configuration LDAP dans l'authentification, mais juste vérifier comment vous avez rempli la question de type LDAP. L'attribut Common Name doit exister indépendamment que vous utilisiez un LDAP normal ou un AD. Mon exemple est fait à partir d'un AD Samba 4, et la question utilise le filtre par défaut quand on la crée.

EC2311 commented 5 years ago

Voici ce que j'ai coté formulaire : image et je ne vois pas de noms s'afficher.

EC2311 commented 5 years ago

En utilisant ldap soft* je vois les utilisateurs, filtres etc... j'ai recupéré filtre... mais toujours rien.

btry commented 5 years ago

Bonjour,

Je tenterai de reproduire. Vous confirmez que vous avez un AD, pas un LDAP (openldap, 389, ...) ?

EC2311 commented 5 years ago

on a AD avec connexion 389. j'essaie d'inserer le DC dans le filtre... mais quelle syntaxe ?

btry commented 5 years ago

Il n'y a pas besoin d'insérer le DC dans le filtre. JE pense que celui qui est dans votre dernière capture d'écran sera bon. Avez-vosu de la latence quand vous affichez le formuliare contenant le champ (utiliser l'ongler "preview" pour faire un essai. Si oui, il se peut qu'il y ait un problème pour joindre votre serveur LDAP.

EC2311 commented 5 years ago

Tout depend de ce que vous entendez par latence... Mais il est vrai que l'affichage n'est pas immédiat contrairement aux autres affichages.

btry commented 5 years ago

Bonjour

La latence serait de l'ordre de 10 seconds ou plus, témoignant d'une incapacité pour le plugin à se connecter à l'annuaire. J'ai pu constater cela récemment suite à une mauvaise configuration. Dans ce scénarion la liste des utilsiateurs est vide.

EC2311 commented 5 years ago

et commentant en etre sur ? Log ?

btry commented 5 years ago

J'en ai eu la certitude car j'étais en train de faire un debug sur un formulaire contenant un champ LDAP avec un annuaire mal configuré sur mon instance. J'ai corrigé la configuration pour réparer le souci et ai réfléchi sur la nature du problème. Pour moi il n'y a pas de bug. J'ai également choisi de ne pas faire apparaitre un message d'avertissement sur le formulaire car cela dérouterait l'utilsiateur final. Cela dit, une amélioration pourrait être faite, mais je n'ai pas encore de solution satisfaisante. LE mieux que j'aie trouvé pour le moment serait de ne pas traiter le champ si l'annuaire LDAP associé ne fonctionne pas (ce qui est fait avec les champs de type Tag)

Le fait que votre dropdown soit vide me fait penser que cette expérience vous arrive également. Une latence anormale à l'affichage du formulaire serait déjà une piste.

Une idée simple pour vérifier : dupliquez votre formulaire, supprimer le champ de type LDAP dans le duplicata, et affichez ce formulaire avec l'onglet "prévisualisation". Si il y a bien une latence sur le formulaire original vous verrez tout de suite la différence.

EC2311 commented 5 years ago

En duspliquant je n'ai pas la meme latence : c'est bien plus rapide, ce qui conforte votre idee. Néanmoins, ce qui me parait etrange c'est que l'authentification via LDAP est ok, vu que les utilisateurs se connectent etc, et ce pour l'ensemble des Ldaps configurés, et que je parviens à faire l'import d'utilisateur ou de groupe AD...

J'ai essayé d'utiliser le debug, mais je ne vois rien... on ne pourrait pas imaginer un 'test'/monitor lors de la connexion du formulaire au ldap afin de vérifier la connexion, un peu comme dans l'onglet 'authentification' ?

dans le formulaire, dans quel script se trouve la connexion au ldap et le rapatriement des données utilisateurs ?

btry commented 5 years ago

la connection à l'annuaire s'effectue dans le fichier suivant : https://github.com/pluginsGLPI/formcreator/blob/develop/inc/fields/ldapselectfield.class.php

Je pense que vous avez ajouté un annuaire dans GLPI, puis créé votre formulaire avec le champ LDAP et finalement détruit puis recréé votre annuaire dans GLPI. Dans une telle situation le champ LDAP fait référence à un annuaire qui n'existe plus et il peut y avoir une tentative de connection vers un hôte dont le nom n'existe pas (chaine vide ou "N/A"; à déterminer en relisant le code).

EC2311 commented 5 years ago

non, je n'ai pas supprimé puis ajouter le ldap.

par contre, je vois dans le fichier ldap_filter.php $filter = "(".$authldap->getField("login_field")."=*)"; $ldap_condition = $authldap->getField('condition'); echo "(& $filter $ldap_condition)";

pourriez vous indiquer ce qui est fait ensuite avec la variable $filter sachant que pour l'authentification dans GLPI j'utilise un compte spécifique à chaque LDAP. où sort la ligne 'echo' ?

EC2311 commented 5 years ago

Sous GLPI 9.3.2, toujours meme chose. Dommage que je n'arrive pas à le faire fonctionner car pour demander ajout d'utilisateur dans des Groupes la connexion LDAP serait plus simple que d'ajouter champ utilisateur (objet glpi) ou texte libre (si l'utilisateur n'existe pas dans la base) Il n'y aurait pas des endroits strategiques ou je pourrais mettre une echo afin de vérifier connexion/retour/variables importantes pour le bon fonctionnement à la connexion LDAP (sachant que mon authentification LDAP fonctionne...)

EC2311 commented 5 years ago

je pense avoir une piste :) ligne 83 du script ldapselectfield.class, j'ai ajouté (lors du catch) echo $ds; echo $e; ainsi j'ai l'erreur (eventuelle) et....

Resource id #21ErrorException: ldap_search(): Partial search results returned: Sizelimit exceeded in \HTTPServer\wwwroot\plugins\formcreator\inc\fields\ldapselectfield.class.php:64 Stack trace: #0 [internal function]: plugin_formcreator_ldap_warning_handler(2, 'ldap_search(): ...', '\...', 64, Array) #1 \HTTPServer\wwwroot\plugins\formcreator\inc\fields\ldapselectfield.class.php(64): ldap_search(Resource id #21, 'OU=xxxxxx,OU=x...', '(& (samaccountn...', Array) #2 HTTPServer\wwwroot\plugins\formcreator\inc\fields\selectfield.class.php(41): PluginFormcreatorLdapselectField->getAvailableValues() #3 \HTTPServer\wwwroot\plugins\formcreator\inc\field.class.php(96): PluginFormcreatorSelectField->displayField(true) #4 \HTTPServer\wwwroot\plugins\formcreator\inc\fields.class.php(122):

trop d'enregistrement à retourner ?

btry commented 5 years ago

A priori il y a trop de résultats. Efectivement en passant récemment sur le code pour préparer la version 2.7 je me suis étonné de n'avoir jamais eu de retour de bug.

Combien d'utilisateurs vous avez dans l'annuaire ?

EC2311 commented 5 years ago

Un tres grand nombre... du coup en mettant certains filtres j'arrive à faire fonctionner, mais pas pratique... NB j'ai du modifier les parametres supp du ldap dans GLPI afin de spécifier d'utiliser les resultats paginés. par contre je ne sais pas si le nbre de resultats (illimité) et taille de la page (100) a un role.

D'autre part j'ai des ldap repliques qui semblent ne pas avoir forcemment les memes données au meme moment... (bizarre) En utilisant un soft ldap (softterra) j'obtiens bien une liste complete des utilisateurs enfin jusque (1000 ensuite ca bloque) alors que si j'utilise un serveur d'authentification (dans le formulaire de glpi) je n'ai pas la meme liste : liste incomplete...

Et comment faire pour faire la liaison ensuite avec les groupes qui ne sont pas dans la meme OU ? Je l'ai defini dans l'authentification ldap : lors de l'imoort ca marche, mais si j'utilise cette connexion cela ne fonctionne pas (niveau formulaire) j'ai l'impression qu'il faut creer une nouvelle connexion LDAP avec baseDN pour l'accés au groupe (via le formulaire) je ne sais pas si je me fais bien comprendre...

EC2311 commented 5 years ago

Pas de news ?

voici ce que j'ai mis cote authentification ldap image mais toujours le meme souci de liste "abregée"...

btry commented 5 years ago

Je n'ai pas encore repris les recherches sur ce bug. De mémoire, le plugin ne réutilsie pas les paramètres de l'annuaire dans GLPI pour faire sa connection LDAP. C'est peut être par là qu'il faudrait améliorer le plugin.

EC2311 commented 5 years ago

sachant que pour les connexions dans GLPI, je n'ai aucun probleme avec les LDAP : toute personne presente dans le ldap arrive à se connecter sans souci et les imports d'utilisateurs sont ok : donc le filtre dans l'authentification est correctement réalisé. A priori dans le formulaire aussi, sachant que je vois des utilisateurs... mais liste incomplete...

btry commented 5 years ago

Je penche pour un problème de pagination. Ca pourrait se confirmer si un filtre restreint les résultats de recherche LDAP à une poignée d'éléments.

EC2311 commented 5 years ago

je confirme Si je restreins la liste via le 'displayname' je vois bien l'ensemble des personnes correspondants donc souci dans la pagination ou buffer (pour grand nombre d'objets ldap ;) )

btry commented 5 years ago

Bonjour

Pouvez-vous vérifier si les résultats paginés sont activés sur votre GLPI ?

image

EC2311 commented 5 years ago

Sur intance de Dev : oui, taille de page 30000 et nbr maxi des resultalts : 300000

btry commented 5 years ago

Et le serveur LDAP est configuré avec les mêmes valeurs ?

EC2311 commented 5 years ago

euh... joker : cela a une importance ?

btry commented 5 years ago

La pagination est imposée par le serveur et les clients sont tenus de faire des requêtes avec des pages de taille inférieure ou égale aux limites du serveur.

Je ne connais pas 389, mais je pense que ça existe.

Le plugin utilise l'API de GLPI pour accéder au serveur LDAP, et à priori, les paramètres de pagination de GLPI doivent s'appliquer.

EC2311 commented 5 years ago

voici ce que je vois si je regarde la conf ldap (softerra) image image

btry commented 5 years ago

Ce logiciel est un client LDAP. Les paramètres de pagination que vous voyez là sont les siens. Il faut que vous trouviez les valeurs côté serveur pour vérifier si la contrainte client <= serveur est repectée.

EC2311 commented 5 years ago

j'ai posé la question : des que j'ai retour j'informe. Néanmoins, il n'y a pas un endroit ou on pourrait voir (en debug?) le retour donné par l'interrogation ? avant que la fenetre soit affichée?) (version 2.8.1 du plugin)

btry commented 5 years ago

Néanmoins, il n'y a pas un endroit ou on pourrait voir (en debug?) le retour donné par l'interrogation ? avant que la fenetre soit affichée?) (version 2.8.1 du plugin)

Il n'y a rien d'implémenté dans le plugin pour cela.

EC2311 commented 3 years ago

Bonjour TOujours le meme probleme :( Version GLPI 9.4.3 et formcreator 2.10.1

J'ai vu que maintenant on a des informations particulieres dans la fenetre en dessous de attributs voici ce que j'ai : {"ldap_auth":"14","ldap_filter":"displayname=*","ldap_attribute":"15"} A quoi correspondent 14 15 ?

Ce qui est étrange est que lorsque j'importe des utilisateurs (du meme ldap) cela fonctionne bien.

btry commented 3 years ago

Bonjour 14 et 15 correspondent à l'ID de 2 objets de GLPI. L'annuaire et un attribut LDAP liste dans GLPI (les intitulés de mémoire).

btry commented 3 years ago

Avez vous pu vérifier les réglages de pagination' de votre annuaire pour les comparer avec les réglages de pagination dans GLPI ?

EC2311 commented 3 years ago

J'ai vérifié et récupéré les informations du serveur LDAP. A priori, ce sont celles par defaut. MaxPoolThreads 4 MaxPercentDirSyncRequests 0 MaxDatagramRecv 4096 MaxReceiveBuffer 10485760 InitRecvTimeout 120 MaxConnections 5000 MaxConnIdleTime 900 MaxPageSize 1000 MaxBatchReturnMessages 0 MaxQueryDuration 120 MaxTempTableSize 10000 MaxResultSetSize 262144 MinResultSets 0 MaxResultSetsPerConn 0 MaxNotificationPerConn 5 MaxValRange 1500 MaxValRangeTransitive 0 ThreadMemoryLimit 0 SystemMemoryLimitPercent 0

coté GLPI, ma configuration du LDAP. image

J'aurais alors tendance à dire qu'il faut modifier le nombre maximum de resultats... fonction peut etre de la mémoire disponible sur le serveur hebergeant mon instance... ?

btry commented 3 years ago

Il faut que je vérifie les détails du proocole LDAP. Vous pouvz essayer de limiter le nombre maximum de résultats à 1000, mais je pense que ça ne changera rien. Je crois que 1200 correspond au nombre total maximum de résultats retournés. Cette notoin ne doit pas appartenir à LDAP.

Je souligne que je me trompe peut être. C'est à vérifier. Par contre l'essai ne coute rien du moment que vous remettez la valeur d'origine après le test.

EC2311 commented 3 years ago

J'ai modifié le nombre de resultat de 1200 en 1000 : pas de changement (32 noms commencant par la lettre A, avec displayname = *). Je pense effectivement que cette valeur intervient plus coté serveur GLPI que coté LDAP, afin de limiter la place mémoire... Pourrait-on voir un souci de remplissage de la fenetre ?

j'ai fait un autre test en spécifiant displayname = a* (avoir tous les displaynames commencant par A donc) et là j'en obtiens beaucoup plus que 32 (je ne peux pas m'amuser à compter, mais ce serait interessant de pouvoir voir combien il en affiche car Via softterra LDAp, on en trouve plus de 800...

EC2311 commented 3 years ago

J'ai repéré un fonctionnement un peu étrange sur le filtre. Par defaut je met displayname= : cela affiche alors une liste que je peux filtrer via selection. si je tape certaines lettre dans la liste, celle ci devrait afficher théoriquement les displayname contenant ces lettres. Or je ne comprends pas l'affichage de la liste. Si je tape eul, je devrais voir alors des displayname contenant 'eul'. or on voit d'autres displayname comportant les lettres e, u , l mais non jointes... Je n'ai pas le meme résultat si je mets displayname = eul -> j'en ai bien moins que si je fais la selection dans la fenetre issue du filtre displayname= et que je tape eul. Comment est géré le "filtre" de la fenetre ?

btry commented 3 years ago

Bonjour

Il ya des appels à des fonctions PHP dépréciées. J'ai fait un patch qui devrait gérer ce problème et cela touche directement à la pagination LDAP. Le patch ci-dessous pourrait vous intéresser : il est susceptible d'améliorer votre situation. C'est un portage pour la branche support/2.10.0

diff --git a/inc/fields/ldapselectfield.class.php b/inc/fields/ldapselectfield.class.php
index d805f3fb..61701cd8 100644
--- a/inc/fields/ldapselectfield.class.php
+++ b/inc/fields/ldapselectfield.class.php
@@ -132,11 +132,43 @@ class PluginFormcreatorLdapselectField extends PluginFormcreatorSelectField
          $cookie = '';
          do {
             if (AuthLDAP::isLdapPageSizeAvailable($config_ldap)) {
-               ldap_control_paged_result($ds, $config_ldap->fields['pagesize'], true, $cookie);
+               if (version_compare(PHP_VERSION, '7.3') < 0) {
+                  // phpcs:ignore Generic.PHP.DeprecatedFunctions
+                  ldap_control_paged_result($ds, $config_ldap->fields['pagesize'], true, $cookie);
+                  $result = ldap_search($ds, $config_ldap->fields['basedn'], $ldap_values->ldap_filter, $attribute);
+               } else {
+                  $controls = [
+                     [
+                        'oid'       =>LDAP_CONTROL_PAGEDRESULTS,
+                        'iscritical' => true,
+                        'value'     => [
+                           'size'   => $config_ldap->fields['pagesize'],
+                           'cookie' => $cookie
+                        ]
+                     ]
+                  ];
+                  $result = ldap_search($ds, $config_ldap->fields['basedn'], $ldap_values->ldap_filter, $attribute, 0, -1, -1, LDAP_DEREF_NEVER, $controls);
+                  ldap_parse_result($ds, $result, $errcode, $matcheddn, $errmsg, $referrals, $controls);
+                  $cookie = $controls[LDAP_CONTROL_PAGEDRESULTS]['value']['cookie'] ?? '';
+               }
+            } else {
+               $result  = ldap_search($ds, $config_ldap->fields['basedn'], $ldap_values->ldap_filter, $attribute);
+            }
+
+            if (in_array(ldap_errno($ds), [4, 11])) {
+               // openldap return 4 for Size limit exceeded
+               $limitexceeded = true;
             }

-            $result  = ldap_search($ds, $config_ldap->fields['basedn'], $ldap_values->ldap_filter, $attribute);
             $entries = ldap_get_entries($ds, $result);
+            if (in_array(ldap_errno($ds), [4, 11])) {
+               // openldap return 4 for Size limit exceeded
+               $limitexceeded = true;
+            }
+
+            if ($limitexceeded) {
+               Session::addMessageAfterRedirect(__('LDAP size limit exceeded', 'formcreator'), true, WARNING);
+            }
             array_shift($entries);

             foreach ($entries as $id => $attr) {
@@ -146,7 +178,8 @@ class PluginFormcreatorLdapselectField extends PluginFormcreatorSelectField
                }
             }

-            if (AuthLDAP::isLdapPageSizeAvailable($config_ldap)) {
+            if (AuthLDAP::isLdapPageSizeAvailable($config_ldap) && version_compare(PHP_VERSION, '7.3') < 0) {
+               // phpcs:ignore Generic.PHP.DeprecatedFunctions
                ldap_control_paged_result_response($ds, $result, $cookie);
             }
EC2311 commented 3 years ago

j'ai mis en place le patch. je ne vois pas de différence : comme je suis en php 7.1.3... je pense que ceci peut expliquer cela.

En attendant y aurait-il une solution de pouvoir saisir une zone et d'utiliser cette zone ((ex ##answer285##) pour alimenter le filtre de la selection (ex dans filtre : (& (cn=*##answer285##*R) (&(objectClass=Group)))

EC2311 commented 3 years ago

Je suis avec PHP 7.3.10 J'ai remis le patch précité : je ne vois pas de différence. J'ai ajouté un echo $result image

voici ce que j'obtiens image

btry commented 3 years ago

Bonjour

Le résultat est normal puisque $result est une ressource.

Si le patch ne change rien, c'est qu'il ne casse rien ? Cela m'intéresse de le fusionner.

EC2311 commented 3 years ago

Si ce le changement n'affecte 'que' le champ lié au LDAP, oui pas de changement à ma connaissance. pas possibilité d'ajouter un echo de mon coté pour 'aider' à trouver ce qui pourrait coincer ?

et sinon "en attendant" y aurait-il une solution de pouvoir saisir une zone et d'utiliser cette zone ((ex ##answer_285##) pour alimenter le filtre de la selection (ex dans filtre : (& (cn=##answer_285##R) (&(objectClass=Group)))

Merci

EC2311 commented 3 years ago

pour information j'ai ajouté un autre point de debug ;) image image

quand on regarde j'ai 'n' ressources effectuées avec 1000 entrées (ce qui correspond à la limite donnée dans l'AD) et à la fin on voit 668, certainement la derniere entrée . Donc pour moi il devrait y avoir '19à52 ressources à 1000 + 668 -> tout cela devrait etre visible dans la petite fenetre de choix 'utilsiateurs'... qu'en pesnez vous ?

btry commented 3 years ago

Je pense que c'est tout à fait juste.

Par contre, vu le nombre d'entrées à afficher, le navigateur va souffrir. Si je tente de faire abstraction de la faute de frappe et que je comprends bien vous vous attendez à avoir 1 952 668 éléments dans votre dropdown ? Ce serait beaucoup trop, le navigateur va être à genoux.

Je pense qu'il serait possible de réécrire cette partie pour avoir un chargement dynamique, comme les dropdowns de GLPI contenant plus de N éléments (N étant réglable dans les préférences utilisateur).

Voyons dans un 1er temps pour résoudre ce souci de pagination.

EC2311 commented 3 years ago

19à52 ressources , soit 52-19 = 33 le tout * 1000, soit 33668 au total.

dans un article php https://www.php.net/manual/fr/function.ldap-search.php Arnold suggere une possibilité (pour les gros volumes)

IF($countResult == 1000 OR $countResult == 1500) { // loop trough the number 97-122 (ASCII number for the characters a-z) For($a=97;$a<=122;$a++) { // translate the number to a character $character = chr($a); // the new search filter withs returns all users with a last name starting with $character $filter = "(&(sn=$character*)(memberOf=$ADGroup))"; $results = ldap_search($ldapconnect, $userBase, $filter, $attr); $countResult2 = ldap_count_entries($ldapconnect,$results);

    // See if the search for all users starting with a specific character still hits the search limit
    // if so than do a new search to find all the users where the last name starts with "aa" and
    // than with "ab", "ac" etc. etc
    // In the best case we can now find 675.324 users per group when the search limit is 1000
    // ((26 * 999  for the fist character) * 26 for the second character)
    // and 1.013.324 when the search limit is 1500
    If($countResult2 == 1000 or $countResult2 == 1500)

..... Je trouve cela pas mal sur le principe,

ou alors de mettre une "filtre dynamique" : on saisit des caracteres et au fur et à mesure le filtre du formulaire se modifie... image

btry commented 3 years ago

Ce qu'il faut c'est utilsier une dropdown chargeant des petits groupes d'éléments progressivement (la 2e solution que vous avez décrite). Dans GLPI cela existe : ce sont les dropdowns avec une zone de saisie pour faire une recherche textuelle. Je pense que c'est possible d'implémenter cela dans ce type de question. Mais là, on en est à une nouvelle feature.