Vincent Liefooghe - Logiciels (libres), CMS, IDM & Co https://www.vincentliefooghe.net/ fr Migration LXD sur Ubuntu 18.04 vers 20.04 https://www.vincentliefooghe.net/content/migration-lxd-sur-ubuntu-1804-vers-2004 <span property="dc:title" class="field field--name-title field--type-string field--label-hidden">Migration LXD sur Ubuntu 18.04 vers 20.04</span> <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="2020-07-26T19:58:54+00:00" datatype="xsd:dateTime" class="field field--name-created field--type-created field--label-hidden">dim 26/07/2020 - 21:58</span> Sun, 26 Jul 2020 19:58:54 +0000 Vincent 206 at https://www.vincentliefooghe.net https://www.vincentliefooghe.net/content/migration-lxd-sur-ubuntu-1804-vers-2004#comments Migration Media et Images Inline https://www.vincentliefooghe.net/content/migration-media-et-images-inline <span class="field field--name-title field--type-string field--label-hidden">Migration Media et Images Inline</span> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><p>Dans la série d'articles sur la migration de mon site <a href="https://www.vincentliefooghe.net/content/migration-drupal-7-vers-drupal-8">https://www.vincentliefooghe.net/content/migration-drupal-7-vers-drupal-8 </a> j'en viens maintenant à une partie qui m'a pris pas mal de temps et demandé un peu de développement.</p> <p>Sur mon site en Drupal 7, j'avais utilisé le module Media_Wysiwyg et Colorbox, qui me permettaient d'insérer des images directement dans le texte.</p> <p>Je n'ai pas trouvé d'équivalent sous Drupal 8, mais en utilisant comme format d'affichage "Colorbox" pour le champ media_image, ceci répond à mon besoin : ouvrir un champ image dans une "lightbox".</p> <article class="media media--type-image media--view-mode-default" data-align="center"> <div class="field field--name-field-media-image field--type-image field--label-visually_hidden"> <div class="field__label visually-hidden">Image</div> <div class="field__item"><a href="https://www.vincentliefooghe.net/sites/default/files/2020-04/Capture%20d%E2%80%99%C3%A9cran%20de%202020-04-20%2021-58-11.png" title="Définition du format d'affichage Media Image" data-colorbox-gallery="gallery-all-ALdEhHi8n0E" class="colorbox" data-cbox-img-attrs="{&quot;alt&quot;:&quot;Définition du format d'affichage Media Image&quot;}"><img src="/sites/default/files/styles/large/public/2020-04/Capture%20d%E2%80%99%C3%A9cran%20de%202020-04-20%2021-58-11.png?itok=nlAgY3jD" width="480" height="154" alt="Définition du format d'affichage Media Image" typeof="foaf:Image" class="image-style-large" /> </a> </div> </div> </article> <p>Il reste donc à convertir les fichiers en média, et ensuite à convertir, dans le corps du texte de chaque contenu, les tags "colorbox" en tags "drupal media".</p> <h2>Création des Media liés aux fichiers</h2> <p>Lors de la migration, les fichiers ont bien été importés. Par contre ils ne sont pas reconnus comme <em>media</em> par Drupal ,et donc pas réutilisables.</p> <p>Après avoir cherché - en vain - des modules qui géraient ceci, j'ai fini par passer par un bout de programme PHP qui utilise les fonctions de Drupal pour réaliser cette opération.</p> <p>Le code php est le suivant :</p> <pre style="margin: 0px; text-indent: 0px;"> &lt;?php // Create Media images from file use Drupal\media\Entity\Media; // Requete pour recupérer les fichiers de type Image $results = \Drupal::database()-&gt;query("select * from file_managed where filemime like 'image%'")-&gt;fetchAll(); foreach ($results as $file ) { echo "File name:",$file-&gt;filename," Id : ",$file-&gt;fid," mime : ",$file-&gt;filemime," uid : ",$file-&gt;uid; echo "Creation du Media Image pour ",$file-&gt;filename,PHP_EOL; $media = Media::create([ 'bundle' =&gt; 'image', 'uid' =&gt; $file-&gt;uid, 'langcode' =&gt; $file-&gt;langcode, 'field_media_image' =&gt; [ 'target_id' =&gt; $file-&gt;fid, 'alt' =&gt; $file-&gt;filename ] ]); $media-&gt;setPublished(TRUE); $retour=$media-&gt;save(); if ( $retour != 1 ) { echo "Retour KO ? ",$retour,PHP_EOL; } } return (TRUE);</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;">On peut le lancer avec drush, via la commande :</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> </p> <pre> drush --uri=drupal.loc scr /chemin/vers/mon/fichier.php</pre><p>Après cette étape, on récupère bien dans la librairies de media tous les fichiers</p> <h2 style="margin: 0px; text-indent: 0px;">Reprise des images inline</h2> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> </p> <p class="western">Pour convertir les tags, j'ai développé un programme PHP qui va remplacer les instructions inline Colorbox, par exemple</p> <pre> &lt;p&gt;[[{"type":"media","view_mode":"colorbox","fid":"88","attributes":{"alt":"","class":"media-image","height":"300","typeof":"foaf:Image","width":"494"}}]]&lt;/p&gt;</pre><p class="western">par</p> <pre> &lt;drupal-media data-align="center" data-entity-type="media" data-entity-uuid="b5631639-11f9-4945-85b7-85a477cbdcf8"&gt;&lt;/drupal-media&gt;</pre><p class="western">Le script sera lancé avec en paramètre le Node Id à traiter :</p> <pre> php mediaInline.php -i nid</pre><p class="western">Par exemple</p> <pre> php mediaInline.php -i 136</pre><p class="western">Note : j'ai fait le choix de traiter les contenus un par un. Au total, j'avais identifié une vingtaine d'articles concernés. La migration unitaire me permettait de vérifier le traitement pour chacun.</p> <p class="western">Afin de voir le résultat, il faut vider le cache Drupal avec la commande :</p> <pre> drush cr</pre><p> </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">lun 20/04/2020 - 21:54</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/cms" hreflang="fr">CMS</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="/taxonomy/term/1" hreflang="fr">Drupal</a></div> <div class="field__item"><a href="/tags/media" hreflang="fr">media</a></div> </div> </div> <div class="field field--name-field-fichier field--type-file field--label-above"> <div class="field__label">Fichier</div> <div class="field__items"> <div class="field__item"> <span class="file file--mime-application-pdf file--application-pdf"> <a href="https://www.vincentliefooghe.net/sites/default/files/mediaInline.php_.pdf" type="application/pdf; length=53900" title="mediaInline.php_.pdf">Script de migration Colorbox vers media</a></span> </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=205&amp;2=comment_node_book&amp;3=comment_node_book" token="fPxOoNJNWdkHGUVo_eQPh31e8VYhG0jBWRM4c513qDE"></drupal-render-placeholder> </section> Mon, 20 Apr 2020 19:54:26 +0000 vincentl 205 at https://www.vincentliefooghe.net Migration avec le module migrate_upgrade https://www.vincentliefooghe.net/content/migration-avec-le-module-migrateupgrade <span class="field field--name-title field--type-string field--label-hidden">Migration avec le module migrate_upgrade</span> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><h2>Installation et activation des modules Drush requis</h2> <p>On va installer les 2 modules suivants : migrate_upgrade, migrate_tools.</p> <pre> <code>composer require drupal/migrate_upgrade composer require drupal/migrate_tools </code></pre><p>Puis activer les modules :</p> <pre> <code>drush pm:enable migrate_upgrade migrate_tools -y </code></pre><p>Dans le fichier <em>settings.php</em> , il faut ajouter la définition de la base source.</p> <p><strong>Important</strong> : elle doit s'appeler <strong>migrate</strong>.</p> <p>Par exemple :</p> <pre> <code>$databases['migrate']['default'] = array ( 'database' =&gt; 'dbdrupal7', 'username' =&gt; 'user_drupal7', 'password' =&gt; 'mdp_drupal7', 'prefix' =&gt; '', 'host' =&gt; 'localhost', 'port' =&gt; '3306', 'namespace' =&gt; 'Drupal\\Core\\Database\\Driver\\mysql', 'driver' =&gt; 'mysql' ); </code></pre><h2>Générer la migration Drupal 7 vers Drupal 8</h2> <p>Dans la version que j'ai installé, on peut utiliser <em>migrate_upgrade</em> pour générer les scripts de migration, qui seront lancés avec <em>drush</em>.</p> <h3>Prérequis</h3> <p>Attention : à cause d'une incompatibilité avec drush 10, cette fonction nécessite que l'on modifie le fichier <code>vendor/drush/drush/includes/drush.inc</code> pour ajouter la définition de drush_print :</p> <pre style="margin: 0px; text-indent: 0px;"> function drush_print($message = '', $indent = 0, $handle = NULL, $newline = TRUE) { $msg = str_repeat(' ', $indent) . (string)$message; if ($newline) { $msg .= &amp;quot;\n&amp;quot;; } if (($charset = 'UTF-8' ) &amp;amp;&amp;amp; function_exists('iconv')) { $msg = iconv('UTF-8', $charset, $msg); } if (!$handle) { $handle = STDOUT; } fwrite($handle, $msg);</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;"> </p> <p>Sinon on a le message :</p> <pre> drush migrate-upgrade --legacy-db-key=migrate --configure-only [error] Error: Call to undefined function drush_get_option() in drush_print()</pre><p>Lancer la commande avec le chemin vers le répertoire source "legacy", ce qui permet de migrer les fichiers également :</p> <pre> drush migrate-upgrade --legacy-db-key=migrate --legacy-root /var/www/drupal7/vincentl --migration-prefix=upg1_ --configure-only</pre><p class="western"><span style="line-height:100%">On peut ensuite voir le résultat avec la commande drush migrate-status</span></p> <p class="western"><span style="line-height:100%">Et on peut lancer la migration avec :</span></p> <pre> drush migrate:import upg1_d7_taxonomy_vocabulary drush migrate:import upg1_d7_taxonomy_term_categorie drush migrate:import upg1_d7_taxonomy_term_tags drush migrate-import --group=migrate_drupal_7 </pre><p><strong>Note</strong> : je lance d'abord les migrations de taxonomie pour que la génération des liens de menu se passe correctement. Comme dit précédemment, le processus est assez itératif et a demandé plusieurs essais avant de trouver les bons réglages.</p> <p>Après cette étape, le contenu a été migré, ainsi que les types de contenu, les menus, etc.</p> <p>Il reste à faire quelques mises au point et reprise de paramétrage sur les formats de texte (insertion du bouton media par exemple), ainsi que refaire le thème, et traiter le cas des images <em>inline</em>.</p> <p> </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">lun 20/04/2020 - 21: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/cms" hreflang="fr">CMS</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="/taxonomy/term/1" hreflang="fr">Drupal</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=204&amp;2=comment_node_book&amp;3=comment_node_book" token="KVD93o-80gUsSKm2muCPtDa4b3TQ3e1ZtQ8mC6723F0"></drupal-render-placeholder> </section> Mon, 20 Apr 2020 19:42:22 +0000 vincentl 204 at https://www.vincentliefooghe.net Processus de migration vers Drupal 8 https://www.vincentliefooghe.net/content/processus-migration-vers-drupal-8 <span class="field field--name-title field--type-string field--label-hidden">Processus de migration vers Drupal 8</span> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><h2>Processus de migration</h2> <p>Le processus de migration a été testé plusieurs fois. Je suis parti sur la base d'une sauvegarde du site Drupal 7 (fichiers + base de données).</p> <p>J'ai installé ça dans un container LXC sur mon PC, ce qui me permettra de supprimer tout cela une fois la migration terminée.</p> <p>Au final, on a donc un container sous Debian 10 avec PHP 7.3.11 et une base MariaDB 10.1.</p> <p>L'idée est donc la suivante :</p> <ul> <li>création d'une base de données pour Drupal 8</li> <li>installation d'un site en Drupal 8, en mode "standard", mais sans contenu</li> <li>installation et activation des modules portés sous Drupal 8</li> <li>installation et activation des modules de migration</li> <li>lancement de la migration des contenus</li> <li>reprise des média et de leur affichage (la migration ne gère pas ce point a priori)</li> <li>ajustements manuels / reparamétrage dans la cible D8.</li> </ul> <p>Le processus a été fait de manière itérative, je m'y suis repris à 3 ou 4 fois avant d'avoir un processus qui tienne la route.</p> <h2>Installation Drupal 8</h2> <p>Une fois la base de données créée, on procède à l'installation de Drupal 8.</p> <p>A la date d'installation, la version est Drupal 8.8.5.</p> <p>Il est maintenant fortement recommandé d'utiliser <em>composer</em> pour installer et mettre à jour Drupal.</p> <p>Sachant que même l'installation de modules utilise <em>composer</em>, c'est la solution que j'ai utilisé. C'est d'ailleurs très pratique quand on refaire plusieurs fois la même installation, puisqu'une fois le fichier _composer.json _ généré, il est possible de s'en resservir.</p> <p>Mon fichier comprend les modules suivants :</p> <pre> <code>"repositories": [ { "type": "composer", "url": "https://packages.drupal.org/8" } ], "require": { "composer/installers": "^1.2", "drupal/colorbox": "^1.4", "drupal/core-composer-scaffold": "^8.8", "drupal/core-project-message": "^8.8", "drupal/core-recommended": "^8.8", "drupal/honeypot": "^1.30", "drupal/pathauto": "^1.6", "drupal/tagclouds": "^1.0", "drupal/token": "^1.6", "drupal/xmlsitemap": "^1.0@RC", "drush/drush": "^10.2" }, </code></pre><p>On remarquera que <em>drush</em> est installé en même temps que Drupal.</p> <p>Une fois le répertoire d'installation créé, et le fichier <em>composer.json</em> copié dans ce répertoire, l'installation se fait simplement :</p> <pre> composer install</pre><p>A ce niveau, on peut déjà accéder au nouveau site (il faut auparavant avoir paramétré le virtualhost qui pointe sur le bon répertoire), entrer les paramètres de la base de données. J'ai personnellement choisi d'installer uniquement le français, car je ne vais pas gérer le multilingue.</p> <p>Comme le site sera migré, on peut s'arrêter avant la configuration du site.</p> <p>L'étape suivante est de préparer et lancer la migration.</p> <p> </p> <p> </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">dim 19/04/2020 - 12:45</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/cms" hreflang="fr">CMS</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="/taxonomy/term/1" hreflang="fr">Drupal</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=203&amp;2=comment_node_book&amp;3=comment_node_book" token="xD-sOgwyT6pbo6nlI2ZTcPkiu5rO3q8ptqPnaVjYMI0"></drupal-render-placeholder> </section> Sun, 19 Apr 2020 10:45:31 +0000 vincentl 203 at https://www.vincentliefooghe.net Problème de démarrage LXC sur device Btrfs https://www.vincentliefooghe.net/content/probl%C3%A8me-d%C3%A9marrage-lxc-sur-device-btrfs <span property="dc:title" class="field field--name-title field--type-string field--label-hidden">Problème de démarrage LXC sur device Btrfs</span> <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="2020-04-15T09:04:12+00:00" datatype="xsd:dateTime" class="field field--name-created field--type-created field--label-hidden">mer 15/04/2020 - 11:04</span> Wed, 15 Apr 2020 09:04:12 +0000 Vincent 201 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 Connexion OpenIDM / AD SSL https://www.vincentliefooghe.net/content/connexion-openidm-ad-ssl <span property="dc:title" class="field field--name-title field--type-string field--label-hidden">Connexion OpenIDM / AD SSL </span> <div property="content:encoded" class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><p><em>De l'importance d'utiliser un nom de serveur correspondant au CN du certificat...</em></p> <h2>Contexte</h2> <p>Afin de pouvoir tester la connexion d'un OpenIDM sur un serveur AD (et par la suite la mise en place du plugin de synchronisation de mot de passe) j'ai mis en place une maquette simple avec :</p> <ul> <li>un serveur OpenIDM sous CentOS</li> <li>un serveur AD sous Windows 2008R2</li> </ul> <p>J'ai mis en place un certificat sur le serveur AD, qui est aussi le contrôleur de domaine principal, avec un certificat qu'il a généré.</p> <p>J'ai importé le certificat dans le Keystore OpenIDM, comme pour toute connexion sécurisée.</p> <h2>Problème</h2> <p>Mais cependant, impossible d'avoir une connexion opérationnelle. La connexion en LDAPS ne fonctionne pas (port 636 / ssl = "true"), alors qu'elle est opérationnelle en LDAP (port 389 / ssl="false")</p> <p>Au démarrage, on trouve ceci dans les logs :</p> <pre>SEVERE: OpenICF connector test of SystemIdentifier{ uri='system/AD/'} failed! org.identityconnectors.framework.common.exceptions.ConnectionFailedException: javax.naming.CommunicationException: mytest-dc.local:636 [Root exception is java.net.SocketException: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: sun.security.ssl.SSLContextImpl$DefaultSSLContext)] </pre><p>Même chose en testant via une requête REST :</p> <pre>http://engine.local:8180/openidm/system/AD/?_action=test Caused by: javax.naming.CommunicationException: mytest-dc.local:636 [Root exception is java.net.SocketException: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: sun.security.ssl.SSLContextImpl$DefaultSSLContext)] </pre><h2>Cause et résolution</h2> <p>Au final, il s'agissait d'un problème de nom DNS. En effet, le serveur AD a son propre nom DNS, et ce n'est pas celui que j'utilisais dans ma connexion (mytest-dc.local).</p> <p>Les logs me donnaient bien une piste :</p> <pre>WARNING: Resource exception: 500 Internal Server Error: "javax.naming.CommunicationException: simple bind failed: lyreco-dc.local:636 [Root exception is javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative DNS name matching lyreco-dc.local found.]" </pre><p>J'ai donc modifié le fichier <em>conf/boot/boot.properties</em> pour positionner le nom de machine égal au CN du certificat du serveur, que l'on peut récupérer avec la commande suivante :</p> <pre>openssl x509 -in adldaps.pem -noout -text |grep Subject Subject: CN=<strong>WIN-RLQ30AF9URF.group.id-num.com</strong> Subject Public Key Info: X509v3 Subject Key Identifier: X509v3 Subject Alternative Name:</pre><p>Une fois le paramétrage du nom effectué, et après avoir modifié mon fichier /etc/hosts pour que mon serveur OpenIDM arrive à faire le lien entre l'adresse IP et le nom, tout est allé beaucoup mieux.</p> <p>Pour que la modification soit prise en compte, il a fallu redémarrer OpenIDM (puisque mon paramétrage se trouve dans le fichier boot.properties).</p> <p>Il a également fallu que je passe par la console d'admin, et que je valide la connexion AD pour que cela soit opérant.</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="2019-11-11T14:17:56+00:00" datatype="xsd:dateTime" class="field field--name-created field--type-created field--label-hidden">lun 11/11/2019 - 15:17</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="/taxonomy/term/3" hreflang="fr">openidm</a></div> <div class="field__item"><a href="/tags/active-directory" hreflang="fr">active directory</a></div> <div class="field__item"><a href="/tags/ssl" hreflang="fr">ssl</a></div> </div> </div> <section class="field field--name-comment-node-blog field--type-comment field--label-hidden comment-wrapper"> </section> Mon, 11 Nov 2019 14:17:56 +0000 vincentl 199 at https://www.vincentliefooghe.net Sailpoint : surcharger une classe Java spécifique https://www.vincentliefooghe.net/content/sailpoint-surcharger-une-classe-java-sp%C3%A9cifique <span property="dc:title" class="field field--name-title field--type-string field--label-hidden">Sailpoint : surcharger une classe Java spécifique</span> <div property="content:encoded" class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><h2 style="margin: 12px 0px; text-indent: 0px;">Contexte</h2> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Dans notre environnement <a href="https://www.sailpoint.com/">Sailpoint</a> IIQ, notre intégrateur développe un ensemble de classes Java pour étendre la solution, en utilisant les nombreuses API.</p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Les différentes livraisons se font sous la forme d'un <span style=" font-style:italic;">gros</span> fichier jar, reprenant l'ensemble des classes Java, qui est déposé dans le répertoire <span style=" font-style:italic;">IIQ_HOME/WEB-INF/lib</span>.</p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Par contre il arrive que l'on souhaite modifier le comportement d'une classe spécifique, sans attendre la prochaine livraison.</p> <p>Ceci est possible, en surchargeant juste la classe concernée.</p> <h2>Solution</h2> <p>Pour surcharger une classe Java, il faut recréer l'arborescence correspondante, sous le répertoire <span style=" font-style:italic;">IIQ_HOME/WEB-INF/classes</span>.</p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Par exemple, si la classe <span style=" font-style:italic;">MaSuperClasse.class</span> se trouve dans le package <span style=" font-style:italic;">com.mycompany.identityiq.utils</span>, on peut surcharger cette classe en créant la structure de répertoires : <span style=" font-style:italic;">IIQ_HOME/WEB-INF/classes/com/mycompany/identityiq/utils</span>, et en y copiant le fichier <span style=" font-style:italic;">MaSuperClasse.class</span>.</p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Après un redémarrage du serveur d'application, la nouvelle classe Java va surcharger celle qui est présente dans le répertoire <span style=" font-style:italic;">lib</span>.</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="2019-08-12T13:48:28+00:00" datatype="xsd:dateTime" class="field field--name-created field--type-created field--label-hidden">lun 12/08/2019 - 15:48</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/sailpoint" hreflang="fr">Sailpoint</a></div> </div> </div> <section class="field field--name-comment-node-blog field--type-comment field--label-hidden comment-wrapper"> </section> Mon, 12 Aug 2019 13:48:28 +0000 vincentl 198 at https://www.vincentliefooghe.net Upgrade Forgerock OpenDJ / DS https://www.vincentliefooghe.net/content/upgrade-forgerock-opendj-ds <span class="field field--name-title field--type-string field--label-hidden">Upgrade Forgerock OpenDJ / DS</span> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><p>Deux scénarios de migration / upgrade seront étudiés :</p> <ul> <li>upgrade "en place" d'un annuaire en version inférieure</li> <li>ajout dans la topologie de réplication d'un annuaire en version supérieure.</li> </ul> <p>Dans cet exemple, on va procéder à une migration de la version OpenDJ 3.5.1 à la version DS 6.5.</p> <h2>Environnement</h2> <p>L'environnement de test est le suivant :</p> <p>3 serveurs : <em>dj1.id-num.com</em>, <em>dj2.id-num.com</em>, <em>dj3.id-num.com</em>.</p> <p>Dans un premier temps, seuls les serveurs dj1 et dj2 sont installés, en mode multi-maîtres :</p> <ul> <li>O.S. CentOS 7</li> <li>Java jre 1.8</li> <li>OpenDJ 3.5.1, avec 2 annuaires répliqués</li> <li>Schéma de données <em>custom</em> avec attributs et classes d'objets spécifiques</li> <li>Annuaire installé dans le répertoire <code>/opt/opendj</code></li> <li>Index créé sur le serveur dj2, sur l'attribut <em>company</em></li> </ul> <h3>Script d'installation</h3> <p>L'installation sur les 2 serveurs a été faite avec le script suivant :</p> <pre><code>#!/bin/sh # # Installation Forgerock OpenDJ 3.5.1 # #--------------------------------------- LDAPPORT=1389 PASS=ldapMaster REPLADM=replicationAdmin REPLPASS=replicationPassword ADMINPORT=4445 HOST1=dj1.id-num.com HOST2=dj2.id-num.com HOST3=dj3.id-num.com JAVAHOME=/opt/jre1.8.0_144 BASEDN="o=example" BASEDIR=/opt/opendj BINDIR=${BASESDIR}/bin export JAVA_HOME=${JAVAHOME} export OPENDJ_JAVA_HOME=${JAVAHOME} ${BASEDIR}/setup \ --cli \ --baseDN ${BASEDN} \ --addBaseEntry \ --ldapPort ${LDAPPORT} \ --adminConnectorPort ${ADMINPORT} \ --rootUserDN cn=Directory\ Manager \ --rootUserPassword ${PASS} \ --acceptLicense \ --no-prompt \ --noPropertiesFile </code></pre><h3>Script de réplication</h3> <p>La réplication est mise en place entre les serveurs <strong>dj1</strong> et <strong>dj2</strong>, via la commande :</p> <pre><code>${BINDIR}/dsreplication enable \ --host1 ${HOST1} --port1 ${ADMINPORT} \ --bindDN1 "cn=Directory Manager" \ --bindPassword1 ${PASS} \ --replicationPort1 8989 \ --host2 ${HOST2} --port2 ${ADMINPORT} \ --bindDN2 "cn=Directory Manager" \ --bindPassword2 ${PASS} \ --replicationPort2 8989 \ --adminUID ${REPLADM} \ --adminPassword ${REPLPASS} \ --baseDN ${BASEDN} \ --trustAll \ --no-prompt </code></pre><p>On peut ensuite lancer l'init, pour tous les serveurs de la topologie :</p> <pre><code>${BINDIR}/dsreplication \ initialize-all \ --adminUID ${REPLADM} \ --adminPassword ${REPLPASS} \ --baseDN ${BASEDN} \ --hostname $(hostname) \ --port ${ADMINPORT} \ --trustAll \ --no-prompt </code></pre><p>On vérifie, avec l'option <em>status</em> :</p> <pre><code>${BINDIR}/dsreplication status \ --adminUID ${REPLADM} \ --adminPassword ${REPLPASS} \ --port ${ADMINPORT} \ --trustAll \ --no-prompt Suffix DN : Server : Entries : Replication enabled : DS ID : RS ID : RS Port (1) : M.C. (2) : A.O.M.C. (3) : Security (4) ---------------------:---------------------:---------:---------------------:-------:-------:-------------:----------:--------------:------------- cn=Directory Manager : dj2.id-num.com:4445 : : : : : : : : o=example : dj1.id-num.com:4445 : 45 : true : 14774 : 27576 : 8989 : 0 : : false o=example : dj2.id-num.com:4445 : : true : 29513 : 481 : 8989 : 0 : : false </code></pre><h3>Schéma spécifique</h3> <p>Le schéma est modifié avec l'ajout de 2 attributs et une classe d'objet :</p> <pre><code>dn: cn=schema changetype: modify add: attributeTypes attributeTypes: ( partneruid-oid NAME 'partneruid' SUP name X-ORIGIN 'user Defined' ) attributeTypes: ( company-oid NAME 'company' SUP name X-ORIGIN 'user Defined' ) - add: objectclasses objectClasses: ( partnerperson-oid NAME 'partnerPerson' SUP inetorgperson MUST ( company ) MAY ( partneruid) ) </code></pre><h3>Version OpenDJ / DS</h3> <p>On peut vérifier la version actuelle avec la commande :</p> <pre><code>/opt/opendj/bin/dsconfig --version 3.5.1 (revision 23b322a7502f029b6d3725212c162de36f038122) </code></pre><h2>Upgrade "en place"</h2> <p>Il faut tout d'abord vérifier la trajectoire de migration supportée.</p> <p>Pour <em>Directory Services 6.5</em>, sorti fin 2018, la migration est supportée depuis la version OpenDJ 2.6 et supérieure.</p> <p>La version de Java est également à vérifier : Java 8 ou 11 pour DS 6.5. Nous utilisons une version 8 ce qui convient donc.</p> <p>Forgerock recommande de faire une sauvegarde <strong>physique</strong> du serveur à <em>upgrader</em>, en arrêtant l'annuaire et en faisant un <em>backup</em> de toute l'arborescence :</p> <pre><code>/opt/opendj/bin/stop-ds tar zcf opendj-3.5.tgz opendj </code></pre><p><strong>Note</strong> : l'upgrade en place nécessite d'arrêter l'instance d'annuaire qui va être migrée.</p> <h3>Procédure de migration</h3> <p>La procédure est simple ; elle consiste essentiellement à :</p> <ul> <li>extraire l'archive de la nouvelle version au dessus de l'ancienne</li> <li>lancer la commande <strong>upgrade</strong></li> <li>vérifier et éventuellement adapter le paramétrage.</li> </ul> <p>En détail :</p> <pre><code>cd /opt unzip /path/to/Software/Forgerock/DS-6.6.0.zip Archive: DS-6.6.0.zip creating: opendj/legal-notices/third-party-licenses/ creating: opendj/template/extlib/ creating: opendj/template/setup-profiles/ .../... creating: opendj/template/setup-profiles/IDM/repo/6.5/ creating: opendj/template/setup-profiles/IDM/repo/6.5/schema/ replace opendj/snmp/mib/rfc2605.txt? [y]es, [n]o, [A]ll, [N]one, [r]ename: y </code></pre><p>Répondre "A" pour écraser / remplacer les anciennes versions de fichiers.</p> <p>Lancer ensuite l'upgrade :</p> <pre><code>/opt/opendj/upgrade &gt;&gt;&gt;&gt; OpenDJ Upgrade Utility * OpenDJ configuration will be upgraded from version 3.5.1.23b322a7502f029b6d3725212c162de36f038122 to 6.5.0.e2a029a050cc6908fd144a6ca9c687e01ad56ea3 * OpenDJ data will be upgraded from version 6.0.0 to 6.5.0.e2a029a050cc6908fd144a6ca9c687e01ad56ea3 * See '/opt/opendj/logs/upgrade.log' for a detailed log of this operation &gt;&gt;&gt;&gt; Preparing to upgrade OpenDJ 5.5.0 changed the indexing algorithm for JSON equality matching rules. All JSON based attribute indexes must be rebuilt which may take a long time. Do you want to rebuild the indexes automatically at the end of the upgrade? (yes/no) [no]: yes OpenDJ 6.5.0 changed the indexing algorithm for replication metadata. Its index must be rebuilt which may take a long time; without a working index every server start will take longer than normal. Do you want to rebuild the index automatically at the end of the upgrade? (yes/no) [no]: yes The upgrade is ready to proceed. Do you wish to continue? (yes/no) [yes]: &gt;&gt;&gt;&gt; Performing upgrade Adding configuration for schema providers........................... 100% Adding configuration entry 'dn: cn=Core Schema,cn=Schema Providers,cn=config'................................................ 100% Removing top configuration entry for matching rules................. 100% Removing configuration for syntaxes................................. 100% .../... Replacing schema file '02-config.ldif'.............................. 100% Archiving concatenated schema....................................... 100% Migrating replication changelog files to 6.5.0 format............... 100% &gt;&gt;&gt;&gt; OpenDJ configuration was successfully upgraded from version 3.5.1.23b322a7502f029b6d3725212c162de36f038122 to 6.5.0.e2a029a050cc6908fd144a6ca9c687e01ad56ea3 &gt;&gt;&gt;&gt; OpenDJ data was successfully upgraded from version 6.0.0 to 6.5.0.e2a029a050cc6908fd144a6ca9c687e01ad56ea3 &gt;&gt;&gt;&gt; Performing post upgrade tasks Rebuilding index(es) '[.caseIgnoreJsonQueryMatch, .caseExactJsonQueryMatch, ds-sync-hist.changeSequenceNumberOrderingMatch]' for base dn(s) '[o=example]'....................................................... 100% &gt;&gt;&gt;&gt; Post upgrade tasks complete </code></pre><p>Les logs de la migration se trouvent dans <code>$DSHOME/logs/upgrade.log</code>.</p> <p>On peut ensuite démarrer l'instance, via la commande <code>bin/start-ds</code></p> <p>L'annuaire est bien passé en version supérieure :</p> <pre><code>/opt/opendj/bin/dsconfig --version 6.5.0 (revision e2a029a050cc6908fd144a6ca9c687e01ad56ea3) </code></pre><h3>Post Upgrade</h3> <p>Si on part d'une version inférieure à la version 5.5, Forgerock rcommande de donner des privilèges spécifiques au compte de réplication. Les privilèges à ajouter sont les suivants :</p> <ul> <li>bypass-lockdown</li> <li>monitor-read</li> <li>server-lockdown</li> </ul> <p>Ceci peut être fait en LDIF. Dans notre cas, le compte utilisé est <em>replicationAdmin</em> :</p> <pre><code>dn: cn=replicationAdmin,cn=Administrators,cn=admin data changetype: modify add: ds-privilege-name ds-privilege-name: bypass-lockdown ds-privilege-name: monitor-read ds-privilege-name: server-lockdown </code></pre><p>La modification n'est à faire qu'une seule fois, les données étant répliquées.</p> <p>L'upgrade peut ensuite être fait pour tous les serveurs de la topologie.</p> <h2>Ajout d'un nouveau serveur dans la topologie</h2> <p>Dans cette option, on va ajouter un nouveau serveur dans la topologie de réplication. Ceci peut donc être fait sans interruption de service.</p> <h3>Installation de DS 6.5</h3> <p>L'installation ds DS 6.5 se fait quasiment de la même manière que OpenDJ 3.5. Les seules différences : pas d'option <em>--cli</em> et l'option <em>--hostname</em> qui est obligatoire.</p> <pre><code>LDAPPORT=1389 PASS=ldapMaster REPLADM=replicationAdmin REPLPASS=replicationPassword ADMINPORT=4445 HOST1=dj1.id-num.com HOST2=dj2.id-num.com HOST3=dj3.id-num.com JAVAHOME=/opt/jre1.8.0_144 BASEDN="o=example" BASEDIR=/opt/opendj BINDIR=${BASESDIR}/bin export JAVA_HOME=${JAVAHOME} export OPENDJ_JAVA_HOME=${JAVAHOME} /opt/opendj/setup \ --hostname ${HOST3} \ --baseDN ${BASEDN} \ --addBaseEntry \ --ldapPort ${LDAPPORT} \ --adminConnectorPort ${ADMINPORT} \ --rootUserDN cn=Directory\ Manager \ --rootUserPassword ${PASS} \ --acceptLicense </code></pre><p>A ce stade, on a donc un annuaire en mode "standby". Nous pouvons l'inclure dans le domaine de réplication.</p> <h3>Ajout dans la réplication</h3> <p>Forgerock recommande d'utiliser la commande <em>dsreplication</em> du nouveau serveur pour l'ajouter dans une topologie de réplication existante.</p> <p>La commande pour configurer une nouvelle réplication utilise maintenant l'option <em>configure</em> plutôt que <em>enable</em> :</p> <pre><code>${BINDIR}/dsreplication configure \ --host1 ${HOST1} --port1 4445 \ --bindDN1 "cn=Directory Manager" \ --bindPassword1 ${PASS} \ --replicationPort1 8989 \ --host2 ${HOST3} --port2 4445 \ --bindDN2 "cn=Directory Manager" \ --bindPassword2 ${PASS} \ --replicationPort2 8989 \ --adminUID ${REPLADM} \ --adminPassword ${REPLPASS} \ --baseDN ${BASEDN} \ --trustAll \ --no-prompt </code></pre><h3>Initialisation de la réplication</h3> <p>On peut maintenant lancer l'initialisation de la réplication sur un seul serveur. Avec l'option <em>initialize</em> plutôt que <em>initialize-all</em> il faut préciser les serveurs sources et destinations :</p> <pre><code>${BINDIR}/dsreplication initialize \ --adminUID ${REPLADM} \ --adminPassword ${REPLPASS} \ --baseDN ${BASEDN} \ --hostSource ${HOST1} \ --portSource ${ADMINPORT} \ --hostDestination ${HOST2} \ --portDestination ${ADMINPORT} \ --trustAll \ --no-prompt </code></pre><p>On peut ensuite vérifier :</p> <pre><code>Suffix DN : Server : Entries : Replication enabled : DS ID : RS ID : RS Port (1) : Delay (ms) : Security (2) ----------:---------------------:---------:---------------------:-------:-------:-------------:------------:------------- o=example : dj1.id-num.com:4445 : 2025 : true : 14774 : 27576 : 8989 : N/A : false o=example : dj2.id-num.com:4445 : 2025 : true : 29513 : 481 : 8989 : 0 : false o=example : dj3.id-num.com:4445 : 2025 : true : 706 : 30128 : 8989 : 0 : false </code></pre><p>Une fois que l'on a ajouté le nouveau serveur, il faut éventuellement paramétrer les éléments propres à l'instance (par exemple les index) qui sont positionnés via l'utilitaire <em>dsconfig</em>.</p> <h3>Adaptations et différences</h3> <p>On peut trouver quelques différences entre OpenDJ 3.5 et DS 6.5. A première vue, on peut citer :</p> <ul> <li>les options des commandes <em>dsconfig</em> ou <em>dsreplication</em></li> <li>les fichiers de définition du schéma qui ont migré de <code>DJ_HOME/config/schema</code> à <code>DS_HOME/db/schema</code></li> </ul> <h2>Synthèse</h2> <p>Nous avons vu que deux possibilités sont offertes pour faire un <em>upgrade</em>, de manière assez simple.</p> <p>L'upgrade "en place" est intéressant pour récupérer toute la configuration spécifique de l'instance (paramètres positionnés par l'utilitaire <strong>dsconfig</strong> et qui ne sont pas répliqués). Dans ce cas, on garde le même serveur, et donc la même version d'O.S., de java, et d'adresse IP.</p> <p>Cependant, ceci nécessite d'arrêter l'une des instances de la topologie de réplication.</p> <p>L'ajout d'une nouvelle instance peut se justifier si on veut changer de version d'O.S. et/ou limiter au maximum les interruptions de service. Cela permet aussi d'adapter les scripts aux nouvelles versions d'outils (<strong>même si l'environnement de Test est fait pour cela</strong>). Par contre, ceci implique de reprendre le paramétrage de la configuration.</p> <table> <tbody> <tr> <th>Méthode</th> <th>Avantages</th> <th>Inconvénients</th> </tr> <tr> <th>Upgrade en place</th> <td>Pas de changement d'adresse IP<br />Récupération de la configuration</td> <td>Arrêt de l'instance</td> </tr> <tr> <th>Ajout d'une nouvelle instance</th> <td>Possibilité de monter de version d'O.S.<br />Pas d'arrêt de serveur<br />Possibilité de tester les outils</td> <td>Nouveau serveur à provisionner<br />Nouvelle adresse IP à gérer<br />Pas de récupération du paramétrage spécifique</td> </tr> </tbody> </table> <p> </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">ven 14/12/2018 - 22:06</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> </div> <section class="field field--name-comment-node-book field--type-comment field--label-hidden comment-wrapper"> </section> Fri, 14 Dec 2018 21:06:26 +0000 vincentl 197 at https://www.vincentliefooghe.net Chiffrement de fichiers avec gnupg https://www.vincentliefooghe.net/content/chiffrement-fichiers-avec-gnupg <span property="dc:title" class="field field--name-title field--type-string field--label-hidden">Chiffrement de fichiers avec gnupg</span> <div property="content:encoded" class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><p>Lors de la mise en place d'une nouvelle architecture d'annuaire LDAP, nous avons sécurisé les différents composants : accès (utilisation LDAPS), suppression des accès anonymes, révision des ACI, chiffrement de la base de données.</p> <p>Les sauvegardes sont également chiffrées par l'outillage éditeur (Ping), et les exports LDIF également. <em>L'export des données en mode LDIF est intéressant pour pouvoir récupérer une seule entrée, sans devoir restaurer l'ensemble de la base</em>.</p> <p>Le souci, c'est que du coup il n'est pas possible de lire les fichiers LDIF chiffrés. Seul l'import dans la topologie de réplication est faisable, ce qui ne nous arrange pas.</p> <p>J'ai donc cherché une manière alternative de faire cela, l'idée étant la suivante :</p> <ul> <li>export LDIF en "clair", compressé</li> <li>chiffrement du fichier (de préférence sans devoir passer en paramètre la clé de chiffrement)</li> </ul> <p>Le déchiffrement du fichier pourrait se faire en saisissant un mot de passe ou une <em>pass phrase</em>. De cette manière, même si une personne accède au fichier et à la machine avec les clés, il ne pourra pas déchiffrer les fichiers.</p> <p>Après en avoir parlé avec un collègue, la solution <strong>gnupg</strong> est apparue comme une bonne solution.</p> <p>Voici donc ce que j'ai testé, avec les différentes étapes :</p> <ul> <li>installation</li> <li>création d'une paire de clés</li> <li>chiffrer un fichier</li> <li>déchiffrer un fichier</li> </ul> <h2>Installation</h2> <p>Sur un serveur linux de type Red Hat / CentOS, l'installation se fait simplement :</p> <pre><code>yum install gnupg2 </code></pre><h2>Création d'une paire de clés</h2> <p>La création d'une paire de clés est simple :</p> <pre>gpg --gen-key</pre><p>Il faut ensuite choisir le type de clé, la longueur (4096 bits recommandé), la durée de vie de la clé, puis un nom, une adresse mail, puis une <em>pass phrase</em></p> <pre><code>gpg --gen-key gpg (GnuPG) 1.4.23; Copyright (C) 2015 Free Software Foundation, Inc. This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Sélectionnez le type de clef désiré : (1) RSA et RSA (par défaut) (2) DSA et Elgamal (3) DSA (signature seule) (4) RSA (signature seule) Quel est votre choix ? 1 les clefs RSA peuvent faire une taille comprise entre 1024 et 4096 bits. Quelle taille de clef désirez-vous ? (2048) 4096 La taille demandée est 4096 bits Veuillez indiquer le temps pendant lequel cette clef devrait être valable. 0 = la clef n'expire pas &lt;n&gt; = la clef expire dans n jours &lt;n&gt;w = la clef expire dans n semaines &lt;n&gt;m = la clef expire dans n mois &lt;n&gt;y = la clef expire dans n ans Pendant combien de temps la clef est-elle valable ? (0) 2y La clef expire le dim. 29 nov. 2020 21:27:58 CET Est-ce correct ? (o/N) o Une identité est nécessaire à la clef ; le programme la construit à partir du nom réel, d'un commentaire et d'une adresse électronique de cette façon : « Heinrich Heine (le poète) &lt;heinrichh@duesseldorf.de&gt; » Nom réel : Vincent Liefooghe Adresse électronique : vincent.liefooghe@id-num.com Commentaire : Vous avez sélectionné cette identité : « Vincent Liefooghe &lt;vincent.liefooghe@id-num.com&gt; » Faut-il modifier le (N)om, le (C)ommentaire, l'(A)dresse électronique ou (O)ui/(Q)uitter ? O Une phrase secrète est nécessaire pour protéger votre clef secrète. De nombreux octets aléatoires doivent être générés. Vous devriez faire autre chose (taper au clavier, déplacer la souris, utiliser les disques) pendant la génération de nombres premiers ; cela donne au générateur de nombres aléatoires une meilleure chance d'obtenir suffisamment d'entropie. </code></pre><p>On peut ensuite lister les clés :</p> <pre><code>gpg --list-keys /root/.gnupg/pubring.gpg ------------------------ pub 4096R/CEBEF56F 2018-11-30 [expires: 2020-11-29] uid Vincent Liefooghe &lt;vincent.liefooghe@id-num.com&gt; sub 4096R/2D9F0F6E 2018-11-30 [expires: 2020-11-29] </code></pre><h2>Chiffrement d'un fichier</h2> <p>La syntaxe de chiffrement d'un fichier est assez simple également :</p> <pre><code>gpg -r "UID du destinataire" --encrypt &lt;FICHIER&gt; </code></pre><p>Par exemple :</p> <pre><code>gpg2 -r "Vincent Liefooghe &lt;vincent.liefooghe@id-num.com&gt;" --encrypt export.ldif </code></pre><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">On peut aussi utiliser l'ID de la clé :</p> <pre style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Monospace';">gpg2 -r 2D9F0F6E </span>--encrypt export.ldif </pre><style type="text/css"> <!--/*--><![CDATA[/* ><!--*/ <!--/*--><![CDATA[/* ><!--*/ p, li { white-space: pre-wrap; } /*--><!]]]]><![CDATA[>*/ /*--><!]]>*/ </style><p> <style type="text/css"> <!--/*--><![CDATA[/* ><!--*/ <!--/*--><![CDATA[/* ><!--*/ p, li { white-space: pre-wrap; } /*--><!]]]]><![CDATA[>*/ /*--><!]]>*/ </style></p> <p>Ceci va créer un fichier avec l'extension <em>.gpg</em>, :</p> <pre><code>ls -l total 14496 -rw-r--r-- 1 root root 13235368 Nov 30 20:41 export.ldif -rw-r--r-- 1 root root 1602319 Nov 30 20:45 export.ldif.gpg </code></pre><p>Le fichier <em>.gpg</em> est un binaire, non lisible :</p> <pre><code>file export* export.ldif: ASCII text export.ldif.gpg: GPG encrypted data </code></pre><h2>Déchiffrement d'un fichier</h2> <p>Une fois le fichier chiffré, il est quand même intéressant de pouvoir le déchiffrer ;-)</p> <p>La syntaxe est la suivante :</p> <pre><code>gpg2 --output &lt;FICHIER_DECHIFFRE&gt; --decrypt &lt;FICHIER_CHIFFRE.gpg&gt; </code></pre><p>Exemple :</p> <pre><code>gpg --output EXPORT.clair.ldif --decrypt export.ldif.gpg Une phrase secrète est nécessaire pour déverrouiller la clef secrète de l'utilisateur : « Vincent Liefooghe &lt;vincent.liefooghe@id-num.com&gt; » clef RSA de 4096 bits, identifiant 2D9F0F6E, créée le 2018-11-30 (identifiant de clef principale CEBEF56F) gpg: chiffré avec une clef RSA de 4096 bits, identifiant 2D9F0F6E, créée le 2018-11-30 « Vincent Liefooghe &lt;vincent.liefooghe@id-num.com&gt; » </code></pre><p>On peut alors voir le résultat :</p> <pre><code>ls -l total 27424 -rw-rw-r--. 1 vliefooghe vliefooghe 13235368 30 nov. 21:54 EXPORT.clair.ldif -rw-r--r--. 1 vliefooghe vliefooghe 13235368 30 nov. 21:53 export.ldif -rw-rw-r--. 1 vliefooghe vliefooghe 1602318 30 nov. 21:54 export.ldif.gpg </code></pre><p>Le fichier <code>EXPORT.clair.ldif</code> est bien en clair, et on peut donc en extraire les données requises :</p> <pre><code>head EXPORT.clair.ldif # Sending search request SearchRequest(baseDN='ou=people,ou=be,o=example', scope=SUB, deref=NEVER, sizeLimit=0, timeLimit=0, filter='(objectclass=*)', attrs={}) dn: ou=People,ou=BE,o=example objectClass: top objectClass: organizationalUnit ou: People dn: uid=117301,ou=People,ou=BE,o=example objectClass: top objectClass: person objectClass: organizationalPerson </code></pre><h2>Références</h2> <p>La documentation Ubuntu est assez bien faite sur ce sujet : <a href="https://doc.ubuntu-fr.org/gnupg">doc.ubuntu-fr.org/gnupg</a>.</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-11-30T21:00:02+00:00" datatype="xsd:dateTime" class="field field--name-created field--type-created field--label-hidden">ven 30/11/2018 - 22:00</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/floss" hreflang="fr">FLOSS</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/securit%C3%A9" hreflang="fr">securité</a></div> <div class="field__item"><a href="/tags/chiffrement" hreflang="fr">chiffrement</a></div> </div> </div> <section class="field field--name-comment-node-blog field--type-comment field--label-hidden comment-wrapper"> </section> Fri, 30 Nov 2018 21:00:02 +0000 vincentl 196 at https://www.vincentliefooghe.net