ldap https://www.vincentliefooghe.net/ fr Problème de connexion ldapsearch sur un AD LDS https://www.vincentliefooghe.net/content/probl%C3%A8me-connexion-ldapsearch-sur-un-ad-lds <span property="dc:title" class="field field--name-title field--type-string field--label-hidden">Problème de connexion ldapsearch sur un AD LDS</span> <div property="content:encoded" class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><p>J'ai été confronté à un problème curieux d'accès à un serveur AD LDS à partir d'un container de type Forgerock DS. </p> <p>Côté réseau, tout était OK, les ports ouverts d'un côté comme de l'autre.</p> <p>Par contre une commande <em>ldapsearch</em> tombait en erreur :</p> <pre> /opt/opendj/bin/ldapsearch --hostname 10.1.2.3 --port 389 -D "CN=admin,CN=Admin-Users,dc=example,dc=fr" -w admin2003 \ -b "CN=Applications,DC=example,DC=fr" "(objectclass=exApplications)" Unable to connect to the server: 91 (Connect Error) Additional Information: Remote close</pre><p>Pas très parlant.</p> <p>Côté AD LDS, en modifiant le niveau de logs, on a :</p> <pre> Internal event: The LDAP server returned an error. Additional Data Error value: 00000057: LdapErr: DSID-0C0C0095, comment: Error decoding ldap message, data 0, v4563</pre><p>Peu d'éléments complémentaires. Sachant qu'en plus, en local sur la machine AD LDS, la même connexion se fait sans problème.</p> <p>En investiguant un peu plus, je tente une connexion en mode "startSSL", pour voir si j'ai le même comportement :</p> <pre> /opt/opendj/bin/ldapsearch --useStartTls --hostname 10.1.2.3</pre><p>Et là, le message d'erreur côté machine cliente est différent et me met sur la piste :</p> <pre> An error occurred while parsing the command-line arguments: You may not provide both the --useStartTls and the --useSsl arguments See "ldapsearch --help" to get more usage help</pre><p>Comme je n'ai pas précisé les 2 options (useStartTls et useSsl) dans ma ligne de commande, l'option useSsl doit venir d'un paramétrage par défaut.</p> <p>Et en effet, par défaut les commandes ldap utilisent un fichier de propriétés (<em>/opt/opendj/config/tools.properties</em>) qui définit un certain nom de paramètres par défaut.<br /> On y trouvait notamment :</p> <pre> useSsl=true trustAll=true</pre><p>Du coup lorsque je tentais une connexion "en clair" sur le port 389, AD LDS recevait une requête sur un port non chiffré, mais avec une instruction qui disait que la connexion devait être chiffrée... d'où les messages d'erreur.</p> <p>En utilisant l'option "--noPropertiesFile" dans le ldapsearch, on peut du coup accéder en LDAP sur le port 389, et récupérer les données.</p> <p>L'autre option (plus sécurisée), serait d'utiliser du LDAPS entre les deux serveurs.</p> </div> <span rel="sioc:has_creator" class="field field--name-uid field--type-entity-reference field--label-hidden"><span lang="" about="/users/vincentl" typeof="schema:Person" property="schema:name" datatype="">vincentl</span></span> <span property="dc:date dc:created" content="2022-05-13T12:05:59+00:00" datatype="xsd:dateTime" class="field field--name-created field--type-created field--label-hidden">ven 13/05/2022 - 14:05</span> <div class="field field--name-field-categorie field--type-entity-reference field--label-above"> <div class="field__label">Catégorie</div> <div class="field__item"><a href="/cat%C3%A9gorie/iam" hreflang="fr">IAM</a></div> </div> <div class="field field--name-field-tags field--type-entity-reference field--label-above"> <div class="field__label">Tag</div> <div class="field__items"> <div class="field__item"><a href="/tags/ldap" hreflang="fr">ldap</a></div> <div class="field__item"><a href="/tags/forgerock" hreflang="fr">forgerock</a></div> </div> </div> <section class="field field--name-comment-node-blog field--type-comment field--label-hidden comment-wrapper"> <h2 class="title comment-form__title">Ajouter un commentaire</h2> <drupal-render-placeholder callback="comment.lazy_builders:renderForm" arguments="0=node&amp;1=216&amp;2=comment_node_blog&amp;3=comment_node_blog" token="93czUIzLBmw8jkXBBdRQU08vkcT1Wk3MoNH84UAYHfA"></drupal-render-placeholder> </section> Fri, 13 May 2022 12:05:59 +0000 vincentl 216 at https://www.vincentliefooghe.net Utilisation de SLAMD pour les benchmarks LDAP https://www.vincentliefooghe.net/content/utilisation-slamd-pour-les-benchmarks-ldap <span property="dc:title" class="field field--name-title field--type-string field--label-hidden">Utilisation de SLAMD pour les benchmarks LDAP</span> <div property="content:encoded" class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><p>Lorsqu'on réalise des études comparatives sur les annuaires LDAP, il est fréquent que le client demande d'établir des tests de performances, pour s'assurer que la solution en place sera capable de répondre à ses exigences.</p> <p>Pour faire celà, j'utilisais souvent les outils <em>authrate</em> ou <em>searchrate</em> présents dans les binaires des annuaires de Forgerock ou Ping.</p> <p>Si ces outils permettent de tester de manière unitaire, et avec un certain nombre de paramètres, ils manquait certaines possibilités / fonctionnalités :</p> <ul><li>pas de possiblité de lancer plusieurs clients en parallèle, de manière synchronisée</li> <li>pas de reporting de base</li> <li>pas de réutilisation des modèles de "tirs"</li> </ul><p>Dans le cadre d'un nouveau projet d'étude, je suis tombé sur l'outil <em>SLAMD</em> disponible sur <a href="https://github.com/dirmgr/slamd">GitHub</a>.</p> <h2>Présentation de SLAMD</h2> <p>Il s'agit d'un outil écrit en Java, par un ancien employé de Sun qui travaillait sur les annuaires OpenDS notamment.</p> <p>On trouve également chez Oracle (qui a racheté Sun il y a plusieurs années), les binaires à télécharger : <a href="https://www.oracle.com/security/identity-management/technologies/slamd-downloads/">Oracle SLAMD Downloads</a></p> <p>L'outil se présente comme "<em>Distributed Load Generation Engine</em>", ce qui donne une idée de son architecture répartie. En effet, <em>SLAMD</em> est articulé autour de plusieurs composants :</p> <ul><li>un serveur, qui tourne dans un serveur Tomcat, qui permet de paramétrer les <em>jobs</em>, et construire les rapports</li> <li>un (ou plusieurs) clients, qui vont communiquer avec le serveur pour récupérer les <em>jobs</em> à traiter, et qui vont effectuer les requêtes demandées (ce sont eux qui vont vraiment faire le travail)</li> <li>un service de monitoring que l'on peut installer sur les serveurs LDAP pour remonter les informations au serveur SLAMD.</li> </ul><p>L'outil a été développé à l'origine pour remplacer / améliorer les <em>authrate</em> et autres, avec une orientation LDAP, mais peut aussi être utilisé pour d'autres protocoles réseau (http, smtp, pop,imap).</p> <h2>Utilisation</h2> <p>Une fois qu'on a récupéré les binaires ou compilé à partir de GitHub et installé les composants sur les serveurs, est de définir les <em>jobs</em> qui seront ensuite activés.</p> <p>Ceci se fait via l'option de menu "Schedule a job", dans laquelle on voit toute la richesse de l'outil.</p> <p>Pour les tests LDAP, on dispose d'une vingtaine de modèle prédéfinis, notamment :</p> <ul><li>Add and Delete : ajout et suppression, utilisé pour les tests d'écriture</li> <li>Basic Bind : connexion simple, sans recherche préalable</li> <li>Basic Search and Bind : connexion après recherche de l'utilisateur ; c'est ce que j'utilise pour tester les mécanismes d'authentification</li> <li>Comprehensive Search : possibilité de mettre plusieurs serveurs, plusieurs filtres et de préciser les attributs retournés</li> <li>Mix load : mélange de Add, Bind, Search, etc</li> </ul><h2>Paramétrage du Search + Bind</h2> <p>Dans la majorité des cas en mode <em>Authentification</em>, celle-ci se passe en 2 étapes :</p> <ul><li>on fait d'abord une recherche de l'utilisateur dans la base, via le RDN (ou un autre attribut)</li> <li>une fois le DN récupéré, on va faire une tentative de connexion avec le mot de passe.</li> </ul><p>Pour tester ceci, on va utiliser différents paramètres (en mode Basic) :</p> <ul><li>Durée du Job</li> <li>Nombre de clients (à savoir que si on n'a pas assez de clients disponibles, le job ne va pas démarrer)</li> <li>Nombre de threads par client</li> <li>Durée de montée en charge / descente de charge</li> <li>Nom et port du serveur LDAP, ainsi que la méthode de sécurité (aucune, StartTLS ou SSL)</li> <li>Bind DN et mot de passe utilisé pour la recherche (généralement, un compte de service)</li> <li>DN de base pour la recherche (par exemple : ou=Users,dc=example,dc=com)</li> <li>Périmètre de recherche (scope = subtree, single-level, base)</li> <li>Search Filter Pattern : le motif de recherche.</li> <li>Mot de passe utilisateur</li> </ul><p>Pour que cela fonctionne, on aura au préalable inséré dans l'annuaire des utilisateurs de tests, avec le même mot de passe, puisque celui-ci est donné dans la configuration.</p> <p>Le motif de recherche LDAP peut être variabilisé. Par exemple, si j'ai généré des utilisateurs avec un uid=userXXXXX (XXXXX = numérique de 1 à 99999), je peux avoir différents motifs pour mon filtre LDAP :</p> <ul><li>(uid=user[1-100000]) : recherche de user1 à user100000 de manière aléatoire</li> <li>(uid=user[1:100000]) : recherche de user1 à user100000 de manière séquentielle</li> </ul><p>Un bouton permet de tester les paramètres (connexion à l'annuaire, existence du Base DN, etc).</p> <p>Une fois le job préparé, on peut l'activer pour qu'il soit traité par les clients. Il passe alors en état "<strong>Running</strong>".</p> <p>Lorsqu'il est terminé, il passe à l'état "<strong>Completed</strong>".</p> <p>On peut dupliquer / cloner un job si on veut le relancer tel quel, ou le modifier pour changer ses paramètres.</p> <h2>Données récupérées</h2> <p>Une fois que le <em>job</em> est terminé, on peut avoir accès aux données recueillies par les clients et centralisées sur le serveur.</p> <p>Les données peuvent être affichées sous forme de graphique, directement sur le serveur, ou être générées sous forme de rapport HTML ou PDF.</p> <p>Le rapport contient pas mal d'informations par défaut :</p> <ul><li>le nom du job, sa description</li> <li>les informations de planification : durée, nombre de clients, nombre de threads</li> <li>paramètres du job</li> <li>les informations d'exécution : date de début et fin, durée, nom des machines clients</li> <li>les résultats des différentes requêtes : nombre, moyenne / seconde, moyenne / intervalle de collecte, ainsi qu'un graphe des données, et la même chose en temps de réponse.</li> <li>répartition des requêtes par statut et temps de réponse.</li> </ul><h2>Autres éléments</h2> <p>Un système de "<em>folders</em>" permet de regrouper ses différents <em>jobs</em> ce qui peut être intéressant pour gérer les séances de tests, soit par type d'annuaire si on en compare plusieurs, soit par type de tests si on fait par exemple changer le nombre de threads.</p> </div> <span rel="sioc:has_creator" class="field field--name-uid field--type-entity-reference field--label-hidden"><span lang="" about="/users/vincentl" typeof="schema:Person" property="schema:name" datatype="">vincentl</span></span> <span property="dc:date dc:created" content="2021-10-13T16:24:59+00:00" datatype="xsd:dateTime" class="field field--name-created field--type-created field--label-hidden">mer 13/10/2021 - 18:24</span> <div class="field field--name-field-categorie field--type-entity-reference field--label-above"> <div class="field__label">Catégorie</div> <div class="field__item"><a href="/cat%C3%A9gorie/autres" hreflang="fr">Autres</a></div> </div> <div class="field field--name-field-tags field--type-entity-reference field--label-above"> <div class="field__label">Tag</div> <div class="field__items"> <div class="field__item"><a href="/tags/ldap" hreflang="fr">ldap</a></div> <div class="field__item"><a href="/tags/benchmark" hreflang="fr">benchmark</a></div> </div> </div> <section class="field field--name-comment-node-blog field--type-comment field--label-hidden comment-wrapper"> <h2 class="title comment-form__title">Ajouter un commentaire</h2> <drupal-render-placeholder callback="comment.lazy_builders:renderForm" arguments="0=node&amp;1=212&amp;2=comment_node_blog&amp;3=comment_node_blog" token="rGeZhG9defyDWatkcDCg4uVhSr1m77C8ZNq7sKOkxhE"></drupal-render-placeholder> </section> Wed, 13 Oct 2021 16:24:59 +0000 vincentl 212 at https://www.vincentliefooghe.net Forgerock OpenDJ / DS - Supprimer les contrôles de syntaxe https://www.vincentliefooghe.net/content/forgerock-opendj-ds-supprimer-les-contr%C3%B4les-syntaxe <span class="field field--name-title field--type-string field--label-hidden">Forgerock OpenDJ / DS - Supprimer les contrôles de syntaxe</span> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><p>Par défaut les nouveaux annuaires LDAP issus des sources OpenDS (tels que OpenDJ / DS chez Forgerock, mais aussi Ping Directory) renforcent les contrôles sur la syntaxe des attributs, le schéma, etc.</p> <p>Ceci empêche par exemple d'avoir un objet avec de multiples classes structurelles non hiérarchiques (par exemple <em>inetorgperson</em> et <em>country</em>).</p> <p>Par contre lorsqu'on importe des données d'un annuaire un peu moins strict (type Sun / Oracle DSEE), on se heurte souvent à des erreurs.</p> <p>La solution la plus propre est de modifier le fichier LDIF pour remettre au carré les données :</p> <ul><li>supprimer / modifier les attributs non conformes</li> <li>modifier le schéma pour éviter les héritages multiples</li> </ul><p>Mais ceci n'est pas toujours faisable.</p> <p>On peut alors relâcher les contrôles effectuer, en utilisant l'utilitaire <em>dsconfig </em>(testé depuis la version OpenDJ 2.6 jusque DS 7) :</p> <pre> #!/bin/bash PORT=5444 HOST=djlyreco BINDPASS="SuperPa$$w0rd" cd /path/to//opendj # Do not check schema bin/dsconfig set-global-configuration-prop --hostname $HOST --port ${PORT} --bindDN "cn=Directory Manager" \ --bindPassword ${BINDPASS} --set check-schema:false --trustAll --no-prompt # Allows multiple structural object classes (warning only) bin/dsconfig set-global-configuration-prop --hostname $HOST --port ${PORT} --bindDN "cn=Directory Manager" \ --bindPassword ${BINDPASS} --set single-structural-objectclass-behavior:warn --trustAll --no-prompt # Allows invalid attribute syntax bin/dsconfig set-global-configuration-prop --hostname $HOST --port ${PORT} \ --bindDN "cn=Directory Manager" --bindPassword ${BINDPASS} --set invalid-attribute-syntax-behavior:warn --trustAll --no-prompt # Allow pre-encoded passwords : pour l'import de compte avec des mots de passe existant bin/dsconfig -p ${PORT} -h $HOST -D "cn=Directory Manager" -w ${BINDPASS} \ set-password-policy-prop --policy-name "Default Password Policy" --set allow-pre-encoded-passwords:true -X -n</pre><p> </p> <p>La dernière ligne permet également d'importer des mots de passe pré-encodés. C'est utile en cas de migration de données entre annuaires, pour garder les mêmes mots de passe.</p> <p> </p> </div> <span class="field field--name-uid field--type-entity-reference field--label-hidden"><span lang="" about="/user/1" typeof="schema:Person" property="schema:name" datatype="">Vincent</span></span> <span class="field field--name-created field--type-created field--label-hidden">mer 09/12/2020 - 11:30</span> <div class="field field--name-field-categorie field--type-entity-reference field--label-above"> <div class="field__label">Catégorie</div> <div class="field__item"><a href="/cat%C3%A9gorie/iam" hreflang="fr">IAM</a></div> </div> <div class="field field--name-field-tags field--type-entity-reference field--label-above"> <div class="field__label">Tag</div> <div class="field__items"> <div class="field__item"><a href="/tags/ldap" hreflang="fr">ldap</a></div> <div class="field__item"><a href="/tags/opendj" hreflang="fr">opendj</a></div> <div class="field__item"><a href="/tags/forgerock" hreflang="fr">forgerock</a></div> </div> </div> <section class="field field--name-comment-node-book field--type-comment field--label-hidden comment-wrapper"> <h2 class="title comment-form__title">Ajouter un commentaire</h2> <drupal-render-placeholder callback="comment.lazy_builders:renderForm" arguments="0=node&amp;1=208&amp;2=comment_node_book&amp;3=comment_node_book" token="FCUJHl0s_eMjKa8Cw3DvkSQUZ310pub5HrSmdbeosj4"></drupal-render-placeholder> </section> Wed, 09 Dec 2020 10:30:28 +0000 Vincent 208 at https://www.vincentliefooghe.net IBM Directory Server : gestion des mots de passe https://www.vincentliefooghe.net/content/ibm-directory-server-gestion-des-mots-passe <span property="dc:title" class="field field--name-title field--type-string field--label-hidden">IBM Directory Server : gestion des mots de passe</span> <div property="content:encoded" class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><p>L'installation par défaut de l'annuaire ISDS ne semble pas "terminée" en ce qui concerne la gestion des mots de passe : pas de politique de mot de passe par défaut, pas d'activation non plus. Et une modification par <em>ldapmodify</em> stocke le mot de passe en clair (tout au moins, il ressort en clair dans un <em>ldapsearch</em>).</p> <h2>Autoriser le changement de mot de passe par l'utilisateur</h2> <p>Par défaut, l'utilisateur ne peut pas modifier lui-même son mot de passe. Par exemple, en utilisant la commande <em>ldapchangepwd</em> renvoie une erreur :</p> <pre> /opt/ibm/ldap/V6.3/bin/ldapchangepwd -D uid=jdoe,ou=people,o=example.com -w secret -n SuperSecret ldap_simple_bind: Error, Password must be changed after reset changing password for entry uid=jdoe,ou=people,o=example.com Insufficient access --- Error, Password may not be modified</pre><p>Pour résoudre ce problème, il faut :</p> <ul><li>ajouter une ACL permettant le changement de mot de passe en mode "Self"</li> <li>permettre le changement de mot de passe par l'utilisateur lui-même dans la politique de mot de passe (qu'il faut créer)</li> </ul><h3>Ajout d'une politique de mot de passe par défaut</h3> <p>On va créer un fichier LDIF qui contient la définition de la politique globale :</p> <pre> dn: cn=pwdpolicy,cn=ibmpolicies objectclass: container objectclass: pwdPolicy objectclass: ibm-pwdPolicyExt objectclass: ibm-pwdGroupAndIndividualPolicies objectclass: top cn: pwdPolicy pwdAttribute: userPassword pwdGraceLoginLimit: 0 pwdLockoutDuration: 0 pwdFailureCountInterval: 0 passwordMaxRepeatedChars: 0 passwordMaxConsecutiveRepeatedChars: 0 pwdMaxAge: 0 pwdMinAge: 0 pwdExpireWarning: 0 passwordMinAlphaChars: 0 passwordMinOtherChars: 0 passwordMinDiffChars: 0 pwdLockout: false pwdAllowUserChange: true pwdMustChange: true pwdSafeModify: false ibm-pwdGroupAndIndividualEnabled: false ibm-pwdPolicy: true pwdCheckSyntax: 1 pwdInHistory: 5 pwdMaxFailure: 3 pwdMinLength: 6</pre><p> </p> <p>Le fichier sera ensuite ajouté à l'annuaire via <em>ldapadd</em> avec un compte administrateur.</p> <h3>Ajout d'une ACL permettant le changement</h3> <p>On va également ajouter une ACL sur l'arborescence qui contient les comptes</p> <pre> dn: ou=people,o=example.com changetype: modify add: aclentry aclentry: access-id:CN=THIS:at.userPassword:rwsc:normal:rsc</pre><p>Et on l'ajoute avec un <em>ldapmodify</em></p> <p>Suite à cela, la modification du mot de passe fonctionne correctement, par l'utilisateur lui-même.</p> <pre> /opt/ibm/ldap/V6.3/bin/ldapchangepwd -D uid=jdoe,ou=people,o=example.com -w secret -n SuperSecret changing password for entry uid=jdoe,ou=people,o=example.com</pre><p>Par contre, si on récupère avec un ldapsearch, la valeur est renvoyée en clair...</p> <pre> /opt/ibm/ldap/V6.3/bin/ldapsearch -D uid=jdoe,ou=people,o=example.com -w SuperSecret -b o=example.com uid=jdoe userpassword uid=jdoe,ou=people,o=example.com userpassword=SuperSecret</pre><h2>Modifier l'algorithme d'encryption</h2> <p>Par défaut, les mots de passe sont chiffrées avec l'algorithme AES256, qui est symétrique. Du coup, le mot de passe est décodé par le moteur de l'annuaire avant d'être affiché.</p> <p>Il vaut mieux donc utiliser un algorithme asymétrique type SSHA ou SHA2-x.</p> <pre> dn: cn=configuration changetype: modify replace: ibm-slapdPwEncryption ibm-slapdPwEncryption: ssha</pre><p>Si on redémarre l'annuaire (ou si on utilise la commande <em>idsldapexop</em>), on voit que le mot de passe est alors stocké de manière irréversible.</p> <pre> /opt/ibm/ldap/V6.3/bin/ldapchangepwd -D uid=jdoe,ou=people,o=example.com -w SuperSecret-n Pa55word changing password for entry uid=jdoe,ou=people,o=example.com /opt/ibm/ldap/V6.3/bin/ldapsearch -D uid=jdoe,ou=people,o=example.com -w SuperSecret -b o=example.com uid=jdoe userpassword uid=jdoe,ou=people,o=example.com userpassword={SSHA}4EqpfNQFq1aWqT+ouD5bEKFPyrIiFSd7AEQORENiet0xYiqgJLi73Q==</pre><h2>Import de mots de passe hachés</h2> <p>Si on migre les données d'un autre annuaire, via un fichier LDIF par exempe, avec un mot de passe chiffré dans un autre algorithme, ITDS utilise alors cet algorithme, et pas celui défini par défaut.</p> <p><strong>Attention</strong>, si on a activé l'option <em>pwdMustChange</em>, dans la politique de mot de passe, l'utilisateur sera obligé de modifier son mot de passe à la première connexion.</p> <p>Ce paramètre est dynamique, on peut donc le repasser à False si nécessaire.</p> <p> </p> <p> </p> <p> </p> <p> </p> <p> </p> </div> <span rel="sioc:has_creator" class="field field--name-uid field--type-entity-reference field--label-hidden"><span lang="" about="/users/vincentl" typeof="schema:Person" property="schema:name" datatype="">vincentl</span></span> <span property="dc:date dc:created" content="2020-04-13T15:42:22+00:00" datatype="xsd:dateTime" class="field field--name-created field--type-created field--label-hidden">lun 13/04/2020 - 17:42</span> <div class="field field--name-field-categorie field--type-entity-reference field--label-above"> <div class="field__label">Catégorie</div> <div class="field__item"><a href="/cat%C3%A9gorie/iam" hreflang="fr">IAM</a></div> </div> <div class="field field--name-field-tags field--type-entity-reference field--label-above"> <div class="field__label">Tag</div> <div class="field__items"> <div class="field__item"><a href="/tags/itds" hreflang="fr">itds</a></div> <div class="field__item"><a href="/tags/ibm" hreflang="fr">ibm</a></div> <div class="field__item"><a href="/tags/ldap" hreflang="fr">ldap</a></div> </div> </div> <section class="field field--name-comment-node-blog field--type-comment field--label-hidden comment-wrapper"> <h2 class="title comment-form__title">Ajouter un commentaire</h2> <drupal-render-placeholder callback="comment.lazy_builders:renderForm" arguments="0=node&amp;1=200&amp;2=comment_node_blog&amp;3=comment_node_blog" token="CguhFyApblCiIABXQL6ywDk-91Pf663FSaAfAxz5ikg"></drupal-render-placeholder> </section> Mon, 13 Apr 2020 15:42:22 +0000 vincentl 200 at https://www.vincentliefooghe.net Evaluation des ACI LDAP dans les annuaires Sun / Oracle / Ping / Forgerock https://www.vincentliefooghe.net/content/evaluation-des-aci-ldap-dans-les-annuaires-sun-oracle-ping-forgerock <span property="dc:title" class="field field--name-title field--type-string field--label-hidden">Evaluation des ACI LDAP dans les annuaires Sun / Oracle / Ping / Forgerock</span> <div property="content:encoded" class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item">Beaucoup d'annuaires ont des ACI compatibles avec celles de l'annuaire Sun (issu des sources de Netscape) :<ul><li>Sun / Oracle DSEE</li><li>389DS / Red Hat Directory Server</li><li>Oracle OUD</li><li>Sun OpenDS / Wren DS</li><li>Forgerock OpenDJ</li><li>Ping Directory.</li></ul>Dans ces annuaires, les ACI peuvent être positionnées directement sur les objets eux-mêmes ou sur des objets plus proches de la racine.Le mécanisme d'évaluation est globalement le suivant :<ul><li>On traverse le DIT depuis la racine de l'annuaire jusqu'à l'entrée que l'on tente d'accéder</li><li>On collecte toutes les ACI rencontrées sur le chemin</li><li>Les ACI collectées sont séparées en 2 paquets : <strong>DENY</strong> (refuser) et <strong>ALLOW</strong> (autoriser)</li><li>Chaque paquet est trier pour que les ACI les plus simples/faciles/rapides sont évaluées en premier</li><li>Le paquet "DENY" est évalué en premier. Si une ACI correspond, l'analyse s'arrête et la requête est refusée</li><li>Si on arrive à la fin du paquet "DENY", on traite le paquet "ALLOW"</li><li>Si une règle ACI ALLOW est trouvée, alors l'analyse s'arrête et l'accès est autorisé</li><li>Si à la fin du traitement du paquet "ALLOW" aucune règle ne correspond, c'est un accès implicite "DENY". L'accès est refusé.</li></ul>On peut donc en déduire les règles suivantes :<ul><li>le placement d'une ACI affecte uniquement son périmètre</li><li>l'ordre d'évaluation est indéterminé. Une règle ACI plus "proche" d'une entrée n'est pas plus prioritaire que celle tout en haut du DIT</li><li>le fait de placer une ACI proche d'une entrée permet seulement de s'assurer que l'ACI ne sera évaluée que lorsqu'on tente d'accéder à la donnée (amélioration des performances)</li><li>par défaut, l'annuaire ne donne pas accès (au moins sur les nouveaux, type Forgerock, Ping). Les règles "<em>DENY</em>" doivent être très rares, et à manier avec précaution (puisqu'elles sont évaluées en premier).</li></ul> </div> <span rel="sioc:has_creator" class="field field--name-uid field--type-entity-reference field--label-hidden"><span lang="" about="/users/vincentl" typeof="schema:Person" property="schema:name" datatype="">vincentl</span></span> <span property="dc:date dc:created" content="2018-10-17T11:34:06+00:00" datatype="xsd:dateTime" class="field field--name-created field--type-created field--label-hidden">mer 17/10/2018 - 13:34</span> <div class="field field--name-field-categorie field--type-entity-reference field--label-above"> <div class="field__label">Catégorie</div> <div class="field__item"><a href="/cat%C3%A9gorie/iam" hreflang="fr">IAM</a></div> </div> <div class="field field--name-field-tags field--type-entity-reference field--label-above"> <div class="field__label">Tag</div> <div class="field__items"> <div class="field__item"><a href="/tags/ldap" hreflang="fr">ldap</a></div> <div class="field__item"><a href="/tags/acl" hreflang="fr">acl</a></div> </div> </div> <section class="field field--name-comment-node-blog field--type-comment field--label-hidden comment-wrapper"> </section> Wed, 17 Oct 2018 11:34:06 +0000 vincentl 195 at https://www.vincentliefooghe.net https://www.vincentliefooghe.net/content/evaluation-des-aci-ldap-dans-les-annuaires-sun-oracle-ping-forgerock#comments Migration Sun DSEE vers un autre annuaire LDAP https://www.vincentliefooghe.net/content/migration-sun-dsee-vers-un-autre-annuaire-ldap <span property="dc:title" class="field field--name-title field--type-string field--label-hidden">Migration Sun DSEE vers un autre annuaire LDAP</span> <div property="content:encoded" class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><p>Suite au rachat (déjà ancien) de Sun par Oracle, l'annuaire LDAP Sun DSEE, devenu Oracle DSEE depuis, arrive en fin de support. Ce produit a eu ses beaux jours en entreprise, à l'époque c'était probablement l'un des meilleurs, capable de gérer des centaines de milliers d'entrées, avec une architecture assez simple.</p> <p>Depuis, pas mal de concurrents sont arrivés, et les entreprises se lancent vers des migrations d'annuaires LDAP Sun / Oracle DSEE vers d'autres solutions plus récentes, soit sur un modèle Open Source (OpenLDAP généralement) ou propriétaires. La migration d'annuaire LDAP peut se faire assez rapidement.</p> <p>Les points d'attention sont les éléments non couverts par le standard LDAP, à savoir :</p> <ul><li>Formalisme du schéma (attributs et classes d'objets)</li> <li>Réplication</li> <li>ACI</li> <li>Privilèges et droits des comptes</li> <li>Politiques de mots de passe</li> </ul><p>Les données elles-mêmes peuvent être <em>relativement</em> facilement, avec un export et import LDIF. Selon la méthode utilisée (<em>ldapsearch</em> ou fonction <em>export</em> de l'annuaire), on peut ou non récupérer des attributs opérationnels.</p> <h2>Schéma de données</h2> <p>Sun DSEE permet de gérer des OID alphanumériques, par exemple :</p> <pre>attributeTypes: (sitename-oid NAME 'sitename' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'user defined' ) </pre><p>Si on veut être conforme aux RFC - par exemple dans le cas de OpenLDAP - il faut utiliser des <em>OID</em> numériques. La bonne pratique demande aussi d'utiliser sa propre classe d'OID avec une demande auprès de l'IANA. Dans ce cas, l'OID serait, par exemple :</p> <pre>attributeTypes: (1.3.6.1.4.1.31488.2.3.51 NAME 'sitename' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'user defined' ) </pre><p>A part cela, la syntaxe elle-même est différente entre Sun DSEE et OpenLDAP. Les objets du schéma OpenLDAD sont préfixés par <em>olc</em></p> <h3>Exemple Sun DSEE</h3> <p>Les éléments spécifique du schéma (attributs et classes d'objets) sont définis dans le fichier <code>[DIRECTORY_HOME]/config/schema/99-user.ldif</code>, au format suivant :</p> <pre>dn: cn=schema objectClass: top objectClass: ldapSubentry objectClass: subschema cn: schema attributeTypes: (sitename-oid NAME 'sitename' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'user defined' ) objectClasses: (1.3.6.1.4.1.31488.2.4.18 NAME 'ocSite' SUP top STRUCTURAL MUST (cn $ description) MAY ( sitename $ c $ l $ telephonenumber ) X-ORIGIN 'user defined' ) </pre><p>Dans le cas d'une migration vers Forgerock, Ping Directory (et généralement tous les annuaires issus des sources de <em>OpenDS</em>), on peut réutiliser la même définition pour les attributs et classes d'objets.</p> <h3>Exemple avec OpenLDAP</h3> <p>OpenLDAP utilise une syntaxe un peu différente, en dehors des OID numériques. On doit notamment préciser le DN complet pour l'objet du schéma. Par exemple :</p> <pre>dn: cn=myschema,cn=schema,cn=config objectClass: olcSchemaConfig cn: myschema olcattributeTypes: ( 1.3.6.1.4.1.31488.2.3.110 NAME 'sitename' DESC 'Site name' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE) olcobjectClasses: ( 1.3.6.1.4.1.31488.2.4.18 NAME 'ocSite' SUP top STRUCTURAL MUST (cn $ description) MAY ( sitename $ c $ l $ telephonenumber ) ) </pre><h3>Différences sur des classes d'objet issues du standard</h3> <p>Suite à une migration à partir de Sun DSEE, je me suis aperçu que Ping Directory &amp; Forgerock définissent également des types différents pour certaines classes d'objet, notamment celles liées aux objets Posix :</p> <pre>objectClasses: ( 1.3.6.1.1.1.2.0 NAME 'posixAccount' SUP top STRUCTURAL DESC 'Abstraction of an account with POSIX attributes' MUST ( cn $ uid $ uidNumber $ gidNumber $ homeDirectory ) MAY ( authPassword $ userPassword $ loginShell $ gecos $ description ) X-ORIGIN 'draft-howard-rfc2307bis' ) objectClasses: ( 1.3.6.1.1.1.2.2 NAME 'posixGroup' SUP top STRUCTURAL DESC 'Abstraction of a group of accounts' MUST gidNumber MAY ( cn $ authPassword $ userPassword $ memberUid $ description ) X-ORIGIN 'draft-howard-rfc2307bis' ) </pre><p>Si dans les données, on utilise ce type d'objets, il peut y avoir des modifications à apporter, sachant qu'il est recommandé d'activer les contrôles de cohérence / validité du schéma lors des imports initiaux, pour avoir une meilleur qualité de données.</p> </div> <span rel="sioc:has_creator" class="field field--name-uid field--type-entity-reference field--label-hidden"><span lang="" about="/users/vincentl" typeof="schema:Person" property="schema:name" datatype="">vincentl</span></span> <span property="dc:date dc:created" content="2018-07-29T09:47:52+00:00" datatype="xsd:dateTime" class="field field--name-created field--type-created field--label-hidden">dim 29/07/2018 - 11:47</span> <div class="field field--name-field-categorie field--type-entity-reference field--label-above"> <div class="field__label">Catégorie</div> <div class="field__item"><a href="/cat%C3%A9gorie/iam" hreflang="fr">IAM</a></div> </div> <div class="field field--name-field-tags field--type-entity-reference field--label-above"> <div class="field__label">Tag</div> <div class="field__items"> <div class="field__item"><a href="/tags/ldap" hreflang="fr">ldap</a></div> <div class="field__item"><a href="/tags/openldap" hreflang="fr">openldap</a></div> <div class="field__item"><a href="/tags/sun-dsee" hreflang="fr">Sun DSEE</a></div> <div class="field__item"><a href="/tags/forgerock" hreflang="fr">forgerock</a></div> <div class="field__item"><a href="/tags/ping-directory" hreflang="fr">ping directory</a></div> </div> </div> <section class="field field--name-comment-node-blog field--type-comment field--label-hidden comment-wrapper"> </section> Sun, 29 Jul 2018 09:47:52 +0000 vincentl 193 at https://www.vincentliefooghe.net LDAP : les types de groupes https://www.vincentliefooghe.net/content/ldap-les-types-groupes <span property="dc:title" class="field field--name-title field--type-string field--label-hidden">LDAP : les types de groupes</span> <div property="content:encoded" class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><p>Les annuaires LDAP sont principalement utilisés pour gérer 2 types d'objets :</p> <ul><li>les comptes utilisateurs (qui vont permettre une authentification centralisée)</li> <li>des groupes d'utilisateurs (qui vont permettre une gestion de droits).</li> </ul><p>D'autres objets annexes sont souvent ajoutés, qui ont un rôle de <em>"listes de valeurs"</em>.</p> <p>Nous allons voir dans cet article les différents types de groupes qui peuvent être utilisés, sachant que selon les RFC LDAP 4519, seuls les premiers sont vraiment standardisés.</p> <h2>Groupes statiques</h2> <p>A l'origine, les groupes statiques, définis par les classes d'objet <em>groupOfNames</em> et <em>groupOfUniqueNames</em> sont juste une liste de membres (donnés par leur DN).</p> <p>Dans un groupe de type <em>groupOfNames</em>, l'attribut utilisé est <em>member</em>, et on peut avoir plusieurs fois le même membre.</p> <p>Dans un groupe de type <em>groupOfUniqueNames</em>, l'attribut utilisé est <em>uniqueMember</em>, et on peut avoir une seule occurence pour chaque membre.</p> <p>Exemple :</p> <pre><code>dn: cn=firstGroup,ou=Groups,dc=example,dc=com objectclass: top objectclass: groupofnames member: uid=john.doe,ou=People,dc=example,dc=com cn: firstGroup </code></pre><p>On peut donc récupérer facilement tous les membres d'un groupe statique, en listant les valeurs de l'attribut <em>uniqueMember</em> ou <em>member</em>, selon le cas. De même, pour connaître les groupes affectés à un utilisateur, on utilisera une recherche du type :</p> <pre><code>ldapsearch -b "dc=example,dc=com" -s sub "(|(&amp;(objectClass=groupOfNames)(member=uid=john.doe,ou=People,dc=example,dc=com)) \ (&amp;(objectClass=groupOfUniqueNames) (uniqueMember=uid=john.doe,ou=People,dc=example,dc=com)) </code></pre><h3>Avantages</h3> <p>C'est le seul type de groupe standardisé, et qui peut donc être utilisé par la plupart des applications ou équipements. Certains équipements réseaux par exemple peuvent utiliser les groupes pour valider les habilitations.</p> <h3>Inconvénients</h3> <p>Le principal inconvénient est la maintenance de ces groupes, puisque l'ajout ou le retrait des membres se fait de manière unitaire. Par défaut il n'y a pas de contrôle de cohérence, on peut donc ajouter comme membre d'un groupe un DN inexistant ; et si on supprime un utilisateur, son DN peut encore apparaître dans la liste des membres.</p> <p><strong>Note</strong> : certains annuaires utilisent un <em>plugin</em> d'intégrité référentiel, qui permet, à la suppression de l'entrée utilisateur, d'aller supprimer le DN correspondant des membres des groupes.</p> <h2>Groupes dynamiques</h2> <p>Il n'y a pas de définition formelle de type RFC pour les groupes dynamiques. L'implémentation dépend du fournisseur d'annuaire. Sur OpenLDAP par exemple, on trouve un <em>overlay</em> <strong>dynlist</strong> qui permet d'apporter cette fonctionnalité.</p> <p>Sur les annuaires tels que Sun/Oracle DSEE, OpenDS et ses descendants (Forgerock OpenDJ, Oracle OUD, UnboundID/Ping Drectory), on utilise un groupe de type <em>groupOfUrls</em>.</p> <p>Les groupes dynamiques utilisent un attribut <em>memberURL</em> qui permet de définir une requête LDAP, de la forme ldap:///BASE_DN?ATTRIBUTS?SCOPE?FILTRE.</p> <p>Exemples de filtres :</p> <pre><code>ldap:///ou=People,dc=example,dc=com?uid,cn,sn?sub?(departmentNumber=IT) </code></pre><p>Recherche à partir de la base DN <code>ou=People,dc=example,dc=com</code>, avec un <em>scope</em> de type <code>subtree</code>, les utilisateurs qui sont dans le département IT, et récupère uniquement les attributs <em>uid, sn</em> et <em>cn</em>.</p> <p>Exemple :</p> <pre><code>dn: cn=IT-Staff,ou=Groups,dc=example,dc=com objectclass: top objectclass: groupOfURLs cn: IT-staff memberURL: ldap:///ou=People,dc=example,dc=com??sub?(departmentNumber=IT) </code></pre><h3>Avantages</h3> <p>Une fois que le filtre est défini, la gestion des membres est automatique, puisque basée sur les attributs de l'utilisateur.</p> <h3>Inconvénients</h3> <p>Par défaut, ce sont les clients qui doivent interpréter la requête LDAP présente dans l'attribut <em>memberURL</em>. On ne peut pas avoir la liste des membres rien qu'en faisant une requête sur le groupe, et on ne peut pas non plus avoir la liste des groupes d'un utilisateur en cherchant son DN dans les membres.</p> <p>Pour pallier ce problème, la plupart des annuaires qui implèmentent les groupes dynamiques gèrent aussi un attribut virtuel <strong>isMemberOf</strong>, qui contient la liste des groupes dont l'utilisateur est membre.</p> <h2>Exemples</h2> <p>Si on injecte le contenu du fichier LDIF suivant dans un annuaire :</p> <pre><code>dn: ou=staff,ou=people,dc=example,dc=com objectClass: organizationalunit objectClass: top ou: staff dn: uid=john.doe,ou=staff,ou=people,dc=example,dc=com givenName: John objectClass: person objectClass: inetOrgPerson objectClass: organizationalPerson objectClass: top uid: john.doe cn: John Doe sn: Doe departmentNumber: Finance dn: uid=elliot.alderson,ou=staff,ou=people,dc=example,dc=com givenName: Elliot objectClass: person objectClass: inetOrgPerson objectClass: organizationalPerson objectClass: top uid: elliot.alderson cn: Elliot Alderson sn: Alderson departmentNumber: IT dn: uid=angela.moss,ou=staff,ou=people,dc=example,dc=com givenName: Angela objectClass: person objectClass: inetOrgPerson objectClass: organizationalPerson objectClass: top uid: angela.moss cn: Angela Moss sn: Moss departmentNumber: IT dn: ou=Groups,dc=example,dc=com objectClass: organizationalunit objectClass: top ou: Groups dn: cn=Staff,ou=Groups,dc=example,dc=com objectclass: top objectclass: groupofnames member: uid=john.doe,ou=staff,ou=people,dc=example,dc=com member: uid=elliot.alderson,ou=staff,ou=people,dc=example,dc=com member: uid=angela.moss,ou=staff,ou=people,dc=example,dc=com cn: Staff dn: cn=IT-Staff,ou=Groups,dc=example,dc=com objectclass: top objectclass: groupOfURLs cn: IT-staff memberURL: ldap:///ou=People,dc=example,dc=com??sub?(departmentNumber=IT) </code></pre><p>La recherche des groupes liés à Elliot Anderson donne le résultat suivant :</p> <pre><code>ldapsearch -b ou=groups,dc=example,dc=com member=uid=elliot.alderson,ou=staff,ou=people,dc=example,dc=com dn dn: cn=Staff,ou=Groups,dc=example,dc=com </code></pre><p>On ne trouve pas le groupe dynamique lié. Par contre, si on utilise l'attribut <em>isMemberOf</em>, on va avoir tous les groupes :</p> <pre><code>ldapsearch -b ou=people,dc=example,dc=com uid=elliot.alderson ismemberof dn: uid=elliot.alderson,ou=staff,ou=people,dc=example,dc=com ismemberof: cn=Staff,ou=Groups,dc=example,dc=com ismemberof: cn=IT-Staff,ou=Groups,dc=example,dc=com </code></pre><h2>Groupes statiques virtuels</h2> <p>Pour tenter de concilier les avantages des deux types de groupes, certains annuaires implémentent un nouveau type de groupe : le groupe Virtuel Static <em>Virtual Static Groups</em>).</p> <p>Les groupes virtuels statiques utilisent une classe d'objet spécifique, <em>ds-virtual-static-group</em>, et font référence à un groupe dynamique (qu'il faudra donc créer auparavant).</p> <p>Exemple :</p> <pre><code>dn: cn=VS-IT-staff,ou=Groups,dc=example,dc=com cn: VS-IT-staff objectclass: top objectclass: groupOfNames objectclass: ds-virtual-static-group ds-target-group-dn: cn=IT-Staff,ou=Groups,dc=example,dc=com </code></pre><p>Si on ajoute le groupe, on le récupère dans l'attribut <em>isMemberOf</em> de l'utilisateur. Par exemple ;</p> <pre><code>/opt/opendj/bin/ldapsearch -b ou=staff,ou=people,dc=example,dc=com uid=elliot.alderson ismemberof dn: uid=elliot.alderson,ou=staff,ou=people,dc=example,dc=com ismemberof: cn=Staff,ou=Groups,dc=example,dc=com ismemberof: cn=IT-Staff,ou=Groups,dc=example,dc=com ismemberof: cn=VS-IT-staff,ou=Groups,dc=example,dc=com </code></pre><p>Par contre par défaut le groupe virtuel statique ne donne pas la liste de ses membres :</p> <pre><code>ldapsearch -b ou=Groups,dc=example,dc=com cn=VS-IT-staff dn: cn=VS-IT-staff,ou=Groups,dc=example,dc=com cn: VS-IT-staff ds-target-group-dn: cn=IT-Staff,ou=Groups,dc=example,dc=com objectClass: groupOfNames objectClass: ds-virtual-static-group objectClass: top </code></pre><h3>Pour récupérer la liste des membres</h3> <p>La récupération de la liste des membres d'un groupe virtuel statique se fait à la volée, et peut donc être consommatrice de ressources, surtout sur de grosses volumétrie. La fonctionnalité est désactivée par défaut. On peut l'activer avec l'utilitaire <strong>dsconfig</strong> :</p> <pre><code>dsconfig set-virtual-attribute-prop --name "Virtual Static member" --set allow-retrieving-membership:true </code></pre><p>Si on recherche directement le groupe , on a bien la liste des membres :</p> <pre><code>ldapsearch -b ou=Groups,dc=example,dc=com cn=VS-IT-staff dn: cn=VS-IT-staff,ou=Groups,dc=example,dc=com member: uid=elliot.alderson,ou=staff,ou=people,dc=example,dc=com member: uid=angela.moss,ou=staff,ou=people,dc=example,dc=com cn: VS-IT-staff ds-target-group-dn: cn=IT-Staff,ou=Groups,dc=example,dc=com objectClass: groupOfNames objectClass: ds-virtual-static-group objectClass: top member: uid=elliot.alderson,ou=staff,ou=people,dc=example,dc=com member: uid=angela.moss,ou=staff,ou=people,dc=example,dc=com </code></pre><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Ce type de groupe peut donc être utilisé si une application cliente veur récupérer la liste des membres, à partir du nom du groupe. Par contre, si on fait une recherche sur les membres, le groupe n'apparaît pas non plus :</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> </p> <pre style="margin: 0px; text-indent: 0px;">ldapsearch -b ou=groups,dc=example,dc=com member=uid=elliot.alderson,ou=staff,ou=people,dc=example,dc=com dn dn: cn=Staff,ou=Groups,dc=example,dc=com</pre><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> </p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Seul l'attribut <em>isMemberOf</em> contient l'ensemble des groupes affectés à la personne.</p> <style type="text/css"> <!--/*--><![CDATA[/* ><!--*/ <!--/*--><![CDATA[/* ><!--*/ p, li { white-space: pre-wrap; } /*--><!]]]]><![CDATA[>*/ /*--><!]]>*/ </style><pre><code> </code></pre></div> <span rel="sioc:has_creator" class="field field--name-uid field--type-entity-reference field--label-hidden"><span lang="" about="/users/vincentl" typeof="schema:Person" property="schema:name" datatype="">vincentl</span></span> <span property="dc:date dc:created" content="2018-04-30T09:20:07+00:00" datatype="xsd:dateTime" class="field field--name-created field--type-created field--label-hidden">lun 30/04/2018 - 11:20</span> <div class="field field--name-field-categorie field--type-entity-reference field--label-above"> <div class="field__label">Catégorie</div> <div class="field__item"><a href="/cat%C3%A9gorie/iam" hreflang="fr">IAM</a></div> </div> <div class="field field--name-field-tags field--type-entity-reference field--label-above"> <div class="field__label">Tag</div> <div class="field__items"> <div class="field__item"><a href="/tags/ldap" hreflang="fr">ldap</a></div> <div class="field__item"><a href="/tags/ping-directory" hreflang="fr">ping directory</a></div> <div class="field__item"><a href="/tags/opendj" hreflang="fr">opendj</a></div> </div> </div> <section class="field field--name-comment-node-blog field--type-comment field--label-hidden comment-wrapper"> </section> Mon, 30 Apr 2018 09:20:07 +0000 vincentl 192 at https://www.vincentliefooghe.net OpenDJ : mise en place du suivi des connexions https://www.vincentliefooghe.net/content/opendj-mise-place-du-suivi-des-connexions <span class="field field--name-title field--type-string field--label-hidden">OpenDJ : mise en place du suivi des connexions</span> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><p>Par défaut, il n'est pas possible de déterminer la date de dernière connexion réussie sur un annuaire LDAP (last login time). Seules les erreurs de connexion peuvent être détectées dans les politiques de mots de passe.</p> <p>Parfois cependant, il est intéressant de connaître la date de dernière connexion, afin de pouvoir supprimer - ou bloquer - des comptes inutilisés depuis plusieurs mois.</p> <p>Certains annuaire permettent de modifier les politiques de mots de passe pour tracer les connexions réussies, mais ceci a un impact sur les authentifications. En effet, à chaque authentification réussie, l'annuaire doit écrire la date de connexion sur l'objet utilisateur. On passe donc d'une suite d'opérations <em>search and bind</em> à une suite <em>search and bind and mod</em>.</p> <p>Quel est donc l'impact de ce suivi sur les performances d'un annuaire ? C'est l'objet de ce test, réalisé sur un annuaire LDAP Forgerock Opendj (DS 5.5).</p> <h2>Configuration utilisée</h2> <p>La configuration utilisée est la suivante :</p> <ul><li>2 vCPU Intel(R) Xeon(R) CPU E5-2698 v3 @ 2.30GHz</li> <li>16 Go de RAM</li> </ul><p>Le jeu de test est constitué d'un fichier LDIF de 481 Mo, comprenant 220 000 entrées utilisateur.</p> <p>Parmi ces 220 000 entrées, 50 000 sont situées dans une OU (<em>organizational unit</em>) spécifique : ou=People,ou=FR,o=example.</p> <h2>Politique de mots de passe par défaut</h2> <p>La politique de mot de passe par défaut est utilisée, avec le chargement des entrées.</p> <pre><code>Property : Value(s) ------------------------------------------:------------------------------------ account-status-notification-handler : - allow-expired-password-changes : false allow-multiple-password-values : false allow-pre-encoded-passwords : false allow-user-password-changes : true default-password-storage-scheme : Salted SHA-512 deprecated-password-storage-scheme : - expire-passwords-without-warning : false force-change-on-add : false force-change-on-reset : false grace-login-count : 0 idle-lockout-interval : 0 s java-class : org.opends.server.core.PasswordPolicyFactory last-login-time-attribute : - last-login-time-format : - lockout-duration : 0 s lockout-failure-count : 0 lockout-failure-expiration-interval : 0 s max-password-age : 25 w 5 d max-password-reset-age : 0 s min-password-age : 0 s password-attribute : userPassword password-change-requires-current-password : false password-expiration-warning-interval : 5 d password-generator : Random Password Generator password-history-count : 5 password-history-duration : 0 s password-validator : Length-Based Password Validator previous-last-login-time-format : - require-change-by-time : - require-secure-authentication : false require-secure-password-changes : false skip-validation-for-administrators : false state-update-failure-policy : reactive </code></pre><h2>Outils de benchmark</h2> <p>Les tests sont lancés avec les utilitaires <em>authrate</em> et <em>searchrate</em>, qui sont intégrés aux binaires de l'annuaire.</p> <p>Pour la recherche :</p> <p><style type="text/css"> <!--/*--><![CDATA[/* ><!--*/ <!--/*--><![CDATA[/* ><!--*/ p, li { white-space: pre-wrap; } /*--><!]]]]><![CDATA[>*/ /*--><!]]>*/ </style></p> <pre style="margin: 0px; text-indent: 0px;">/opt/opendj/bin/searchrate -h 10.150.29.161 -p 1389 -D 'uid=user.1,ou=people,ou=fr,o=example' -w password -F -c 10 -b o=example -m 300000 -g 'rand(100,49000)' '(uid=user.%d)'</pre><p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> </p> <p>Pour les authentifications, en mode search + bind :</p> <pre><code>/opt/opendj/bin/authrate -h 10.150.29.161 -p 1389 -D '%2$s' -w password -f -c 10 -b ou=people,ou=fr,o=example -s sub -m 300000 -g 'rand(100,49000)' '(uid=user.%d)' </code></pre><h2>Procédure de tests</h2> <p>La procédure de tests est la suivante :</p> <ul><li>démarrage de l'annuaire</li> <li>lancement d'un premier test de type <em>searchrate</em>, qui permet de cacher les entrées en RAM</li> <li>lancement d'un test d'authentification avec <em>authrate</em> en mode search + bind</li> </ul><h2>Mesures sans suivi de la date de dernière connexion</h2> <p>Avec le paramétrage par défaut, on obtient un débit moyen de 4283 authentifications par seconde, avec un temps de réponse moyen de 2.131 millisecondes.</p> <pre><code>------------------------------------------------------------------------------ Throughput Response Time (ops/second) (milliseconds) recent average recent average 99.9% 99.99% 99.999% err/sec bind time % ------------------------------------------------------------------------------ 3901.6 3907.1 2.573 2.573 25.304 162.729 167.620 0.0 44.4 4186.4 4047.8 2.372 2.469 26.546 166.949 195.819 0.0 46.6 4540.4 4212.9 2.183 2.365 23.388 166.223 195.819 0.0 44.2 4624.0 4315.7 2.147 2.307 22.435 162.729 195.819 0.0 42.6 4609.7 4374.6 2.156 2.275 22.083 160.540 172.100 0.0 43.0 4663.1 4422.7 2.130 2.250 21.634 158.399 172.100 0.0 42.5 4765.9 4471.7 2.088 2.225 21.431 154.617 172.100 0.0 42.8 4764.9 4508.4 2.089 2.207 20.982 141.395 172.100 0.0 42.0 4864.1 4547.9 2.050 2.188 21.024 39.778 169.393 0.0 42.2 4811.6 4574.2 2.077 2.177 20.934 34.832 169.393 0.0 42.0 4777.0 4592.6 2.091 2.169 20.525 32.932 169.393 0.0 41.8 4825.5 4611.9 2.072 2.160 20.090 32.724 169.393 0.0 41.9 4101.4 4572.6 1.898 2.142 19.807 32.213 169.393 0.0 41.7 530.8 4283.0 0.869 2.131 19.703 32.118 167.620 0.0 41.0 </code></pre><p>La CPU est utilisée à 90 % environ sur le serveur cible (qui dispose de 2 vCPU).</p> <h2>Mise en place du suivi du <em>last login time</em></h2> <h3>Création d'un attribut spécifique</h3> <p>La mise en place du suivi demande tout d'abord de créer un attribut qui sera utilisé pour stocker la date de dernière connexion. La documentation donne justement un exemple de politique de mots de passe qui met en oeuvre le suivi.</p> <pre><code>dn: cn=schema changetype: modify add: attributeTypes attributeTypes: ( lastLoginTime-oid NAME 'lastLoginTime' DESC 'Last time the user logged in' EQUALITY generalizedTimeMatch ORDERING generalizedTimeOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation X-ORIGIN 'OpenDJ example documentation' ) </code></pre><p>On ajoute l'attribut au schéma via la commande <em>ldapmodify</em> :</p> <pre><code>ldapmodify \ --hostname localhost \ --port 1389 \ --bindDN "cn=Directory Manager" \ --bindPassword password \ lastLoginTime.ldif </code></pre><h3>Création d'une politique de mots de passe spécifique</h3> <p>Si on veut cibler certains comptes utilisateurs, on peut créer une politique de mots de passe spécifiquement pour cet usage :</p> <pre><code>/opt/opendj/bin/dsconfig \ create-password-policy \ --hostname localhost --port 4444 \ --bindDN "cn=Directory Manager" \ --bindPassword password \ --policy-name "Track Last Login Time" \ --type password-policy \ --set default-password-storage-scheme:"Salted SHA-512" \ --set password-attribute:userPassword \ --set last-login-time-attribute:lastLoginTime \ --set last-login-time-format:"yyyyMMddHH'Z'" \ --trustAll \ --no-prompt </code></pre><h3>Modification de la politique de mots de passe</h3> <p>On peut créer une nouvelle politique de mots de passe, ou modifier la politique existante. Dans ce cas, la commande à utiliser est la suivante :</p> <pre><code>/opt/opendj/bin/dsconfig set-password-policy-prop \ --policy-name Default\ Password\ Policy \ --set last-login-time-attribute:lastLoginTime \ --set last-login-time-format:"yyyyMMddHH'Z'" \ --hostname localhost \ --port 4444 \ --bindDn cn=Directory\ Manager \ --bindPassword password \ --trustAll \ --no-prompt </code></pre><h2>Test sur une entrée</h2> <p>Si on fait une requête avec un utilisateur en se connectant, on peut ensuite récupérer la date de dernière connexion sur son entrée, à condition de disposer des droits adéquats.</p> <p>Par exemple :</p> <pre><code>ldapsearch -x -h localhost -p 1389 -D 'cn=Directory Manager' -w password -b o=example '(uid=user.2)' lastLoginTime dn: uid=user.2,ou=People,ou=FR,o=example lastLoginTime: 2017121909Z </code></pre><p>On constate que la date est bien au format déclaré, c'est à dire comprenant l'année, le mois, le jour et l'heure. En effet, il n'est pas nécessaire de suivre les connexions à la minute près.</p> <h2>Mesures AVEC suivi de la date de dernière connexion</h2> <p>Avec le nouveau paramétrage, incluant la mise à jour de la dernière date de connexion, on obtient un débit maximum de 2860 authentifications par seconde en moyenne, avec un temps de réponse moyen de 3.382 millisecondes.</p> <p>La charge CPU sur le serveur d'annuaire oscille entre 50 et 95%, avec des I/O wait.</p> <p>On a bien un impact assez fort, avec notamment des phases pendant laquelle l'annuaire est en I/O wait, révélateur des mises à jour effectuées sur les entrées.</p> <pre><code>------------------------------------------------------------------------------ Throughput Response Time (ops/second) (milliseconds) recent average recent average 99.9% 99.99% 99.999% err/sec bind time % ------------------------------------------------------------------------------ 1570.3 1573.1 6.421 6.421 152.833 177.026 177.026 0.0 63.6 2308.4 1942.2 4.325 5.170 53.701 176.974 177.026 0.0 57.0 2479.4 2122.0 4.023 4.722 49.889 165.267 177.026 0.0 53.3 1025.2 1847.4 3.712 4.581 48.670 165.267 177.026 0.0 51.6 0.0 1477.0 - 4.581 48.670 165.267 177.026 0.0 NaN 1013.4 1399.8 25.871 7.149 50.589 11195.648 11204.023 0.0 93.5 2996.8 1627.5 3.332 6.147 46.142 11193.992 11204.023 0.0 49.8 3301.1 1836.1 3.028 5.447 44.262 11187.622 11204.023 0.0 48.4 3329.9 2001.8 2.737 4.948 41.735 11165.580 11204.023 0.0 47.0 0.0 1800.9 - 4.948 41.735 11165.580 11204.023 0.0 NaN 92.4 1645.4 226.166 6.078 43.042 11156.315 11204.023 0.0 99.2 4024.9 1843.1 2.485 5.426 39.488 10339.090 11203.705 0.0 45.4 4193.7 2023.6 2.382 4.942 38.478 10328.566 11203.705 0.0 44.3 4487.2 2199.3 2.227 4.547 36.814 10316.059 11203.705 0.0 43.1 4496.0 2352.3 2.222 4.251 35.540 10313.618 11203.705 0.0 43.3 4530.5 2488.3 2.207 4.018 34.530 10213.330 11203.705 0.0 43.0 4535.5 2608.8 2.204 3.833 33.649 168.792 11202.112 0.0 43.3 4479.8 2712.7 2.230 3.686 33.112 163.941 11202.112 0.0 42.7 4722.0 2818.5 2.116 3.547 32.285 160.038 11202.112 0.0 42.6 4710.9 2913.1 2.108 3.431 31.666 79.285 11202.112 0.0 42.5 1816.5 2860.5 1.834 3.382 31.418 75.221 11195.866 0.0 42.9 </code></pre><p><em>Note</em> : ceci est cependant à modérer, puisque notre première campagne de tir va déclencher une écriture pour chaque utilisateur qui s'authentifie. Si on relance un deuxième tir dans l'heure (qui est l'unité minimale de suivi de la date de connexion), on retrouve des résultats quasiment identiques au premier cas : un débit de 4291 authentifications par seconde, et un temps de réponse de 2.195 ms. Si on regarde la charge sur le serveur d'annuaire, on ne constate plus d'écritures sur disque.</p> <pre><code>------------------------------------------------------------------------------ Throughput Response Time (ops/second) (milliseconds) recent average recent average 99.9% 99.99% 99.999% err/sec bind time % ------------------------------------------------------------------------------ 3988.3 3994.8 2.514 2.514 23.066 163.522 167.640 0.0 42.6 .../... 4628.0 4525.7 2.159 2.206 18.978 28.433 158.819 0.0 42.9 4327.2 4510.4 2.219 2.207 19.051 28.221 158.819 0.0 43.0 1450.9 4291.0 1.721 2.195 18.968 28.071 158.406 0.0 42.1 </code></pre><h2>Conclusion</h2> <p>Si l'impact du suivi de la date de dernière connexion n'est pas anodin, surtout dans le cas d'un test, en situation réelle, l'impact peut être relativement négligeable, notamment si les authentifications se font au fil de l'eau.</p> </div> <span class="field field--name-uid field--type-entity-reference field--label-hidden"><span lang="" about="/users/vincentl" typeof="schema:Person" property="schema:name" datatype="">vincentl</span></span> <span class="field field--name-created field--type-created field--label-hidden">mar 19/12/2017 - 10:42</span> <div class="field field--name-field-categorie field--type-entity-reference field--label-above"> <div class="field__label">Catégorie</div> <div class="field__item"><a href="/cat%C3%A9gorie/iam" hreflang="fr">IAM</a></div> </div> <div class="field field--name-field-tags field--type-entity-reference field--label-above"> <div class="field__label">Tag</div> <div class="field__items"> <div class="field__item"><a href="/tags/forgerock" hreflang="fr">forgerock</a></div> <div class="field__item"><a href="/tags/opendj" hreflang="fr">opendj</a></div> <div class="field__item"><a href="/tags/ldap" hreflang="fr">ldap</a></div> <div class="field__item"><a href="/tags/performances" hreflang="fr">performances</a></div> </div> </div> <section class="field field--name-comment-node-book field--type-comment field--label-hidden comment-wrapper"> </section> Tue, 19 Dec 2017 09:42:42 +0000 vincentl 187 at https://www.vincentliefooghe.net https://www.vincentliefooghe.net/content/opendj-mise-place-du-suivi-des-connexions#comments Installation Sun DSEE sur Red Hat https://www.vincentliefooghe.net/content/installation-sun-dsee-sur-red-hat <span property="dc:title" class="field field--name-title field--type-string field--label-hidden">Installation Sun DSEE sur Red Hat </span> <div property="content:encoded" class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><h2>Pré-requis</h2> <p>Installer sur une distribution Red Hat Enterprise Server 6.x (6.8 dans notre cas). Mode <em>Basic Server</em></p> <p><strong>Attention</strong> : même sur un système 64 bits, Sun DSEE fonctionne en mode 32 bits. Il faut donc s'assurer d'avoir installé les librairies compatibles.</p> <h2>Pré-requis logiciels</h2> <p>Installer les paquets :</p> <ul><li>unzip</li> <li>wget</li> <li>compat-glibc</li> <li>compat-gcc-32</li> <li>compat-libstdc++</li> <li>libstdc++</li> <li>zlib.i686</li> </ul><p>On utilise <em>yum</em> pour installer tout cela :</p> <pre>yum install unzip wget compat-libstdc++-33.x86_64 compat-libstdc++-33.i686 compat-glibc compat-gcc compat-libstdc++-296.i686 libstdc++ libstdc++.i686 zlib.i686 </pre><h2>Répertoires</h2> <p>On a créer / utiliser les répertoires suivants :</p> <ul><li>/opt/dsee7 : sera créé lors de l'extraction de l'archive. C'est ici que se trouveront les exécutables</li> <li>/var/lib/dsee : à créer. C'est ici qu'on aura les données et paramètres des instances</li> </ul><h1>Installation</h1> <p>Récupérer le zip,et l'extraire.</p> <pre>unzip ofm_odsee_linux_11.1.1.5.0_64_disk1_1of1-1.zip </pre><p>On peut alors se positionner dans le répertoire <code>ODSEE_ZIP_Distribution</code> et lancer l'utilitaire <strong>idsktune</strong>. Cet utilitaire va vérifier la version de l'OS, les librairies installées, etc.<br />Exemple de sortie :</p> <pre>./idsktune ODSEE 11gR1+PS1 platform tuning analysis version May 2 2011 (ODSEE 11.1.1.5.0). Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. ERROR : compat-glibc-2.3.4 is not installed. ERROR : Required 32-bit Run-Time is not installed. NOTICE : System is x86_64-unknown-rhel60linux3.10.0-514.26.2.el7.x86_64 (2 processors). WARNING: Only 3790MB of physical memory is available on the system. 4000MB is the recommended minimum for a production system. Consult "Oracle Directory Server Enterprise Edition 11gR1+PS1 Deployment Planning Guide: Tuning System Characteristics and Hardware Sizing" for more information about system sizing. NOTICE : The net.ipv4.tcp_keepalive_time is set to 7200000 milliseconds (120 minutes). This may cause temporary server congestion from lost client connections. ERROR : The above errors MUST be corrected before proceeding. </pre><p>Une fois les erreurs résolues, on peut alors extraire le fichier <code>sun-dsee7.zip</code>. Dans notre exemple, on va installer dans <code>/opt</code></p> <pre>cd /opt unzip /opt/ODSEE_ZIP_Distribution/sun-dsee7.zip </pre><h1>Administration des instances</h1> <h2>Création d'une instance</h2> <p>On crée une instance avec l'utilitaire <em>dsadm</em>, en fournissant les ports d'écoute (ldap et ldaps) ainsi que le répertoire d'installation de l'instance. Par exemple :</p> <pre>/opt/dsee7/bin/dsadm create -p 1389 -P 1636 /var/lib/dsee/monInstance Choose the Directory Manager password: Confirm the Directory Manager password: Use 'dsadm start '/var/lib/dsee/monInstance'' to start the instance </pre><h2>Démarrage d'une instance</h2> <p>Le démarrage se fait avec la commande <em>dsadm start</em> :</p> <pre>/opt/dsee7/bin/dsadm start /var/lib/dsee/monInstance</pre><h2>Création d'un root Suffix</h2> <p>La configuration d'une instance se fait avec la commande <em>dsconf</em> :</p> <pre>/opt/dsee7/bin/dsconf create-suffix -p 1389 -e dc=example,dc=com </pre><p>Il faut saisir le mot de passe du compte administrateur de l'instance.</p> <h2>Import de données</h2> <p>On peut ensuite importer des données. Dans l'installation, on trouve des fichiers d'exemple (dans le répertoire <code>resources/ldif</code>).</p> <p>La syntaxe est la suivante :</p> <pre>/opt/dsee7/bin/dsconf import -p 1389 -e /opt/dsee7/resources/ldif/Example.ldif dc=example,dc=com Enter "cn=Directory Manager" password: New data will override existing data of the suffix "dc=example,dc=com". Initialization will have to be performed on replicated suffixes. Do you want to continue [y/n] ? y ## Index buffering enabled with bucket size 40 ## Beginning import job... ## Starting to process and index entries ## Processing file "/opt/dsee7/resources/ldif/Example.ldif" ## Finished scanning file "/opt/dsee7/resources/ldif/Example.ldif" (160 entries) ## Workers finished; cleaning up... ## Cleaning up producer thread... ## Indexing complete. ## Starting numsubordinates attribute generation. ## This may take a while, please wait for further activity reports. ## Numsubordinates attribute generation complete. Flushing caches... ## Closing files... ## Import complete. Processed 160 entries in 4 seconds. (40.00 entries/sec) Task completed (slapd exit code: 0). </pre><p> </p> </div> <span rel="sioc:has_creator" class="field field--name-uid field--type-entity-reference field--label-hidden"><span lang="" about="/users/vincentl" typeof="schema:Person" property="schema:name" datatype="">vincentl</span></span> <span property="dc:date dc:created" content="2017-12-06T13:03:23+00:00" datatype="xsd:dateTime" class="field field--name-created field--type-created field--label-hidden">mer 06/12/2017 - 14:03</span> <div class="field field--name-field-categorie field--type-entity-reference field--label-above"> <div class="field__label">Catégorie</div> <div class="field__item"><a href="/cat%C3%A9gorie/iam" hreflang="fr">IAM</a></div> </div> <div class="field field--name-field-tags field--type-entity-reference field--label-above"> <div class="field__label">Tag</div> <div class="field__items"> <div class="field__item"><a href="/tags/sun-dsee" hreflang="fr">Sun DSEE</a></div> <div class="field__item"><a href="/tags/ldap" hreflang="fr">ldap</a></div> </div> </div> <section class="field field--name-comment-node-blog field--type-comment field--label-hidden comment-wrapper"> </section> Wed, 06 Dec 2017 13:03:23 +0000 vincentl 186 at https://www.vincentliefooghe.net Mise en place de Splunk sur des logs LDAP https://www.vincentliefooghe.net/content/mise-place-splunk-sur-des-logs-ldap <span property="dc:title" class="field field--name-title field--type-string field--label-hidden">Mise en place de Splunk sur des logs LDAP</span> <div property="content:encoded" class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><p>Dans une architecture LDAP de production, on met généralement en place plusieurs instances d'annuaires, qui sont répliquées entre elles. L'inconvénient dans ce cas est que les logs sont répartis sur chaque serveur, et qu'il devient difficile d'avoir une vue d'ensemble des opérations.</p> <p>Il existe cependant des solutions de centralisation, aggrégation et visualisation de données. Les plus connues étant Splunk et ELK.</p> <p><a href="https://www.splunk.com">Splunk</a> est une solution permettant la centralisation, l'agrégation et l'analyse de données.<br />On peut la comparer à la <em>stack <a href="https://www.elastic.co">ELK</a> (ElasticSearch / LogStashs / Kibana)</em>. A la différence de ELK, c'est une solution propriétaire. Il existe cependant une version gratuite, limitée à 500 Mo / jour.</p> <p>La tarification s'effectue en fonction du volume de Go indexés par jour (de l'ordre de 1000 $ / Go pour un an).</p> <h2>Installation de Splunk</h2> <p>Récupérer le tgz (ou le rpm selon le cas). Il faut pour cela s'enregistrer sur le site (<a href="https://www.splunk.com/en_us/download.html">https://www.splunk.com/en_us/download.html</a>).</p> <pre>tar zxf /xchange/Software/splunk-6.6.3-e21ee54bc796-Linux-x86_64.tgz -C /opt/splunk </pre><p>L'installation est auto-suffisante. Pas de java à installer, pas de base de données. C'est à mon sens une des forces par rapport à ELK, qui demande plus d'efforts pour la mise en place.</p> <h2>Création d'un index</h2> <p>Par défaut, toutes les données vont dans un index unique, <em>main</em>. On peut cependant avoir des index différents selon les données que l'on veut analyser, notamment pour gagner en souplesse dans la gestion de l'espace disque ou avoir des durées de rétention différentes.</p> <p>Les actions sont à faire sur le serveur Splunk principal (indexer). Plusieurs options possibles :<br />Via la console Web, dans Settings / Indexes<br />Cliquer sur New Index<br />Entrer un nom, la taille et éventuellement les répertoires</p> <p>En ligne de commande</p> <pre>splunk add index opends </pre><p> </p> <p>Via le fichier <code>indexes.conf</code>. Ajouter un fichier dans <code>$SPLUNK_HOME/etc/system/local</code> :</p> <pre>[opends] homePath = $SPLUNK_DB/opends/db coldPath = $SPLUNK_DB/opends/colddb thawedPath = $SPLUNK_DB/opends/thaweddb tstatsHomePath = volume:_splunk_summaries/opends/datamodel_summary maxMemMB = 20 maxConcurrentOptimizes = 6 maxHotIdleSecs = 86400 maxHotBuckets = 5 maxDataSize = auto </pre><p><strong>Note</strong> : certains paramètres ne sont accessibles qu'en modifiant le fichier <code>indexes.conf</code></p> <h2>Autoriser la réception</h2> <p>Si on veut utiliser une instance Splunk globale (pour centraliser des logs par exemple), il faut mettre en place une architecture avec un receiver et des forwarders</p> <p>Pour autoriser la réception, via la console Web :</p> <ul><li>Settings / Forwarding and Receiving</li> <li>Receive data</li> <li>Cliquer sur New</li> <li>entrer le port d'écoute (9997 par défaut)</li> </ul><p> </p> <h2>Mise en place d'un forwarder</h2> <p>Installer via le tgz splunkforwarder ou le rpm</p> <pre>cd /opt tar zxf splunkforwarder-6.6.3-e21ee54bc796-Linux-x86_64.tgz </pre><p>ou</p> <pre>rpm -ivh splunkforwarder-6.6.3-e21ee54bc796-linux-2.6-x86_64.rpm </pre><p>Puis il faut paramétrer le <em>forwarding</em> vers le serveur / indexer Splunk :</p> <pre>./splunk add forward-server splunkserver.exemple.com:9997 -auth admin:changeme </pre><h3>Activation du démarrage au boot</h3> <p>Splunk fournit une commande permettant de démarrer le <em>forwarder</em> lors du boot.</p> <pre># ./splunk enable boot-start Init script installed at /etc/init.d/splunk. Init script is configured to run at boot.</pre><p> </p> <h3>Définition des inputs</h3> <p>Dans le répertoire <code>$SPLUNKFORWARDER/etc/system/local </code><br />Fichier <code>inputs.conf</code> :</p> <pre>[default] host = ds2dj.hebinweb [monitor:///opt/OpenDS-2.3.0/logs/access] sourcetype = LDAP_DS_ACCESS [monitor:///opt/OpenDS-2.3.0/logs/errors] sourcetype = LDAP_DS_ERRORS [monitor:///opt/opendj/logs/access] sourcetype = LDAP_DJ_ACCESS [monitor:///opt/opendj/logs/errors] sourcetype = LDAP_DJ_ERRORS </pre><h3>Définition de l'output</h3> <p>Fichier <em>outputs.conf</em></p> <pre>[tcpout] defaultGroup = default-autolb-group [tcpout:default-autolb-group] server = splunkserver.exemple.com:9997 [tcpout-server://splunkserver.exemple.com:9997] </pre><h2>Utilisation d'un index spécifique pour la source</h2> <p>Sur le serveur forwarder, ajouter dans le fichier <code>$SPLUNKHOME/etc/system/local/inputs.conf</code> :</p> <pre>[monitor:///opt/OpenDS-2.3.0/logs/access] sourcetype = LDAP_DS_ACCESS disabled = false index = opends [monitor:///opt/OpenDS-2.3.0/logs/errors] sourcetype = LDAP_DS_ERRORS disabled = false index = opends [monitor:///opt/opendj/logs/access] sourcetype = LDAP_DJ_ACCESS index = ldap </pre><h2>Filtrage des events</h2> <p>Sur le serveur indexer, ajouter / modifier les fichiers <em>props.conf</em> et <em>transforms.conf</em></p> <p>Fichier <em>props.conf</em></p> <pre>[LDAP_DS_ACCESS] TRANSFORMS-null = sendToNull [LDAP_DS_ERRORS] TRANSFORMS-null = sendToNull [LDAP_DJ_ACCESS] TRANSFORMS-null = sendToNull [LDAP_DJ_ERRORS] TRANSFORMS-null = sendToNull </pre><p>Fichier <em>transforms.conf</em></p> <pre>[sendToNull] REGEX=UNBIND|DISCONNECT DEST_KEY=queue FORMAT=nullQueue </pre><p>Il faut ensuite redémarrer <strong>splunk</strong> pour prendre en compte les modifications</p> <pre>$SPLUNK_HOME/bin/splunk restart </pre><p> </p> <h2>Purge les données des index</h2> <p>Dans la fenêtre de recherche Splunk, on peut "piper" le verbe <em>delete</em> avec la recherche. Par exemple</p> <pre>index=ldap UNBIND |delete </pre><p><strong>Note</strong> : le compte utilisé doit avoir le rôle <em>can_delete</em>. Par défaut, même le compte admin ne dispose pas d'un tel droit. En fait, ceci ne supprime pas les données de l'index, mais l'opération delete marque les données comme "non cherchables". Pour supprimer les données, il faut lancer une opération sur l'indexer. Par contre ceci <strong>supprime toutes les données</strong> de l'index. A utiliser avec précaution, par exemple sur un index de test.</p> <pre>$SPLUNK_JHOME/bin/splunk stop $SPLUNK_JHOME/bin/splunk clean eventdata -index ldap This action will permanently erase all events from the index 'ldap'; it cannot be undone. Are you sure you want to continue [y/n]? </pre><h2>Configuration Splunk pour les logs Sun / Oracle DSEE</h2> <p>Les logs d'accès de l'annuaire DSEE (Directory Server Enterprise Edition) sont très verbeux par rapport aux besoins d'analyse.</p> <p>Par exemple, sur un fichier de 200 Mo, représentant 1 865 484 lignes, on a quasiment 80% de lignes composées des actions suivantes :</p> <ul><li>RESULT err=0 : la requête est correcte...</li> <li>EXT oid=x.x. : logs de la réplication, extension interne de l'annuaire, pas exploitable</li> <li>UNBIND : déconnexions</li> <li>closed / closing : fermeture des connexions LDAP</li> </ul><p>Il est donc possible de définir une REGEX de transformations pour soulager l'indexer.<br />Notre fichier <code>transforms.conf</code> est le suivant :</p> <pre>[setnull] REGEX=EXT\ oid|closed|UNBIND|closing|err=0 DEST_KEY=queue FORMAT=nullQueue</pre><p>Le fichier <code>props.conf</code> étant :</p> <pre>[LDAP_DATA_ACCESS] TRANSFORMS-null=setnull [LDAP_ADM_ACCESS] TRANSFORMS-null=setnull </pre><p> </p> </div> <span rel="sioc:has_creator" class="field field--name-uid field--type-entity-reference field--label-hidden"><span lang="" about="/user/1" typeof="schema:Person" property="schema:name" datatype="">Vincent</span></span> <span property="dc:date dc:created" content="2017-09-01T14:22:35+00:00" datatype="xsd:dateTime" class="field field--name-created field--type-created field--label-hidden">ven 01/09/2017 - 16:22</span> <div class="field field--name-field-categorie field--type-entity-reference field--label-above"> <div class="field__label">Catégorie</div> <div class="field__item"><a href="/cat%C3%A9gorie/iam" hreflang="fr">IAM</a></div> </div> <div class="field field--name-field-tags field--type-entity-reference field--label-above"> <div class="field__label">Tag</div> <div class="field__items"> <div class="field__item"><a href="/tags/logs" hreflang="fr">logs</a></div> <div class="field__item"><a href="/tags/splunk" hreflang="fr">splunk</a></div> <div class="field__item"><a href="/tags/ldap" hreflang="fr">ldap</a></div> </div> </div> <section class="field field--name-comment-node-blog field--type-comment field--label-hidden comment-wrapper"> </section> Fri, 01 Sep 2017 14:22:35 +0000 Vincent 184 at https://www.vincentliefooghe.net