<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://lunik.tiwabbit.fr/blog/fr/</id>
    <title>Lunik's Blog</title>
    <updated>2026-05-16T00:00:00.000Z</updated>
    <generator>https://github.com/jpmonette/feed</generator>
    <link rel="alternate" href="https://lunik.tiwabbit.fr/blog/fr/"/>
    <subtitle>LeadTech DevOps &amp; Cloud &amp; IA engineer blog</subtitle>
    <icon>https://lunik.tiwabbit.fr/blog/fr/img/favicon.ico</icon>
    <rights>Copyright © 2026 Guillaume MARTINEZ</rights>
    <entry>
        <title type="html"><![CDATA[Vibe Coding à presque zéro coût : Claude Code + OpenRouter avec des modèles gratuits]]></title>
        <id>https://lunik.tiwabbit.fr/blog/fr/vibe-coding-claude-code-openrouter</id>
        <link href="https://lunik.tiwabbit.fr/blog/fr/vibe-coding-claude-code-openrouter"/>
        <updated>2026-05-16T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Comment je construis un logiciel pour pratiquement aucun coût en combinant Claude Code et les modèles gratuits d'OpenRouter]]></summary>
        <content type="html"><![CDATA[<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2026-05-16-vibe-coding-claude-code-openrouter/cover.png" alt="cover" class="img__Ss2"></p>
<p>J'ai intégré l'IA dans mon flux de travail de développement, mais j'ai rapidement réalisé que les coûts pouvaient exploser si je ne surveillais pas chaque appel d'API. Les assistants de codage basés sur l'IA avec leurs modèles d'abonnement et leurs "offres pro" peuvent devenir très chers - surtout pour des projets personnels ou open‑source où le budget est limité. Je devais suivre chaque appel d'API et surveiller mon utilisation comme un fou.</p>
<p>La barrière de coût pour les assistants de codage IA a finalement disparu. Après des mois d'expérimentations, j'ai trouvé une combinaison qui me permet de construire un logiciel de qualité production tout en dépensant presque rien : <a href="https://github.com/anthropics/claude-code" target="_blank" rel="noopener noreferrer" class="">Claude Code</a> associé aux modèles gratuits d'<a href="https://openrouter.ai/" target="_blank" rel="noopener noreferrer" class="">OpenRouter</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="lévolution-de-mon-environnement-dia">L'évolution de mon environnement d'IA<a href="https://lunik.tiwabbit.fr/blog/fr/vibe-coding-claude-code-openrouter#l%C3%A9volution-de-mon-environnement-dia" class="hash-link" aria-label="Lien direct vers L'évolution de mon environnement d'IA" title="Lien direct vers L'évolution de mon environnement d'IA" translate="no">​</a></h2>
<p>Lorsque j'ai commencé à utiliser les assistants de codage IA, la réalité m'a rapidement frappé : la qualité a un prix. Les modèles premium d'Anthropic, OpenAI, et d'autres peuvent facilement faire exploser la facture de 50 $ à 100 $+ par mois pour un usage régulier. En tant que développeur indépendant, ce n'est pas durable.</p>
<p>Mon parcours s'est déroulé ainsi :</p>
<ol>
<li class=""><strong>Premiers essais</strong> : appels API directs vers les modèles premium (coûteux) – <a href="https://platform.claude.com/docs/en/about-claude/models/overview" target="_blank" rel="noopener noreferrer" class="">Claude Opus/Sonnet</a> était excellent mais prohibitif.</li>
<li class=""><strong>Phase intermédiaire</strong> : mélange de modèles premium et open‑source (coût moyen) – j'ai testé les modèles Mistral moins chers, mais la qualité était nettement inférieure.</li>
<li class=""><strong>Expériences locales</strong> : tentative d'exécuter les modèles en local avec Ollama – le MacBook Air M2 (16 Go) manque de VRAM pour les gros modèles, les petits modèles (Gemma) ont une qualité médiocre, et même avec le swap, les modèles moyens (Qwen quantifié) sont très lents.</li>
<li class=""><strong>Configuration actuelle</strong> : <a href="https://github.com/anthropics/claude-code" target="_blank" rel="noopener noreferrer" class="">Claude Code</a> + <a href="https://openrouter.ai/" target="_blank" rel="noopener noreferrer" class="">OpenRouter</a> free tier (coût quasi nul).</li>
</ol>
<p>Le déclic est intervenu quand j'ai compris que, pour de nombreuses tâches de codage, je n'avais pas besoin des modèles les plus chers et les plus récents. J'avais besoin de modèles qui :</p>
<ul>
<li class="">Soient suffisamment bons pour comprendre le contexte du code</li>
<li class="">Puissent générer du code fonctionnel</li>
<li class="">Soient assez rapides pour ne pas interrompre mon flux de travail</li>
<li class="">Soient gratuits ou très bon marché</li>
</ul>
<p>L'approche que j'ai gardé, c'est d'utiliser un modèle volumineux pour la phase de planification (mode plan <a href="https://github.com/anthropics/claude-code" target="_blank" rel="noopener noreferrer" class="">Claude Code</a>), j'utilise ensuite un modèle peu coûteux, souvent gratuit, pour développer la fonctionnalité. Cette approche hybride me permet de structurer la tâche avec la puissance d'un gros modèle tout en limitant les coûts pendant le codage réel.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="pourquoi-claude-code">Pourquoi Claude Code ?<a href="https://lunik.tiwabbit.fr/blog/fr/vibe-coding-claude-code-openrouter#pourquoi-claude-code" class="hash-link" aria-label="Lien direct vers Pourquoi Claude Code ?" title="Lien direct vers Pourquoi Claude Code ?" translate="no">​</a></h2>
<p><a href="https://github.com/anthropics/claude-code" target="_blank" rel="noopener noreferrer" class="">Claude Code</a> est devenu mon interface principale pour le codage assisté par IA parce qu'il offre quelque chose d'unique : une expérience native du terminal qui ressemble à du pair‑programming avec un collègue expérimenté.</p>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="points-forts">Points forts :<a href="https://lunik.tiwabbit.fr/blog/fr/vibe-coding-claude-code-openrouter#points-forts" class="hash-link" aria-label="Lien direct vers Points forts :" title="Lien direct vers Points forts :" translate="no">​</a></h3>
<ul>
<li class=""><strong>Intégration terminale fluide</strong> : aucune perte de contexte entre l'IDE et le chat.</li>
<li class=""><strong>Opérations conscientes du fichier</strong> : il comprend la structure du projet et peut lire/écrire des fichiers directement.</li>
<li class=""><strong>Flux de travail basé sur les commandes</strong> : intégration naturelle avec les pratiques de développement existantes.</li>
<li class=""><strong>Mémoire de session</strong> : se souvient du contexte au cours d'une même session.</li>
<li class=""><strong>Boucle agentique :</strong> Claude Code utilise une boucle d'agentisation qui analyse le contexte, propose des actions (édition, lecture, exécution) et les itère automatiquement, offrant une assistance réactive et proactive.</li>
<li class=""><strong>Outils et skills :</strong> il intègre des compétences intégrées comme ultrareview, planification, gestion des dépendances et d’autres micro‑outils qui rendent le flux de travail fluides et puissants.</li>
</ul>
<p>Ce qui distingue réellement <a href="https://github.com/anthropics/claude-code" target="_blank" rel="noopener noreferrer" class="">Claude Code</a>, c'est la façon dont il gère les opérations multi‑fichiers complexes. Au lieu de simplement proposer des extraits, il peut implémenter des fonctionnalités à travers plusieurs fichiers, exécuter des tests et même déboguer des problèmes.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="lavantage-du-tier-gratuit-dopenrouter">L'avantage du tier gratuit d'OpenRouter<a href="https://lunik.tiwabbit.fr/blog/fr/vibe-coding-claude-code-openrouter#lavantage-du-tier-gratuit-dopenrouter" class="hash-link" aria-label="Lien direct vers L'avantage du tier gratuit d'OpenRouter" title="Lien direct vers L'avantage du tier gratuit d'OpenRouter" translate="no">​</a></h2>
<p><a href="https://openrouter.ai/" target="_blank" rel="noopener noreferrer" class="">OpenRouter</a> propose plusieurs modèles de haute qualité sans frais :</p>
<p><strong>Modèles que j'utilise régulièrement :</strong></p>
<ul>
<li class=""><strong>Nemotron 3 Super</strong> (modèle principal gratuit, parfois avec une petite commission par requête) : excellent pour la génération de code et la compréhension – je l'ai choisi pour ses capacités de raisonnement, son temps de première token rapide et son débit.</li>
<li class=""><strong>Modèles Mistral</strong> : bonnes performances sur les tâches de codage.</li>
<li class=""><strong>Modèles Gemma de Google</strong> : étonnamment capables pour leur taille.</li>
<li class=""><strong>OpenAI GPT OSS (120 b)</strong> : modèle open‑source très grand, offrant une compréhension approfondie du texte et du code, idéal pour les prompts détaillés et les tâches nécessitant de larges fenêtres de contexte.</li>
</ul>
<p><strong>Note importante sur les limites du tier gratuit</strong> : les modèles sont gratuits, mais OpenRouter impose des limites de débit pour éviter les abus. Les utilisateurs du tier gratuit sont limités à 20 requêtes par minute. Il existe également des limites quotidiennes basées sur le crédit :</p>
<ul>
<li class="">Moins de 10 crédits : 50 requêtes gratuites par jour.</li>
<li class="">Au moins 10 crédits : 1000 requêtes gratuites par jour.</li>
</ul>
<p>J'ai constaté qu'acheter seulement 10 $ de crédit sur OpenRouter (ce qui dure longtemps vu le faible coût des modèles) me donne largement de marge pour le travail quotidien. Le coût est négligeable comparé aux assistants IA traditionnels.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="linsight-clé-choisir-le-bon-modèle-selon-la-tâche">L'insight clé : choisir le bon modèle selon la tâche<a href="https://lunik.tiwabbit.fr/blog/fr/vibe-coding-claude-code-openrouter#linsight-cl%C3%A9-choisir-le-bon-mod%C3%A8le-selon-la-t%C3%A2che" class="hash-link" aria-label="Lien direct vers L'insight clé : choisir le bon modèle selon la tâche" title="Lien direct vers L'insight clé : choisir le bon modèle selon la tâche" translate="no">​</a></h2>
<ul>
<li class=""><strong>Conversations d'architecture / design</strong> : utilisez le modèle gratuit le plus performant.</li>
<li class=""><strong>Génération de code simple</strong> : les modèles de milieu de gamme suffisent largement.</li>
<li class=""><strong>Débogage / analyse de logs</strong> : même les petits modèles excellent dans le pattern matching.</li>
<li class=""><strong>Apprentissage / exploration</strong> : n'importe quel modèle peut aider à expliquer des concepts.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="analyse-des-coûts--un-développement-quasi-gratuit">Analyse des coûts – Un développement quasi gratuit<a href="https://lunik.tiwabbit.fr/blog/fr/vibe-coding-claude-code-openrouter#analyse-des-co%C3%BBts--un-d%C3%A9veloppement-quasi-gratuit" class="hash-link" aria-label="Lien direct vers Analyse des coûts – Un développement quasi gratuit" title="Lien direct vers Analyse des coûts – Un développement quasi gratuit" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="approche-traditionnelle">Approche traditionnelle :<a href="https://lunik.tiwabbit.fr/blog/fr/vibe-coding-claude-code-openrouter#approche-traditionnelle" class="hash-link" aria-label="Lien direct vers Approche traditionnelle :" title="Lien direct vers Approche traditionnelle :" translate="no">​</a></h3>
<ul>
<li class="">Claude Pro : 20 $/mois</li>
<li class="">GitHub Copilot : 10 $/mois</li>
<li class="">Utilisation de l'API OpenAI : 20‑50 $/mois (selon l'usage)</li>
<li class=""><strong>Total : 50‑80 $/mois</strong></li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="mon-approche-actuelle">Mon approche actuelle :<a href="https://lunik.tiwabbit.fr/blog/fr/vibe-coding-claude-code-openrouter#mon-approche-actuelle" class="hash-link" aria-label="Lien direct vers Mon approche actuelle :" title="Lien direct vers Mon approche actuelle :" translate="no">​</a></h3>
<ul>
<li class=""><a href="https://github.com/anthropics/claude-code" target="_blank" rel="noopener noreferrer" class="">Claude Code</a> : gratuit (outil CLI open‑source)</li>
<li class="">Tier gratuit d'<a href="https://openrouter.ai/" target="_blank" rel="noopener noreferrer" class="">OpenRouter</a> : 0 $</li>
<li class="">Utilisation occasionnelle de modèles premium pour les tâches complexes : &lt; 2 $/mois</li>
<li class=""><strong>Total : &lt; 2 $/mois</strong></li>
</ul>
<p>Cela représente une réduction de 95‑97 % tout en conservant une excellente vélocité de développement.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="considérations-de-qualité">Considérations de qualité<a href="https://lunik.tiwabbit.fr/blog/fr/vibe-coding-claude-code-openrouter#consid%C3%A9rations-de-qualit%C3%A9" class="hash-link" aria-label="Lien direct vers Considérations de qualité" title="Lien direct vers Considérations de qualité" translate="no">​</a></h2>
<p>Vous vous demandez peut‑être si l'utilisation de modèles gratuits compromet la qualité. Mon expérience montre que ce n'est pas le cas, avec quelques réserves :</p>
<p><strong>Où les modèles gratuits excellent :</strong></p>
<ul>
<li class="">Génération de code boilerplate</li>
<li class="">Algorithmes et structures de données standards</li>
<li class="">Intégration d'API</li>
<li class="">Documentation et commentaires</li>
<li class="">Corrections de bugs et refactorisations</li>
</ul>
<p><strong>Où vous pourriez préférer les modèles premium :</strong></p>
<ul>
<li class="">Décisions architecturales complexes</li>
<li class="">Développement d'algorithmes novateurs</li>
<li class="">Gestion des cas limites dans du code critique pour la sécurité</li>
<li class="">Quand une fiabilité maximale est requise</li>
</ul>
<p>L'astuce consiste à savoir quand utiliser quel modèle. Pour 80 % de mes tâches de codage, les modèles gratuits d'<a href="https://openrouter.ai/" target="_blank" rel="noopener noreferrer" class="">OpenRouter</a> sont largement suffisants.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="astuces-pour-maximiser-lutilisation-du-tier-gratuit">Astuces pour maximiser l'utilisation du tier gratuit<a href="https://lunik.tiwabbit.fr/blog/fr/vibe-coding-claude-code-openrouter#astuces-pour-maximiser-lutilisation-du-tier-gratuit" class="hash-link" aria-label="Lien direct vers Astuces pour maximiser l'utilisation du tier gratuit" title="Lien direct vers Astuces pour maximiser l'utilisation du tier gratuit" translate="no">​</a></h2>
<ol>
<li class=""><strong>Soyez précis dans vos prompts</strong> : les requêtes vagues gaspillent des tokens et donnent de moins bons résultats.</li>
<li class=""><strong>Divisez les problèmes en plus petits morceaux</strong> : plus facile pour les modèles, moins de contexte nécessaire.</li>
<li class=""><strong>Utilisez le bon modèle pour chaque tâche</strong> : faites correspondre la capacité du modèle à la complexité de la tâche.</li>
<li class=""><strong>Exploitez les opérations de fichiers de Claude Code</strong> : laissez‑lui lire votre base de code pour un meilleur contexte.</li>
<li class=""><strong>Mettez en cache les bons prompts</strong> : sauvegardez les modèles de prompts efficaces pour les réutiliser.</li>
<li class=""><strong>Surveillez l'usage</strong> : gardez un œil sur les modèles que vous utilisez le plus efficacement.</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="la-vision-plus-large-lia-pour-tous">La vision plus large : l'IA pour tous<a href="https://lunik.tiwabbit.fr/blog/fr/vibe-coding-claude-code-openrouter#la-vision-plus-large-lia-pour-tous" class="hash-link" aria-label="Lien direct vers La vision plus large : l'IA pour tous" title="Lien direct vers La vision plus large : l'IA pour tous" translate="no">​</a></h2>
<p>Ce qui me passionne le plus dans cette configuration, ce n'est pas seulement les économies - c'est l'effet de démocratisation. Lorsque le développement assisté par IA devient accessible à quasiment n'importe qui avec une connexion Internet, nous libérons un potentiel créatif immense.</p>
<p>Imaginez :</p>
<ul>
<li class="">Des étudiants dans des pays en développement apprenant à coder avec l'aide d'une IA.</li>
<li class="">Des hobbyistes construisant des projets sans se soucier des factures d'API.</li>
<li class="">Des entrepreneurs validant rapidement leurs idées à moindre coût.</li>
<li class="">Des contributeurs open‑source œuvrant plus efficacement.</li>
</ul>
<p>Ce n'est pas seulement une question d'économie ; c'est abaisser la barrière d'entrée pour la création de logiciels.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="pour-commencer-vousmême">Pour commencer vous‑même<a href="https://lunik.tiwabbit.fr/blog/fr/vibe-coding-claude-code-openrouter#pour-commencer-vousm%C3%AAme" class="hash-link" aria-label="Lien direct vers Pour commencer vous‑même" title="Lien direct vers Pour commencer vous‑même" translate="no">​</a></h2>
<ol>
<li class=""><strong>Installez Claude Code</strong> : <code>brew install claude-code</code> (via <a href="https://brew.sh/" target="_blank" rel="noopener noreferrer" class="">Homebrew</a>)</li>
<li class=""><strong>Inscrivez‑vous sur OpenRouter</strong> : <a href="https://openrouter.ai/" target="_blank" rel="noopener noreferrer" class="">OpenRouter</a> (tier gratuit disponible immédiatement)</li>
<li class=""><strong>Configurez votre clé API OpenRouter</strong> dans les paramètres de <a href="https://github.com/anthropics/claude-code" target="_blank" rel="noopener noreferrer" class="">Claude Code</a>
<div class="language-text codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-text codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">export ANTHROPIC_BASE_URL="https://openrouter.ai/api"</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">export ANTHROPIC_AUTH_TOKEN="&lt;votre‑clé‑OpenRouter&gt;"</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">export ANTHROPIC_API_KEY=""</span><br></div></code></pre></div></div>
<!-- -->Laisser <code>ANTHROPIC_API_KEY</code> vide indique à Claude Code d'ignorer la clé intégrée et d'utiliser l'URL et le token personnalisés ci‑dessus.</li>
<li class=""><strong>Commencez avec des tâches simples</strong> pour vous familiariser avec les réponses des modèles.</li>
<li class=""><strong>Expérimentez différents modèles</strong> pour identifier ce qui fonctionne le mieux dans votre flux de travail.</li>
</ol>
<p><strong>Configuration du modèle :</strong> J'utilise <code>openai/gpt-oss-120b:free</code> avec <code>maxContextTokens</code> réglé à 135000 dans <code>~/.claude/settings.json</code>.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="lavenir-du-codage-ia-abordable">L'avenir du codage IA abordable<a href="https://lunik.tiwabbit.fr/blog/fr/vibe-coding-claude-code-openrouter#lavenir-du-codage-ia-abordable" class="hash-link" aria-label="Lien direct vers L'avenir du codage IA abordable" title="Lien direct vers L'avenir du codage IA abordable" translate="no">​</a></h2>
<p>À mesure que les modèles open‑source s'améliorent et que des plateformes comme <a href="https://openrouter.ai/" target="_blank" rel="noopener noreferrer" class="">OpenRouter</a> élargissent leurs tiers gratuits, je suis convaincu que nous nous dirigeons vers un futur où l'IA‑assisted coding de haute qualité sera à la portée de tous, quel que soit le budget.</p>
<p>Les outils sont déjà là. La barrière de coût tombe. Il ne reste plus qu'à construire.</p>]]></content>
        <author>
            <name>Guillaume MARTINEZ</name>
            <uri>https://github.com/Lunik</uri>
        </author>
        <category label="ai" term="ai"/>
        <category label="coding" term="coding"/>
        <category label="claude-code" term="claude-code"/>
        <category label="openrouter" term="openrouter"/>
        <category label="llm" term="llm"/>
        <category label="productivité" term="productivité"/>
        <category label="développement-logiciel" term="développement-logiciel"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Scripts crypto : Stellar XLM & Ethereum]]></title>
        <id>https://lunik.tiwabbit.fr/blog/fr/building-crypto-send-receive-scripts</id>
        <link href="https://lunik.tiwabbit.fr/blog/fr/building-crypto-send-receive-scripts"/>
        <updated>2026-04-24T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Un guide pratique pour construire des scripts sûrs, prêts pour la production, permettant d'envoyer et recevoir des cryptomonnaies sur les réseaux Stellar et Ethereum]]></summary>
        <content type="html"><![CDATA[<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2026-04-24-building-crypto-send-receive-scripts/cover.png" alt="cover" class="img__Ss2"></p>
<p>Je ne fais pas confiance aux applications avec ma crypto. Chaque <em>wallet</em>, <em>exchange</em>, et <em>dapp</em> est une boîte noire. Vous confiez votre clé privée, cliquez sur « envoyer », et espérez que le code fait ce qu'il prétend. Donc j'ai construit mes propres scripts à la place : de petits programmes Python auditables que je peux lire et comprendre complètement.</p>
<p>Les différences entre Stellar et Ethereum forcent à confronter la philosophie de conception de chaque blockchain. Voici ce que j'ai appris en construisant des scripts pour les deux.</p>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="commencer--génération-de-paires-de-clés">Commencer : génération de paires de clés<a href="https://lunik.tiwabbit.fr/blog/fr/building-crypto-send-receive-scripts#commencer--g%C3%A9n%C3%A9ration-de-paires-de-cl%C3%A9s" class="hash-link" aria-label="Lien direct vers Commencer : génération de paires de clés" title="Lien direct vers Commencer : génération de paires de clés" translate="no">​</a></h3>
<p>La première différence m'a frappé immédiatement : <strong>comment financer un compte <em>testnet</em> ?</strong></p>
<p>Avec Stellar, c'est presque trop facile. Générer une paire de clés, puis appeler Friendbot une fois :</p>
<div class="language-python codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-python codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">keypair </span><span class="token operator">=</span><span class="token plain"> Keypair</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">random</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">public_key </span><span class="token operator">=</span><span class="token plain"> keypair</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">public_key</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">url </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">f"https://friendbot.stellar.org?addr=</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">public_key</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">response </span><span class="token operator">=</span><span class="token plain"> urllib</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">urlopen</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">url</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">body </span><span class="token operator">=</span><span class="token plain"> json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">loads</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">response</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">read</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">funding_tx </span><span class="token operator">=</span><span class="token plain"> body</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"hash"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></div></code></pre></div></div>
<p>Boom. <code>10 000 XLM</code>, instantanément. Stellar a été conçu pour les développeurs.</p>
<p>Ethereum ? Une histoire différente.</p>
<div class="language-python codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-python codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">account </span><span class="token operator">=</span><span class="token plain"> Account</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">create</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">address </span><span class="token operator">=</span><span class="token plain"> account</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">address</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">private_key </span><span class="token operator">=</span><span class="token plain"> account</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">key</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token builtin" style="color:rgb(189, 147, 249)">hex</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></div></code></pre></div></div>
<p>Puis il faut aller trouver un <em>faucet</em> qui permettra d'alimenter le compte sur le réseau <em>testnet</em>. J'ai opté pour l'<a href="https://cloud.google.com/application/web3/faucet/ethereum/sepolia" target="_blank" rel="noopener noreferrer" class="">Ethereum Sepolia Faucet</a> de Google qui m'a permis de commencer rapidement avec <code>0.05 Sepolia ETH</code>.</p>
<p>Le <em>testnet</em> d'Ethereum vous demande de prouver que vous êtes humain. Ce n'est pas un défaut, c'est un choix de conception. Sepolia est rare par conception, et cette rareté vous force à être intentionnel à propos des tests.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="le-problème-des-décimales">Le problème des décimales<a href="https://lunik.tiwabbit.fr/blog/fr/building-crypto-send-receive-scripts#le-probl%C3%A8me-des-d%C3%A9cimales" class="hash-link" aria-label="Lien direct vers Le problème des décimales" title="Lien direct vers Le problème des décimales" translate="no">​</a></h2>
<p>J'ai découvert le problème des limites de décimales par accident. J'ai essayé d'envoyer <code>10.12345678 XLM</code> et Stellar l'a rejeté silencieusement au niveau <em>RPC</em>. Il s'avère que Stellar s'arrête à <code>7</code> décimales :</p>
<div class="language-python codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-python codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">value </span><span class="token operator">=</span><span class="token plain"> Decimal</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">amount</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">decimals </span><span class="token operator">=</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">abs</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">value</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">as_tuple</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">exponent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)"># Stellar : max 7</span><br></div></code></pre></div></div>
<p>Ethereum va beaucoup plus loin. <code>18</code> décimales, parce que <em>wei</em> (<code>10^-18 ETH</code>) est la plus petite unité :</p>
<div class="language-python codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-python codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">value </span><span class="token operator">=</span><span class="token plain"> Decimal</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">amount</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">amount_wei </span><span class="token operator">=</span><span class="token plain"> Web3</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">to_wei</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">value</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"ether"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)"># Ethereum : max 18</span><br></div></code></pre></div></div>
<p>Cela m'a enseigné quelque chose : <strong>les blockchains ne sont pas interchangeables</strong>. Elles ont des contraintes dures intégrées dans leur protocole. On ne peut pas simplement déplacer du code de l'une à l'autre, il faut comprendre et respecter les limites de chaque système.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="mémos--différents-compromis">Mémos : différents compromis<a href="https://lunik.tiwabbit.fr/blog/fr/building-crypto-send-receive-scripts#m%C3%A9mos--diff%C3%A9rents-compromis" class="hash-link" aria-label="Lien direct vers Mémos : différents compromis" title="Lien direct vers Mémos : différents compromis" translate="no">​</a></h2>
<p>Je voulais inclure des mémos descriptifs dans les transactions, quelque chose comme « facture #12345 » pour suivre les paiements. Stellar l'a rendu simple :</p>
<div class="language-python codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-python codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">memo </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"payment"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">builder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">add_text_memo</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">memo</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)"># 28 octets UTF-8, gratuit</span><br></div></code></pre></div></div>
<p><code>28 octets</code>, inclus dans les frais de base. Terminé.</p>
<p>Ethereum n'a pas de mémos natifs. À la place, vous encodez les données dans la transaction elle-même :</p>
<div class="language-python codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-python codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">memo </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"payment"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">data </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"0x"</span><span class="token plain"> </span><span class="token operator">+</span><span class="token plain"> memo</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">encode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"utf-8"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token builtin" style="color:rgb(189, 147, 249)">hex</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">tx</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"data"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> data  </span><span class="token comment" style="color:rgb(98, 114, 164)"># Chaque octet ≈ 16 gaz</span><br></div></code></pre></div></div>
<p>C'est coûteux. Un mémo de <code>256 octets</code> coûte <code>~4 000 gaz</code>, ce qui aux taux actuels représente environ <code>0,10 $</code>. Donc sur Ethereum, vous y pensez à deux fois avant d'ajouter des métadonnées à une transaction. Sur Stellar, vous le mettez sans y penser. Conception différente, compromis différents.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="le-problème-de-destination">Le problème de destination<a href="https://lunik.tiwabbit.fr/blog/fr/building-crypto-send-receive-scripts#le-probl%C3%A8me-de-destination" class="hash-link" aria-label="Lien direct vers Le problème de destination" title="Lien direct vers Le problème de destination" translate="no">​</a></h2>
<p>Quand j'ai testé l'envoi vers un compte inexistant, j'ai obtenu des comportements complètement différents.</p>
<p>Sur Stellar, cela échoue :</p>
<div class="language-python codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-python codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">server</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">load_account</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">destination</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)"># Vérifier si le compte existe</span><br></div></code></pre></div></div>
<p>Stellar vous oblige à prouver que le compte de destination est réel. S'il n'existe pas, vous ne pouvez pas envoyer. Vous avez besoin d'une opération <code>create_account</code> d'abord, puis d'un envoi. Deux étapes. Cela vous force à réfléchir à ce que vous faites.</p>
<p>Sur Ethereum, n'importe quelle adresse est valide :</p>
<div class="language-python codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-python codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">destination </span><span class="token operator">=</span><span class="token plain"> Web3</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">to_checksum_address</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">destination</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)"># Normaliser avec checksum</span><br></div></code></pre></div></div>
<p>Ethereum enverra volontiers des fonds vers une adresse qui n'existe pas encore. L'adresse est valide, la transaction réussit, et maintenant ces fonds sont verrouillés dans une adresse contractuelle que personne ne possède. Pour toujours. Le <em>checksum</em> vous aide à éviter les fautes de frappe, mais il ne peut pas vous sauver d'une mauvaise adresse.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="modèles-de-frais--la-plus-grande-différence">Modèles de frais : la plus grande différence<a href="https://lunik.tiwabbit.fr/blog/fr/building-crypto-send-receive-scripts#mod%C3%A8les-de-frais--la-plus-grande-diff%C3%A9rence" class="hash-link" aria-label="Lien direct vers Modèles de frais : la plus grande différence" title="Lien direct vers Modèles de frais : la plus grande différence" translate="no">​</a></h2>
<p>C'est ici que Stellar et Ethereum ont révélé leurs philosophies fondamentalement différentes.</p>
<p>Le modèle de frais de Stellar est d'une simplicité désarmante :</p>
<div class="language-python codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-python codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">base_fee </span><span class="token operator">=</span><span class="token plain"> server</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">fetch_base_fee</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">ops_count </span><span class="token operator">=</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">len</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">transaction</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">transaction</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">operations</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">fee </span><span class="token operator">=</span><span class="token plain"> base_fee </span><span class="token operator">*</span><span class="token plain"> ops_count </span><span class="token operator">/</span><span class="token plain"> </span><span class="token number">10_000_000</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">print</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">f"Frais : </span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">fee</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)"> XLM (</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">ops_count</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)"> opérations)"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></div></code></pre></div></div>
<p>Récupérer les frais de base, multiplier par le nombre d'opérations, terminé. Les frais sont prévisibles. Ils s'ajustent doucement avec la charge du réseau. Vous pouvez estimer les coûts de gaz avec précision avant de soumettre.</p>
<p>Le modèle d'Ethereum est... plus complexe :</p>
<div class="language-python codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-python codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">gas_price </span><span class="token operator">=</span><span class="token plain"> w3</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">eth</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">gas_price</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">tx </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"from"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> source</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"to"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> dest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"value"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> amount_wei</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">gas_limit </span><span class="token operator">=</span><span class="token plain"> w3</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">eth</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">estimate_gas</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">tx</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">fee </span><span class="token operator">=</span><span class="token plain"> gas_limit </span><span class="token operator">*</span><span class="token plain"> gas_price</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">print</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">f"Frais : ~</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">Web3</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token string-interpolation interpolation">from_wei</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string-interpolation interpolation">fee</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token string-interpolation interpolation"> </span><span class="token string-interpolation interpolation string" style="color:rgb(255, 121, 198)">'ether'</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token string-interpolation interpolation format-spec">.8f</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)"> ETH"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></div></code></pre></div></div>
<p>Vous devez estimer. Et l'estimation peut changer. Le <code>~</code> dans ma sortie n'est pas cosmétique, c'est un avertissement que ce frais est approximatif. Les prix du gaz augmentent. Les estimations sont incorrectes. Vous devez vérifier à nouveau juste avant de soumettre. Cela impose un workflow différent : <strong>toujours faire un <em>dry-run</em> d'abord</strong>.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="séquences-et-nonces--le-problème-de-synchronisation">Séquences et <em>nonces</em> : le problème de synchronisation<a href="https://lunik.tiwabbit.fr/blog/fr/building-crypto-send-receive-scripts#s%C3%A9quences-et-nonces--le-probl%C3%A8me-de-synchronisation" class="hash-link" aria-label="Lien direct vers séquences-et-nonces--le-problème-de-synchronisation" title="Lien direct vers séquences-et-nonces--le-problème-de-synchronisation" translate="no">​</a></h2>
<p>Les deux blockchains utilisent des compteurs pour garantir que les transactions ne soient pas dupliquées ou réordonnées. Mais elles exposent le problème différemment.</p>
<p>Les numéros de séquence de Stellar s'auto-incrémentent :</p>
<div class="language-python codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-python codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">source_account </span><span class="token operator">=</span><span class="token plain"> server</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">load_account</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">public_key</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">builder </span><span class="token operator">=</span><span class="token plain"> TransactionBuilder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">source_account</span><span class="token operator">=</span><span class="token plain">source_account</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">transaction </span><span class="token operator">=</span><span class="token plain"> builder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">build</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></div></code></pre></div></div>
<p>Commode, mais aussi dangereux. Si vous soumettez deux transactions simultanément, elles auront le même numéro de séquence et l'une échouera. Pour les scripts, je le documente simplement comme une limitation. Pour les systèmes de production, vous auriez besoin d'une file d'attente ou d'un <em>mutex</em>.</p>
<p>Le <em>nonce</em> d'Ethereum est quelque chose que vous récupérez :</p>
<div class="language-python codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-python codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">nonce </span><span class="token operator">=</span><span class="token plain"> w3</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">eth</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">get_transaction_count</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">source_address</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">tx </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"nonce"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> nonce</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></div></code></pre></div></div>
<p>Même problème, même solution nécessaire, mais maintenant c'est explicite. Vous êtes responsable de la récupération du <em>nonce</em>. Vous voyez le problème immédiatement. D'une certaine manière, Ethereum vous force à réfléchir à la concurrence.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="gestion-des-clés--deux-philosophies">Gestion des clés : deux philosophies<a href="https://lunik.tiwabbit.fr/blog/fr/building-crypto-send-receive-scripts#gestion-des-cl%C3%A9s--deux-philosophies" class="hash-link" aria-label="Lien direct vers Gestion des clés : deux philosophies" title="Lien direct vers Gestion des clés : deux philosophies" translate="no">​</a></h2>
<p>Pour les tests, les deux blockchains vous permettent d'utiliser des clés privées en clair. Mais Ethereum a également un format de clé prêt pour la production : le <em>keystore</em> chiffré.</p>
<p>Stellar : texte en clair avec permissions restrictives :</p>
<div class="language-python codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-python codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">with</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">open</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">f"keys/</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">public_key</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">.secret"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"w"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> f</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    os</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">chmod</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">f</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token number">0o600</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)"># chmod 600</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    f</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">write</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">secret_key</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></div></code></pre></div></div>
<p>Pour <em>testnet</em>, c'est correct. Pour <em>mainnet</em>, vous êtes livré à vous-même.</p>
<p>Ethereum : chiffrement intégré :</p>
<div class="language-python codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-python codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">password </span><span class="token operator">=</span><span class="token plain"> getpass</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">getpass</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Choisir un mot de passe :"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">keystore </span><span class="token operator">=</span><span class="token plain"> Account</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">encrypt</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">private_key</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> password</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># L'utiliser plus tard</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">python send_eth</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">py </span><span class="token operator">-</span><span class="token operator">-</span><span class="token plain">keystore keystores</span><span class="token operator">/</span><span class="token number">0x123</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">json</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># Demande le mot de passe lors de l'exécution</span><br></div></code></pre></div></div>
<p>Donc j'ai construit les deux <em>workflows</em>. Pour Ethereum <em>mainnet</em>, j'utilise toujours des <em>keystores</em> chiffrés. Le mot de passe n'est jamais stocké, je le tape à chaque utilisation. C'est une étape supplémentaire, mais cela compte.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="fiabilité-rpc--stellar-vs-ethereum">Fiabilité <em>RPC</em> : Stellar vs Ethereum<a href="https://lunik.tiwabbit.fr/blog/fr/building-crypto-send-receive-scripts#fiabilit%C3%A9-rpc--stellar-vs-ethereum" class="hash-link" aria-label="Lien direct vers fiabilité-rpc--stellar-vs-ethereum" title="Lien direct vers fiabilité-rpc--stellar-vs-ethereum" translate="no">​</a></h2>
<p>Stellar a un seul point de terminaison officiel : Horizon. Solide comme le roc.</p>
<p>Ethereum en a des centaines de publics, et ils sont tous peu fiables :</p>
<div class="language-python codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-python codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">rpcs </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"https://ethereum-sepolia-rpc.publicnode.com"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"https://rpc.sepolia.org"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">for</span><span class="token plain"> rpc_url </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">in</span><span class="token plain"> rpcs</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    w3 </span><span class="token operator">=</span><span class="token plain"> Web3</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">Web3</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">HTTPProvider</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">rpc_url</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> w3</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">is_connected</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">break</span><br></div></code></pre></div></div>
<p>Les <em>RPC</em> publics tombent. Ils limitent le débit. Ils sont peu fiables. Donc je réessaie plusieurs points de terminaison. C'est ennuyeux, mais nécessaire.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="messages-derreur--structurés-vs-analysés">Messages d'erreur : structurés vs analysés<a href="https://lunik.tiwabbit.fr/blog/fr/building-crypto-send-receive-scripts#messages-derreur--structur%C3%A9s-vs-analys%C3%A9s" class="hash-link" aria-label="Lien direct vers Messages d'erreur : structurés vs analysés" title="Lien direct vers Messages d'erreur : structurés vs analysés" translate="no">​</a></h2>
<p>Quand une transaction échoue, Stellar est explicite :</p>
<div class="language-python codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-python codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)"># Horizon retourne des codes structurés comme :</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># "tx_insufficient_balance", "tx_bad_seq", "op_no_destination"</span><br></div></code></pre></div></div>
<p>Lire le code, comprendre ce qui ne va pas, le corriger.</p>
<p>Ethereum retourne des messages d'erreur :</p>
<div class="language-python codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-python codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)"># Les erreurs RPC arrivent comme des chaînes :</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># "insufficient funds", "nonce too low", "gas too low"</span><br></div></code></pre></div></div>
<p>J'ai dû écrire une logique d'analyse de chaînes pour extraire l'erreur réelle. Pas élégant, mais ça fonctionne.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="journalisation-daudit--non-négociable">Journalisation d'audit : non-négociable<a href="https://lunik.tiwabbit.fr/blog/fr/building-crypto-send-receive-scripts#journalisation-daudit--non-n%C3%A9gociable" class="hash-link" aria-label="Lien direct vers Journalisation d'audit : non-négociable" title="Lien direct vers Journalisation d'audit : non-négociable" translate="no">​</a></h2>
<p>Après une transaction réussie sur l'une ou l'autre blockchain, je la journalise immédiatement :</p>
<div class="language-python codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-python codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">timestamp </span><span class="token operator">=</span><span class="token plain"> datetime</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">now</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">timezone</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">utc</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">isoformat</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">log_line </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">f"</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">timestamp</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)"> | </span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">network</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)"> | from=</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">source</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)"> | to=</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">dest</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)"> | amount=</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">amount</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)"> | tx=</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">tx_hash</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">\n"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">with</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">open</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">f"transactions.</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">network</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">.log"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"a"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> f</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    f</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">write</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">log_line</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></div></code></pre></div></div>
<p>Ne jamais journaliser les clés privées, juste la source, la destination, le montant, et le <em>hash</em> de transaction. C'est votre reçu. Des mois plus tard, vous aurez besoin de la preuve de ce qui s'est passé. Le journal est cette preuve.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="dry-run--toujours-tester-dabord"><em>Dry-run</em> : toujours tester d'abord<a href="https://lunik.tiwabbit.fr/blog/fr/building-crypto-send-receive-scripts#dry-run--toujours-tester-dabord" class="hash-link" aria-label="Lien direct vers dry-run--toujours-tester-dabord" title="Lien direct vers dry-run--toujours-tester-dabord" translate="no">​</a></h2>
<p>Les deux scripts supportent un drapeau <code>--dry-run</code> qui simule la transaction sans la soumettre :</p>
<div class="language-python codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-python codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> dry_run</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">print</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">f"De       : </span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">source</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">print</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">f"À        : </span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">destination</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">print</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">f"Montant  : </span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">amount</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">print</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">f"Frais    : </span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">fee</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">print</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">f"Solde    : </span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">balance</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><br></div></code></pre></div></div>
<p>Sur Ethereum surtout, c'est critique. Vous voyez le coût du gaz avant de vous engager. Vous vérifiez le solde. Vous vérifiez l'adresse de destination. Le <em>workflow</em> devient : <em>dry-run testnet</em>, <em>dry-run mainnet</em>, soumission <em>mainnet</em>.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="la-vraie-leçon">La vraie leçon<a href="https://lunik.tiwabbit.fr/blog/fr/building-crypto-send-receive-scripts#la-vraie-le%C3%A7on" class="hash-link" aria-label="Lien direct vers La vraie leçon" title="Lien direct vers La vraie leçon" translate="no">​</a></h2>
<p>J'ai construit ces scripts parce que <strong>je ne fais pas confiance aux boîtes noires avec ma crypto</strong>. Chaque <em>exchange</em>, chaque <em>wallet</em>, chaque <em>dapp</em> est un point centralisé de défaillance. N'importe lequel d'eux pourrait avoir un bug qui vide votre compte. N'importe lequel pourrait être piraté. N'importe lequel pourrait disparaître.</p>
<p>Mais quand je lis mon propre code, quand j'ai écrit chaque ligne, je sais exactement ce qui se passe quand j'appuie sur Entrée. Pas de points de terminaison cachés. Pas d'intermédiaires. Juste Python + bibliothèques standard + appels blockchain directs.</p>
<p>Stellar et Ethereum sont des plateformes solides. Mais elles ne peuvent pas vous protéger de :</p>
<ul>
<li class="">Un <em>wallet</em> buggué qui calcule mal le gaz</li>
<li class="">Un <em>exchange</em> qui verrouille votre compte</li>
<li class="">Une <em>dapp</em> qui demande trop de permissions</li>
<li class="">Une clé privée volée du cache d'un navigateur</li>
</ul>
<p>L'auto-garde via du code auditable est la réponse.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="si-vous-construisez-ceci-aussi">Si vous construisez ceci aussi<a href="https://lunik.tiwabbit.fr/blog/fr/building-crypto-send-receive-scripts#si-vous-construisez-ceci-aussi" class="hash-link" aria-label="Lien direct vers Si vous construisez ceci aussi" title="Lien direct vers Si vous construisez ceci aussi" translate="no">​</a></h2>
<ol>
<li class=""><strong>Faire confiance au code, pas aux interfaces</strong>, Vous devriez comprendre chaque ligne qui déplace vos actifs.</li>
<li class=""><strong>Commencer sur <em>testnet</em></strong>, Fonds gratuits. Zéro risque. Parfait pour apprendre.</li>
<li class=""><strong>Tout journaliser</strong>, Vous avez besoin de la preuve. Le journal est votre reçu.</li>
<li class=""><strong><em>Dry-run</em> d'abord</strong>, Voir les frais. Voir la structure. Avant de vous engager.</li>
<li class=""><strong>Garder simple</strong>, Pas d'abstractions. Pas de magie. Juste des étapes simples.</li>
</ol>
<p>Si vous n'êtes pas à l'aise avec le code qui déplace vos actifs, ne l'utilisez pas. Et si vous utilisez un service dont vous <em>ne pouvez pas</em> lire le code, vous faites confiance au jugement de quelqu'un d'autre avec votre argent.</p>
<p><strong>Lire le code. L'auditer. Le modifier. Le posséder.</strong></p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="code-source">Code source<a href="https://lunik.tiwabbit.fr/blog/fr/building-crypto-send-receive-scripts#code-source" class="hash-link" aria-label="Lien direct vers Code source" title="Lien direct vers Code source" translate="no">​</a></h2>
<p>Les deux scripts sont <em>open source</em> :</p>
<ul>
<li class=""><strong>Stellar XLM</strong>: <a href="https://github.com/Lunik/stellar_xlm" target="_blank" rel="noopener noreferrer" class="">https://github.com/Lunik/stellar_xlm</a></li>
<li class=""><strong>Ethereum</strong>: <a href="https://github.com/Lunik/ethereum" target="_blank" rel="noopener noreferrer" class="">https://github.com/Lunik/ethereum</a></li>
</ul>]]></content>
        <author>
            <name>Guillaume MARTINEZ</name>
            <uri>https://github.com/Lunik</uri>
        </author>
        <category label="blockchain" term="blockchain"/>
        <category label="ethereum" term="ethereum"/>
        <category label="stellar" term="stellar"/>
        <category label="python" term="python"/>
        <category label="cryptocurrency" term="cryptocurrency"/>
        <category label="scripting" term="scripting"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Rafraîchir le blog — encore une fois]]></title>
        <id>https://lunik.tiwabbit.fr/blog/fr/refreshing-the-blog</id>
        <link href="https://lunik.tiwabbit.fr/blog/fr/refreshing-the-blog"/>
        <updated>2026-04-15T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Comment et pourquoi j'ai migré mon site personnel de MkDocs + HTML brut vers un monorepo Docusaurus + Vite]]></summary>
        <content type="html"><![CDATA[<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2026-04-15-refreshing-the-blog/cover.png" alt="cover" class="img__Ss2"></p>
<p>Il y a quelque temps j'ai écrit <a class="" href="https://lunik.tiwabbit.fr/blog/fr/blog/init">un article sur comment j'avais créé ce blog</a>. À l'époque c'était <a href="https://getpelican.com/" target="_blank" rel="noopener noreferrer" class="">Pelican</a>, un générateur de site statique en <a href="https://www.python.org/" target="_blank" rel="noopener noreferrer" class="">Python</a>. Ensuite je l'ai migré vers <a href="https://www.mkdocs.org/" target="_blank" rel="noopener noreferrer" class="">MkDocs</a> — toujours en <a href="https://www.python.org/" target="_blank" rel="noopener noreferrer" class="">Python</a>, un peu plus moderne, un meilleur support pour mon setup bilingue. Et nous voilà encore. Troisième fois.</p>
<p>Voici l'histoire de pourquoi je l'ai fait et comment ça s'est passé.</p>
<div class="theme-admonition theme-admonition-info admonition_IZjC alert alert--info"><div class="admonitionHeading_uVvU"><span class="admonitionIcon_HiR3"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_bl22"><p>Si vous lisez ceci sur le blog, c'est que la migration est terminée. Félicitations, vous avez survécu à la downtime.</p></div></div>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="lancien-setup">L'ancien setup<a href="https://lunik.tiwabbit.fr/blog/fr/refreshing-the-blog#lancien-setup" class="hash-link" aria-label="Lien direct vers L'ancien setup" title="Lien direct vers L'ancien setup" translate="no">​</a></h2>
<p>Laissez-moi décrire ce que j'avais avant pour que vous compreniez pourquoi je voulais changer.</p>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="le-portfolio">Le portfolio<a href="https://lunik.tiwabbit.fr/blog/fr/refreshing-the-blog#le-portfolio" class="hash-link" aria-label="Lien direct vers Le portfolio" title="Lien direct vers Le portfolio" translate="no">​</a></h3>
<p>Un site <a href="https://developer.mozilla.org/en-US/docs/Web/HTML" target="_blank" rel="noopener noreferrer" class="">HTML</a>/<a href="https://developer.mozilla.org/en-US/docs/Web/CSS" target="_blank" rel="noopener noreferrer" class="">CSS</a>/<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript" target="_blank" rel="noopener noreferrer" class="">JavaScript</a> brut. Pas d'étape de build. Pas de bundler. Juste des fichiers sur un disque que j'uploadais sur <a href="https://aws.amazon.com/s3/" target="_blank" rel="noopener noreferrer" class="">S3</a>.</p>
<p>Ça fonctionnait. Mais c'était douloureux à maintenir. Tout le <a href="https://developer.mozilla.org/en-US/docs/Web/CSS" target="_blank" rel="noopener noreferrer" class="">CSS</a> était dans un seul fichier de 600 lignes mélangeant couleurs, mise en page et composants. Il n'y avait pas de séparation claire entre les données et la présentation. Le <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript" target="_blank" rel="noopener noreferrer" class="">JavaScript</a> était procédural, avec des appels à <code>eval()</code> pour mapper des noms de propriétés en chaînes de caractères vers des attributs DOM. Les dépendances étaient chargées depuis des CDN avec des numéros de version codés en dur dans des balises <code>&lt;script&gt;</code>.</p>
<p>À chaque fois que je devais toucher quelque chose, je devais redécouvrir comment c'était assemblé.</p>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="le-blog">Le blog<a href="https://lunik.tiwabbit.fr/blog/fr/refreshing-the-blog#le-blog" class="hash-link" aria-label="Lien direct vers Le blog" title="Lien direct vers Le blog" translate="no">​</a></h3>
<p><a href="https://www.mkdocs.org/" target="_blank" rel="noopener noreferrer" class="">MkDocs</a> est un générateur de site statique tout à fait correct. Je n'ai rien de négatif à dire dessus. Mais c'était un projet séparé, avec son propre environnement <a href="https://www.python.org/" target="_blank" rel="noopener noreferrer" class="">Python</a>, son propre pipeline <a href="https://docs.gitlab.com/ee/ci/" target="_blank" rel="noopener noreferrer" class="">GitLab CI</a>, et son propre processus de déploiement S3. Deux projets, deux pipelines, deux processus de déploiement.</p>
<p>Et <a href="https://www.mkdocs.org/" target="_blank" rel="noopener noreferrer" class="">MkDocs</a> n'est pas vraiment conçu pour un blog. J'utilisais le <a href="https://squidfunk.github.io/mkdocs-material/plugins/blog/" target="_blank" rel="noopener noreferrer" class="">plugin Blog de MkDocs Material</a> qui est très bien mais qui ajoute une couche sur quelque chose qui n'a pas été construit pour ce cas d'usage dès le départ.</p>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="la-situation-ci">La situation CI<a href="https://lunik.tiwabbit.fr/blog/fr/refreshing-the-blog#la-situation-ci" class="hash-link" aria-label="Lien direct vers La situation CI" title="Lien direct vers La situation CI" translate="no">​</a></h3>
<p>Deux fichiers <code>.gitlab-ci.yml</code>. Deux stratégies de cache séparées. Deux jobs de déploiement séparés. Quand je voulais faire un changement qui touchait à la fois le portfolio et le blog — comme mettre à jour les liens du footer — je devais coordonner deux pipelines séparés et deux déploiements séparés. C'était pénible.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="pourquoi-docusaurus-et-vite">Pourquoi Docusaurus et Vite<a href="https://lunik.tiwabbit.fr/blog/fr/refreshing-the-blog#pourquoi-docusaurus-et-vite" class="hash-link" aria-label="Lien direct vers Pourquoi Docusaurus et Vite" title="Lien direct vers Pourquoi Docusaurus et Vite" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="docusaurus">Docusaurus<a href="https://lunik.tiwabbit.fr/blog/fr/refreshing-the-blog#docusaurus" class="hash-link" aria-label="Lien direct vers Docusaurus" title="Lien direct vers Docusaurus" translate="no">​</a></h3>
<p><a href="https://docusaurus.io/" target="_blank" rel="noopener noreferrer" class="">Docusaurus</a> est un générateur de site statique basé sur <a href="https://react.dev/" target="_blank" rel="noopener noreferrer" class="">React</a> fait par <a href="https://opensource.fb.com/" target="_blank" rel="noopener noreferrer" class="">Meta</a>, principalement conçu pour la documentation. Mais il a un mode blog qui est assez bon. Il supporte :</p>
<ul>
<li class="">Le contenu bilingue nativement avec son système i18n</li>
<li class="">L'estimation du temps de lecture</li>
<li class="">Les profils d'auteurs</li>
<li class="">Les flux RSS/Atom</li>
<li class="">Les pages de tags</li>
</ul>
<p>Il est construit sur <a href="https://nodejs.org/" target="_blank" rel="noopener noreferrer" class="">Node.js</a> et <a href="https://www.npmjs.com/" target="_blank" rel="noopener noreferrer" class="">npm</a>, ce qui signifie que je suis de retour dans l'écosystème que je déteste mais au moins c'est le même écosystème que les outils de build du portfolio. La cohérence a une valeur.</p>
<p>J'ai considéré <a href="https://astro.build/" target="_blank" rel="noopener noreferrer" class="">Astro</a> et <a href="https://www.11ty.dev/" target="_blank" rel="noopener noreferrer" class="">11ty</a>. <a href="https://astro.build/" target="_blank" rel="noopener noreferrer" class="">Astro</a> est intéressant mais il nécessitait plus de configuration pour le même résultat. <a href="https://www.11ty.dev/" target="_blank" rel="noopener noreferrer" class="">11ty</a> est élégant dans sa simplicité mais le support i18n de <a href="https://docusaurus.io/" target="_blank" rel="noopener noreferrer" class="">Docusaurus</a> est difficile à égaler sans l'écrire soi-même.</p>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="vite">Vite<a href="https://lunik.tiwabbit.fr/blog/fr/refreshing-the-blog#vite" class="hash-link" aria-label="Lien direct vers Vite" title="Lien direct vers Vite" translate="no">​</a></h3>
<p><a href="https://vitejs.dev/" target="_blank" rel="noopener noreferrer" class="">Vite</a> est le choix évident pour le portfolio. C'est rapide, ça gère bien les applications multi-pages, et il a un support de première classe pour les <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules" target="_blank" rel="noopener noreferrer" class="">ES modules</a>. La migration du <a href="https://developer.mozilla.org/en-US/docs/Web/HTML" target="_blank" rel="noopener noreferrer" class="">HTML</a> brut + <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript" target="_blank" rel="noopener noreferrer" class="">JavaScript</a> procédural vers une vraie application multi-pages <a href="https://vitejs.dev/" target="_blank" rel="noopener noreferrer" class="">Vite</a> m'a donné la structure dont j'avais besoin sans me forcer à adopter un framework de composants.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="la-structure-monorepo">La structure monorepo<a href="https://lunik.tiwabbit.fr/blog/fr/refreshing-the-blog#la-structure-monorepo" class="hash-link" aria-label="Lien direct vers La structure monorepo" title="Lien direct vers La structure monorepo" translate="no">​</a></h2>
<p>La décision de fusionner les deux projets en un seul dépôt était la plus importante. Tout le reste en découle.</p>
<div class="language-text codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-text codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">my_website_v2/</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">├── package.json          # racine npm workspaces</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">├── packages/</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">│   ├── website/          # portfolio Vite</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">│   └── blog/             # blog Docusaurus</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">└── dist/                 # output assemblé</span><br></div></code></pre></div></div>
<p>Le <code>package.json</code> racine déclare les deux packages comme <a href="https://docs.npmjs.com/cli/using-npm/workspaces" target="_blank" rel="noopener noreferrer" class="">npm workspaces</a> et orchestre le build :</p>
<div class="language-json codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-json codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"scripts"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"build"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"npm run build:website &amp;&amp; npm run build:blog &amp;&amp; npm run assemble"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"assemble"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"mkdir -p dist &amp;&amp; cp -r packages/website/dist/. dist/ &amp;&amp; mkdir -p dist/blog &amp;&amp; cp -r packages/blog/build/. dist/blog/"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></div></code></pre></div></div>
<p>Le portfolio se build dans <code>dist/</code>, le blog se build dans <code>dist/blog/</code>. La structure d'URL est préservée : <code>/</code> pour le portfolio, <code>/blog/</code> pour le blog. Une seule commande <code>rclone sync</code> en CI pour tout pousser vers S3.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="migration-du-portfolio">Migration du portfolio<a href="https://lunik.tiwabbit.fr/blog/fr/refreshing-the-blog#migration-du-portfolio" class="hash-link" aria-label="Lien direct vers Migration du portfolio" title="Lien direct vers Migration du portfolio" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="refactoring-css">Refactoring CSS<a href="https://lunik.tiwabbit.fr/blog/fr/refreshing-the-blog#refactoring-css" class="hash-link" aria-label="Lien direct vers Refactoring CSS" title="Lien direct vers Refactoring CSS" translate="no">​</a></h3>
<p>La première chose que j'ai faite a été d'extraire la palette de couleurs <a href="https://github.com/morhetz/gruvbox" target="_blank" rel="noopener noreferrer" class="">Gruvbox</a> en <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties" target="_blank" rel="noopener noreferrer" class="">propriétés CSS personnalisées</a> :</p>
<div class="language-css codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-css codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token selector pseudo-class" style="color:rgb(255, 121, 198)">:root</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">--gb-bg</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">      </span><span class="token hexcode color">#1d2021</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">--gb-bg1</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">     </span><span class="token hexcode color">#282828</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">--gb-fg</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">      </span><span class="token hexcode color">#ebdbb2</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">--gb-cyan</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">    </span><span class="token hexcode color">#689d6a</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">--gb-yellow</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">  </span><span class="token hexcode color">#d79921</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)">/* ... */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></div></code></pre></div></div>
<p>Ensuite j'ai remplacé chaque couleur codée en dur dans les feuilles de style des composants par ces variables. Aucun changement visuel, mais maintenant le thème est en un seul endroit.</p>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="modules-javascript">Modules JavaScript<a href="https://lunik.tiwabbit.fr/blog/fr/refreshing-the-blog#modules-javascript" class="hash-link" aria-label="Lien direct vers Modules JavaScript" title="Lien direct vers Modules JavaScript" translate="no">​</a></h3>
<p>Le principal défi était le pattern <code>eval()</code>. Le code original utilisait des noms de propriétés en chaîne pour définir des variables CSS dynamiques :</p>
<div class="language-javascript codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-javascript codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">// Avant</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">config</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">forEach</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">function</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token parameter">item</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token known-class-name class-name">Object</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">keys</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">item</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">forEach</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">function</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token parameter">key</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">eval</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"element."</span><span class="token plain"> </span><span class="token operator">+</span><span class="token plain"> key </span><span class="token operator">+</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">" = item[key]"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></div></code></pre></div></div>
<p>Je l'ai remplacé par une map de propriétés explicite :</p>
<div class="language-javascript codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-javascript codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">// Après</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">PROPERTY_MAP</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function-variable function" style="color:rgb(80, 250, 123)">textContent</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token parameter">el</span><span class="token parameter punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token parameter"> v</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> el</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">textContent</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> v </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function-variable function" style="color:rgb(80, 250, 123)">href</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token parameter">el</span><span class="token parameter punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token parameter"> v</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> el</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">href</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> v </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function-variable function" style="color:rgb(80, 250, 123)">style</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token parameter">el</span><span class="token parameter punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token parameter"> v</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> el</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">setAttribute</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">'style'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> v</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></div></code></pre></div></div>
<p>Moins malin, mais ça fonctionne sans <code>eval()</code> et c'est lisible.</p>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="uaparserjs">UAParser.js<a href="https://lunik.tiwabbit.fr/blog/fr/refreshing-the-blog#uaparserjs" class="hash-link" aria-label="Lien direct vers UAParser.js" title="Lien direct vers UAParser.js" translate="no">​</a></h3>
<p>Le portfolio utilise <a href="https://github.com/faisalman/ua-parser-js" target="_blank" rel="noopener noreferrer" class="">UAParser.js</a> pour afficher le navigateur et l'OS du visiteur sur la homepage terminal. Avant il était chargé depuis un CDN :</p>
<div class="language-html codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-html codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">script</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">src</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(248, 248, 242)">=</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag attr-value" style="color:rgb(255, 121, 198)">https://cdn.jsdelivr.net/npm/ua-parser-js@1/src/ua-parser.min.js</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token script"></span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">script</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><br></div></code></pre></div></div>
<p>Maintenant c'est une dépendance <a href="https://www.npmjs.com/" target="_blank" rel="noopener noreferrer" class="">npm</a> correcte importée en tant qu'ES module :</p>
<div class="language-javascript codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-javascript codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token imports"> </span><span class="token imports maybe-class-name">UAParser</span><span class="token imports"> </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">'ua-parser-js'</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="migration-du-contenu-du-blog">Migration du contenu du blog<a href="https://lunik.tiwabbit.fr/blog/fr/refreshing-the-blog#migration-du-contenu-du-blog" class="hash-link" aria-label="Lien direct vers Migration du contenu du blog" title="Lien direct vers Migration du contenu du blog" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="le-script-de-migration">Le script de migration<a href="https://lunik.tiwabbit.fr/blog/fr/refreshing-the-blog#le-script-de-migration" class="hash-link" aria-label="Lien direct vers Le script de migration" title="Lien direct vers Le script de migration" translate="no">​</a></h3>
<p>J'ai écrit un script <a href="https://nodejs.org/" target="_blank" rel="noopener noreferrer" class="">Node.js</a> à usage unique pour migrer tous les articles <a href="https://www.mkdocs.org/" target="_blank" rel="noopener noreferrer" class="">MkDocs</a> vers le format <a href="https://docusaurus.io/" target="_blank" rel="noopener noreferrer" class="">Docusaurus</a>. Les principales choses qu'il devait gérer :</p>
<p><strong>Frontmatter</strong> : <a href="https://www.mkdocs.org/" target="_blank" rel="noopener noreferrer" class="">MkDocs</a> Material utilise <code>categories</code> et <code>tags</code> comme champs séparés, <a href="https://docusaurus.io/" target="_blank" rel="noopener noreferrer" class="">Docusaurus</a> n'a que <code>tags</code>. Le script les fusionne et déduplique. Il supprime aussi le champ <code>readtime</code> car <a href="https://docusaurus.io/" target="_blank" rel="noopener noreferrer" class="">Docusaurus</a> calcule automatiquement le temps de lecture.</p>
<p><strong>Admonitions</strong> : <a href="https://www.mkdocs.org/" target="_blank" rel="noopener noreferrer" class="">MkDocs</a> utilise la syntaxe <code>!!! warning "Titre"</code>, <a href="https://docusaurus.io/" target="_blank" rel="noopener noreferrer" class="">Docusaurus</a> utilise <code>:::warning[Titre]</code>. Une regex gère la conversion :</p>
<div class="language-javascript codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-javascript codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">content </span><span class="token operator">=</span><span class="token plain"> content</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">replace</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token regex regex-delimiter">/</span><span class="token regex regex-source language-regex anchor function" style="color:rgb(80, 250, 123)">^</span><span class="token regex regex-source language-regex">!!!</span><span class="token regex regex-source language-regex char-set class-name">\s</span><span class="token regex regex-source language-regex quantifier number">+</span><span class="token regex regex-source language-regex group punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token regex regex-source language-regex char-set class-name">\w</span><span class="token regex regex-source language-regex quantifier number">+</span><span class="token regex regex-source language-regex group punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token regex regex-source language-regex group punctuation" style="color:rgb(248, 248, 242)">(?:</span><span class="token regex regex-source language-regex char-set class-name">\s</span><span class="token regex regex-source language-regex quantifier number">+</span><span class="token regex regex-source language-regex">"</span><span class="token regex regex-source language-regex group punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token regex regex-source language-regex char-class char-class-punctuation punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token regex regex-source language-regex char-class char-class-negation operator">^</span><span class="token regex regex-source language-regex char-class">"</span><span class="token regex regex-source language-regex char-class char-class-punctuation punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token regex regex-source language-regex quantifier number">*</span><span class="token regex regex-source language-regex group punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token regex regex-source language-regex">"</span><span class="token regex regex-source language-regex group punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token regex regex-source language-regex quantifier number">?</span><span class="token regex regex-source language-regex escape">\n</span><span class="token regex regex-source language-regex escape">\n</span><span class="token regex regex-source language-regex quantifier number">?</span><span class="token regex regex-source language-regex group punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token regex regex-source language-regex group punctuation" style="color:rgb(248, 248, 242)">(?:</span><span class="token regex regex-source language-regex group punctuation" style="color:rgb(248, 248, 242)">(?:</span><span class="token regex regex-source language-regex">    </span><span class="token regex regex-source language-regex alternation keyword" style="color:rgb(189, 147, 249);font-style:italic">|</span><span class="token regex regex-source language-regex escape">\t</span><span class="token regex regex-source language-regex group punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token regex regex-source language-regex char-class char-class-punctuation punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token regex regex-source language-regex char-class char-class-negation operator">^</span><span class="token regex regex-source language-regex char-class escape">\n</span><span class="token regex regex-source language-regex char-class char-class-punctuation punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token regex regex-source language-regex quantifier number">*</span><span class="token regex regex-source language-regex escape">\n</span><span class="token regex regex-source language-regex quantifier number">?</span><span class="token regex regex-source language-regex group punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token regex regex-source language-regex quantifier number">+</span><span class="token regex regex-source language-regex group punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token regex regex-delimiter">/</span><span class="token regex regex-flags">gm</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token parameter">_</span><span class="token parameter punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token parameter"> type</span><span class="token parameter punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token parameter"> title</span><span class="token parameter punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token parameter"> body</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> dedented </span><span class="token operator">=</span><span class="token plain"> body</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">replace</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token regex regex-delimiter">/</span><span class="token regex regex-source language-regex anchor function" style="color:rgb(80, 250, 123)">^</span><span class="token regex regex-source language-regex group punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token regex regex-source language-regex">    </span><span class="token regex regex-source language-regex alternation keyword" style="color:rgb(189, 147, 249);font-style:italic">|</span><span class="token regex regex-source language-regex escape">\t</span><span class="token regex regex-source language-regex group punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token regex regex-delimiter">/</span><span class="token regex regex-flags">gm</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">''</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> header </span><span class="token operator">=</span><span class="token plain"> title </span><span class="token operator">?</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string string" style="color:rgb(255, 121, 198)">:::</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">type</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string string" style="color:rgb(255, 121, 198)">[</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">title</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string string" style="color:rgb(255, 121, 198)">]</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token plain"> </span><span class="token operator">:</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string string" style="color:rgb(255, 121, 198)">:::</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">type</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">header</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string string" style="color:rgb(255, 121, 198)">\n</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">dedented</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation method function property-access" style="color:rgb(80, 250, 123)">trim</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string string" style="color:rgb(255, 121, 198)">\n:::\n</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></div></code></pre></div></div>
<p><strong>Structure des répertoires</strong> : Les articles <a href="https://www.mkdocs.org/" target="_blank" rel="noopener noreferrer" class="">MkDocs</a> sont dans <code>docs/en/posts/slug/index.md</code> sans date dans le chemin. <a href="https://docusaurus.io/" target="_blank" rel="noopener noreferrer" class="">Docusaurus</a> veut <code>blog/YYYY-MM-DD-slug/index.md</code>. Le script lit le champ <code>date:</code> du frontmatter et préfixe le nom du répertoire.</p>
<p><strong>Marqueurs de troncature</strong> : <a href="https://www.mkdocs.org/" target="_blank" rel="noopener noreferrer" class="">MkDocs</a> utilise <code>&lt;!-- more --&gt;</code> pour le cutoff de l'extrait d'article. <a href="https://docusaurus.io/" target="_blank" rel="noopener noreferrer" class="">Docusaurus</a> utilise <code>&lt;!-- truncate --&gt;</code>. Un simple chercher et remplacer.</p>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="contenu-bilingue">Contenu bilingue<a href="https://lunik.tiwabbit.fr/blog/fr/refreshing-the-blog#contenu-bilingue" class="hash-link" aria-label="Lien direct vers Contenu bilingue" title="Lien direct vers Contenu bilingue" translate="no">​</a></h3>
<p>Les articles EN vont dans <code>packages/blog/blog/</code>. Les articles FR vont dans <code>packages/blog/i18n/fr/docusaurus-plugin-content-blog/</code>. Les images sont stockées avec l'article EN et les articles FR les référencent avec le même chemin relatif — <a href="https://docusaurus.io/" target="_blank" rel="noopener noreferrer" class="">Docusaurus</a> les résout correctement au moment du build.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="les-problèmes-amusants">Les problèmes amusants<a href="https://lunik.tiwabbit.fr/blog/fr/refreshing-the-blog#les-probl%C3%A8mes-amusants" class="hash-link" aria-label="Lien direct vers Les problèmes amusants" title="Lien direct vers Les problèmes amusants" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="node-25-et-lerreur-localstorage">Node 25 et l'erreur localStorage<a href="https://lunik.tiwabbit.fr/blog/fr/refreshing-the-blog#node-25-et-lerreur-localstorage" class="hash-link" aria-label="Lien direct vers Node 25 et l'erreur localStorage" title="Lien direct vers Node 25 et l'erreur localStorage" translate="no">​</a></h3>
<p>Le build SSG de <a href="https://docusaurus.io/" target="_blank" rel="noopener noreferrer" class="">Docusaurus</a> crashait sur <a href="https://nodejs.org/" target="_blank" rel="noopener noreferrer" class="">Node.js</a> 25 avec :</p>
<div class="language-text codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-text codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">Cannot initialize local storage without a --localstorage-file path.</span><br></div></code></pre></div></div>
<p><a href="https://nodejs.org/" target="_blank" rel="noopener noreferrer" class="">Node.js</a> 25 embarque l'<a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API" target="_blank" rel="noopener noreferrer" class="">API Web Storage</a> nativement, mais contrairement aux navigateurs, il nécessite un chemin de fichier explicite pour persister les données. <a href="https://docusaurus.io/" target="_blank" rel="noopener noreferrer" class="">Docusaurus</a> utilise <code>localStorage</code> en interne lors du SSG pour la persistance du thème et n'avait aucune idée que cette API nécessitait maintenant une initialisation.</p>
<p>Le fix est un flag <a href="https://nodejs.org/" target="_blank" rel="noopener noreferrer" class="">Node.js</a> :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">NODE_OPTIONS</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">'--localstorage-file=/tmp/docusaurus-ls'</span><span class="token plain"> docusaurus build</span><br></div></code></pre></div></div>
<p>Il est dans le script <code>build</code> du <code>package.json</code> et dans le bloc <code>variables</code> du <a href="https://docs.gitlab.com/ee/ci/" target="_blank" rel="noopener noreferrer" class="">GitLab CI</a>.</p>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="les-espaces-insécables">Les espaces insécables<a href="https://lunik.tiwabbit.fr/blog/fr/refreshing-the-blog#les-espaces-ins%C3%A9cables" class="hash-link" aria-label="Lien direct vers Les espaces insécables" title="Lien direct vers Les espaces insécables" translate="no">​</a></h3>
<p>Le HTML réduit les espaces consécutifs ordinaires en un seul. Tout le monde le sait. Moins de monde y pense quand on écrit des chaînes qui seront injectées via <code>innerHTML</code>.</p>
<p>La homepage terminal a deux commandes dont l'affichage repose sur l'alignement en colonnes : <code>locate</code> (les liens sont paddés à une largeur commune avant le commentaire <code>#</code>) et <code>ls -l /bin</code> (les tailles de fichiers et les dates sont alignées à droite). Le code source original utilisait des espaces insécables U+00A0 pour ce padding, pas des espaces normaux. En HTML, <code>&amp;nbsp;</code> ou son équivalent Unicode est le seul caractère d'espacement qui ne se réduit pas.</p>
<p>Pendant la migration, chaque éditeur de texte, outil de diff, et copier-coller impliqué dans le déplacement de ces chaînes a traité U+00A0 comme un espace ordinaire. Ils sont tous ressortis en U+0020. Les colonnes ont disparu silencieusement — pas d'erreur de build, pas d'échec de test, juste une régression cosmétique qu'on ne remarque que si on regarde la page.</p>
<p>Le fix est chirurgical : retrouver le code source original, extraire les octets bruts, les restaurer. Un one-liner Python pour grep le fichier original et compter les occurrences de <code>\xa0</code> l'a confirmé, puis une substitution directe au niveau des octets les a remis en place.</p>
<p>Leçon : si l'alignement en colonnes dans du HTML est important, utiliser un <code>&lt;pre&gt;</code> ou <code>white-space: pre</code> et garder la chaîne dans un fichier séparé où un linter ne peut pas la toucher.</p>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="webpack-5106-et-webpackbar">webpack 5.106 et webpackbar<a href="https://lunik.tiwabbit.fr/blog/fr/refreshing-the-blog#webpack-5106-et-webpackbar" class="hash-link" aria-label="Lien direct vers webpack 5.106 et webpackbar" title="Lien direct vers webpack 5.106 et webpackbar" translate="no">​</a></h3>
<p><a href="https://docusaurus.io/" target="_blank" rel="noopener noreferrer" class="">Docusaurus</a> 3 utilise <a href="https://webpack.js.org/" target="_blank" rel="noopener noreferrer" class="">webpack</a> 5 en interne. <a href="https://github.com/unjs/webpackbar" target="_blank" rel="noopener noreferrer" class="">webpackbar</a> — le plugin de barre de progression — a été mis à jour vers la version 6.0.1, qui passait des options (<code>name</code>, <code>color</code>, <code>reporters</code>) au <code>ProgressPlugin</code> de <a href="https://webpack.js.org/" target="_blank" rel="noopener noreferrer" class="">webpack</a>. Mais <a href="https://webpack.js.org/" target="_blank" rel="noopener noreferrer" class="">webpack</a> 5.100+ avait supprimé ces options de <code>ProgressPlugin</code>.</p>
<p>Le résultat : le build du blog crashait au démarrage avec une erreur obscure sur les options du plugin.</p>
<p>Le fix a été de fixer <a href="https://webpack.js.org/" target="_blank" rel="noopener noreferrer" class="">webpack</a> à <code>5.95.0</code> comme <code>devDependency</code> directe dans <code>packages/blog/package.json</code>. La résolution npm workspaces le récupère et l'utilise à la place de résoudre la dernière version 5.x.</p>
<div class="language-json codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-json codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"devDependencies"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"webpack"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"5.95.0"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></div></code></pre></div></div>
<p>Pas idéal, mais ça fonctionne jusqu'à ce que <a href="https://docusaurus.io/" target="_blank" rel="noopener noreferrer" class="">Docusaurus</a> publie un fix en amont.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="le-pipeline-ci">Le pipeline CI<a href="https://lunik.tiwabbit.fr/blog/fr/refreshing-the-blog#le-pipeline-ci" class="hash-link" aria-label="Lien direct vers Le pipeline CI" title="Lien direct vers Le pipeline CI" translate="no">​</a></h2>
<p>Le nouveau <code>.gitlab-ci.yml</code> est en trois étapes : <code>install</code>, <code>build</code>, <code>deploy</code>.</p>
<div class="language-text codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-text codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">install → build → pages (branche develop)</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">                → publish (branche master)</span><br></div></code></pre></div></div>
<p>Le job <code>pages</code> copie <code>dist/</code> vers <code>public/</code> pour <a href="https://docs.gitlab.com/ee/user/project/pages/" target="_blank" rel="noopener noreferrer" class="">GitLab Pages</a> sur la branche <code>develop</code>. Le job <code>publish</code> lance <code>rclone sync</code> pour pousser <code>dist/</code> vers S3 sur la branche <code>master</code>.</p>
<p>Avant, j'avais deux pipelines avec deux jobs de déploiement S3 séparés, dont l'un utilisait un pattern d'exclusion pour éviter d'écraser le blog déployé depuis l'autre pipeline. Maintenant c'est un seul <code>rclone sync</code> sans exclusions :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">rclone </span><span class="token function" style="color:rgb(80, 250, 123)">sync</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--checksum</span><span class="token plain"> --delete-during </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--quiet</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  --s3-provider AWS </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  --s3-access-key-id </span><span class="token string" style="color:rgb(255, 121, 198)">"</span><span class="token string variable" style="color:rgb(189, 147, 249);font-style:italic">$AWS_ACCESS_KEY_ID</span><span class="token string" style="color:rgb(255, 121, 198)">"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  --s3-secret-access-key </span><span class="token string" style="color:rgb(255, 121, 198)">"</span><span class="token string variable" style="color:rgb(189, 147, 249);font-style:italic">$AWS_SECRET_ACCESS_KEY</span><span class="token string" style="color:rgb(255, 121, 198)">"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  --s3-region eu-west-3 </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  ./dist :s3:website-lunik.tiwabbit.fr</span><br></div></code></pre></div></div>
<p><code>--delete-during</code> supprime du bucket les fichiers qui n'existent plus dans <code>dist/</code> pendant la synchronisation. <code>--checksum</code> utilise des checksums plutôt que les dates de modification pour détecter les changements — plus fiable pour des fichiers réassemblés depuis les mêmes sources. Propre.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="conclusion">Conclusion<a href="https://lunik.tiwabbit.fr/blog/fr/refreshing-the-blog#conclusion" class="hash-link" aria-label="Lien direct vers Conclusion" title="Lien direct vers Conclusion" translate="no">​</a></h2>
<p>Trois itérations de ce blog. <a href="https://getpelican.com/" target="_blank" rel="noopener noreferrer" class="">Pelican</a>, puis <a href="https://www.mkdocs.org/" target="_blank" rel="noopener noreferrer" class="">MkDocs</a>, maintenant <a href="https://docusaurus.io/" target="_blank" rel="noopener noreferrer" class="">Docusaurus</a>. À chaque fois les outils s'améliorent et la charge de maintenance diminue.</p>
<p>Le monorepo était le bon choix. Avoir le portfolio et le blog dans le même dépôt, avec le même pipeline de build, est vraiment moins pénible que de maintenir deux projets séparés. J'aurais dû le faire plus tôt.</p>
<p>Le code source est sur <a href="https://gitlab.com/Lunik/my_website_v2" target="_blank" rel="noopener noreferrer" class="">gitlab.com/Lunik/my_website_v2</a>.</p>]]></content>
        <author>
            <name>Guillaume MARTINEZ</name>
            <uri>https://github.com/Lunik</uri>
        </author>
        <category label="blog" term="blog"/>
        <category label="website" term="website"/>
        <category label="docusaurus" term="docusaurus"/>
        <category label="vite" term="vite"/>
        <category label="npm" term="npm"/>
        <category label="nodejs" term="nodejs"/>
        <category label="monorepo" term="monorepo"/>
        <category label="gitlab-ci" term="gitlab-ci"/>
        <category label="devops" term="devops"/>
        <category label="sysops" term="sysops"/>
        <category label="it" term="it"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Apple Keyframer Saturn SVG]]></title>
        <id>https://lunik.tiwabbit.fr/blog/fr/apple-keyframer-saturn-svg</id>
        <link href="https://lunik.tiwabbit.fr/blog/fr/apple-keyframer-saturn-svg"/>
        <updated>2024-05-22T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Simplement le SVG utilisé par Apple dans leur application de démonstration Keyframer.]]></summary>
        <content type="html"><![CDATA[<p>J'ai suivi les recherches en machine learning d'Apple depuis un certain temps maintenant et j'ai été stupéfait par leur <a href="https://machinelearning.apple.com/research/keyframer" target="_blank" rel="noopener noreferrer" class="">application de démonstration Keyframer</a>. J'ai essayé de reproduire le SVG de Saturne utilisé dans la démo et je pense avoir trouvé une approximation assez bonne.</p>
<p>Cliquez avec le clic droit sur l'image ci-dessous et enregistrez-la au format de fichier SVG.</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2024-05-22-apple-keyframer-saturn-svg/saturn.svg" alt="saturn" class="img__Ss2"></p>
<p><strong>N'oubliez pas de créditer Apple pour le design original. Tous droits réservés. Et moi pour l'approximation.</strong></p>]]></content>
        <author>
            <name>Guillaume MARTINEZ</name>
            <uri>https://github.com/Lunik</uri>
        </author>
        <category label="apple" term="apple"/>
        <category label="svg" term="svg"/>
        <category label="genai" term="genai"/>
        <category label="keyframer" term="keyframer"/>
        <category label="saturn" term="saturn"/>
        <category label="transform" term="transform"/>
        <category label="animation" term="animation"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Environnements virtuels Python, le paradis]]></title>
        <id>https://lunik.tiwabbit.fr/blog/fr/python-venv-paradise</id>
        <link href="https://lunik.tiwabbit.fr/blog/fr/python-venv-paradise"/>
        <updated>2024-02-20T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Pourquoi vous devriez utiliser les environnements virtuels Python et comment les utiliser.]]></summary>
        <content type="html"><![CDATA[<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2024-02-20-python-venv-paradise/cover.png" alt="cover" class="img__Ss2"></p>
<p>Dans cet article, j'expliquerai pourquoi les environnements virtuels Python sont si intéressants lorsqu'on sait les utiliser correctement. Je vous montrerai également comment les utiliser correctement.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="de-quoi-sagit-il-">De quoi s'agit-il ?<a href="https://lunik.tiwabbit.fr/blog/fr/python-venv-paradise#de-quoi-sagit-il-" class="hash-link" aria-label="Lien direct vers De quoi s'agit-il ?" title="Lien direct vers De quoi s'agit-il ?" translate="no">​</a></h2>
<p>Les environnements virtuels Python sont un moyen d'isoler votre environnement Python de l'environnement Python du système. C'est utile lorsque vous travaillez sur plusieurs projets qui nécessitent différentes versions de Python ou différentes versions du même paquetage.</p>
<p>J'ai souvent entendu dire que les gens avaient peur d'utiliser les environnements virtuels Python parce qu'ils pensaient que c'était compliqué et inutile. Mais en même temps, il y a plus de centaines de paquets Python qui tentent de résoudre le même problème : pyenv, virtualenv, pipenv, conda, poetry, pew, et bien d'autres.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="un-peu-dhistoire">Un peu d'histoire<a href="https://lunik.tiwabbit.fr/blog/fr/python-venv-paradise#un-peu-dhistoire" class="hash-link" aria-label="Lien direct vers Un peu d'histoire" title="Lien direct vers Un peu d'histoire" translate="no">​</a></h2>
<p>Revenons aux bases. Il existe un module intégré pour cela : <code>venv</code> ! Qui l'aurait cru ? Il a été introduit pour la première fois dans Python <code>3.3</code> avec le <a href="https://peps.python.org/pep-0405/" target="_blank" rel="noopener noreferrer" class="">PEP 405 - Python Virtual Environments</a>.</p>
<blockquote>
<p>Ce PEP propose d'ajouter à Python un mécanisme pour des "environnements virtuels" légers avec leurs propres répertoires de site, éventuellement isolés des répertoires de site du système. Chaque environnement virtuel possède son propre binaire Python (ce qui permet de créer des environnements avec différentes versions de Python) et peut avoir son propre ensemble indépendant de paquets Python installés dans ses répertoires de site, mais partage la bibliothèque standard avec le Python de base installé.</p>
</blockquote>
<p>Qu'en est-il de tous ces gens qui tentent de résoudre le même problème ? Eh bien, ils essaient de faciliter l'utilisation et la gestion. Mais au final, ils fournissent tous la même chose : un moyen d'isoler votre environnement Python.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="comment-les-utiliser-correctement-">Comment les utiliser correctement ?<a href="https://lunik.tiwabbit.fr/blog/fr/python-venv-paradise#comment-les-utiliser-correctement-" class="hash-link" aria-label="Lien direct vers Comment les utiliser correctement ?" title="Lien direct vers Comment les utiliser correctement ?" translate="no">​</a></h2>
<p>Il suffit de connaître 3 commandes pour utiliser les environnements virtuels Python de la bonne manière.</p>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="créer-un-nouvel-environnement-virtuel">Créer un nouvel environnement virtuel<a href="https://lunik.tiwabbit.fr/blog/fr/python-venv-paradise#cr%C3%A9er-un-nouvel-environnement-virtuel" class="hash-link" aria-label="Lien direct vers Créer un nouvel environnement virtuel" title="Lien direct vers Créer un nouvel environnement virtuel" translate="no">​</a></h3>
<div class="language-bash codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-bash codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">python </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-m</span><span class="token plain"> venv myenv</span><br></div></code></pre></div></div>
<p>Cette commande va créer un nouveau répertoire appelé <code>myenv</code> qui contient un environnement Python. Vous pouvez remplacer <code>myenv</code> par n'importe quel nom.
Le nom le plus courant est <code>venv</code> de <code>.venv</code>. (N'oubliez pas de l'ajouter à votre fichier <code>.gitignore</code> si vous utilisez git).</p>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="activer-lenvironnement-virtuel">Activer l'environnement virtuel<a href="https://lunik.tiwabbit.fr/blog/fr/python-venv-paradise#activer-lenvironnement-virtuel" class="hash-link" aria-label="Lien direct vers Activer l'environnement virtuel" title="Lien direct vers Activer l'environnement virtuel" translate="no">​</a></h3>
<div class="language-bash codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-bash codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token builtin class-name" style="color:rgb(189, 147, 249)">source</span><span class="token plain"> myenv/bin/activate</span><br></div></code></pre></div></div>
<p>Cette commande activera l'environnement virtuel. Vous pouvez constater que l'invite a changé. Elle contient désormais le nom de l'environnement virtuel en début de ligne.</p>
<div class="language-bash codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-bash codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">myenv</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> user@host:~$</span><br></div></code></pre></div></div>
<p>Vous pouvez vérifier les binaires Python utilisés par l'environnement virtuel à l'aide de la commande suivante.</p>
<div class="language-bash codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-bash codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">which</span><span class="token plain"> python</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="désactiver-lenvironnement-virtuel">Désactiver l'environnement virtuel<a href="https://lunik.tiwabbit.fr/blog/fr/python-venv-paradise#d%C3%A9sactiver-lenvironnement-virtuel" class="hash-link" aria-label="Lien direct vers Désactiver l'environnement virtuel" title="Lien direct vers Désactiver l'environnement virtuel" translate="no">​</a></h3>
<div class="language-bash codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-bash codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">deactivate</span><br></div></code></pre></div></div>
<p>Cette commande désactive l'environnement virtuel. Vous êtes maintenant de retour dans l'environnement Python du système.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="et-maintenant-">Et maintenant ?<a href="https://lunik.tiwabbit.fr/blog/fr/python-venv-paradise#et-maintenant-" class="hash-link" aria-label="Lien direct vers Et maintenant ?" title="Lien direct vers Et maintenant ?" translate="no">​</a></h2>
<p>Maintenant que vous savez comment utiliser les environnements virtuels Python, vous pouvez les utiliser dans vos projets.</p>
<p>Dans ma routine, lorsque je démarre un nouveau projet ou que je travaille sur un projet existant, la première chose que je fais est de créer un nouvel environnement virtuel. Ensuite, je l'active et j'installe les paquets nécessaires.</p>
<div class="language-bash codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-bash codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">python </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-m</span><span class="token plain"> venv .venv</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">source</span><span class="token plain"> .venv/bin/activate</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">pip </span><span class="token function" style="color:rgb(80, 250, 123)">install</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-r</span><span class="token plain"> requirements.txt</span><br></div></code></pre></div></div>
<p>Cela me permet de travailler sur plusieurs projets qui nécessitent différentes versions de Python ou différentes versions du même paquetage sans aucun conflit.
Sans cette technique, je devrais faire face à de nombreux conflits et je devrais désinstaller et réinstaller les paquets en permanence.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="conclusion">Conclusion<a href="https://lunik.tiwabbit.fr/blog/fr/python-venv-paradise#conclusion" class="hash-link" aria-label="Lien direct vers Conclusion" title="Lien direct vers Conclusion" translate="no">​</a></h2>
<p>Les environnements virtuels Python sont un excellent moyen d'isoler votre environnement Python de l'environnement Python du système. Ils sont faciles à utiliser et très utiles lorsque vous travaillez sur plusieurs projets qui nécessitent différentes versions de Python ou différentes versions d'un même paquetage. Vous devriez les utiliser dans vos projets. Vous gagnerez beaucoup de temps et vous vous épargnerez bien des maux de tête.</p>
<p>N'oubliez pas que Python fournit déjà un module intégré pour créer des environnements virtuels. Vous n'avez pas besoin d'utiliser un paquetage tiers pour le faire. <strong>Faites confiance à Python, pas à un paquet que vous avez trouvé au hasard sur Internet</strong></p>]]></content>
        <author>
            <name>Guillaume MARTINEZ</name>
            <uri>https://github.com/Lunik</uri>
        </author>
        <category label="python" term="python"/>
        <category label="development" term="development"/>
        <category label="venv" term="venv"/>
        <category label="virtualenv" term="virtualenv"/>
        <category label="pip" term="pip"/>
        <category label="local" term="local"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Configurer l'image de démarrage par défaut dans Grub2]]></title>
        <id>https://lunik.tiwabbit.fr/blog/fr/config-default-grub2-boot-img</id>
        <link href="https://lunik.tiwabbit.fr/blog/fr/config-default-grub2-boot-img"/>
        <updated>2024-02-08T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Guide pour configurer l'image de démarrage par défaut dans Grub2 et choisir le noyau Linux qui démarre automatiquement sur votre système.]]></summary>
        <content type="html"><![CDATA[<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2024-02-08-config-default-grub2-boot-img/cover.jpg" alt="cover" class="img__Ss2"></p>
<p>Aujourd'hui, j'ai mis à jour mon serveur <a href="https://fedoraproject.org/" target="_blank" rel="noopener noreferrer" class="">Fedora</a> depuis la version <code>33</code> vers <code>38</code> mais tout ne s'est pas passé comme prévu.</p>
<p>J'ai <a href="https://github.com/openzfs/zfs" target="_blank" rel="noopener noreferrer" class="">OpenZFS</a> d'intallé pour gérer mon stockage et la version actuelle de <a href="https://github.com/openzfs/zfs" target="_blank" rel="noopener noreferrer" class="">OpenZFS</a> (<a href="https://github.com/openzfs/zfs/releases/tag/zfs-2.2.2" target="_blank" rel="noopener noreferrer" class="">2.2.2</a>) n'est pas compatible avec le dernier <a href="https://www.kernel.org/" target="_blank" rel="noopener noreferrer" class="">kernel</a> (<code>6.7</code>). J'étais coincé avec mon nouveau <a href="https://www.kernel.org/" target="_blank" rel="noopener noreferrer" class="">kernel</a> et incapable d'accéder à mes données.</p>
<p>Pour référence, voici le message d'erreur que j'obtenais :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">zfs list</span><br></div></code></pre></div></div>
<p>Output :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">The ZFS modules cannot be auto-loaded.</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">Try running </span><span class="token string" style="color:rgb(255, 121, 198)">'modprobe zfs'</span><span class="token plain"> as root to manually load them.</span><br></div></code></pre></div></div>
<p>Et :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">modprobe zfs</span><br></div></code></pre></div></div>
<p>Output :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">modprobe: FATAL: Module zfs not found </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">in</span><span class="token plain"> directory /lib/modules/6.7.3-100.fc38.x86_64</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="troubleshooting">Troubleshooting<a href="https://lunik.tiwabbit.fr/blog/fr/config-default-grub2-boot-img#troubleshooting" class="hash-link" aria-label="Lien direct vers Troubleshooting" title="Lien direct vers Troubleshooting" translate="no">​</a></h2>
<p>La première chose que j'ai faite a été de vérifier quelle version de <a href="https://www.kernel.org/" target="_blank" rel="noopener noreferrer" class="">kernel</a> est supportée par la dernière version de <a href="https://github.com/openzfs/zfs" target="_blank" rel="noopener noreferrer" class="">OpenZFS</a> (<a href="https://github.com/openzfs/zfs/releases/tag/zfs-2.2.2" target="_blank" rel="noopener noreferrer" class="">2.2.2</a>) et j'ai découvert que la dernière version supportée de <a href="https://www.kernel.org/" target="_blank" rel="noopener noreferrer" class="">kernel</a> est <code>6.6</code>. Je l'ai manqué d'une version mineure.</p>
<p>Ce n'est pas grave, je peux juste installer le <a href="https://www.kernel.org/" target="_blank" rel="noopener noreferrer" class="">kernel</a> précédent et démarrer dessus, non ?</p>
<p>Voyons quels sont les noyaux disponibles :</p>
<div class="language-bash codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-bash codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">dnf </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--releasever</span><span class="token operator">=</span><span class="token number">38</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--showduplicates</span><span class="token plain"> list kernel</span><br></div></code></pre></div></div>
<p>Output :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">Paquets disponibles</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">kernel.x86_64          </span><span class="token number">6.2</span><span class="token plain">.9-300.fc38          fedora  </span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">kernel.x86_64          </span><span class="token number">6.7</span><span class="token plain">.3-100.fc38          pdates </span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="installer-le-noyau-précédent">Installer le noyau précédent<a href="https://lunik.tiwabbit.fr/blog/fr/config-default-grub2-boot-img#installer-le-noyau-pr%C3%A9c%C3%A9dent" class="hash-link" aria-label="Lien direct vers Installer le noyau précédent" title="Lien direct vers Installer le noyau précédent" translate="no">​</a></h2>
<p>Ce n'est pas vraiment ce à quoi je m'attendais. J'espérais voir la version précédente <a href="https://www.kernel.org/" target="_blank" rel="noopener noreferrer" class="">kernel</a> <code>6.6</code> mais elle n'est pas là.
Essayons d'installer la version <code>6.2.9</code> et voyons ce qui se passe :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">dnf </span><span class="token function" style="color:rgb(80, 250, 123)">install</span><span class="token plain"> kernel-6.2.9-300.fc38</span><br></div></code></pre></div></div>
<p>Redémarrons et voyons si ça fonctionne.</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">uname</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-r</span><br></div></code></pre></div></div>
<p>Output :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token number">6.7</span><span class="token plain">.3-100.fc38.x86_64</span><br></div></code></pre></div></div>
<p>Après avoir redémarré, je démarrais toujours avec le dernier <a href="https://www.kernel.org/" target="_blank" rel="noopener noreferrer" class="">kernel</a> <code>6.7</code>.</p>
<p>Branchons un écran et voyons ce qui se passe pendant le processus de démarrage.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="grub2">Grub2<a href="https://lunik.tiwabbit.fr/blog/fr/config-default-grub2-boot-img#grub2" class="hash-link" aria-label="Lien direct vers Grub2" title="Lien direct vers Grub2" translate="no">​</a></h2>
<p>Pendant le processus de démarrage, j'ai obtenu le menu Grub2 et j'ai pu sélectionner la version précédente <a href="https://www.kernel.org/" target="_blank" rel="noopener noreferrer" class="">kernel</a> <code>6.2.9</code> mais ce n'était pas l'image de démarrage par défaut. Je dois la sélectionner manuellement à chaque fois que je redémarre le serveur.</p>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="résolution-des-problèmes-à-nouveau">Résolution des problèmes (à nouveau)<a href="https://lunik.tiwabbit.fr/blog/fr/config-default-grub2-boot-img#r%C3%A9solution-des-probl%C3%A8mes-%C3%A0-nouveau" class="hash-link" aria-label="Lien direct vers Résolution des problèmes (à nouveau)" title="Lien direct vers Résolution des problèmes (à nouveau)" translate="no">​</a></h3>
<p>Jetons un coup d'oeil à la configuration de Grub2 pour voir quelle est la configuration par défaut :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">cat</span><span class="token plain"> /etc/default/grub</span><br></div></code></pre></div></div>
<p>Output :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">GRUB_TIMEOUT</span><span class="token operator">=</span><span class="token number">5</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">GRUB_DISTRIBUTOR</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"</span><span class="token string variable" style="color:rgb(189, 147, 249);font-style:italic">$(</span><span class="token string variable function" style="color:rgb(80, 250, 123);font-style:italic">sed</span><span class="token string variable" style="color:rgb(189, 147, 249);font-style:italic"> </span><span class="token string variable string" style="color:rgb(255, 121, 198);font-style:italic">'s, release .*$,,g'</span><span class="token string variable" style="color:rgb(189, 147, 249);font-style:italic"> /etc/system-release</span><span class="token string variable" style="color:rgb(189, 147, 249);font-style:italic">)</span><span class="token string" style="color:rgb(255, 121, 198)">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">GRUB_DEFAULT</span><span class="token operator">=</span><span class="token plain">saved</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">GRUB_DISABLE_SUBMENU</span><span class="token operator">=</span><span class="token plain">true</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">GRUB_TERMINAL_OUTPUT</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"console"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">GRUB_CMDLINE_LINUX</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"resume=/dev/mapper/fedora_nubs-swap rd.lvm.lv=fedora_nubs/root rd.lvm.lv=fedora_nubs/swap rhgb quiet"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">GRUB_DISABLE_RECOVERY</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"true"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">GRUB_ENABLE_BLSCFG</span><span class="token operator">=</span><span class="token plain">true</span><br></div></code></pre></div></div>
<p>Hum. <code>GRUB_DEFAULT=saved</code>. On dirait que l'image de démarrage par défaut est sauvegardée quelque part. Jetons un coup d'oeil au fichier de configuration de Grub2 :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">grep</span><span class="token plain"> saved /etc/grub2.cfg</span><br></div></code></pre></div></div>
<p>Output :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">   </span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">set</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">default</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"</span><span class="token string variable" style="color:rgb(189, 147, 249);font-style:italic">${saved_entry}</span><span class="token string" style="color:rgb(255, 121, 198)">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"</span><span class="token string variable" style="color:rgb(189, 147, 249);font-style:italic">${prev_saved_entry}</span><span class="token string" style="color:rgb(255, 121, 198)">"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">then</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">set</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">saved_entry</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"</span><span class="token string variable" style="color:rgb(189, 147, 249);font-style:italic">${prev_saved_entry}</span><span class="token string" style="color:rgb(255, 121, 198)">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  save_env saved_entry</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">set</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">prev_saved_entry</span><span class="token operator">=</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  save_env prev_saved_entry</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">function</span><span class="token plain"> </span><span class="token function-name function" style="color:rgb(80, 250, 123)">savedefault</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">saved_entry</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"</span><span class="token string variable" style="color:rgb(189, 147, 249);font-style:italic">${chosen}</span><span class="token string" style="color:rgb(255, 121, 198)">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    save_env saved_entry</span><br></div></code></pre></div></div>
<p>Le fichier de configuration de grub2 est assez complexe et je ne veux pas y toucher, mais il semble qu'il définisse l'image de démarrage par défaut dans la variable <code>saved_entry</code>.</p>
<p>J'ai découvert qu'il existe un binaire pour travailler avec les variables d'environnement de grub2 : <code>grub2-editenv</code>.</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">grub2-editenv list</span><br></div></code></pre></div></div>
<p>Output :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">saved_entry</span><span class="token operator">=</span><span class="token plain">8bfb6e63623d4ee6aab1634ebafdd5d4-5.6.15-200.fc31.x86_64</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">kernelopts</span><span class="token operator">=</span><span class="token plain">root</span><span class="token operator">=</span><span class="token plain">/dev/mapper/fedora_nubs-root ro </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">resume</span><span class="token operator">=</span><span class="token plain">/dev/mapper/fedora_nubs-swap </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">rd.lvm.lv</span><span class="token operator">=</span><span class="token plain">fedora_nubs/root </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">rd.lvm.lv</span><span class="token operator">=</span><span class="token plain">fedora_nubs/swap rhgb quiet </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">systemd.unified_cgroup_hierarchy</span><span class="token operator">=</span><span class="token number">0</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">boot_success</span><span class="token operator">=</span><span class="token number">0</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">boot_indeterminate</span><span class="token operator">=</span><span class="token number">1</span><br></div></code></pre></div></div>
<p><code>5.6.15</code> ! C'est une vieille version du noyau. Je suppose que ma précédente mise à jour depuis <a href="https://fedoraproject.org/" target="_blank" rel="noopener noreferrer" class="">Fedora</a> <code>31</code> n'était pas aussi propre que je le pensais.</p>
<p>Comment je peux changer l'image de démarrage par défaut ? Et quelle est cette longue chaîne hexadécimale au début de la variable <code>saved_entry</code> ?</p>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="changer-limage-de-démarrage-par-défaut">Changer l'image de démarrage par défaut<a href="https://lunik.tiwabbit.fr/blog/fr/config-default-grub2-boot-img#changer-limage-de-d%C3%A9marrage-par-d%C3%A9faut" class="hash-link" aria-label="Lien direct vers Changer l'image de démarrage par défaut" title="Lien direct vers Changer l'image de démarrage par défaut" translate="no">​</a></h3>
<p>Nous devons d'abord trouver la liste des images de démarrage disponibles. J'ai trouvé un autre binaire pratique pour faire cela <code>grubby</code>.</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">grubby </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--info</span><span class="token plain"> ALL</span><br></div></code></pre></div></div>
<p>Output :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">index</span><span class="token operator">=</span><span class="token number">0</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">kernel</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"/boot/vmlinuz-6.7.3-100.fc38.x86_64"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">args</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"ro resume=/dev/mapper/fedora_nubs-swap rd.lvm.lv=fedora_nubs/root rd.lvm.lv=fedora_nubs/swap rhgb quiet systemd.unified_cgroup_hierarchy=0"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">root</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"/dev/mapper/fedora_nubs-root"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">initrd</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"/boot/initramfs-6.7.3-100.fc38.x86_64.img"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">title</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"Fedora Linux (6.7.3-100.fc38.x86_64) 38 (Server Edition)"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">id</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"8bfb6e63623d4ee6aab1634ebafdd5d4-6.7.3-100.fc38.x86_64"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">index</span><span class="token operator">=</span><span class="token number">1</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">kernel</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"/boot/vmlinuz-6.5.12-100.fc37.x86_64"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">args</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"ro resume=/dev/mapper/fedora_nubs-swap rd.lvm.lv=fedora_nubs/root rd.lvm.lv=fedora_nubs/swap rhgb quiet systemd.unified_cgroup_hierarchy=0"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">root</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"/dev/mapper/fedora_nubs-root"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">initrd</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"/boot/initramfs-6.5.12-100.fc37.x86_64.img"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">title</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"Fedora Linux (6.5.12-100.fc37.x86_64) 37 (Server Edition)"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">id</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"8bfb6e63623d4ee6aab1634ebafdd5d4-6.5.12-100.fc37.x86_64"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">index</span><span class="token operator">=</span><span class="token number">2</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">kernel</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"/boot/vmlinuz-6.2.9-300.fc38.x86_64"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">args</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"ro resume=/dev/mapper/fedora_nubs-swap rd.lvm.lv=fedora_nubs/root rd.lvm.lv=fedora_nubs/swap rhgb quiet systemd.unified_cgroup_hierarchy=0"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">root</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"/dev/mapper/fedora_nubs-root"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">initrd</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"/boot/initramfs-6.2.9-300.fc38.x86_64.img"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">title</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"Fedora Linux (6.2.9-300.fc38.x86_64) 38 (Server Edition)"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">id</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"8bfb6e63623d4ee6aab1634ebafdd5d4-6.2.9-300.fc38.x86_64"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">index</span><span class="token operator">=</span><span class="token number">3</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">kernel</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"/boot/vmlinuz-0-rescue-8bfb6e63623d4ee6aab1634ebafdd5d4"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">args</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"ro resume=/dev/mapper/fedora_nubs-swap rd.lvm.lv=fedora_nubs/root rd.lvm.lv=fedora_nubs/swap rhgb quiet systemd.unified_cgroup_hierarchy=0"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">root</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"/dev/mapper/fedora_nubs-root"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">initrd</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"/boot/initramfs-0-rescue-8bfb6e63623d4ee6aab1634ebafdd5d4.img"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">title</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"Fedora (0-rescue-8bfb6e63623d4ee6aab1634ebafdd5d4) 30 (Thirty)"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">id</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"8bfb6e63623d4ee6aab1634ebafdd5d4-0-rescue"</span><br></div></code></pre></div></div>
<p>Attendez un peu. La liste de sortie est vraiment similaire à ce que j'ai sur mon moniteur pendant le processus de démarrage. Et le champ <code>id</code> a le même format que la variable <code>saved_entry</code>.</p>
<p>Je suppose que si je change la variable <code>saved_entry</code> par l'<code>id</code> de l'image de démarrage sur laquelle je veux démarrer, cela devrait fonctionner.</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">grub2-editenv - </span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">set</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">saved_entry</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">'8bfb6e63623d4ee6aab1634ebafdd5d4-6.2.9-300.fc38.x86_64'</span><br></div></code></pre></div></div>
<p>Vérification de la variable <code>saved_entry</code> :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">grub2-editenv list</span><br></div></code></pre></div></div>
<p>Output :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">saved_entry</span><span class="token operator">=</span><span class="token plain">8bfb6e63623d4ee6aab1634ebafdd5d4-6.2.9-300.fc38.x86_64</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">kernelopts</span><span class="token operator">=</span><span class="token plain">root</span><span class="token operator">=</span><span class="token plain">/dev/mapper/fedora_nubs-root ro </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">resume</span><span class="token operator">=</span><span class="token plain">/dev/mapper/fedora_nubs-swap </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">rd.lvm.lv</span><span class="token operator">=</span><span class="token plain">fedora_nubs/root </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">rd.lvm.lv</span><span class="token operator">=</span><span class="token plain">fedora_nubs/swap rhgb quiet </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">systemd.unified_cgroup_hierarchy</span><span class="token operator">=</span><span class="token number">0</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">boot_success</span><span class="token operator">=</span><span class="token number">1</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">boot_indeterminate</span><span class="token operator">=</span><span class="token number">1</span><br></div></code></pre></div></div>
<p>Ça a l'air pas mal. Il est temps de procéder au test final. Redémarrage du serveur...</p>
<p>Je vois le menu Grub2 et l'image sélectionnée par défaut est celle que j'ai définie. Ne bougez pas ... 5 ... 4 ... 3 ... 2 ... 1 ... 0.</p>
<p>Ca démarre !</p>
<p>Dernière vérification :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">uname</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-r</span><br></div></code></pre></div></div>
<p>Output :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token number">6.2</span><span class="token plain">.9-300.fc38.x86_64</span><br></div></code></pre></div></div>
<p>Et mon ZFS ?</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">zfs list</span><br></div></code></pre></div></div>
<p>Output :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">The ZFS modules cannot be auto-loaded.</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">Try running </span><span class="token string" style="color:rgb(255, 121, 198)">'modprobe zfs'</span><span class="token plain"> as root to manually load them.</span><br></div></code></pre></div></div>
<p>Argh. J'ai oublié de réinstaller les modules <a href="https://github.com/openzfs/zfs" target="_blank" rel="noopener noreferrer" class="">OpenZFS</a> pour le nouveau <a href="https://www.kernel.org/" target="_blank" rel="noopener noreferrer" class="">kernel</a>. Faisons ça.</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">dnf </span><span class="token function" style="color:rgb(80, 250, 123)">install</span><span class="token plain"> zfs</span><br></div></code></pre></div></div>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">zfs list</span><br></div></code></pre></div></div>
<p>Output :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">NAME                           USED  AVAIL  REFER  MOUNTPOINT</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">poule                         </span><span class="token number">3</span><span class="token plain">.64T  </span><span class="token number">3</span><span class="token plain">.47T   141K  /poule</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token plain">.</span><br></div></code></pre></div></div>
<p>C'est vivant !</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="conclusion">Conclusion<a href="https://lunik.tiwabbit.fr/blog/fr/config-default-grub2-boot-img#conclusion" class="hash-link" aria-label="Lien direct vers Conclusion" title="Lien direct vers Conclusion" translate="no">​</a></h2>
<p>J'espère que ce guide vous aidera à configurer l'image de démarrage par défaut dans Grub2. C'est une tâche simple mais qui peut s'avérer délicate si vous ne savez pas où chercher. Soyez également très prudent lorsque vous jouez avec Grub2, vous pouvez facilement casser votre système. Ayez toujours un plan de secours (je ne l'ai pas fait ... YOLO).</p>]]></content>
        <author>
            <name>Guillaume MARTINEZ</name>
            <uri>https://github.com/Lunik</uri>
        </author>
        <category label="linux" term="linux"/>
        <category label="grub" term="grub"/>
        <category label="boot" term="boot"/>
        <category label="grub2" term="grub2"/>
        <category label="initramfs" term="initramfs"/>
        <category label="kernel" term="kernel"/>
        <category label="image" term="image"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Forcer la vitesse des liens réseau sous Linux]]></title>
        <id>https://lunik.tiwabbit.fr/blog/fr/focre-network-link-speed-linux</id>
        <link href="https://lunik.tiwabbit.fr/blog/fr/focre-network-link-speed-linux"/>
        <updated>2024-01-14T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Dépannage simple de la vitesse de connexion au réseau sous Linux]]></summary>
        <content type="html"><![CDATA[<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2024-01-14-force-network-link-speed/cover.png" alt="cover" class="img__Ss2"></p>
<p>Aujourd'hui, j'ai été confronté à un problème assez ennuyeux. J'ai un serveur avec une carte réseau de 1Gbps connectée à un switch de 1Gbps. J'ai essayé de sauvegarder mes données comme d'habitude mais le transfert était plus lent que d'habitude. En utilisant <code>ethtool</code>, j'ai vu que la vitesse du lien n'était que de 100Mbps !</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="debug-the-current-link-speed-déboguer-la-vitesse-de-la-liaison">Debug the current link speed (déboguer la vitesse de la liaison)<a href="https://lunik.tiwabbit.fr/blog/fr/focre-network-link-speed-linux#debug-the-current-link-speed-d%C3%A9boguer-la-vitesse-de-la-liaison" class="hash-link" aria-label="Lien direct vers Debug the current link speed (déboguer la vitesse de la liaison)" title="Lien direct vers Debug the current link speed (déboguer la vitesse de la liaison)" translate="no">​</a></h2>
<p>Tout d'abord, je dois récupérer le nom de l'interface réseau. Je pensais que c'était <code>eth0</code> mais c'était <code>enp2s0</code>. Merci à Fedora pour cette nouvelle convention de nommage !</p>
<p>En utilisant la commande <code>ip</code>, je peux donc obtenir la liste de toutes les interfaces réseau et leur statut actuel.</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">ip</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">link</span><span class="token plain"> show</span><br></div></code></pre></div></div>
<p>Output :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token number">1</span><span class="token plain">: lo: </span><span class="token operator">&lt;</span><span class="token plain">LOOPBACK,UP,LOWER_UP</span><span class="token operator">&gt;</span><span class="token plain"> mtu </span><span class="token number">65536</span><span class="token plain"> qdisc noqueue state UNKNOWN mode DEFAULT group default qlen </span><span class="token number">1000</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token number">2</span><span class="token plain">: enp2s0: </span><span class="token operator">&lt;</span><span class="token plain">BROADCAST,MULTICAST,UP,LOWER_UP</span><span class="token operator">&gt;</span><span class="token plain"> mtu </span><span class="token number">1500</span><span class="token plain"> qdisc fq_codel state UP mode DEFAULT group default qlen </span><span class="token number">1000</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    link/ether </span><span class="token number">12</span><span class="token plain">:34:56:78:9a:bc brd ff:ff:ff:ff:ff:ff</span><br></div></code></pre></div></div>
<p>L'interface <code>enp2s0</code> est celle que je recherche. Je peux maintenant utiliser <code>ethtool</code> pour obtenir la vitesse actuelle du lien.</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">ethtool</span><span class="token plain"> enp2s0</span><br></div></code></pre></div></div>
<p>Output :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">Settings </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">for</span><span class="token plain"> enp2s0:</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	Supported ports: </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"> TP	 MII </span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	Supported </span><span class="token function" style="color:rgb(80, 250, 123)">link</span><span class="token plain"> modes:   10baseT/Half 10baseT/Full</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	                        100baseT/Half 100baseT/Full</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	                        1000baseT/Full</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	Supported pause frame use: Symmetric Receive-only</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	Supports auto-negotiation: Yes</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	Supported FEC modes: Not reported</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	Advertised </span><span class="token function" style="color:rgb(80, 250, 123)">link</span><span class="token plain"> modes:  100baseT/Full</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	Advertised pause frame use: Symmetric Receive-only</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	Advertised auto-negotiation: Yes</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	Advertised FEC modes: Not reported</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	Link partner advertised </span><span class="token function" style="color:rgb(80, 250, 123)">link</span><span class="token plain"> modes:  10baseT/Half 10baseT/Full</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	                                     100baseT/Half 100baseT/Full</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	                                     1000baseT/Half 1000baseT/Full</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	Link partner advertised pause frame use: Symmetric Receive-only</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	Link partner advertised auto-negotiation: Yes</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	Link partner advertised FEC modes: Not reported</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	Speed: 100Mb/s</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	Duplex: Full</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	Auto-negotiation: on</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	master-slave cfg: preferred slave</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	master-slave status: slave</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	Port: Twisted Pair</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	PHYAD: </span><span class="token number">0</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	Transceiver: external</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	MDI-X: Unknown</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	Supports Wake-on: pumbg</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	Wake-on: g</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	Link detected: </span><span class="token function" style="color:rgb(80, 250, 123)">yes</span><br></div></code></pre></div></div>
<p>La ligne <code>Speed</code> est celle que je recherche. Elle indique <code>1000b/s</code>, ce qui n'est pas ce que j'attends. <code>Auto-negotiation</code> est <code>on</code> donc la carte réseau devrait être capable de négocier la vitesse du lien avec le switch.</p>
<p>Ma carte supporte <code>1000baseT/Full</code> comme le montre la ligne <code>Supported link modes</code>. Le switch supporte également <code>1000baseT/Full</code> comme le montre la ligne <code>Link partner advertised link modes</code>. Alors pourquoi la vitesse du lien n'est-elle que de 100Mbps ?</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="forcer-la-vitesse-du-lien">Forcer la vitesse du lien<a href="https://lunik.tiwabbit.fr/blog/fr/focre-network-link-speed-linux#forcer-la-vitesse-du-lien" class="hash-link" aria-label="Lien direct vers Forcer la vitesse du lien" title="Lien direct vers Forcer la vitesse du lien" translate="no">​</a></h2>
<p>Je peux forcer la vitesse du lien en utilisant la commande <code>ethtool</code>.</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">ethtool</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-s</span><span class="token plain"> enp2s0 speed </span><span class="token number">1000</span><br></div></code></pre></div></div>
<p>Vérifions à nouveau la vitesse du lien.</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">ethtool</span><span class="token plain"> enp2s0</span><br></div></code></pre></div></div>
<p>Output :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">Settings </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">for</span><span class="token plain"> enp2s0:</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	Supported ports: </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"> TP	 MII </span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	Supported </span><span class="token function" style="color:rgb(80, 250, 123)">link</span><span class="token plain"> modes:   10baseT/Half 10baseT/Full</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	                        100baseT/Half 100baseT/Full</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	                        1000baseT/Full</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	Supported pause frame use: Symmetric Receive-only</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	Supports auto-negotiation: Yes</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	Supported FEC modes: Not reported</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	Advertised </span><span class="token function" style="color:rgb(80, 250, 123)">link</span><span class="token plain"> modes:  1000baseT/Full</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	Advertised pause frame use: Symmetric Receive-only</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	Advertised auto-negotiation: Yes</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	Advertised FEC modes: Not reported</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	Link partner advertised </span><span class="token function" style="color:rgb(80, 250, 123)">link</span><span class="token plain"> modes:  10baseT/Half 10baseT/Full</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	                                     100baseT/Half 100baseT/Full</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	                                     1000baseT/Half 1000baseT/Full</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	Link partner advertised pause frame use: Symmetric Receive-only</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	Link partner advertised auto-negotiation: Yes</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	Link partner advertised FEC modes: Not reported</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	Speed: 1000Mb/s</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	Duplex: Full</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	Auto-negotiation: on</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	master-slave cfg: preferred slave</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	master-slave status: slave</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	Port: Twisted Pair</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	PHYAD: </span><span class="token number">0</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	Transceiver: external</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	MDI-X: Unknown</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	Supports Wake-on: pumbg</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	Wake-on: g</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">	Link detected: </span><span class="token function" style="color:rgb(80, 250, 123)">yes</span><br></div></code></pre></div></div>
<p>La ligne <code>Speed</code> indique maintenant <code>1000Mb/s</code>, ce qui correspond à ce que j'attendais.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="conclusion">Conclusion<a href="https://lunik.tiwabbit.fr/blog/fr/focre-network-link-speed-linux#conclusion" class="hash-link" aria-label="Lien direct vers Conclusion" title="Lien direct vers Conclusion" translate="no">​</a></h2>
<p>Je ne sais pas vraiment pourquoi la vitesse du lien n'était que de 100Mbps. Peut-être y avait-il un problème avec le switch ou le câble. Je ferai des recherches plus tard. Pour l'instant, je suis content de ma vitesse de liaison de 1Gbps.</p>]]></content>
        <author>
            <name>Guillaume MARTINEZ</name>
            <uri>https://github.com/Lunik</uri>
        </author>
        <category label="linux" term="linux"/>
        <category label="network" term="network"/>
        <category label="speed" term="speed"/>
        <category label="link" term="link"/>
        <category label="ethtool" term="ethtool"/>
        <category label="ip" term="ip"/>
        <category label="ifconfig" term="ifconfig"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Authentification SSH avec une CA]]></title>
        <id>https://lunik.tiwabbit.fr/blog/fr/ssh-ca-authentication</id>
        <link href="https://lunik.tiwabbit.fr/blog/fr/ssh-ca-authentication"/>
        <updated>2023-09-19T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Comment mettre en place une autorité de certification SSH (CA) pour signer des clés et s'authentifier de manière sécurisée sur des serveurs SSH.]]></summary>
        <content type="html"><![CDATA[<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2023-09-19-ssh-ca-authentication/cover.jpg" alt="cover" class="img__Ss2"></p>
<p>Cet article décrit comment utiliser une autorité de certification SSH pour s'authentifier auprès des serveurs SSH. Ceci est particulièrement utile lorsque vous avez beaucoup de serveurs à gérer et que vous souhaitez éviter les tracas liés à la gestion d'un grand nombre de clés SSH.</p>
<p>L'idée de base est d'avoir une AC (Certificate Authority) qui signera les clés publiques des utilisateurs. Ensuite, les utilisateurs pourront s'authentifier auprès des serveurs en utilisant leur clé publique signée. De cette façon, vous n'avez pas à gérer les clés publiques des utilisateurs sur les serveurs, vous n'avez qu'à gérer les clés publiques de l'AC. Vous pouvez également limiter la validité des clés publiques signées à une certaine durée ou à un certain ensemble de serveurs et d'utilisateurs.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="conditions-préalables">Conditions préalables<a href="https://lunik.tiwabbit.fr/blog/fr/ssh-ca-authentication#conditions-pr%C3%A9alables" class="hash-link" aria-label="Lien direct vers Conditions préalables" title="Lien direct vers Conditions préalables" translate="no">​</a></h2>
<p>Cet article suppose que vous disposez d'une connaissance de base de SSH et que vous disposez d'un serveur SSH exécuté sur une machine Linux.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="la-théorie">La théorie<a href="https://lunik.tiwabbit.fr/blog/fr/ssh-ca-authentication#la-th%C3%A9orie" class="hash-link" aria-label="Lien direct vers La théorie" title="Lien direct vers La théorie" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="quest-ce-quune-autorité-de-certification-ssh">Qu'est-ce qu'une autorité de certification SSH&nbsp;?<a href="https://lunik.tiwabbit.fr/blog/fr/ssh-ca-authentication#quest-ce-quune-autorit%C3%A9-de-certification-ssh" class="hash-link" aria-label="Lien direct vers Qu'est-ce qu'une autorité de certification SSH&nbsp;?" title="Lien direct vers Qu'est-ce qu'une autorité de certification SSH&nbsp;?" translate="no">​</a></h3>
<p>Une autorité de certification SSH est simplement une paire de clés SSH de base (publique et privée) utilisée pour signer d'autres clés publiques SSH. La clé publique de l'AC est ensuite distribuée aux serveurs et la clé privée est gardée secrète.</p>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="comment-ça-marche">Comment ça marche?<a href="https://lunik.tiwabbit.fr/blog/fr/ssh-ca-authentication#comment-%C3%A7a-marche" class="hash-link" aria-label="Lien direct vers Comment ça marche?" title="Lien direct vers Comment ça marche?" translate="no">​</a></h3>
<p>Lorsqu'un utilisateur souhaite s'authentifier auprès d'un serveur, le serveur lui demandera de fournir une clé publique. L'utilisateur fournira ensuite une clé publique signée par l'AC. Le serveur vérifiera alors la signature de la clé publique à l'aide de la clé publique de l'AC. Si la signature est valide, l'utilisateur sera authentifié.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="la-pratique">La pratique<a href="https://lunik.tiwabbit.fr/blog/fr/ssh-ca-authentication#la-pratique" class="hash-link" aria-label="Lien direct vers La pratique" title="Lien direct vers La pratique" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="générer-la-paire-de-clés-ca">Générer la paire de clés CA<a href="https://lunik.tiwabbit.fr/blog/fr/ssh-ca-authentication#g%C3%A9n%C3%A9rer-la-paire-de-cl%C3%A9s-ca" class="hash-link" aria-label="Lien direct vers Générer la paire de clés CA" title="Lien direct vers Générer la paire de clés CA" translate="no">​</a></h3>
<p>La première étape consiste à générer la paire de clés CA. Pour ce faire, vous pouvez utiliser la commande <code>ssh-keygen</code>&nbsp;:</p>
<div class="language-bash codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-bash codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">ssh-keygen </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-t</span><span class="token plain"> rsa </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-b</span><span class="token plain"> </span><span class="token number">4096</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-f</span><span class="token plain"> my_ssh_ca</span><br></div></code></pre></div></div>
<table><thead><tr><th>Paramètre</th><th>Descriptif</th></tr></thead><tbody><tr><td><code>-t</code></td><td>L'algorithme à utiliser pour générer la paire de clés.</td></tr><tr><td><code>-b</code></td><td>La taille (en bits) de la paire de clés.</td></tr><tr><td><code>-f</code></td><td>Le nom du fichier de sortie (sans les extensions).</td></tr></tbody></table>
<p>Cela générera deux fichiers&nbsp;: <code>my_ssh_ca</code> et <code>my_ssh_ca.pub</code>. La première est la clé privée de l’AC et la seconde est la clé publique de l’AC.</p>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="générer-une-paire-de-clés-ssh-personnelles-facultatif">Générer une paire de clés SSH personnelles (facultatif)<a href="https://lunik.tiwabbit.fr/blog/fr/ssh-ca-authentication#g%C3%A9n%C3%A9rer-une-paire-de-cl%C3%A9s-ssh-personnelles-facultatif" class="hash-link" aria-label="Lien direct vers Générer une paire de clés SSH personnelles (facultatif)" title="Lien direct vers Générer une paire de clés SSH personnelles (facultatif)" translate="no">​</a></h3>
<p>Cette étape suppose que vous disposez déjà d’une paire de clés SSH personnelle. Si ce n'est pas le cas, vous pouvez en générer un à l'aide de la commande <code>ssh-keygen</code>&nbsp;:</p>
<div class="language-bash codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-bash codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">ssh-keygen </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-t</span><span class="token plain"> ed25519 </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-b</span><span class="token plain"> </span><span class="token number">256</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-f</span><span class="token plain"> my_ssh_key</span><br></div></code></pre></div></div>
<table><thead><tr><th>Paramètre</th><th>Descriptif</th></tr></thead><tbody><tr><td><code>-t</code></td><td>L'algorithme à utiliser pour générer la paire de clés.</td></tr><tr><td><code>-b</code></td><td>La taille (en bits) de la paire de clés.</td></tr><tr><td><code>-f</code></td><td>Le nom du fichier de sortie (sans les extensions).</td></tr></tbody></table>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="distribuer-la-clé-publique-de-lac">Distribuer la clé publique de l'AC<a href="https://lunik.tiwabbit.fr/blog/fr/ssh-ca-authentication#distribuer-la-cl%C3%A9-publique-de-lac" class="hash-link" aria-label="Lien direct vers Distribuer la clé publique de l'AC" title="Lien direct vers Distribuer la clé publique de l'AC" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_SAay" id="configurer-le-serveur-ssh">Configurer le serveur SSH<a href="https://lunik.tiwabbit.fr/blog/fr/ssh-ca-authentication#configurer-le-serveur-ssh" class="hash-link" aria-label="Lien direct vers Configurer le serveur SSH" title="Lien direct vers Configurer le serveur SSH" translate="no">​</a></h4>
<p>Tout d’abord, vous devez configurer le serveur SSH pour accepter la clé publique SSH de l'AC. Pour ce faire, vous devez vous authentifier auprès du serveur et devenir root. Ensuite, vous devez éditer le fichier <code>/etc/ssh/sshd_config</code> et ajouter la ligne suivante à la fin du fichier :</p>
<div class="language-text codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-text codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">Match Address 192.168.42.*</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  TrustedUserCAKeys /etc/ssh/ssh_user_ca</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  AuthorizedPrincipalsFile /etc/ssh/authorized_principals/%u</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  RevokedKeys /etc/ssh/revoked_keys</span><br></div></code></pre></div></div>
<table><thead><tr><th>Paramètre</th><th>Descriptif</th></tr></thead><tbody><tr><td><code>Match Address 192.168.42.*</code></td><td>Cette ligne permet d'appliquer la configuration suivante uniquement aux clients correspondant à l'adresse indiquée. Dans ce cas, nous souhaitons uniquement appliquer la configuration suivante aux clients qui correspondent à l'adresse <code>192.168.42.*</code>.</td></tr><tr><td><code>TrustedUserCAKeys</code></td><td>Le chemin d’accès à la clé publique SSH CA.</td></tr><tr><td><code>AuthorizedPrincipalsFile</code></td><td>Le chemin d'accès au fichier contenant la liste des principaux SSH autorisés à s'authentifier auprès des utilisateurs.</td></tr><tr><td><code>RevokedKeys</code></td><td>Le chemin d'accès au fichier contenant la liste des clés publiques SSH révoquées.</td></tr></tbody></table>
<p>Ensuite, vous devez créer le fichier <code>/etc/ssh/ssh_user_ca</code> et y ajouter la clé publique de l'AC SSH&nbsp;:</p>
<div class="language-bash codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-bash codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">cat</span><span class="token plain"> my_ssh_ca.pub </span><span class="token operator">&gt;</span><span class="token plain"> /etc/ssh/ssh_user_ca</span><br></div></code></pre></div></div>
<p>Pour l'instant, nous n'avons aucune clé publique SSH CA à révoquer, il nous suffit donc de créer un fichier vide pour le paramètre <code>RevokedKeys</code>&nbsp;:</p>
<div class="language-bash codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-bash codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">touch</span><span class="token plain"> /etc/ssh/revoked_keys</span><br></div></code></pre></div></div>
<p>Enfin, nous devons créer le répertoire <code>/etc/ssh/authorized_principals</code> pour stocker la liste des principaux SSH autorisés à s'authentifier auprès des utilisateurs&nbsp;:</p>
<div class="language-bash codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-bash codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">mkdir</span><span class="token plain"> /etc/ssh/authorized_principals</span><br></div></code></pre></div></div>
<h5 class="anchor anchorTargetStickyNavbar_SAay" id="configurer-lauthentification-basée-sur-le-principal">Configurer l'authentification basée sur le principal<a href="https://lunik.tiwabbit.fr/blog/fr/ssh-ca-authentication#configurer-lauthentification-bas%C3%A9e-sur-le-principal" class="hash-link" aria-label="Lien direct vers Configurer l'authentification basée sur le principal" title="Lien direct vers Configurer l'authentification basée sur le principal" translate="no">​</a></h5>
<p>A titre d'exemple, nous allons configurer le serveur SSH pour me permettre de m'authentifier auprès de l'utilisateur <code>wabbit</code>. Pour ce faire, nous devons créer le fichier <code>/etc/ssh/authorized_principals/wabbit</code> et y ajouter la ligne suivante&nbsp;:</p>
<div class="language-text codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-text codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">wabbit_ops</span><br></div></code></pre></div></div>
<p>Cela me permettra de m'authentifier auprès de l'utilisateur <code>wabbit</code> en utilisant le principal <code>wabbit_ops</code>. Attention, un principal n'est pas un nom d'utilisateur, c'est juste un nom qui servira à identifier l'utilisateur ou un rôle. Vous pouvez utiliser le nom de votre choix, mais il est préférable d'utiliser un nom facile à retenir.</p>
<h4 class="anchor anchorTargetStickyNavbar_SAay" id="appliquer-la-configuration">Appliquer la configuration<a href="https://lunik.tiwabbit.fr/blog/fr/ssh-ca-authentication#appliquer-la-configuration" class="hash-link" aria-label="Lien direct vers Appliquer la configuration" title="Lien direct vers Appliquer la configuration" translate="no">​</a></h4>
<p>Une fois la configuration effectuée, vous devez redémarrer le serveur SSH pour appliquer les modifications&nbsp;:</p>
<div class="language-bash codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-bash codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">systemctl restart sshd</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="configurer-le-client-ssh">Configurer le client SSH<a href="https://lunik.tiwabbit.fr/blog/fr/ssh-ca-authentication#configurer-le-client-ssh" class="hash-link" aria-label="Lien direct vers Configurer le client SSH" title="Lien direct vers Configurer le client SSH" translate="no">​</a></h3>
<p>Maintenant que le serveur SSH est configuré, nous devons configurer le client SSH pour qu'il utilise l'autorité de certification SSH pour s'authentifier auprès du serveur SSH.</p>
<h4 class="anchor anchorTargetStickyNavbar_SAay" id="signez-la-clé-publique-ssh-personnelle">Signez la clé publique SSH personnelle<a href="https://lunik.tiwabbit.fr/blog/fr/ssh-ca-authentication#signez-la-cl%C3%A9-publique-ssh-personnelle" class="hash-link" aria-label="Lien direct vers Signez la clé publique SSH personnelle" title="Lien direct vers Signez la clé publique SSH personnelle" translate="no">​</a></h4>
<p>Tout d’abord, nous devons signer la clé publique SSH personnelle à l’aide de la clé privée CA. Pour ce faire, nous devons utiliser la commande <code>ssh-keygen</code>&nbsp;:</p>
<div class="language-bash codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-bash codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">ssh-keygen </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-s</span><span class="token plain"> my_ssh_ca </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-I</span><span class="token plain"> lunik@my_server </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-n</span><span class="token plain"> wabbit_ops </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-V</span><span class="token plain"> +1d </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  my_ssh_key.pub</span><br></div></code></pre></div></div>
<table><thead><tr><th>Paramètre</th><th>Descriptif</th></tr></thead><tbody><tr><td><code>-s</code></td><td>Le chemin d'accès à la clé privée de l'autorité de certification.</td></tr><tr><td><code>-I</code></td><td>L'identité de la clé publique signée. Ceci est utilisé pour identifier la clé publique signée. C'est une bonne idée d'utiliser le nom d'utilisateur, le nom d'hôte et le nom du serveur. Cela n'a aucun impact sur l'authentification.</td></tr><tr><td><code>-n</code></td><td>Le principal autorisé lors de l’authentification.</td></tr><tr><td><code>-V</code></td><td>Durée de validité de la clé publique signée.</td></tr><tr><td><code>my_ssh_key.pub</code></td><td>Le chemin d’accès à la clé publique à signer.</td></tr></tbody></table>
<p>Cela générera un fichier <code>my_ssh_key-cert.pub</code> qui contient la clé publique signée.</p>
<p>Pour vérifier la signature de la clé publique signée, vous pouvez utiliser la commande <code>ssh-keygen</code>&nbsp;:</p>
<div class="language-bash codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-bash codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">ssh-keygen </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-L</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-f</span><span class="token plain"> my_ssh_key-cert.pub</span><br></div></code></pre></div></div>
<table><thead><tr><th>Paramètre</th><th>Descriptif</th></tr></thead><tbody><tr><td><code>-L</code></td><td>Vérifiez la signature de la clé publique.</td></tr><tr><td><code>-f</code></td><td>Le chemin d'accès à la clé publique à vérifier.</td></tr></tbody></table>
<p>Cela imprimera le résultat suivant&nbsp;:</p>
<div class="language-text codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-text codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">my_ssh_key-cert.pub:</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        Type: ssh-ed25519-cert-v01@openssh.com user certificate</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        Public key: ED25519-CERT SHA256:Nbe7SXv788c0t3g8D8GQ/5dwHXX4zXtoaEC7r97h5oM</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        Signing CA: RSA SHA256:jitBsmIydxjgdW7DttD9piKIWmb4RPQQ7i7wfQ+M4Vg (using rsa-sha2-512)</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        Key ID: "lunik@my_server"</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        Serial: 0</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        Valid: from 2023-09-19T19:13:00 to 2023-09-20T19:14:07</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        Principals: </span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">                wabbit_ops</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        Critical Options: (none)</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        Extensions: </span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">                permit-X11-forwarding</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">                permit-agent-forwarding</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">                permit-port-forwarding</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">                permit-pty</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">                permit-user-rc</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="sauthentifier-sur-le-serveur-ssh">S'authentifier sur le serveur SSH<a href="https://lunik.tiwabbit.fr/blog/fr/ssh-ca-authentication#sauthentifier-sur-le-serveur-ssh" class="hash-link" aria-label="Lien direct vers S'authentifier sur le serveur SSH" title="Lien direct vers S'authentifier sur le serveur SSH" translate="no">​</a></h3>
<p>Maintenant que le client SSH est configuré, nous pouvons nous authentifier auprès du serveur SSH à l'aide de la clé publique signée. Pour ce faire, nous devons utiliser la commande <code>ssh</code>&nbsp;:</p>
<div class="language-bash codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-bash codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">ssh</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-i</span><span class="token plain"> my_ssh_key </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  wabbit@my_server</span><br></div></code></pre></div></div>
<table><thead><tr><th>Paramètre</th><th>Descriptif</th></tr></thead><tbody><tr><td><code>-i</code></td><td>Le chemin d’accès à la clé privée à utiliser pour s’authentifier.</td></tr><tr><td><code>wabbit@mon_serveur</code></td><td>Le nom d'utilisateur et le nom d'hôte du serveur SSH.</td></tr></tbody></table>]]></content>
        <author>
            <name>Guillaume MARTINEZ</name>
            <uri>https://github.com/Lunik</uri>
        </author>
        <category label="ssh" term="ssh"/>
        <category label="security" term="security"/>
        <category label="ca" term="ca"/>
        <category label="authority" term="authority"/>
        <category label="authentication" term="authentication"/>
        <category label="public" term="public"/>
        <category label="private" term="private"/>
        <category label="key" term="key"/>
        <category label="keys" term="keys"/>
        <category label="ssh-keygen" term="ssh-keygen"/>
        <category label="ssh-keyscan" term="ssh-keyscan"/>
        <category label="ssh-copy-id" term="ssh-copy-id"/>
        <category label="ssh-agent" term="ssh-agent"/>
        <category label="ssh-add" term="ssh-add"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Media center automatisé]]></title>
        <id>https://lunik.tiwabbit.fr/blog/fr/auto-media-center</id>
        <link href="https://lunik.tiwabbit.fr/blog/fr/auto-media-center"/>
        <updated>2023-06-21T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Media center totalement automatisé étape par étape : de la demande au visionnage en moins de 5 minutes]]></summary>
        <content type="html"><![CDATA[<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2023-06-21-auto-media-center/cover.png" alt="cover" class="img__Ss2"></p>
<p>J'ai beaucoup de médias à regarder et je ne veux pas passer du temps à les chercher, les télécharger, les renommer, les déplacer, etc. Je veux pouvoir demander un film ou une émission de télévision et le regarder en moins de 5 minutes. Je veux également pouvoir le regarder sur n'importe quel appareil, n'importe où, à tout moment.</p>
<div class="theme-admonition theme-admonition-warning admonition_IZjC alert alert--warning"><div class="admonitionHeading_uVvU"><span class="admonitionIcon_HiR3"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>attention</div><div class="admonitionContent_bl22"><p>Cet article est uniquement à des fins éducatives. Je n'encourage pas le piratage de contenus sous licence. Les actions décrites dans cet article sont illégales dans certains pays. Je ne suis pas responsable de l'utilisation que vous faites de cet article.</p></div></div>
<p>Je n'utilise pas cette configuration pour télécharger et regarder du contenu piraté. Aucun contenu piraté n'a été téléchargé lors de la rédaction de cet article. Des fichiers de substitution ont été utilisés à la place.</p>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="prérequis">Prérequis<a href="https://lunik.tiwabbit.fr/blog/fr/auto-media-center#pr%C3%A9requis" class="hash-link" aria-label="Lien direct vers Prérequis" title="Lien direct vers Prérequis" translate="no">​</a></h3>
<p>Nous allons utiliser les outils suivants :</p>
<ul>
<li class=""><a href="https://www.plex.tv/" target="_blank" rel="noopener noreferrer" class="">Plex</a> : Serveur et lecteur multimédia</li>
<li class=""><a href="https://sonarr.tv/" target="_blank" rel="noopener noreferrer" class="">Sonarr</a> : Gestionnaire d'émissions de télévision</li>
<li class=""><a href="https://radarr.video/" target="_blank" rel="noopener noreferrer" class="">Radarr</a> : Gestionnaire de films</li>
<li class=""><a href="https://prowlarr.com/" target="_blank" rel="noopener noreferrer" class="">Prowlarr</a> : Indexeur de torrents</li>
<li class=""><a href="https://overseerr.dev/" target="_blank" rel="noopener noreferrer" class="">Overseerr</a> : Gestionnaire de demandes</li>
<li class=""><a href="https://www.qbittorrent.org/" target="_blank" rel="noopener noreferrer" class="">qBittorrent</a> : Client de torrents</li>
</ul>
<p>Nous aurons également besoin d'un serveur basé sur Linux pour héberger tout cela.</p>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="déploiement">Déploiement<a href="https://lunik.tiwabbit.fr/blog/fr/auto-media-center#d%C3%A9ploiement" class="hash-link" aria-label="Lien direct vers Déploiement" title="Lien direct vers Déploiement" translate="no">​</a></h3>
<p>Pour le déploiement, nous allons utiliser <a href="https://www.docker.com/" target="_blank" rel="noopener noreferrer" class="">Docker</a> et <a href="https://docs.docker.com/compose/" target="_blank" rel="noopener noreferrer" class="">Docker Compose</a>.</p>
<h4 class="anchor anchorTargetStickyNavbar_SAay" id="docker-compose">Docker Compose<a href="https://lunik.tiwabbit.fr/blog/fr/auto-media-center#docker-compose" class="hash-link" aria-label="Lien direct vers Docker Compose" title="Lien direct vers Docker Compose" translate="no">​</a></h4>
<p>Le fichier <code>docker-compose.yml</code> complet est disponible <a class="" href="https://lunik.tiwabbit.fr/blog/fr/assets/docker-compose.yml">ici</a>.</p>
<p>Ensuite, nous pouvons démarrer la pile avec la commande suivante :</p>
<div class="language-bash codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-bash codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">docker</span><span class="token plain"> compose up </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-d</span><br></div></code></pre></div></div>
<p>Ensuite, nous pouvons vérifier que tout fonctionne avec :</p>
<div class="language-bash codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-bash codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">docker</span><span class="token plain"> compose </span><span class="token function" style="color:rgb(80, 250, 123)">ps</span><br></div></code></pre></div></div>
<p>Le résultat devrait ressembler à ceci :</p>
<div class="language-bash codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-bash codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">NAME                              IMAGE                                    COMMAND             SERVICE             CREATED             STATUS              PORTS</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">auto-media-center-prowlarr-1      lscr.io/linuxserver/prowlarr:latest      </span><span class="token string" style="color:rgb(255, 121, 198)">"/init"</span><span class="token plain">             prowlarr            </span><span class="token number">20</span><span class="token plain"> minutes ago      Up </span><span class="token number">20</span><span class="token plain"> minutes       </span><span class="token number">0.0</span><span class="token plain">.0.0:9696-</span><span class="token operator">&gt;</span><span class="token number">9696</span><span class="token plain">/tcp</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">auto-media-center-overseerr-1     lscr.io/linuxserver/overseerr:latest     </span><span class="token string" style="color:rgb(255, 121, 198)">"/init"</span><span class="token plain">             overseerr           </span><span class="token number">9</span><span class="token plain"> minutes ago       Up </span><span class="token number">9</span><span class="token plain"> minutes        </span><span class="token number">0.0</span><span class="token plain">.0.0:5055-</span><span class="token operator">&gt;</span><span class="token number">5055</span><span class="token plain">/tcp</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">auto-media-center-plex-1          lscr.io/linuxserver/plex:latest          </span><span class="token string" style="color:rgb(255, 121, 198)">"/init"</span><span class="token plain">             plex                </span><span class="token number">9</span><span class="token plain"> minutes ago       Up </span><span class="token number">9</span><span class="token plain"> minutes        </span><span class="token number">0.0</span><span class="token plain">.0.0:3005-</span><span class="token operator">&gt;</span><span class="token number">3005</span><span class="token plain">/tcp, </span><span class="token number">0.0</span><span class="token plain">.0.0:8324-</span><span class="token operator">&gt;</span><span class="token number">8324</span><span class="token plain">/tcp, </span><span class="token number">0.0</span><span class="token plain">.0.0:1900-</span><span class="token operator">&gt;</span><span class="token number">1900</span><span class="token plain">/udp, </span><span class="token number">0.0</span><span class="token plain">.0.0:32410-</span><span class="token operator">&gt;</span><span class="token number">32410</span><span class="token plain">/udp, </span><span class="token number">0.0</span><span class="token plain">.0.0:32400-</span><span class="token operator">&gt;</span><span class="token number">32400</span><span class="token plain">/tcp, </span><span class="token number">0.0</span><span class="token plain">.0.0:32412-32414-</span><span class="token operator">&gt;</span><span class="token number">32412</span><span class="token plain">-32414/udp, </span><span class="token number">0.0</span><span class="token plain">.0.0:32469-</span><span class="token operator">&gt;</span><span class="token number">32469</span><span class="token plain">/tcp, </span><span class="token number">5353</span><span class="token plain">/udp</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">auto-media-center-qbittorrent-1   lscr.io/linuxserver/qbittorrent:latest   </span><span class="token string" style="color:rgb(255, 121, 198)">"/init"</span><span class="token plain">             qbittorrent         </span><span class="token number">20</span><span class="token plain"> minutes ago      Up </span><span class="token number">20</span><span class="token plain"> minutes       </span><span class="token number">0.0</span><span class="token plain">.0.0:6881-</span><span class="token operator">&gt;</span><span class="token number">6881</span><span class="token plain">/tcp, </span><span class="token number">0.0</span><span class="token plain">.0.0:8080-</span><span class="token operator">&gt;</span><span class="token number">8080</span><span class="token plain">/tcp, </span><span class="token number">0.0</span><span class="token plain">.0.0:6881-</span><span class="token operator">&gt;</span><span class="token number">6881</span><span class="token plain">/udp</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">auto-media-center-radarr-1        lscr.io/linuxserver/radarr:latest        </span><span class="token string" style="color:rgb(255, 121, 198)">"/init"</span><span class="token plain">             radarr              </span><span class="token number">20</span><span class="token plain"> minutes ago      Up </span><span class="token number">19</span><span class="token plain"> minutes       </span><span class="token number">0.0</span><span class="token plain">.0.0:7878-</span><span class="token operator">&gt;</span><span class="token number">7878</span><span class="token plain">/tcp</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">auto-media-center-sonarr-1        lscr.io/linuxserver/sonarr:latest        </span><span class="token string" style="color:rgb(255, 121, 198)">"/init"</span><span class="token plain">             sonarr              </span><span class="token number">20</span><span class="token plain"> minutes ago      Up </span><span class="token number">19</span><span class="token plain"> minutes       </span><span class="token number">0.0</span><span class="token plain">.0.0:8989-</span><span class="token operator">&gt;</span><span class="token number">8989</span><span class="token plain">/tcp</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="configuration">Configuration<a href="https://lunik.tiwabbit.fr/blog/fr/auto-media-center#configuration" class="hash-link" aria-label="Lien direct vers Configuration" title="Lien direct vers Configuration" translate="no">​</a></h3>
<p>Maintenant que tout est en place, nous pouvons commencer la configuration.</p>
<h4 class="anchor anchorTargetStickyNavbar_SAay" id="plex">Plex<a href="https://lunik.tiwabbit.fr/blog/fr/auto-media-center#plex" class="hash-link" aria-label="Lien direct vers Plex" title="Lien direct vers Plex" translate="no">​</a></h4>
<p>C'est la première chose que nous allons configurer. <a href="https://www.plex.tv/" target="_blank" rel="noopener noreferrer" class="">Plex</a> est le serveur multimédia et le lecteur. C'est le cœur de notre centre multimédia.</p>
<p>Tout d'abord, nous devons accéder au service via l'interface web. Le port par défaut est <code>32400</code>. Nous pouvons donc y accéder à l'adresse <code>http://&lt;adresse-ip-du-serveur&gt;:32400/web</code>.</p>
<p>Si vous n'avez pas de compte <a href="https://www.plex.tv/" target="_blank" rel="noopener noreferrer" class="">Plex</a>, vous pouvez en créer un gratuitement. Ensuite, vous pourrez accéder à l'interface web.</p>
<p>Après avoir suivi l'assistant, vous devriez voir quelque chose comme ceci :</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2023-06-21-auto-media-center/plex-web-interface-init.png" alt="Interface web de Plex au démarrage" class="img__Ss2"></p>
<p>Nous pouvons maintenant ajouter nos bibliothèques multimédia. Dans cet exemple, je vais ajouter une bibliothèque de séries TV et une bibliothèque de films.</p>
<p>Tout d'abord, la configuration de la bibliothèque de films :</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2023-06-21-auto-media-center/plex-movie-library-config-01.png" alt="Configuration de la bibliothèque de films dans Plex 01" class="img__Ss2">
<img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2023-06-21-auto-media-center/plex-movie-library-config-02.png" alt="Configuration de la bibliothèque de films dans Plex 02" class="img__Ss2"></p>
<p>Ensuite, la configuration de la bibliothèque de séries TV :</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2023-06-21-auto-media-center/plex-tv-library-config-01.png" alt="Configuration de la bibliothèque de séries TV dans Plex 01" class="img__Ss2">
<img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2023-06-21-auto-media-center/plex-tv-library-config-02.png" alt="Configuration de la bibliothèque de séries TV dans Plex 02" class="img__Ss2"></p>
<p>Enfin, le serveur <a href="https://www.plex.tv/" target="_blank" rel="noopener noreferrer" class="">Plex</a> devrait ressembler à ceci :</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2023-06-21-auto-media-center/plex-library-config.png" alt="Interface web finale de Plex" class="img__Ss2"></p>
<h4 class="anchor anchorTargetStickyNavbar_SAay" id="qbittorrent">QBittorrent<a href="https://lunik.tiwabbit.fr/blog/fr/auto-media-center#qbittorrent" class="hash-link" aria-label="Lien direct vers QBittorrent" title="Lien direct vers QBittorrent" translate="no">​</a></h4>
<p><a href="https://www.qbittorrent.org/" target="_blank" rel="noopener noreferrer" class="">qBittorrent</a> est un client de torrents. Il nous permettra de télécharger des torrents.</p>
<p>Tout d'abord, nous devons accéder au service via l'interface web. Le port par défaut est <code>8080</code>. Nous pouvons donc y accéder à l'adresse suivante : <code>http://&lt;adresse-ip-du-serveur&gt;:8080</code>.
Le nom d'utilisateur par défaut est <code>admin</code> et le mot de passe par défaut est <code>adminadmin</code>.</p>
<p>Vous devriez voir quelque chose comme ceci :</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2023-06-21-auto-media-center/qbittorrent-web-interface-init.png" alt="Interface web QBittorrent" class="img__Ss2"></p>
<p>Ensuite, nous devons configurer le dossier de téléchargement dans (<strong>Options</strong> &gt; <strong>Downloads</strong>). Pour cet exemple, j'utiliserai <code>/downloads</code> comme dossier de téléchargement et <code>/incomplete-downloads</code> comme dossier de téléchargements incomplets. N'oubliez pas de cliquer sur <code>Save</code> en bas de la page.</p>
<h4 class="anchor anchorTargetStickyNavbar_SAay" id="sonarr">Sonarr<a href="https://lunik.tiwabbit.fr/blog/fr/auto-media-center#sonarr" class="hash-link" aria-label="Lien direct vers Sonarr" title="Lien direct vers Sonarr" translate="no">​</a></h4>
<p><a href="https://sonarr.tv/" target="_blank" rel="noopener noreferrer" class="">Sonarr</a> est un gestionnaire de séries télévisées. Il nous permettra de rechercher des séries télévisées et de les télécharger automatiquement.</p>
<p>Tout d'abord, nous devons accéder au service via l'interface web. Le port par défaut est <code>8989</code>. Nous pouvons donc y accéder à l'adresse suivante : <code>http://&lt;adresse-serveur&gt;:8989</code>.</p>
<p>Vous devriez voir quelque chose comme ceci :</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2023-06-21-auto-media-center/sonarr-web-interface-init.png" alt="Interface web initiale de Sonarr" class="img__Ss2"></p>
<h5 class="anchor anchorTargetStickyNavbar_SAay" id="indexeurs">Indexeurs<a href="https://lunik.tiwabbit.fr/blog/fr/auto-media-center#indexeurs" class="hash-link" aria-label="Lien direct vers Indexeurs" title="Lien direct vers Indexeurs" translate="no">​</a></h5>
<p>Nous allons voir la configuration des indexeurs dans (<strong>Paramètres</strong> &gt; <strong>Indexeurs</strong>). Cela sera automatiquement configuré par <a href="https://lunik.tiwabbit.fr/blog/fr/auto-media-center#prowlarr" class="">Prowlarr</a> plus tard.</p>
<h5 class="anchor anchorTargetStickyNavbar_SAay" id="client-de-téléchargement">Client de téléchargement<a href="https://lunik.tiwabbit.fr/blog/fr/auto-media-center#client-de-t%C3%A9l%C3%A9chargement" class="hash-link" aria-label="Lien direct vers Client de téléchargement" title="Lien direct vers Client de téléchargement" translate="no">​</a></h5>
<p>Nous allons configurer le client de téléchargement dans (<strong>Settings</strong> &gt; <strong>Download Client</strong>). Pour cet exemple, je vais utiliser la configuration suivante :</p>
<table><thead><tr><th style="text-align:left">Champ</th><th style="text-align:right">Valeur</th></tr></thead><tbody><tr><td style="text-align:left">Type</td><td style="text-align:right"><code>qBittorrent</code></td></tr><tr><td style="text-align:left">Enable</td><td style="text-align:right"><code>Yes</code></td></tr><tr><td style="text-align:left">Host</td><td style="text-align:right"><code>qbittorrent</code></td></tr><tr><td style="text-align:left">Port</td><td style="text-align:right"><code>8080</code></td></tr><tr><td style="text-align:left">UseSsl</td><td style="text-align:right"><code>No</code></td></tr><tr><td style="text-align:left">Username</td><td style="text-align:right"><code>admin</code></td></tr><tr><td style="text-align:left">Password</td><td style="text-align:right"><code>adminadmin</code></td></tr></tbody></table>
<p>Nous pouvons tester la connexion en cliquant sur <code>Test</code> en bas de la page.</p>
<p><strong>Note :</strong> Vous pouvez définir l'<strong>Initial State</strong> sur <code>Paused</code> si vous ne souhaitez pas que <a href="https://sonarr.tv/" target="_blank" rel="noopener noreferrer" class="">Sonarr</a> télécharge tous les épisodes des séries que vous ajoutez.</p>
<h5 class="anchor anchorTargetStickyNavbar_SAay" id="gestion-des-médias">Gestion des médias<a href="https://lunik.tiwabbit.fr/blog/fr/auto-media-center#gestion-des-m%C3%A9dias" class="hash-link" aria-label="Lien direct vers Gestion des médias" title="Lien direct vers Gestion des médias" translate="no">​</a></h5>
<p>Nous allons configurer la gestion des médias dans (<strong>Settings</strong> &gt; <strong>Media Management</strong>). Cela permettra à <a href="https://sonarr.tv/" target="_blank" rel="noopener noreferrer" class="">Sonarr</a> de renommer et déplacer les épisodes téléchargés depuis qBittorrent dans le dossier approprié pour que <a href="https://www.plex.tv/" target="_blank" rel="noopener noreferrer" class="">Plex</a> puisse les trouver.</p>
<p>Pour cet exemple, je vais utiliser la configuration suivante :</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2023-06-21-auto-media-center/sonarr-media-management-config-01.png" alt="Configuration de la gestion des médias de Sonarr" class="img__Ss2"></p>
<h5 class="anchor anchorTargetStickyNavbar_SAay" id="test">Test<a href="https://lunik.tiwabbit.fr/blog/fr/auto-media-center#test" class="hash-link" aria-label="Lien direct vers Test" title="Lien direct vers Test" translate="no">​</a></h5>
<p>Maintenant, nous devrions pouvoir ajouter une série télévisée. Dans (<strong>Séries</strong> &gt; <strong>Ajouter une série</strong>), nous pouvons rechercher <code>Game of Thrones</code> et l'ajouter :</p>
<table><thead><tr><th style="text-align:left">Champ</th><th style="text-align:right">Valeur</th></tr></thead><tbody><tr><td style="text-align:left">Root Folder</td><td style="text-align:right"><code>/media/Series/Game of Thrones</code></td></tr><tr><td style="text-align:left">Monitor</td><td style="text-align:right"><code>All Episodes</code></td></tr><tr><td style="text-align:left">Quality Profile</td><td style="text-align:right"><code>HD-1080p</code></td></tr></tbody></table>
<p>Ensuite, nous cliquons sur la carte <code>Game of Thrones</code> et nous devrions voir quelque chose comme ceci :</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2023-06-21-auto-media-center/sonarr-tv-example.png" alt="Exemple de série télévisée dans Sonarr" class="img__Ss2"></p>
<p>Ensuite, nous pouvons cliquer sur le bouton <code>Recherche interactive</code> (icône de personne) pour rechercher les torrents de la première saison :</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2023-06-21-auto-media-center/sonarr-tv-example-search.png" alt="Recherche d'exemple de série télévisée dans Sonarr" class="img__Ss2"></p>
<p>Nous pouvons cliquer sur le bouton <code>Télécharger</code> pour déclencher le téléchargement de la première saison.</p>
<p>Dans la section (<strong>Activity</strong> &gt; <strong>Queue</strong>), nous pouvons voir l'avancement du téléchargement :</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2023-06-21-auto-media-center/sonarr-tv-example-download.png" alt="Téléchargement d'exemple de série télévisée dans Sonarr" class="img__Ss2"></p>
<p>Et dans <a href="https://www.qbittorrent.org/" target="_blank" rel="noopener noreferrer" class="">qBittorrent</a>, nous pouvons voir l'avancement du téléchargement :</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2023-06-21-auto-media-center/qbittorrent-tv-example-download.png" alt="Téléchargement d'exemple de série télévisée dans qBittorrent" class="img__Ss2"></p>
<p>Enfin, lorsque le téléchargement est terminé, <a href="https://sonarr.tv/" target="_blank" rel="noopener noreferrer" class="">Sonarr</a> renommera et déplacera l'épisode dans le dossier approprié. Et <a href="https://www.plex.tv/" target="_blank" rel="noopener noreferrer" class="">Plex</a> détectera le nouvel épisode et l'ajoutera à la bibliothèque.</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2023-06-21-auto-media-center/sonarr-tv-example-final.png" alt="Exemple final de série télévisée dans Sonarr" class="img__Ss2"></p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2023-06-21-auto-media-center/plex-tv-example-final.png" alt="Exemple final de série télévisée dans Plex" class="img__Ss2"></p>
<h4 class="anchor anchorTargetStickyNavbar_SAay" id="radarr">Radarr<a href="https://lunik.tiwabbit.fr/blog/fr/auto-media-center#radarr" class="hash-link" aria-label="Lien direct vers Radarr" title="Lien direct vers Radarr" translate="no">​</a></h4>
<p><a href="https://radarr.video/" target="_blank" rel="noopener noreferrer" class="">Radarr</a> est un gestionnaire de films. Il nous permettra de rechercher des films et de les télécharger automatiquement.</p>
<p>Tout d'abord, nous devons accéder au service via l'interface web. Le port par défaut est <code>7878</code>. Nous pouvons y accéder à l'adresse suivante : <code>http://&lt;adresse-ip-serveur&gt;:7878</code>.</p>
<p>Vous devriez voir quelque chose comme ceci :</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2023-06-21-auto-media-center/radarr-web-interface-init.png" alt="Interface web de Radarr" class="img__Ss2"></p>
<h5 class="anchor anchorTargetStickyNavbar_SAay" id="indexeurs-1">Indexeurs<a href="https://lunik.tiwabbit.fr/blog/fr/auto-media-center#indexeurs-1" class="hash-link" aria-label="Lien direct vers Indexeurs" title="Lien direct vers Indexeurs" translate="no">​</a></h5>
<p>Nous allons voir la configuration des indexeurs dans (<strong>Paramètres</strong> &gt; <strong>Indexeurs</strong>). Cela sera automatiquement configuré par <a href="https://lunik.tiwabbit.fr/blog/fr/auto-media-center#prowlarr" class="">Prowlarr</a> plus tard.</p>
<h5 class="anchor anchorTargetStickyNavbar_SAay" id="client-de-téléchargement-1">Client de téléchargement<a href="https://lunik.tiwabbit.fr/blog/fr/auto-media-center#client-de-t%C3%A9l%C3%A9chargement-1" class="hash-link" aria-label="Lien direct vers Client de téléchargement" title="Lien direct vers Client de téléchargement" translate="no">​</a></h5>
<p>Nous allons configurer le client de téléchargement dans (<strong>Settings</strong> &gt; <strong>Download Client</strong>). Pour cet exemple, je vais utiliser la configuration suivante :</p>
<table><thead><tr><th style="text-align:left">Champ</th><th style="text-align:right">Valeur</th></tr></thead><tbody><tr><td style="text-align:left">Type</td><td style="text-align:right"><code>qBittorrent</code></td></tr><tr><td style="text-align:left">Enable</td><td style="text-align:right"><code>Yes</code></td></tr><tr><td style="text-align:left">Host</td><td style="text-align:right"><code>qbittorrent</code></td></tr><tr><td style="text-align:left">Port</td><td style="text-align:right"><code>8080</code></td></tr><tr><td style="text-align:left">UseSsl</td><td style="text-align:right"><code>No</code></td></tr><tr><td style="text-align:left">Username</td><td style="text-align:right"><code>admin</code></td></tr><tr><td style="text-align:left">Password</td><td style="text-align:right"><code>adminadmin</code></td></tr></tbody></table>
<p>Nous pouvons tester la connexion en cliquant sur <code>Test</code> en bas de la page.</p>
<p><strong>Note :</strong> Vous pouvez définir l'<strong>Initial State</strong> sur <code>Paused</code> si vous ne souhaitez pas que <a href="https://radarr.video/" target="_blank" rel="noopener noreferrer" class="">Radarr</a> télécharge tous les films que vous ajoutez.</p>
<h5 class="anchor anchorTargetStickyNavbar_SAay" id="gestion-des-médias-1">Gestion des médias<a href="https://lunik.tiwabbit.fr/blog/fr/auto-media-center#gestion-des-m%C3%A9dias-1" class="hash-link" aria-label="Lien direct vers Gestion des médias" title="Lien direct vers Gestion des médias" translate="no">​</a></h5>
<p>Nous allons configurer la gestion des médias dans (<strong>Settings</strong> &gt; <strong>Media Management</strong>). Cela permettra à <a href="https://radarr.video/" target="_blank" rel="noopener noreferrer" class="">Radarr</a> de renommer et déplacer les films téléchargés depuis qBittorrent dans le dossier approprié pour que <a href="https://www.plex.tv/" target="_blank" rel="noopener noreferrer" class="">Plex</a> puisse les trouver.</p>
<p>Pour cet exemple, je vais utiliser la configuration suivante :</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2023-06-21-auto-media-center/radarr-media-management-config-01.png" alt="Configuration de la gestion des médias dans Radarr" class="img__Ss2"></p>
<h5 class="anchor anchorTargetStickyNavbar_SAay" id="test-1">Test<a href="https://lunik.tiwabbit.fr/blog/fr/auto-media-center#test-1" class="hash-link" aria-label="Lien direct vers Test" title="Lien direct vers Test" translate="no">​</a></h5>
<p>Maintenant, nous devrions pouvoir ajouter une série TV. Dans (<strong>Series</strong> &gt; <strong>Add Series</strong>), nous pouvons rechercher <code>Avengers</code> et l'ajouter :</p>
<table><thead><tr><th style="text-align:left">Champ</th><th style="text-align:right">Valeur</th></tr></thead><tbody><tr><td style="text-align:left">Root Folder</td><td style="text-align:right"><code>/media/Films/The Avengers (2012)</code></td></tr><tr><td style="text-align:left">Monitor</td><td style="text-align:right"><code>Movie Only</code></td></tr><tr><td style="text-align:left">Quality Profile</td><td style="text-align:right"><code>HD-1080p</code></td></tr></tbody></table>
<p>Ensuite, nous cliquons sur la carte <code>The Avengers</code> et nous devrions voir quelque chose comme ceci :</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2023-06-21-auto-media-center/radarr-movie-example.png" alt="Exemple de film dans Radarr" class="img__Ss2"></p>
<p>Ensuite, nous pouvons cliquer sur l'onglet <code>Search</code> pour rechercher les torrents de films :</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2023-06-21-auto-media-center/radarr-movie-example-search.png" alt="Exemple de recherche de film dans Radarr" class="img__Ss2"></p>
<p>Nous pouvons cliquer sur le bouton <code>Télécharger</code> pour déclencher le téléchargement de la première saison.</p>
<p>Dans la section (<strong>Activity</strong> &gt; <strong>Queue</strong>), nous pouvons voir l'avancement du téléchargement :</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2023-06-21-auto-media-center/radarr-movie-example-download.png" alt="Exemple de téléchargement de film dans Radarr" class="img__Ss2"></p>
<p>Et dans <a href="https://www.qbittorrent.org/" target="_blank" rel="noopener noreferrer" class="">qBittorrent</a>, nous pouvons voir l'avancement du téléchargement :</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2023-06-21-auto-media-center/qbittorrent-movie-example-download.png" alt="Exemple de téléchargement de film dans qBittorrent" class="img__Ss2"></p>
<p>Et enfin, lorsque le téléchargement est terminé, <a href="https://radarr.video/" target="_blank" rel="noopener noreferrer" class="">Radarr</a> renommera et déplacera l'épisode dans le bon dossier. Et <a href="https://www.plex.tv/" target="_blank" rel="noopener noreferrer" class="">Plex</a> détectera le nouvel épisode et l'ajoutera à la bibliothèque.</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2023-06-21-auto-media-center/radarr-movie-example-final.png" alt="Exemple final de film dans Radarr" class="img__Ss2"></p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2023-06-21-auto-media-center/plex-movie-example-final.png" alt="Exemple final de film dans Plex" class="img__Ss2"></p>
<h4 class="anchor anchorTargetStickyNavbar_SAay" id="prowlarr">Prowlarr<a href="https://lunik.tiwabbit.fr/blog/fr/auto-media-center#prowlarr" class="hash-link" aria-label="Lien direct vers Prowlarr" title="Lien direct vers Prowlarr" translate="no">​</a></h4>
<p><a href="https://prowlarr.com/" target="_blank" rel="noopener noreferrer" class="">Prowlarr</a> est un indexeur de torrents. Il nous permettra de rechercher des torrents sur plusieurs trackers en même temps.</p>
<p>Tout d'abord, nous devons accéder au service via l'interface web. Le port par défaut est <code>9696</code>. Nous pouvons donc y accéder à l'adresse suivante : <code>http://&lt;adresse-ip-du-serveur&gt;:9696</code>.</p>
<p>Vous devriez voir quelque chose comme ceci :</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2023-06-21-auto-media-center/prowlarr-web-interface-init.png" alt="Prowlarr web interface init" class="img__Ss2"></p>
<p>Ensuite, nous devons ajouter quelques indexeurs. Pour cet exemple, je vais ajouter les indexeurs suivants :</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2023-06-21-auto-media-center/prowlarr-indexer-config.png" alt="Prowlarr indexer config" class="img__Ss2"></p>
<h5 class="anchor anchorTargetStickyNavbar_SAay" id="applications">Applications<a href="https://lunik.tiwabbit.fr/blog/fr/auto-media-center#applications" class="hash-link" aria-label="Lien direct vers Applications" title="Lien direct vers Applications" translate="no">​</a></h5>
<p>Cette section dans <strong>Paramètres</strong> permettra de lier Prowlarr à <a href="https://lunik.tiwabbit.fr/blog/fr/auto-media-center#radarr" class="">Radarr</a> et <a href="https://lunik.tiwabbit.fr/blog/fr/auto-media-center#sonarr" class="">Sonarr</a>. Ainsi, tous les indexeurs que nous ajoutons dans Prowlarr seront automatiquement ajoutés dans <a href="https://lunik.tiwabbit.fr/blog/fr/auto-media-center#radarr" class="">Radarr</a> et <a href="https://lunik.tiwabbit.fr/blog/fr/auto-media-center#sonarr" class="">Sonarr</a>.</p>
<p>Ajoutez deux applications :</p>
<table><thead><tr><th style="text-align:left">Champ</th><th style="text-align:right">Valeur</th></tr></thead><tbody><tr><td style="text-align:left">Nom</td><td style="text-align:right"><code>Radarr</code></td></tr><tr><td style="text-align:left">Niveau de sync</td><td style="text-align:right"><code>Sync complète</code></td></tr><tr><td style="text-align:left">Serveur Prowlarr</td><td style="text-align:right"><code>http://prowlarr:9696</code></td></tr><tr><td style="text-align:left">Serveur Radarr</td><td style="text-align:right"><code>http://radarr:7878</code></td></tr><tr><td style="text-align:left">Clé API</td><td style="text-align:right">Clé API copiée depuis l'interface web de <a href="https://radarr.video/" target="_blank" rel="noopener noreferrer" class="">Radarr</a> (<strong>Paramètres</strong> &gt; <strong>Général</strong>).</td></tr></tbody></table>
<table><thead><tr><th style="text-align:left">Champ</th><th style="text-align:right">Valeur</th></tr></thead><tbody><tr><td style="text-align:left">Nom</td><td style="text-align:right"><code>Sonarr</code></td></tr><tr><td style="text-align:left">Niveau de sync</td><td style="text-align:right"><code>Sync complète</code></td></tr><tr><td style="text-align:left">Serveur Prowlarr</td><td style="text-align:right"><code>http://prowlarr:9696</code></td></tr><tr><td style="text-align:left">Serveur Sonarr</td><td style="text-align:right"><code>http://sonarr:8989</code></td></tr><tr><td style="text-align:left">Clé API</td><td style="text-align:right">Clé API copiée depuis l'interface web de <a href="https://sonarr.tv/" target="_blank" rel="noopener noreferrer" class="">Sonarr</a> (<strong>Paramètres</strong> &gt; <strong>Général</strong>).</td></tr></tbody></table>
<p>En allant véfier dans <a href="https://lunik.tiwabbit.fr/blog/fr/auto-media-center#radarr" class="">Radarr</a> et <a href="https://lunik.tiwabbit.fr/blog/fr/auto-media-center#sonarr" class="">Sonarr</a>, on peut voir que les indexers ont bien été ajoutés dans la section <strong>Indexers</strong>.</p>
<h4 class="anchor anchorTargetStickyNavbar_SAay" id="overseerr">Overseerr<a href="https://lunik.tiwabbit.fr/blog/fr/auto-media-center#overseerr" class="hash-link" aria-label="Lien direct vers Overseerr" title="Lien direct vers Overseerr" translate="no">​</a></h4>
<p>Comme vous pouvez le constater, <a href="https://radarr.video/" target="_blank" rel="noopener noreferrer" class="">Radarr</a> et <a href="https://sonarr.tv/" target="_blank" rel="noopener noreferrer" class="">Sonarr</a> sont de superbes outils. Cependant, ils ne sont pas très conviviaux. <a href="https://overseerr.dev/" target="_blank" rel="noopener noreferrer" class="">Overseerr</a> nous permettra de demander des séries télévisées et des films via une interface web agréable.</p>
<p>Tout d'abord, nous devons accéder au service via l'interface web. Le port par défaut est <code>5055</code>. Nous pouvons donc y accéder à l'adresse <code>http://&lt;adresse-serveur&gt;:5055</code>.</p>
<p>Lors de la première configuration, nous devons remplir les champs suivants :</p>
<p><strong>Paramètres Plex</strong></p>
<p>Cela permettra à <a href="https://overseerr.dev/" target="_blank" rel="noopener noreferrer" class="">Overseerr</a> de se connecter à <a href="https://www.plex.tv/" target="_blank" rel="noopener noreferrer" class="">Plex</a> et de vérifier si les médias sont déjà disponibles dans la bibliothèque.</p>
<table><thead><tr><th style="text-align:left">Champ</th><th style="text-align:right">Valeur</th></tr></thead><tbody><tr><td style="text-align:left">Server</td><td style="text-align:right"><code>Votre serveur Plex</code></td></tr><tr><td style="text-align:left">Hostname or IP Address</td><td style="text-align:right"><code>http://plex</code></td></tr><tr><td style="text-align:left">Port</td><td style="text-align:right"><code>32400</code></td></tr><tr><td style="text-align:left">Use SSL</td><td style="text-align:right"><code>No</code></td></tr><tr><td style="text-align:left"><a href="https://www.plex.tv/" target="_blank" rel="noopener noreferrer" class="">Plex</a> Libraries</td><td style="text-align:right"><code>Films,Series</code></td></tr></tbody></table>
<p><strong>Paramètres Radarr</strong></p>
<p>Cela permettra à <a href="https://overseerr.dev/" target="_blank" rel="noopener noreferrer" class="">Overseerr</a> de se connecter à <a href="https://radarr.video/" target="_blank" rel="noopener noreferrer" class="">Radarr</a> et de déclencher le téléchargement des films demandés.</p>
<table><thead><tr><th style="text-align:left">Champ</th><th style="text-align:right">Valeur</th></tr></thead><tbody><tr><td style="text-align:left">Default Server</td><td style="text-align:right"><code>Yes</code></td></tr><tr><td style="text-align:left">Server Name</td><td style="text-align:right"><code>Radarr</code></td></tr><tr><td style="text-align:left">Hostname or IP Address</td><td style="text-align:right"><code>http://radarr</code></td></tr><tr><td style="text-align:left">Port</td><td style="text-align:right"><code>7878</code></td></tr><tr><td style="text-align:left">API Key</td><td style="text-align:right">Clé API copiée depuis l'interface web de <a href="https://radarr.video/" target="_blank" rel="noopener noreferrer" class="">Radarr</a> (<strong>Settings</strong> &gt; <strong>Général</strong>).</td></tr><tr><td style="text-align:left">Quality Profile</td><td style="text-align:right"><code>HD-1080p</code></td></tr><tr><td style="text-align:left">Root Folder</td><td style="text-align:right"><code>/media/Films</code></td></tr></tbody></table>
<p><strong>Paramètres Sonarr</strong></p>
<p>Cela permettra à <a href="https://overseerr.dev/" target="_blank" rel="noopener noreferrer" class="">Overseerr</a> de se connecter à <a href="https://sonarr.tv/" target="_blank" rel="noopener noreferrer" class="">Sonarr</a> et de déclencher le téléchargement des séries télévisées demandées.</p>
<table><thead><tr><th style="text-align:left">Champ</th><th style="text-align:right">Valeur</th></tr></thead><tbody><tr><td style="text-align:left">Default Server</td><td style="text-align:right"><code>Yes</code></td></tr><tr><td style="text-align:left">Server Name</td><td style="text-align:right"><code>Sonarr</code></td></tr><tr><td style="text-align:left">Hostname or IP Address</td><td style="text-align:right"><code>http://sonarr</code></td></tr><tr><td style="text-align:left">Port</td><td style="text-align:right"><code>8989</code></td></tr><tr><td style="text-align:left">API Key</td><td style="text-align:right">Clé API copiée depuis l'interface web de <a href="https://sonarr.tv/" target="_blank" rel="noopener noreferrer" class="">Sonarr</a> (<strong>Settings</strong> &gt; <strong>Général</strong>).</td></tr><tr><td style="text-align:left">Quality Profile</td><td style="text-align:right"><code>HD-1080p</code></td></tr><tr><td style="text-align:left">Root Folder</td><td style="text-align:right"><code>/media/Series</code></td></tr></tbody></table>
<p>Si tout est configuré correctement, vous devriez voir quelque chose comme ceci dans l'onglet Découverte :</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2023-06-21-auto-media-center/overseerr-discovery.png" alt="Overseerr découverte" class="img__Ss2"></p>
<p>Nous pouvons voir que le film <code>Avengers</code> et la série télévisée <code>Game of Thrones</code> sont déjà disponibles dans <a href="https://www.plex.tv/" target="_blank" rel="noopener noreferrer" class="">Plex</a>.</p>
<p><strong>Remarques :</strong>
Les utilisateurs qui ont accès à votre serveur <a href="https://www.plex.tv/" target="_blank" rel="noopener noreferrer" class="">Plex</a> pourront demander des films et des séries télévisées. Ils peuvent se connecter avec leur compte <a href="https://www.plex.tv/" target="_blank" rel="noopener noreferrer" class="">Plex</a>.</p>
<p>Vous pouvez configurer les utilisateurs dans l'onglet <strong>Utilisateurs</strong>. Par exemple, vous pouvez créer des utilisateurs locaux qui pourront accéder à <a href="https://overseerr.dev/" target="_blank" rel="noopener noreferrer" class="">Overseerr</a> sans compte <a href="https://www.plex.tv/" target="_blank" rel="noopener noreferrer" class="">Plex</a>.</p>
<h5 class="anchor anchorTargetStickyNavbar_SAay" id="demande-de-média">Demande de média<a href="https://lunik.tiwabbit.fr/blog/fr/auto-media-center#demande-de-m%C3%A9dia" class="hash-link" aria-label="Lien direct vers Demande de média" title="Lien direct vers Demande de média" translate="no">​</a></h5>
<p>Nous allons maintenant essayer de demander un film à <a href="https://overseerr.dev/" target="_blank" rel="noopener noreferrer" class="">Overseerr</a>. Nous utiliserons un utilisateur local pour cet exemple.</p>
<p>Essayons de demander le film <code>Le Daim</code>. Depuis l'onglet <strong>Discover</strong>, nous pouvons rechercher <code>Le Daim</code> et nous devrions voir quelque chose comme ceci :</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2023-06-21-auto-media-center/overseerr-movie-search.png" alt="Overseerr recherche de film" class="img__Ss2"></p>
<p>Ensuite, nous pouvons cliquer sur le bouton <code>Request</code> pour demander le film.</p>
<p>En revenant à l'onglet <strong>Requests</strong> avec notre compte administrateur, nous pouvons voir la demande :</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2023-06-21-auto-media-center/overseerr-movie-request.png" alt="Overseerr demande de film" class="img__Ss2"></p>
<p>Nous pouvons cliquer sur le bouton <code>Approve</code> pour approuver la demande. Cela déclenchera le téléchargement du film dans <a href="https://radarr.video/" target="_blank" rel="noopener noreferrer" class="">Radarr</a> et le téléchargera comme nous l'avons vu précédemment dans la section <a href="https://radarr.video/" target="_blank" rel="noopener noreferrer" class="">Radarr</a>.</p>
<p>Et enfin, lorsque tout le processus est terminé, nous pouvons voir que le film est disponible dans <a href="https://overseerr.dev/" target="_blank" rel="noopener noreferrer" class="">Overseerr</a> et <a href="https://www.plex.tv/" target="_blank" rel="noopener noreferrer" class="">Plex</a>.</p>]]></content>
        <author>
            <name>Guillaume MARTINEZ</name>
            <uri>https://github.com/Lunik</uri>
        </author>
        <category label="media" term="media"/>
        <category label="media-center" term="media-center"/>
        <category label="plex" term="plex"/>
        <category label="svod" term="svod"/>
        <category label="streaming" term="streaming"/>
        <category label="radarr" term="radarr"/>
        <category label="sonarr" term="sonarr"/>
        <category label="prowlarr" term="prowlarr"/>
        <category label="overseerr" term="overseerr"/>
        <category label="qbitorrent" term="qbitorrent"/>
        <category label="torrent" term="torrent"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Installation d'un CA custom sur IOS]]></title>
        <id>https://lunik.tiwabbit.fr/blog/fr/install-custom-ca-on-ios</id>
        <link href="https://lunik.tiwabbit.fr/blog/fr/install-custom-ca-on-ios"/>
        <updated>2023-01-28T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Installation pas à pas d'un certificat root CA sur IOS]]></summary>
        <content type="html"><![CDATA[<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2023-01-28-install-custom-ca-on-ios/cover.jpg" alt="cover" class="img__Ss2"></p>
<p>Maintenant que j'ai généré ma propre chaîne de certification personnalisé dans l'article précédent "gestion de certificats x509", je dois installer l'autorité de certification (CA) sur mon iPhone.</p>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="installer-le-certificat">Installer le certificat<a href="https://lunik.tiwabbit.fr/blog/fr/install-custom-ca-on-ios#installer-le-certificat" class="hash-link" aria-label="Lien direct vers Installer le certificat" title="Lien direct vers Installer le certificat" translate="no">​</a></h3>
<p>Je dois d'abord installer le certificat CA sur l'appareil.</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2023-01-28-install-custom-ca-on-ios/1_download_folder.jpg" alt="1_download_folder" class="img__Ss2"></p>
<p>Le fichier était sur l'appareil et je l'ai ouvert à partir de l'explorateur de fichiers.</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2023-01-28-install-custom-ca-on-ios/2_open_file.jpg" alt="2_open_file" class="img__Ss2"></p>
<p>Ensuite, je dois aller dans les paramètres IOS. Dans la rubrique "Général".</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2023-01-28-install-custom-ca-on-ios/3_general_settings.jpg" alt="3_general_settings" class="img__Ss2"></p>
<p>Puis dans la rubrique "VPN et gestion de l'appareil".</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2023-01-28-install-custom-ca-on-ios/4_device_managment.jpg" alt="4_device_managment" class="img__Ss2"></p>
<p>Je clique sur l'autorité de certification dans la section "Profil téléchargé".</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2023-01-28-install-custom-ca-on-ios/5_downloaded_profile.jpg" alt="5_downloaded_profile" class="img__Ss2"></p>
<p>J'ai ensuite suivi le processus d'installation.</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2023-01-28-install-custom-ca-on-ios/6_install_profile_01.jpg" alt="6_install_profile_01" class="img__Ss2">
<img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2023-01-28-install-custom-ca-on-ios/7_install_profile_02.jpg" alt="7_install_profile_02" class="img__Ss2"></p>
<p>Vérifié ensuite l'installation.</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2023-01-28-install-custom-ca-on-ios/8_verify_install.jpg" alt="8_verify_install" class="img__Ss2"></p>
<p>Enfin, je dois approuver l'autorité de certification en tant qu'autorité racine sur l'appareil.
En revenant à la rubrique "Général". Maintenant dans la section "Informations".</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2023-01-28-install-custom-ca-on-ios/9_informations.jpg" alt="9_informations" class="img__Ss2"></p>
<p>Puis dans la rubrique "Réglages des certificats".</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2023-01-28-install-custom-ca-on-ios/10_certificats_settings.jpg" alt="10_certificats_settings" class="img__Ss2"></p>
<p>Enfin, j'ai activé le certificat et terminé l'installation.</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2023-01-28-install-custom-ca-on-ios/11_toggle_certificate.jpg" alt="11_toggle_certificate" class="img__Ss2">
<img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2023-01-28-install-custom-ca-on-ios/12_validate_toggle_certificate.jpg" alt="12_validate_toggle_certificate" class="img__Ss2"></p>]]></content>
        <author>
            <name>Guillaume MARTINEZ</name>
            <uri>https://github.com/Lunik</uri>
        </author>
        <category label="tls" term="tls"/>
        <category label="certificate" term="certificate"/>
        <category label="ios" term="ios"/>
        <category label="iphone" term="iphone"/>
        <category label="ca" term="ca"/>
        <category label="root" term="root"/>
        <category label="install" term="install"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Déchiffrer les states Terraform GitLab]]></title>
        <id>https://lunik.tiwabbit.fr/blog/fr/decrypt-terraform-state-gitlab-backend</id>
        <link href="https://lunik.tiwabbit.fr/blog/fr/decrypt-terraform-state-gitlab-backend"/>
        <updated>2022-10-05T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Cet article explique comment récupérer et déchiffrer les states Terraform stockés dans le backend GitLab à partir d'une sauvegarde GitLab]]></summary>
        <content type="html"><![CDATA[<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2022-10-05-decrypt-terraform-state-gitlab-backend/cover.jpeg" alt="cover" class="img__Ss2"></p>
<p>En supposant que vous utilisez la <a href="https://docs.gitlab.com/ee/user/infrastructure/iac/terraform_state.html" target="_blank" rel="noopener noreferrer" class="">fonctionnalité de stockage des states Terraform dans GitLab</a> dans votre instance managée et que vous utilisez l'<a href="https://docs.gitlab.com/charts/backup-restore/" target="_blank" rel="noopener noreferrer" class="">utilitaire intégré de sauvegarde fourni par GitLab</a>.</p>
<p>Les fichiers de state Terraform sont chiffrés avant d'être stockés. Cela signifie que vous ne pouvez pas récupérer leur contenu à froid.
À cette fin, GitLab utilise <a href="https://docs.gitlab.com/ee/development/application_secrets.html" target="_blank" rel="noopener noreferrer" class="">applications secrets</a> (et dérive de nouveaux secrets à partir de ces clés si nécessaire) pour chiffrer le contenu sensible.</p>
<p>Vous souhaitez récupérer le contenu d'un fichier de state à partir d'une sauvegarde GitLab. Comme expliqué dans <a href="https://gitlab.com/gitlab-org/gitlab/-/issues/335739" target="_blank" rel="noopener noreferrer" class="">cette issue</a>, il n'est pas possible de récupérer facilement un contenu déchiffré si l'instance est hors ligne.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="procédure-de-récupération">Procédure de récupération<a href="https://lunik.tiwabbit.fr/blog/fr/decrypt-terraform-state-gitlab-backend#proc%C3%A9dure-de-r%C3%A9cup%C3%A9ration" class="hash-link" aria-label="Lien direct vers Procédure de récupération" title="Lien direct vers Procédure de récupération" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="récupération-des-secrets-dinstance-gitlab">Récupération des secrets d'instance GitLab<a href="https://lunik.tiwabbit.fr/blog/fr/decrypt-terraform-state-gitlab-backend#r%C3%A9cup%C3%A9ration-des-secrets-dinstance-gitlab" class="hash-link" aria-label="Lien direct vers Récupération des secrets d'instance GitLab" title="Lien direct vers Récupération des secrets d'instance GitLab" translate="no">​</a></h3>
<p>En utilisant la <a href="https://docs.gitlab.com/ee/development/application_secrets.html" target="_blank" rel="noopener noreferrer" class="">documentation GitLab sur les secrets d'application</a>, vous devez récupérer la valeur de <code>db_key_base</code>.</p>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="récupération-des-informations-du-projet">Récupération des informations du projet<a href="https://lunik.tiwabbit.fr/blog/fr/decrypt-terraform-state-gitlab-backend#r%C3%A9cup%C3%A9ration-des-informations-du-projet" class="hash-link" aria-label="Lien direct vers Récupération des informations du projet" title="Lien direct vers Récupération des informations du projet" translate="no">​</a></h3>
<p>Le stockage des states Terraform est lié à un projet GitLab. Si le projet existe toujours dans votre instance, enregistrez le <code>project_id</code> pour plus tard.</p>
<p>Si vous avez supprimé le projet, nous aurons besoin de la sauvegarde de la base de données (également stockée dans la sauvegarde GitLab).</p>
<p>Commencez par rechercher dans la table <code>public.routes</code> votre projet. Vous pouvez filtrer par <code>source_type=Project</code> et <code>path=path/of/your/project</code>. Notez la valeur dans la colonne <code>namespace_id</code>.</p>
<p>Regardez ensuite la table <code>public.projects</code> filtrant le <code>namespace_id</code> récupéré juste avant. Notez l'<code>id</code> du projet.</p>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="calcul-du-chemin-de-stockage-du-state">Calcul du chemin de stockage du state<a href="https://lunik.tiwabbit.fr/blog/fr/decrypt-terraform-state-gitlab-backend#calcul-du-chemin-de-stockage-du-state" class="hash-link" aria-label="Lien direct vers Calcul du chemin de stockage du state" title="Lien direct vers Calcul du chemin de stockage du state" translate="no">​</a></h3>
<p>Les states sont stockés avec un chemin haché.</p>
<p>La première partie est la somme hash256 du projet <code>id</code>. Vous pouvez utiliser la commande suivante pour le calculer :</p>
<div class="language-bash codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-bash codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token builtin class-name" style="color:rgb(189, 147, 249)">echo</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-n</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"&lt;id_projet&gt;"</span><span class="token plain"> </span><span class="token operator">|</span><span class="token plain"> openssl dgst-sha256</span><br></div></code></pre></div></div>
<p>La deuxième partie peut être récupérée de la base de données dans la table <code>public.terraform_states</code>. Filtrez par <code>project_id</code> et le <code>name</code> du state enregistrez le <code>uuid</code>.</p>
<p>Le chemin complet du dossier contenant le fichier de state est maintenant :</p>
<div class="language-text codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-text codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">&lt;part_1[0:1]&gt;/&lt;part_1[2:3]&gt;/&lt;part_1&gt;/&lt;part_2&gt;</span><br></div></code></pre></div></div>
<p>Si vous avez activé le versionning, le state est stocké avec le nom de fichier <code>&lt;serial_number&gt;.tfstate</code></p>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="récupération-du-contenu">Récupération du contenu<a href="https://lunik.tiwabbit.fr/blog/fr/decrypt-terraform-state-gitlab-backend#r%C3%A9cup%C3%A9ration-du-contenu" class="hash-link" aria-label="Lien direct vers Récupération du contenu" title="Lien direct vers Récupération du contenu" translate="no">​</a></h3>
<p>C'est la partie la plus difficile et vous devez être un peu familier avec <a href="https://www.ruby-lang.org/" target="_blank" rel="noopener noreferrer" class="">Ruby</a>.</p>
<p>GitLab utilise un outil nommé <a href="https://github.com/ankane/lockbox" target="_blank" rel="noopener noreferrer" class="">Lockbox</a> pour chiffrer le contenu du state de Terraform avant de le stocker. Nous allons utiliser le même outil pour déchiffrer nos fichiers.</p>
<p>Compléter et utilisez le script suivant :</p>
<div class="language-ruby codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-ruby codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">#################</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"># Configuration #</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">#################</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"># Retreived from GitLab rails secrets</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"># https://docs.gitlab.com/ee/development/application_secrets.html</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"># This is a dummy key base. Don't bother using it</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">db_key_base = "&lt;FILL_DB_KEY_BASE&gt;"</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"># The project ID in GitLab</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">project_id = "&lt;FILL_PROJECT_ID&gt;"</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"># The file to decrypt</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">input_file = "&lt;FILL_ENCRYPTED_STATE_FILE_PATH&gt;"</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"># The file where to write the terraform state content</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">output_file = "&lt;FILL_DECRYPTED_STATE_FILE_PATH&gt;"</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">#############</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"># ALGORITHM #</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">#############</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"># Compute encryption key</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">key = OpenSSL::HMAC.digest('SHA256', db_key_base, project_id)</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"># Generate LockBox tool</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"># https://github.com/ankane/lockbox</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">lockbox = Lockbox.new(key: key)</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">encrypted_state_content = File.binread(input_file)</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">state_content = lockbox.decrypt_str(encrypted_state_content)</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">File.write(output_file, state_content)</span><br></div></code></pre></div></div>
<p>Je ne suis pas un expert en <a href="https://www.ruby-lang.org/" target="_blank" rel="noopener noreferrer" class="">Ruby</a> mais voici un simple script bash pour configurer le bon environnement :</p>
<div class="language-bash codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-bash codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token shebang important">#!/bin/bash</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">rails new myapp</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">cd</span><span class="token plain"> myapp/</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">echo</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">'gem "lockbox"'</span><span class="token plain"> </span><span class="token operator">&gt;&gt;</span><span class="token plain"> Gemfile</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">bundle </span><span class="token function" style="color:rgb(80, 250, 123)">install</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">bundle </span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">exec</span><span class="token plain"> rails runner decode.rb</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="resources">Resources<a href="https://lunik.tiwabbit.fr/blog/fr/decrypt-terraform-state-gitlab-backend#resources" class="hash-link" aria-label="Lien direct vers Resources" title="Lien direct vers Resources" translate="no">​</a></h2>
<ul>
<li class=""><a href="https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/uploaders/terraform/state_uploader.rb" target="_blank" rel="noopener noreferrer" class="">Code source GitLab utilisé pour chiffrer les fichiers d'état</a></li>
<li class=""><a href="https://gitlab.com/gitlab-org/gitlab/-/issues/342225" target="_blank" rel="noopener noreferrer" class="">Problème GitLab pour documenter la procédure de récupération</a></li>
</ul>]]></content>
        <author>
            <name>Guillaume MARTINEZ</name>
            <uri>https://github.com/Lunik</uri>
        </author>
        <category label="terraform" term="terraform"/>
        <category label="gitlab" term="gitlab"/>
        <category label="terraform-state" term="terraform-state"/>
        <category label="state" term="state"/>
        <category label="backend" term="backend"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Maitriser le Git flow]]></title>
        <id>https://lunik.tiwabbit.fr/blog/fr/properly-handle-git-flow</id>
        <link href="https://lunik.tiwabbit.fr/blog/fr/properly-handle-git-flow"/>
        <updated>2022-09-11T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Exemple complet du cycle de vie d'un dépôt Git]]></summary>
        <content type="html"><![CDATA[<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2022-09-11-properly-handle-git-flow/cover.png" alt="cover" class="img__Ss2"></p>
<p>Tout développeur utilise ou utilisera <a href="https://git-scm.com/" target="_blank" rel="noopener noreferrer" class="">Git</a> à un moment donné de sa carrière. La plupart du temps, ils devront travailler avec d'autres personnes sur le même dépôt <a href="https://git-scm.com/" target="_blank" rel="noopener noreferrer" class="">Git</a>. Pour éviter que ce soit un champ de bataille de branche et commit, voici un guide simple sur la façon de contribuer correctement sur un dépôt <a href="https://git-scm.com/" target="_blank" rel="noopener noreferrer" class="">Git</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="bases">Bases<a href="https://lunik.tiwabbit.fr/blog/fr/properly-handle-git-flow#bases" class="hash-link" aria-label="Lien direct vers Bases" title="Lien direct vers Bases" translate="no">​</a></h2>
<p>Tout d'abord, le dépôt <a href="https://git-scm.com/" target="_blank" rel="noopener noreferrer" class="">Git</a> devrait avoir une branche par défaut souvent appelée <code>master</code> ou <code>main</code> (cela peut être n'importe quoi d'autre tant que tout le monde s'accorde sur le nom).</p>
<p>Ensuite, une deuxième branche utilisée à des fins de développement. Celle-ci suivra de très près la branche par défaut. Elle sera un réceptacle pour tout nouveau développement. Cette branche est la seule autorisée à être fusionnée sur la branche par défaut.</p>
<p>Enfin, toutes les autres branches entrent dans la dernière catégorie. Ce sont des fonctionnalités, des corrections de bogues et autres.</p>
<p><strong>Remarque :</strong> Seules les branches HotFix sont autorisées à contourner la branche de développement.</p>
<p>Voici un exemple de dépôt <a href="https://git-scm.com/" target="_blank" rel="noopener noreferrer" class="">Git</a> simple</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2022-09-11-properly-handle-git-flow/01_example-git-repository-graph.png" alt="example-git-repository-graph" class="img__Ss2"></p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="exemple-complet-dun-cycle-de-vie-de-dun-dépôt">Exemple complet d'un cycle de vie de d'un dépôt<a href="https://lunik.tiwabbit.fr/blog/fr/properly-handle-git-flow#exemple-complet-dun-cycle-de-vie-de-dun-d%C3%A9p%C3%B4t" class="hash-link" aria-label="Lien direct vers Exemple complet d'un cycle de vie de d'un dépôt" title="Lien direct vers Exemple complet d'un cycle de vie de d'un dépôt" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="initialisation-dun-dépôt">Initialisation d'un dépôt<a href="https://lunik.tiwabbit.fr/blog/fr/properly-handle-git-flow#initialisation-dun-d%C3%A9p%C3%B4t" class="hash-link" aria-label="Lien direct vers Initialisation d'un dépôt" title="Lien direct vers Initialisation d'un dépôt" translate="no">​</a></h3>
<p>La première chose à faire lors de la création d'un nouveau référentiel est d'initialiser la structure de base.</p>
<p>Créez le dépôt <a href="https://git-scm.com/" target="_blank" rel="noopener noreferrer" class="">Git</a> :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">mkdir</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-p</span><span class="token plain"> myrepository</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">cd</span><span class="token plain"> myrepository</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">git</span><span class="token plain"> init</span><br></div></code></pre></div></div>
<p>Vous voudrez peut-être créer vos premiers fichiers. Comme le <code>README.md</code>/<code>.gitignore</code> et certains fichiers de package comme <code>package.json</code> ou <code>pom.xml</code>.</p>
<p>Créez ensuite le commit initial du dépôt avec ces fichiers :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">git</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">add</span><span class="token plain"> </span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">git</span><span class="token plain"> commit </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-m</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Initial commit"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">git</span><span class="token plain"> tag v0.0.0</span><br></div></code></pre></div></div>
<p>Créez enfin la branche de développement :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">git</span><span class="token plain"> branch develop</span><br></div></code></pre></div></div>
<p>Le référentiel devrait ressembler à :</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2022-09-11-properly-handle-git-flow/02_init-git-repository-graph.png" alt="init-git-repository-graph" class="img__Ss2"></p>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="initialisation-de-la-branche-de-développement">Initialisation de la branche de développement<a href="https://lunik.tiwabbit.fr/blog/fr/properly-handle-git-flow#initialisation-de-la-branche-de-d%C3%A9veloppement" class="hash-link" aria-label="Lien direct vers Initialisation de la branche de développement" title="Lien direct vers Initialisation de la branche de développement" translate="no">​</a></h3>
<p>Maintenant que vous avez notre structure de base sur le dépôt <a href="https://git-scm.com/" target="_blank" rel="noopener noreferrer" class="">Git</a>, il est temps d'initialiser la branche de développement.</p>
<p>Créer en premier la branche développement :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">git</span><span class="token plain"> checkout develop</span><br></div></code></pre></div></div>
<p>Parfois, vous voudrez peut-être ajouter un commit initial sur la branche de développement avec la modification de la version actuelle dans votre fichier de package <code>package.json</code>, <code>pom.xml</code> ou autre.</p>
<p>Editez ces fichiers puis créez un commit :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">git</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">add</span><span class="token plain"> </span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">git</span><span class="token plain"> commit </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-m</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Prepare development version"</span><br></div></code></pre></div></div>
<p>Le dépôt devrait ressembler à :</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2022-09-11-properly-handle-git-flow/03_init-develop-git-repository-graph.png" alt="init-develop-git-repository-graph" class="img__Ss2"></p>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="ajouter-la-première-fonctionnalité">Ajouter la première fonctionnalité<a href="https://lunik.tiwabbit.fr/blog/fr/properly-handle-git-flow#ajouter-la-premi%C3%A8re-fonctionnalit%C3%A9" class="hash-link" aria-label="Lien direct vers Ajouter la première fonctionnalité" title="Lien direct vers Ajouter la première fonctionnalité" translate="no">​</a></h3>
<p>Créons maintenant la première fonctionnalité de notre application.</p>
<p>Vérifiez que vous êtes bien sur la branche développement :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">git</span><span class="token plain"> branch</span><br></div></code></pre></div></div>
<p>Résultat :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">* develop</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  master</span><br></div></code></pre></div></div>
<p>Si ce n'est pas le cas, changer pour la branche de développement.</p>
<p>Ensuite, créer une branche de fonctionnalité :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">git</span><span class="token plain"> checkout </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-b</span><span class="token plain"> feature/my-first-feature</span><br></div></code></pre></div></div>
<p>Maintenant, écrivez la fonctionnalité et commitez de temps en temps avec :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">git</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">add</span><span class="token plain"> </span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">git</span><span class="token plain"> commit </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-m</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"save dev"</span><br></div></code></pre></div></div>
<p>Le dépôt devrait ressembler à :</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2022-09-11-properly-handle-git-flow/04_feature-branch-git-repository-graph.png" alt="feature-branch-git-repository-graph" class="img__Ss2"></p>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="travailler-sur-une-fonctionnalité-requise">Travailler sur une fonctionnalité requise<a href="https://lunik.tiwabbit.fr/blog/fr/properly-handle-git-flow#travailler-sur-une-fonctionnalit%C3%A9-requise" class="hash-link" aria-label="Lien direct vers Travailler sur une fonctionnalité requise" title="Lien direct vers Travailler sur une fonctionnalité requise" translate="no">​</a></h3>
<p>Vous travailliez sur la première fonctionnalité mais vous réalisez que vous en aviez besoin d'une autre pour continuer.</p>
<p><strong>/!\ Assurez-vous que vous n'avez pas de modifications non commités avant de changer de branche</strong></p>
<p>Reproduisez les mêmes commandes que pour la première fonctionnalité :</p>
<ul>
<li class="">Checkout sur la branche développement</li>
<li class="">Ensuite, création d'une branche de fonctionnalité</li>
<li class="">Écrivez votre code et créez des commits</li>
</ul>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">git</span><span class="token plain"> checkout develop</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">git</span><span class="token plain"> checkout </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-b</span><span class="token plain"> feature/my-required-feature</span><br></div></code></pre></div></div>
<p>Le dépôt devrait ressembler à :</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2022-09-11-properly-handle-git-flow/05_feature2-branch-git-repository-graph.png" alt="feature2-branch-git-repository-graph" class="img__Ss2"></p>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="fusionner-la-fonctionnalité-requise">Fusionner la fonctionnalité requise<a href="https://lunik.tiwabbit.fr/blog/fr/properly-handle-git-flow#fusionner-la-fonctionnalit%C3%A9-requise" class="hash-link" aria-label="Lien direct vers Fusionner la fonctionnalité requise" title="Lien direct vers Fusionner la fonctionnalité requise" translate="no">​</a></h3>
<p>Maintenant que vous avez terminé votre travail sur la fonctionnalité requise, il est temps de fusionner le code avec la branche de développement.</p>
<p>Vous devez d'abord rebaser la branche pour supprimer tous les commits inutiles :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">git</span><span class="token plain"> rebase </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-i</span><span class="token plain"> develop</span><br></div></code></pre></div></div>
<p>Le premier commit doit toujours être sélectionné. Tous les autres commits peuvent être écrasés.</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">pick fa71872 save dev</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">squash 5d9a97a save dev</span><br></div></code></pre></div></div>
<p>Le dépôt devrait ressembler à :</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2022-09-11-properly-handle-git-flow/06_feature2-rebase-git-repository-graph.png" alt="feature2-rebase-git-repository-graph" class="img__Ss2"></p>
<p>Passez à la branche de développement et fusionnez la branche de fonctionnalité requise :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">git</span><span class="token plain"> checkout develop</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">git</span><span class="token plain"> merge --no-ff feature/my-required-feature</span><br></div></code></pre></div></div>
<p>Le dépôt devrait ressembler à :</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2022-09-11-properly-handle-git-flow/07_feature2-merge-git-repository-graph.png" alt="feature2-merge-git-repository-graph" class="img__Ss2"></p>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="poursuivre-le-travail-sur-la-première-fonctionnalité">Poursuivre le travail sur la première fonctionnalité<a href="https://lunik.tiwabbit.fr/blog/fr/properly-handle-git-flow#poursuivre-le-travail-sur-la-premi%C3%A8re-fonctionnalit%C3%A9" class="hash-link" aria-label="Lien direct vers Poursuivre le travail sur la première fonctionnalité" title="Lien direct vers Poursuivre le travail sur la première fonctionnalité" translate="no">​</a></h3>
<p>Maintenant que vous avez terminé la fonctionnalité requise, vous souhaitez rebaser votre travail actuel sur la première fonctionnalité pour récupérer le contenu de la fonctionnalité requise.</p>
<ul>
<li class="">Changement pour la branche de fonctionnalités</li>
<li class="">La rebaser sur la branche de développement</li>
</ul>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">git</span><span class="token plain"> checkout feature/my-first-feature</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">git</span><span class="token plain"> rebase develop</span><br></div></code></pre></div></div>
<p>Ce que fait cette commande, c'est prendre tous les commits de la branche de fonctionnalité et les appliquer à la fin de la branche de développement.</p>
<p>Le dépôt devrait ressembler à :</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2022-09-11-properly-handle-git-flow/08_feature-rebase-git-repository-graph.png" alt="feature-rebase-git-repository-graph" class="img__Ss2"></p>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="fusion-de-la-première-fonctionnalité">Fusion de la première fonctionnalité<a href="https://lunik.tiwabbit.fr/blog/fr/properly-handle-git-flow#fusion-de-la-premi%C3%A8re-fonctionnalit%C3%A9" class="hash-link" aria-label="Lien direct vers Fusion de la première fonctionnalité" title="Lien direct vers Fusion de la première fonctionnalité" translate="no">​</a></h3>
<p>Maintenant que vous avez terminé votre travail sur la première fonctionnalité, il est temps de fusionner le code avec la branche de développement.</p>
<p>Vous devez d'abord rebaser la branche pour supprimer tous les commits inutiles :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">git</span><span class="token plain"> rebase </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-i</span><span class="token plain"> develop</span><br></div></code></pre></div></div>
<p>Le premier commit doit toujours être sélectionné. Tous les autres commits peuvent être écrasés.</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">pick 717051b save dev</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">squash 7d39273 save dev</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">squash 7b700f1 save dev</span><br></div></code></pre></div></div>
<p>Le dépôt devrait ressembler à :</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2022-09-11-properly-handle-git-flow/09_feature-rebase2-git-repository-graph.png" alt="feature-rebase2-git-repository-graph" class="img__Ss2"></p>
<p>Passez à la branche de développement et fusionnez la branche de fonctionnalité requise :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">git</span><span class="token plain"> checkout develop</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">git</span><span class="token plain"> merge --no-ff feature/my-first-feature</span><br></div></code></pre></div></div>
<p>Le dépôt devrait ressembler à :</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2022-09-11-properly-handle-git-flow/10_feature-merge-git-repository-graph.png" alt="feature-merge-git-repository-graph" class="img__Ss2"></p>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="correction-dun-problème-critique">Correction d'un problème critique<a href="https://lunik.tiwabbit.fr/blog/fr/properly-handle-git-flow#correction-dun-probl%C3%A8me-critique" class="hash-link" aria-label="Lien direct vers Correction d'un problème critique" title="Lien direct vers Correction d'un problème critique" translate="no">​</a></h3>
<p>Un problème critique a été découvert sur l'application de production et vous devez produire rapidement un correctif. Vous n'avez pas le temps de parcourir tout le processus de publication.</p>
<ul>
<li class="">Changement pour la branche par défaut</li>
<li class="">Créez une nouvelle branche de correctifs et changer pour la branche</li>
<li class="">Faire la correction</li>
<li class="">Fusionner dans la branche par défaut</li>
<li class="">Taguez votre nouvelle version</li>
</ul>
<p>Le dépôt devrait ressembler à :</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2022-09-11-properly-handle-git-flow/11_hotfix-git-repository-graph.png" alt="hotfix-git-repository-graph" class="img__Ss2"></p>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="publier-votre-travail">Publier votre travail<a href="https://lunik.tiwabbit.fr/blog/fr/properly-handle-git-flow#publier-votre-travail" class="hash-link" aria-label="Lien direct vers Publier votre travail" title="Lien direct vers Publier votre travail" translate="no">​</a></h3>
<p>Il est maintenant temps de publier tout ce travail acharné.</p>
<p>Vous devez d'abord fusionner la branche par défaut pour récupérer toutes les correctifs.</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">git</span><span class="token plain"> checkout develop</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">git</span><span class="token plain"> merge --no-ff master</span><br></div></code></pre></div></div>
<p>Le dépôt devrait ressembler à :</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2022-09-11-properly-handle-git-flow/12_develop-rebase-git-repository-graph.png" alt="develop-rebase-git-repository-graph" class="img__Ss2"></p>
<p>Et enfin, fusionnez votre développement sur la branche par défaut.</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">git</span><span class="token plain"> checkout master</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">git</span><span class="token plain"> merge --no-ff develop</span><br></div></code></pre></div></div>
<p>Le dépôt devrait ressembler à :</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2022-09-11-properly-handle-git-flow/13_develop-merge-git-repository-graph.png" alt="develop-merge-git-repository-graph" class="img__Ss2"></p>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="nettoyer">Nettoyer<a href="https://lunik.tiwabbit.fr/blog/fr/properly-handle-git-flow#nettoyer" class="hash-link" aria-label="Lien direct vers Nettoyer" title="Lien direct vers Nettoyer" translate="no">​</a></h3>
<p>Faisons un peu de nettoyage en supprimant certaines références inutilisées telles que les branches de fonctionnalités et de correctifs.</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">git</span><span class="token plain"> branch </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-D</span><span class="token plain"> feature/my-first-feature</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">git</span><span class="token plain"> branch </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-D</span><span class="token plain"> feature/my-required-feature</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">git</span><span class="token plain"> branch </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-D</span><span class="token plain"> hotfix/correct-critical-issue  </span><br></div></code></pre></div></div>
<p>Le référentiel devrait ressembler à :</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2022-09-11-properly-handle-git-flow/14_cleanup-git-repository-graph.png" alt="cleanup-git-repository-graph" class="img__Ss2"></p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="remarques">Remarques<a href="https://lunik.tiwabbit.fr/blog/fr/properly-handle-git-flow#remarques" class="hash-link" aria-label="Lien direct vers Remarques" title="Lien direct vers Remarques" translate="no">​</a></h2>
<p>Tous les graphiques Git ont été générés avec <a href="https://bit-booster.com/" target="_blank" rel="noopener noreferrer" class="">Bit-Booster app</a></p>]]></content>
        <author>
            <name>Guillaume MARTINEZ</name>
            <uri>https://github.com/Lunik</uri>
        </author>
        <category label="git" term="git"/>
        <category label="gitflow" term="gitflow"/>
        <category label="merge request" term="merge request"/>
        <category label="pull request" term="pull request"/>
        <category label="feature" term="feature"/>
        <category label="merge" term="merge"/>
        <category label="pull" term="pull"/>
        <category label="request" term="request"/>
        <category label="branche" term="branche"/>
        <category label="rebase" term="rebase"/>
        <category label="checkout" term="checkout"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Zero trust deployment with Kubernetes]]></title>
        <id>https://lunik.tiwabbit.fr/blog/fr/zero-trust-kubernetes-deployment</id>
        <link href="https://lunik.tiwabbit.fr/blog/fr/zero-trust-kubernetes-deployment"/>
        <updated>2022-08-11T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[How to securely deploy application inside a Kubernetes Cluster. Especially with untrusted application or OpenSource software.]]></summary>
        <content type="html"><![CDATA[<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2022-08-11-zero-trust-kubernetes-deployment/cover.jpg" alt="cover" class="img__Ss2"></p>
<p>Using <a href="https://en.wikipedia.org/wiki/Open-source_model" target="_blank" rel="noopener noreferrer" class="">OpenSource</a> software written by unkown people sometimes can be a little scary. Even more when I deploy them I a production environment in my company.
On my case, I have created a brand new <a href="https://kubernetes.io/" target="_blank" rel="noopener noreferrer" class="">Kubernetes</a> cluster to host some private services on my local network and I wanted to be sure that they don't do anything malicious on my network.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="isolate-applications-and-services">Isolate applications and services<a href="https://lunik.tiwabbit.fr/blog/fr/zero-trust-kubernetes-deployment#isolate-applications-and-services" class="hash-link" aria-label="Lien direct vers Isolate applications and services" title="Lien direct vers Isolate applications and services" translate="no">​</a></h2>
<p>First thing to do is to isolate each of the services inside a <a href="https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/" target="_blank" rel="noopener noreferrer" class="">Kubernetes namespace</a>. This is a core resource of <a href="https://kubernetes.io/" target="_blank" rel="noopener noreferrer" class="">Kubernetes</a> that allow to isolate groups of resources within a single cluster. It then allow to have a more fine control on access, permissions, network on the resources.</p>
<p>A <a href="https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/" target="_blank" rel="noopener noreferrer" class="">Namespace</a> can be create pretty easily with the following command :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">kubectl create namespace </span><span class="token operator">&lt;</span><span class="token plain">insert-namespace-name-here</span><span class="token operator">&gt;</span><br></div></code></pre></div></div>
<p>Then I can list <a href="https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/" target="_blank" rel="noopener noreferrer" class="">Namespaces</a> with :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">kubectl get namespaces</span><br></div></code></pre></div></div>
<p>Result :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">NAME              STATUS   AGE</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">default           Active   4h52m</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">kube-system       Active   4h52m</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">kube-public       Active   4h52m</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">kube-node-lease   Active   4h52m</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">tiwabbit-prod     Active   2s</span><br></div></code></pre></div></div>
<p><em>Ignore <a href="https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/" target="_blank" rel="noopener noreferrer" class="">Namespaces</a> prefixed with <code>kube-</code> who are defined for the <a href="https://kubernetes.io/docs/concepts/overview/components/#control-plane-components" target="_blank" rel="noopener noreferrer" class="">Kubernetes control plane</a></em></p>
<p>I can now create resources inside my <a href="https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/" target="_blank" rel="noopener noreferrer" class="">Namespace</a>. Let's start with a <a href="https://kubernetes.io/docs/concepts/configuration/secret/" target="_blank" rel="noopener noreferrer" class="">Secret</a> for example :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">kubectl </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--namespace</span><span class="token plain"> tiwabbit-prod </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  create secret generic </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  db-credentials </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  --from-literal</span><span class="token operator">=</span><span class="token plain">username</span><span class="token operator">=</span><span class="token plain">tiwabbit </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  --from-literal</span><span class="token operator">=</span><span class="token plain">password</span><span class="token operator">=</span><span class="token plain">mysecurepassword</span><br></div></code></pre></div></div>
<p>If I list all <a href="https://kubernetes.io/docs/concepts/configuration/secret/" target="_blank" rel="noopener noreferrer" class="">Secrets</a> in my cluster :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">kubectl get secrets --all-namespaces</span><br></div></code></pre></div></div>
<p>Result :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">NAMESPACE       NAME                  TYPE                                  DATA   AGE</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token plain">.</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">default         default-token-m59jl   kubernetes.io/service-account-token   </span><span class="token number">3</span><span class="token plain">      4h58m</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">tiwabbit-prod   default-token-8zkr2   kubernetes.io/service-account-token   </span><span class="token number">3</span><span class="token plain">      3m15s</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">tiwabbit-prod   db-credentials        Opaque                                </span><span class="token number">2</span><span class="token plain">      49s</span><br></div></code></pre></div></div>
<p>In theory, only <a href="https://kubernetes.io/docs/concepts/workloads/pods/" target="_blank" rel="noopener noreferrer" class="">Pods</a> running inside my <a href="https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/" target="_blank" rel="noopener noreferrer" class="">Namespace</a> (<code>tiwabbit-prod</code>) can mount this secret and read it.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="rbac-securization">RBAC securization<a href="https://lunik.tiwabbit.fr/blog/fr/zero-trust-kubernetes-deployment#rbac-securization" class="hash-link" aria-label="Lien direct vers RBAC securization" title="Lien direct vers RBAC securization" translate="no">​</a></h2>
<p>By default all <a href="https://kubernetes.io/docs/concepts/workloads/pods/" target="_blank" rel="noopener noreferrer" class="">Pods</a> without specific configuration use the <code>default</code> <a href="https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/" target="_blank" rel="noopener noreferrer" class="">ServiceAccount</a> of the <a href="https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/" target="_blank" rel="noopener noreferrer" class="">Namespace</a> they are running in.
This last one dosn't have any right on the <a href="https://kubernetes.io/docs/concepts/overview/kubernetes-api/" target="_blank" rel="noopener noreferrer" class="">Kubernetes API</a> witch is a great thing and should not be changed.</p>
<p>How ever in some scenarios my application may needs to call the <a href="https://kubernetes.io/docs/concepts/overview/kubernetes-api/" target="_blank" rel="noopener noreferrer" class="">Kubernetes API</a>. For exemple if it need to create batch using a <a href="https://kubernetes.io/docs/concepts/workloads/controllers/job/" target="_blank" rel="noopener noreferrer" class="">Kubernetes Job</a>. Let's take that last exemple to create a <a href="https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/" target="_blank" rel="noopener noreferrer" class="">ServiceAccount</a> with those permission an assign it to my application <a href="https://kubernetes.io/docs/concepts/workloads/pods/" target="_blank" rel="noopener noreferrer" class="">Pod</a>.</p>
<p>First I need to create a new <a href="https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/" target="_blank" rel="noopener noreferrer" class="">ServiceAccount</a> :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">kubectl </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--namespace</span><span class="token plain"> tiwabbit-prod </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  create serviceaccount </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  my-application</span><br></div></code></pre></div></div>
<p>Then I need a <a href="https://kubernetes.io/docs/reference/access-authn-authz/rbac/" target="_blank" rel="noopener noreferrer" class="">Role</a> that implement the level of permission that my <a href="https://kubernetes.io/docs/concepts/workloads/pods/" target="_blank" rel="noopener noreferrer" class="">Pod</a> need. here is the manifest :</p>
<div class="language-yaml codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-yaml codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token key atrule">apiVersion</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> rbac.authorization.k8s.io/v1</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">kind</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> Role</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">metadata</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> my</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">application</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">batch</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">creator</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">namespace</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> tiwabbit</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">prod</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">rules</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">apiGroups</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">resources</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"> pods</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> pods/status</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> pods/log </span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">verbs</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"> get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> list</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> watch </span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">apiGroups</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"> batch </span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">resources</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"> jobs </span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">verbs</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"> create</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> list</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> watch</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> patch</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> update</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> delete </span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><br></div></code></pre></div></div>
<p>Finally, I need to assign the <a href="https://kubernetes.io/docs/reference/access-authn-authz/rbac/" target="_blank" rel="noopener noreferrer" class="">Role</a> to my <a href="https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/" target="_blank" rel="noopener noreferrer" class="">ServiceAccount</a> using a <a href="https://kubernetes.io/docs/reference/access-authn-authz/rbac/" target="_blank" rel="noopener noreferrer" class="">RoleBinding</a> with the following manifest definition :</p>
<div class="language-yaml codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-yaml codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token key atrule">apiVersion</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> rbac.authorization.k8s.io/v1</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">kind</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> RoleBinding</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">metadata</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> my</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">application</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">permissions</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">namespace</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> tiwabbit</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">prod</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">roleRef</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">apiGroup</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> rbac.authorization.k8s.io</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">kind</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> Role</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> my</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">application</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">batch</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">creator</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">subjects</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">kind</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> ServiceAccount</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> my</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">application</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">namespace</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> tiwabbit</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">prod</span><br></div></code></pre></div></div>
<p>Now let's create a <a href="https://kubernetes.io/docs/concepts/workloads/pods/" target="_blank" rel="noopener noreferrer" class="">Pod</a> with the <a href="https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/" target="_blank" rel="noopener noreferrer" class="">ServiceAccount</a> and review the actions allowed by the role. Here is a <a href="https://kubernetes.io/docs/concepts/workloads/controllers/deployment/" target="_blank" rel="noopener noreferrer" class="">Deployment</a> manifest :</p>
<div class="language-yaml codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-yaml codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token key atrule">apiVersion</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> apps/v1</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">kind</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> Deployment</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">metadata</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> my</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">application</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">namespace</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> tiwabbit</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">prod</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">spec</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">replicas</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">1</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">selector</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">matchLabels</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token key atrule">app</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> my</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">application</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">template</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">metadata</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token key atrule">labels</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token key atrule">app</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> my</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">application</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">spec</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token key atrule">serviceAccountName</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> my</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">application</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token key atrule">containers</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">command</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> sleep</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> 1d</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token key atrule">image</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> alpine</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">latest</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> alpine</span><br></div></code></pre></div></div>
<p>Geting inside the <a href="https://kubernetes.io/docs/concepts/workloads/pods/" target="_blank" rel="noopener noreferrer" class="">Pod</a> and follow the <a href="https://kubernetes.io/docs/tasks/tools/#kubectl" target="_blank" rel="noopener noreferrer" class="">Kubernetes documentation to install <code>kubectl</code></a>.</p>
<p>Let's check if I can list <a href="https://kubernetes.io/docs/concepts/workloads/pods/" target="_blank" rel="noopener noreferrer" class="">Pods</a> by querying the Kubernetes API :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">kubectl get pods</span><br></div></code></pre></div></div>
<p>Result :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">NAME                             READY   STATUS    RESTARTS   AGE</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">my-application-df5b5cb75-8twc5   </span><span class="token number">1</span><span class="token plain">/1     Running   </span><span class="token number">0</span><span class="token plain">          5m21s</span><br></div></code></pre></div></div>
<p>Then I should try to create a batch execution with a <a href="https://kubernetes.io/docs/concepts/workloads/controllers/job/" target="_blank" rel="noopener noreferrer" class="">Job</a> :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">kubectl create job my-application-batch </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--image</span><span class="token plain"> alpine:latest -- </span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">echo</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Hello World"</span><br></div></code></pre></div></div>
<p>Listing all the <a href="https://kubernetes.io/docs/concepts/workloads/controllers/job/" target="_blank" rel="noopener noreferrer" class="">Jobs</a> in the <a href="https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/" target="_blank" rel="noopener noreferrer" class="">Namespace</a> :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">kubectl get </span><span class="token function" style="color:rgb(80, 250, 123)">jobs</span><br></div></code></pre></div></div>
<p>Result :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">NAME                   COMPLETIONS   DURATION   AGE</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">my-application-batch   </span><span class="token number">0</span><span class="token plain">/1           2s         2s</span><br></div></code></pre></div></div>
<p>Listing the <a href="https://kubernetes.io/docs/concepts/workloads/pods/" target="_blank" rel="noopener noreferrer" class="">Pods</a> in the <a href="https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/" target="_blank" rel="noopener noreferrer" class="">Namespace</a> :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">kubectl get pods</span><br></div></code></pre></div></div>
<p>Result :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">NAME                             READY   STATUS    RESTARTS   AGE</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">my-application-df5b5cb75-8twc5   </span><span class="token number">1</span><span class="token plain">/1     Running   </span><span class="token number">0</span><span class="token plain">          11m</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">my-application-batch-f2pf6       </span><span class="token number">1</span><span class="token plain">/1     Running   </span><span class="token number">0</span><span class="token plain">          3s</span><br></div></code></pre></div></div>
<p>My <a href="https://kubernetes.io/docs/concepts/workloads/controllers/job/" target="_blank" rel="noopener noreferrer" class="">Job</a> finished and I can delete it with :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">kubectl delete job/my-application-batch</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="conclusions">Conclusions<a href="https://lunik.tiwabbit.fr/blog/fr/zero-trust-kubernetes-deployment#conclusions" class="hash-link" aria-label="Lien direct vers Conclusions" title="Lien direct vers Conclusions" translate="no">​</a></h3>
<p>If the process in my <a href="https://kubernetes.io/docs/concepts/workloads/pods/" target="_blank" rel="noopener noreferrer" class="">Pod</a> doesn't need to communicate with the <a href="https://kubernetes.io/docs/concepts/overview/kubernetes-api/" target="_blank" rel="noopener noreferrer" class="">Kubernetes API</a> (for creating, querying, deleting ressources), use the <code>default</code> <a href="https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/" target="_blank" rel="noopener noreferrer" class="">ServiceAccount</a> witch give zero permission to my <a href="https://kubernetes.io/docs/concepts/workloads/pods/" target="_blank" rel="noopener noreferrer" class="">Pod</a>. In other case, use a custom <a href="https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/" target="_blank" rel="noopener noreferrer" class="">ServiceAccount</a> for each of my apps and multiple <a href="https://kubernetes.io/docs/reference/access-authn-authz/rbac/" target="_blank" rel="noopener noreferrer" class="">Role</a> and <a href="https://kubernetes.io/docs/reference/access-authn-authz/rbac/" target="_blank" rel="noopener noreferrer" class="">RoleBinding</a> for each of my application use case.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="prevent-usage-of-root-user-or-privileged-escalation">Prevent usage of root user or privileged escalation<a href="https://lunik.tiwabbit.fr/blog/fr/zero-trust-kubernetes-deployment#prevent-usage-of-root-user-or-privileged-escalation" class="hash-link" aria-label="Lien direct vers Prevent usage of root user or privileged escalation" title="Lien direct vers Prevent usage of root user or privileged escalation" translate="no">​</a></h2>
<p>Kubernetes allow by default multiple security options that can be applied to pods and underlaying containers. Most of them can be configured with the <a href="https://kubernetes.io/docs/tasks/configure-pod-container/security-context/" target="_blank" rel="noopener noreferrer" class="">SecurityContext</a> block as follow :</p>
<div class="language-yaml codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-yaml codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token key atrule">apiVersion</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> v1</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">kind</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> Pod</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">metadata</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> my</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">secure</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">pod</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">spec</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">securityContext</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">containers</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> my</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">secure</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">container</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">image</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> nginx</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">latest</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">securityContext</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> my</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">second</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">secure</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">container</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">image</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> busybox</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">latest</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">command</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"sleep"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"infinity"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">securityContext</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></div></code></pre></div></div>
<p>Obviously such options can be added to a <a href="https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/" target="_blank" rel="noopener noreferrer" class="">StatefulSet</a> or <a href="https://kubernetes.io/docs/concepts/workloads/controllers/deployment/" target="_blank" rel="noopener noreferrer" class="">Deployment</a> template.</p>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="running-pod-as-non-root">Running pod as non root<a href="https://lunik.tiwabbit.fr/blog/fr/zero-trust-kubernetes-deployment#running-pod-as-non-root" class="hash-link" aria-label="Lien direct vers Running pod as non root" title="Lien direct vers Running pod as non root" translate="no">​</a></h3>
<p>The easiest setup to secure the <a href="https://kubernetes.io/docs/concepts/workloads/pods/" target="_blank" rel="noopener noreferrer" class="">Pod</a> is to overwrite the <a href="https://en.wikipedia.org/wiki/User_identifier" target="_blank" rel="noopener noreferrer" class="">UID</a> and <a href="https://en.wikipedia.org/wiki/Group_identifier" target="_blank" rel="noopener noreferrer" class="">GID</a> of the user running the main process. This way, what ever the default user in the image, <a href="https://kubernetes.io/" target="_blank" rel="noopener noreferrer" class="">Kubernetes</a> will bypass it. An <a href="https://en.wikipedia.org/wiki/User_identifier" target="_blank" rel="noopener noreferrer" class="">UID</a> and <a href="https://en.wikipedia.org/wiki/Group_identifier" target="_blank" rel="noopener noreferrer" class="">GID</a> superior or equal to <code>1000</code> should be used.</p>
<p>Three parameters can be used :</p>
<ul>
<li class=""><code>runAsUser</code> : Allow to change the <a href="https://en.wikipedia.org/wiki/User_identifier" target="_blank" rel="noopener noreferrer" class="">UID</a> of the default process</li>
<li class=""><code>runAsGroup</code> : Allow to change the <a href="https://en.wikipedia.org/wiki/Group_identifier" target="_blank" rel="noopener noreferrer" class="">GID</a> of the default process</li>
<li class=""><code>fsGroup</code> : If specified, the user will also be in that group and all files and directories created will take that <a href="https://en.wikipedia.org/wiki/Group_identifier" target="_blank" rel="noopener noreferrer" class="">GID</a> as owner.<!-- -->
<ul>
<li class="">This last parameter can increase the mount time of a given external volume because <a href="https://kubernetes.io/" target="_blank" rel="noopener noreferrer" class="">Kubernetes</a> ensure that files are owned by the group defined by <code>fsGroup</code>. Resulting on an <code>chmod -R</code> of all the filesystem.</li>
<li class=""><code>fsGroupChangePolicy</code> can be used to change this behaviour with those values :<!-- -->
<ul>
<li class=""><code>OnRootMismatch</code> : only check the root directory and change all filesystem if the group mismatch</li>
<li class=""><code>Always</code> : it's in the option name</li>
</ul>
</li>
</ul>
</li>
</ul>
<div class="language-yaml codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-yaml codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token key atrule">apiVersion</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> v1</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">kind</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> Pod</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">metadata</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> my</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">secure</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">pod</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">spec</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">securityContext</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">runAsUser</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">1000</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">runAsGroup</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">1000</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">fsGroup</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">2000</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">fsGroupChangePolicy</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> OnRootMismatch</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">containers</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> my</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">secure</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">container</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">image</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> busybox</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">latest</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">command</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"sleep"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"infinity"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">securityContext</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token key atrule">runAsUser</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">2000</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token key atrule">runAsGroup</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">2000</span><br></div></code></pre></div></div>
<p>Enforcing running as non <code>root</code> could be achieved with <code>runAsNonRoot</code> parameter :</p>
<div class="language-yaml codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-yaml codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token key atrule">apiVersion</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> v1</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">kind</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> Pod</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">metadata</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> my</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">secure</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">pod</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">spec</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">securityContext</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">runAsNonRoot</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token boolean important">true</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">containers</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> my</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">secure</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">container</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">image</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> busybox</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">latest</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">command</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"sleep"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"infinity"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">securityContext</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="use-readonly-filesystem">Use readonly filesystem<a href="https://lunik.tiwabbit.fr/blog/fr/zero-trust-kubernetes-deployment#use-readonly-filesystem" class="hash-link" aria-label="Lien direct vers Use readonly filesystem" title="Lien direct vers Use readonly filesystem" translate="no">​</a></h3>
<p>Preventing all write/update/delete operation on the root filesystem can prevent malicious process (or breached application) to take advantage of the container environment and modify it.
The <code>readOnlyRootFilesystem</code> option allow to achieve that :</p>
<div class="language-yaml codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-yaml codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token key atrule">apiVersion</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> v1</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">kind</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> Pod</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">metadata</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> my</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">secure</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">pod</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">spec</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">securityContext</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">containers</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> my</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">secure</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">container</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">image</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> busybox</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">latest</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">command</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"sleep"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"infinity"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">securityContext</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token key atrule">readOnlyRootFilesystem</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token boolean important">true</span><br></div></code></pre></div></div>
<p>If the application need to write temporary or application data during the runtime, I can still create an <a href="https://kubernetes.io/docs/concepts/storage/volumes/#emptydir" target="_blank" rel="noopener noreferrer" class="">EmptyDir</a> volume and mounting it inside the container :</p>
<div class="language-yaml codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-yaml codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token key atrule">apiVersion</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> v1</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">kind</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> Pod</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">metadata</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> my</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">secure</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">pod</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">spec</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">securityContext</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">containers</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> my</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">secure</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">container</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">image</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> busybox</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">latest</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">command</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"sleep"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"infinity"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">securityContext</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token key atrule">readOnlyRootFilesystem</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token boolean important">true</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">volumeMounts</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">mountPath</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> /data</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> my</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">data</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">volumes</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> my</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">data</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">emptyDir</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="prevent-priviled-escalation">Prevent priviled escalation<a href="https://lunik.tiwabbit.fr/blog/fr/zero-trust-kubernetes-deployment#prevent-priviled-escalation" class="hash-link" aria-label="Lien direct vers Prevent priviled escalation" title="Lien direct vers Prevent priviled escalation" translate="no">​</a></h3>
<p>Linux kernel expose low level function for a process to change is current <a href="https://en.wikipedia.org/wiki/User_identifier" target="_blank" rel="noopener noreferrer" class="">UID</a> or <a href="https://en.wikipedia.org/wiki/Group_identifier" target="_blank" rel="noopener noreferrer" class="">GID</a>. For example using [setuid][linux-setuid-wikipedia] or <a href="https://en.wikipedia.org/wiki/Setuid" target="_blank" rel="noopener noreferrer" class="">setgid</a> privitive functions.</p>
<p>Using the option <code>allowPrivilegeEscalation</code> can prevent this to happens.</p>
<div class="language-yaml codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-yaml codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token key atrule">apiVersion</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> v1</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">kind</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> Pod</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">metadata</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> my</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">secure</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">pod</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">spec</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">securityContext</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">containers</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> my</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">secure</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">container</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">image</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> busybox</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">latest</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">command</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"sleep"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"infinity"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">securityContext</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token key atrule">allowPrivilegeEscalation</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token boolean important">false</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="dropping-all-capabilities">Dropping all capabilities<a href="https://lunik.tiwabbit.fr/blog/fr/zero-trust-kubernetes-deployment#dropping-all-capabilities" class="hash-link" aria-label="Lien direct vers Dropping all capabilities" title="Lien direct vers Dropping all capabilities" translate="no">​</a></h3>
<p>As for privileged escalation, Linux give <a href="https://manpages.ubuntu.com/manpages/jammy/en/man7/capabilities.7.html" target="_blank" rel="noopener noreferrer" class="">Capabilities</a> to process allowing them to make high privileged system calls. Like binding network ports under <code>1024</code>.</p>
<p>We want to only give our process only the necessary capabilities for it to run.
In the cas of the exemple we can have :</p>
<div class="language-yaml codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-yaml codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token key atrule">apiVersion</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> v1</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">kind</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> Pod</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">metadata</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> my</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">secure</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">pod</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">spec</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">securityContext</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">containers</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> my</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">second</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">secure</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">container</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">image</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> busybox</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">latest</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">command</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"sleep"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"infinity"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">securityContext</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token key atrule">capabilities</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token key atrule">drop</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> ALL</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token key atrule">add</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> NET_BIND_SERVICE</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="network-communication-hardening">Network communication hardening<a href="https://lunik.tiwabbit.fr/blog/fr/zero-trust-kubernetes-deployment#network-communication-hardening" class="hash-link" aria-label="Lien direct vers Network communication hardening" title="Lien direct vers Network communication hardening" translate="no">​</a></h2>
<p>In the world of pods, by default every pods in every namespace can talk to each other. If you have multiple application or even multiple clients on the same Kubernetes cluster, you should not allow them to communicate (at least not by default).</p>
<p>That's why, <a href="https://kubernetes.io/docs/concepts/services-networking/network-policies/" target="_blank" rel="noopener noreferrer" class="">NetworkPolicies</a> must be created with <code>deny all</code> by default. Then open point to point connections if services/clients needs to communicates with each others.</p>
<p>The default <code>deny all</code> config will looks like this :</p>
<div class="language-yaml codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-yaml codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token key atrule">apiVersion</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> networking.k8s.io/v1</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">kind</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> NetworkPolicy</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">metadata</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> default</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">deny</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">ingress</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">spec</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">podSelector</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">policyTypes</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> Ingress</span><br></div></code></pre></div></div>
<p>Then if you have a third party application that needs to access your application pods :</p>
<div class="language-yaml codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-yaml codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token key atrule">apiVersion</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> networking.k8s.io/v1</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">kind</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> NetworkPolicy</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">metadata</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> test</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">network</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">policy</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">namespace</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> my</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">namespace</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">spec</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">podSelector</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">matchLabels</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token key atrule">application</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> my</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">application</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token key atrule">component</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> api</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">policyTypes</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> Ingress</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">ingress</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">from</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">namespaceSelector</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token key atrule">matchLabels</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">              </span><span class="token key atrule">project</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> my</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">friend</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">namespace</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">podSelector</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token key atrule">matchLabels</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">              </span><span class="token key atrule">application</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> his</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">application</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token key atrule">ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">protocol</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> TCP</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token key atrule">port</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">8080</span><br></div></code></pre></div></div>]]></content>
        <author>
            <name>Guillaume MARTINEZ</name>
            <uri>https://github.com/Lunik</uri>
        </author>
        <category label="kubernetes" term="kubernetes"/>
        <category label="security" term="security"/>
        <category label="firewall" term="firewall"/>
        <category label="network" term="network"/>
        <category label="zero-trust" term="zero-trust"/>
        <category label="namespace" term="namespace"/>
        <category label="capabilities" term="capabilities"/>
        <category label="system" term="system"/>
        <category label="privileged" term="privileged"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Comprendre les mots de passe TOTP]]></title>
        <id>https://lunik.tiwabbit.fr/blog/fr/understanding-totp</id>
        <link href="https://lunik.tiwabbit.fr/blog/fr/understanding-totp"/>
        <updated>2022-04-28T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Pongée dans le protocole TOTP]]></summary>
        <content type="html"><![CDATA[<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2022-04-28-understanding-totp/cover.png" alt="cover" class="img__Ss2"></p>
<p>Maintenant que tous les services web nous encouragent, de plus en plus, à utiliser une <a href="https://en.wikipedia.org/wiki/Multi-factor_authentication" target="_blank" rel="noopener noreferrer" class="">MFA</a> pour sécuriser nos compte, l'un d'entre eux reste le plus utilisé que les autres : <a href="https://fr.wikipedia.org/wiki/Mot_de_passe_%C3%A0_usage_unique_bas%C3%A9_sur_le_temps" target="_blank" rel="noopener noreferrer" class="">Mot de passe à usage unique basé sur le temps ou TOTP</a> génère un code unique de <code>6</code> chiffres ou plus à saisir juste après avoir tapé votre mot de passe.</p>
<p>Le serveur ou l'application Web permettant de configurer le <a href="https://fr.wikipedia.org/wiki/Mot_de_passe_%C3%A0_usage_unique_bas%C3%A9_sur_le_temps" target="_blank" rel="noopener noreferrer" class="">TOTP</a> donne un <a href="https://fr.wikipedia.org/wiki/Code_QR" target="_blank" rel="noopener noreferrer" class="">QRCode</a> à scanner (ou une chaîne <a href="https://tools.ietf.org/html/rfc4648" target="_blank" rel="noopener noreferrer" class="">Base32</a>) à configurer dans une application génératrice de <a href="https://fr.wikipedia.org/wiki/Mot_de_passe_%C3%A0_usage_unique_bas%C3%A9_sur_le_temps" target="_blank" rel="noopener noreferrer" class="">TOTP</a> comme <a href="https://www.microsoft.com/en-us/security/mobile-authenticator-app" target="_blank" rel="noopener noreferrer" class="">Microsoft Authenticator</a>, <a href="https://support.google.com/accounts/answer/1066447" target="_blank" rel="noopener noreferrer" class="">Google Authenticator</a>, <a href="https://bitwarden.com/" target="_blank" rel="noopener noreferrer" class="">Bitwarden</a> ou plus.</p>
<p>Nous l'utilisons tous, mais comment ça marche ? Est-ce sécurisé ? Mon compte est-il sécurisé lorsque j'utilise un générateur de <a href="https://fr.wikipedia.org/wiki/Mot_de_passe_%C3%A0_usage_unique_bas%C3%A9_sur_le_temps" target="_blank" rel="noopener noreferrer" class="">TOTP</a> tiers ??</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="le-protocole">Le protocole<a href="https://lunik.tiwabbit.fr/blog/fr/understanding-totp#le-protocole" class="hash-link" aria-label="Lien direct vers Le protocole" title="Lien direct vers Le protocole" translate="no">​</a></h2>
<p>Je vais approfondir dans les détails le protocole sous-jacent vous permettant de générer des <a href="https://fr.wikipedia.org/wiki/Mot_de_passe_%C3%A0_usage_unique_bas%C3%A9_sur_le_temps" target="_blank" rel="noopener noreferrer" class="">TOTP</a> et comment le serveur le vérifie.</p>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="bases">Bases<a href="https://lunik.tiwabbit.fr/blog/fr/understanding-totp#bases" class="hash-link" aria-label="Lien direct vers Bases" title="Lien direct vers Bases" translate="no">​</a></h3>
<p>L'idée de base est assez simple. Vous et le serveur avez partagé un secret, une chaîne <a href="https://tools.ietf.org/html/rfc4648" target="_blank" rel="noopener noreferrer" class="">Base32</a> de <code>16</code> caractères (parfois stockée dans un <a href="https://fr.wikipedia.org/wiki/Code_QR" target="_blank" rel="noopener noreferrer" class="">QRCode</a>). Puis vous synchronisez tous les deux vos horloges.</p>
<p>Enfin, lorsque vous souhaitez vous connecter, vous exécutez une fonction magique sophistiquée et vous obtenez un <a href="https://fr.wikipedia.org/wiki/Mot_de_passe_%C3%A0_usage_unique_bas%C3%A9_sur_le_temps" target="_blank" rel="noopener noreferrer" class="">TOTP</a>.
Le serveur calcule le <a href="https://fr.wikipedia.org/wiki/Mot_de_passe_%C3%A0_usage_unique_bas%C3%A9_sur_le_temps" target="_blank" rel="noopener noreferrer" class="">TOTP</a> de son côté et vous demande celui que vous avez généré de votre côté. Si les deux <a href="https://fr.wikipedia.org/wiki/Mot_de_passe_%C3%A0_usage_unique_bas%C3%A9_sur_le_temps" target="_blank" rel="noopener noreferrer" class="">TOTP</a> correspondent, le serveur vous autorise à entrer.</p>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="protocole-totp">Protocole TOTP<a href="https://lunik.tiwabbit.fr/blog/fr/understanding-totp#protocole-totp" class="hash-link" aria-label="Lien direct vers Protocole TOTP" title="Lien direct vers Protocole TOTP" translate="no">​</a></h3>
<p>Explorons le protocole <a href="https://fr.wikipedia.org/wiki/Mot_de_passe_%C3%A0_usage_unique_bas%C3%A9_sur_le_temps" target="_blank" rel="noopener noreferrer" class="">TOTP</a>. Selon la <a href="https://tools.ietf.org/html/rfc6238" target="_blank" rel="noopener noreferrer" class="">RFC 6238</a> vous avez besoin :</p>
<ul>
<li class="">Un <code>compteur</code> changeant qui doit être synchronisé entre les deux parties</li>
<li class="">Un <code>secret</code> partagé entre les deux parties</li>
</ul>
<p>Le <code>compteur</code> est calculé sur la base du temps <a href="https://fr.wikipedia.org/wiki/Epoch" target="_blank" rel="noopener noreferrer" class="">epoch</a> (Ainsi tout le monde est synchronisé) avec la formule suivante :</p>
<div class="language-text codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-text codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">C = (T - T0) / X</span><br></div></code></pre></div></div>
<p>Avec :</p>
<ul>
<li class=""><code>C</code> la valeur du compteur</li>
<li class=""><code>T</code> l'heure Unix actuelle en secondes depuis <a href="https://fr.wikipedia.org/wiki/Epoch" target="_blank" rel="noopener noreferrer" class="">epoch</a></li>
<li class=""><code>T0</code> une heure Unix de début arbitraire. <code>0</code> par défaut</li>
<li class=""><code>X</code> le pas de temps en secondes ou la fréquence de mise à jour du code. <code>30</code> par défaut</li>
</ul>
<p>Si nous essayons de faire une implémentation <a href="https://www.python.org/" target="_blank" rel="noopener noreferrer" class="">Python</a>, cela ressemblera à :</p>
<div class="language-python codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-python codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">t0 </span><span class="token operator">=</span><span class="token plain"> </span><span class="token number">0</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># https://docs.python.org/3/library/time.html#time.time</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">current_unix_time </span><span class="token operator">=</span><span class="token plain"> time</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">time</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">time_step </span><span class="token operator">=</span><span class="token plain"> </span><span class="token number">30</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">counter </span><span class="token operator">=</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">int</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">current_unix_time </span><span class="token operator">-</span><span class="token plain"> t0</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">/</span><span class="token plain"> time_step</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></div></code></pre></div></div>
<div class="language-python codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-python codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">current_unix_time</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">1651094239.491242</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">counter </span><span class="token operator">=</span><span class="token operator">&gt;</span><span class="token plain"> </span><span class="token number">55036474</span><br></div></code></pre></div></div>
<p>Maintenant la valeur <a href="https://fr.wikipedia.org/wiki/Mot_de_passe_%C3%A0_usage_unique_bas%C3%A9_sur_le_temps" target="_blank" rel="noopener noreferrer" class="">TOTP</a> peut être récupérée avec la formule suivante :</p>
<div class="language-text codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-text codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">TOTP = HOTP(K, C, D)</span><br></div></code></pre></div></div>
<p>Avec:</p>
<ul>
<li class=""><code>C</code> la valeur du compteur</li>
<li class=""><code>K</code> la clé secrète</li>
<li class=""><code>D</code> le nombre de chiffres dans nos <a href="https://fr.wikipedia.org/wiki/Mot_de_passe_%C3%A0_usage_unique_bas%C3%A9_sur_le_temps" target="_blank" rel="noopener noreferrer" class="">TOTP</a>s</li>
<li class=""><code>HOTP</code> la fonction magique qui calcule l'OTP</li>
</ul>
<p>En <a href="https://www.python.org/" target="_blank" rel="noopener noreferrer" class="">Python</a>, on obtient :</p>
<div class="language-python codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-python codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">counter </span><span class="token operator">=</span><span class="token plain"> </span><span class="token number">55036474</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">key </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"ABCDEFGHYJKLMNOP"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">digits </span><span class="token operator">=</span><span class="token plain"> </span><span class="token number">6</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">totp </span><span class="token operator">=</span><span class="token plain"> hotp</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">key</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> counter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> digits</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></div></code></pre></div></div>
<div class="language-python codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-python codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">totp </span><span class="token operator">=</span><span class="token operator">&gt;</span><span class="token plain"> </span><span class="token number">934929</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="protocole-hotp">Protocole HOTP<a href="https://lunik.tiwabbit.fr/blog/fr/understanding-totp#protocole-hotp" class="hash-link" aria-label="Lien direct vers Protocole HOTP" title="Lien direct vers Protocole HOTP" translate="no">​</a></h3>
<p>Ce deuxième protocole est utilisé pour calculer une valeur unique, une valeur compteur et une clé secrete. De la <a href="https://tools.ietf.org/html/rfc4226" target="_blank" rel="noopener noreferrer" class="">RFC rfc4226</a>, nous apprenons qu'il est basé sur le <a href="https://tools.ietf.org/html/rfc2104" target="_blank" rel="noopener noreferrer" class="">protocole de hachage HMAC</a>.</p>
<p>Asseyez-vous bien car cela va commencer à être difficile et j'espère que vous êtes à l'aise avec les opérations binaires.</p>
<h4 class="anchor anchorTargetStickyNavbar_SAay" id="gérer-les-entrées">Gérer les entrées<a href="https://lunik.tiwabbit.fr/blog/fr/understanding-totp#g%C3%A9rer-les-entr%C3%A9es" class="hash-link" aria-label="Lien direct vers Gérer les entrées" title="Lien direct vers Gérer les entrées" translate="no">​</a></h4>
<p>Tout d'abord, nous devons gérer les 2 de nos 3 paramètres d'entrée : <code>counter</code>, <code>key</code></p>
<ul>
<li class=""><code>counter</code> doit être converti en une liste d'octets de type <code>unsigned long long</code> et <code>big-endian</code>.</li>
</ul>
<p>En <a href="https://www.python.org/" target="_blank" rel="noopener noreferrer" class="">Python</a> :</p>
<div class="language-python codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-python codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> struct</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># https://docs.python.org/3/library/struct.html#struct.pack</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># https://docs.python.org/3/library/struct.html#byte-order-size-and-alignment</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># https://docs.python.org/3/library/struct.html#format-characters</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">bytes_counter </span><span class="token operator">=</span><span class="token plain"> struct</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">pack</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">'&gt;Q'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> counter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></div></code></pre></div></div>
<div class="language-python codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-python codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">counter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">55036474</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">bytes_counter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token builtin" style="color:rgb(189, 147, 249)">bin</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">=</span><span class="token operator">&gt;</span><span class="token plain"> </span><span class="token number">00000011</span><span class="token plain"> </span><span class="token number">01000111</span><span class="token plain"> </span><span class="token number">11001010</span><span class="token plain"> </span><span class="token number">00111010</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">bytes_counter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token builtin" style="color:rgb(189, 147, 249)">hex</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">=</span><span class="token operator">&gt;</span><span class="token plain"> </span><span class="token number">03</span><span class="token plain"> </span><span class="token number">47</span><span class="token plain"> ca 3a</span><br></div></code></pre></div></div>
<ul>
<li class=""><code>key</code> doit être une chaîne <a href="https://tools.ietf.org/html/rfc4648" target="_blank" rel="noopener noreferrer" class="">Base32</a> valide. La <a href="https://tools.ietf.org/html/rfc4648" target="_blank" rel="noopener noreferrer" class="">RFC 4648</a> nous indique que la longueur de la chaîne doit être un facteur de <code>8</code>. Ainsi, du "padding" peut être ajouté avec le caractère <code>=</code> à la fin s'il est trop court. Par exemple : <code>AA</code> =&gt; <code>AA======</code>, <code>BBBBBBBBBB</code> =&gt; <code>BBBBBBBBBB======</code>, <code>CCCCCCCC</code> =&gt; <code>CCCCCCCC</code></li>
</ul>
<div class="language-python codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-python codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">padding </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">'='</span><span class="token plain"> </span><span class="token operator">*</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token number">8</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">len</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">key</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">%</span><span class="token plain"> </span><span class="token number">8</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">valid_key </span><span class="token operator">=</span><span class="token plain"> key </span><span class="token operator">+</span><span class="token plain"> padding</span><br></div></code></pre></div></div>
<div class="language-python codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-python codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">key</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> ABCDEFGHIJKLMNOP</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">valid_key </span><span class="token operator">=</span><span class="token operator">&gt;</span><span class="token plain"> ABCDEFGHIJKLMNOP</span><br></div></code></pre></div></div>
<p>Ensuite, nous convertissons la clé mise à jour en valeur en liste d'octets :</p>
<div class="language-python codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-python codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> base64</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">bytes_key </span><span class="token operator">=</span><span class="token plain"> base64</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">b32decode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">key</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></div></code></pre></div></div>
<div class="language-python codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-python codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">valid_key</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> ABCDEFGHIJKLMNOP</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">bytes_key</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token builtin" style="color:rgb(189, 147, 249)">bin</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">=</span><span class="token operator">&gt;</span><span class="token plain"> </span><span class="token number">10001000</span><span class="token plain"> </span><span class="token number">01100100</span><span class="token plain"> </span><span class="token number">00101001</span><span class="token plain"> </span><span class="token number">10001110</span><span class="token plain"> </span><span class="token number">10000100</span><span class="token plain"> </span><span class="token number">10101001</span><span class="token plain"> </span><span class="token number">01101100</span><span class="token plain"> </span><span class="token number">0110101</span><span class="token plain"> </span><span class="token number">11001111</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">bytes_key</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token builtin" style="color:rgb(189, 147, 249)">hex</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">=</span><span class="token operator">&gt;</span><span class="token plain"> </span><span class="token number">44</span><span class="token plain"> </span><span class="token number">32</span><span class="token plain"> </span><span class="token number">14</span><span class="token plain"> c7 </span><span class="token number">42</span><span class="token plain"> </span><span class="token number">54</span><span class="token plain"> b6 </span><span class="token number">35</span><span class="token plain"> cf</span><br></div></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_SAay" id="calculer-le-hmac">Calculer le HMAC<a href="https://lunik.tiwabbit.fr/blog/fr/understanding-totp#calculer-le-hmac" class="hash-link" aria-label="Lien direct vers Calculer le HMAC" title="Lien direct vers Calculer le HMAC" translate="no">​</a></h4>
<p>En utilisant la <a href="https://tools.ietf.org/html/rfc2104" target="_blank" rel="noopener noreferrer" class="">RFC 2104</a> nous pouvons en comprendre le fonctionnement de la <a href="https://tools.ietf.org/html/rfc2104" target="_blank" rel="noopener noreferrer" class="">fonction HMAC</a>. Nous devons choisir une fonction de hachage. <a href="https://en.wikipedia.org/wiki/HMAC-based_one-time_password" target="_blank" rel="noopener noreferrer" class="">HOTP</a> ou <a href="https://tools.ietf.org/html/rfc4226" target="_blank" rel="noopener noreferrer" class="">RFC 4226</a> utilise la fonction de hachage cryptographique <a href="https://tools.ietf.org/html/rfc3174" target="_blank" rel="noopener noreferrer" class="">SHA-1</a>.</p>
<p><a href="https://www.python.org/" target="_blank" rel="noopener noreferrer" class="">Python</a> implémente la <a href="https://docs.python.org/3/library/hmac.html" target="_blank" rel="noopener noreferrer" class="">bibliothèque HMAC</a> :</p>
<div class="language-python codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-python codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> hmac</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># Calculate the HMAC-SHA1 value</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># Produce a 20 bytes (or 160 bites) long string</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">mac </span><span class="token operator">=</span><span class="token plain"> hmac</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">new</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">bytes_key</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> bytes_counter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"SHA1"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">digest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></div></code></pre></div></div>
<div class="language-python codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-python codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">bytes_counter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token builtin" style="color:rgb(189, 147, 249)">hex</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">03</span><span class="token plain"> </span><span class="token number">47</span><span class="token plain"> ca 3a</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">bytes_key</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token builtin" style="color:rgb(189, 147, 249)">hex</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">44</span><span class="token plain"> </span><span class="token number">32</span><span class="token plain"> </span><span class="token number">14</span><span class="token plain"> c7 </span><span class="token number">42</span><span class="token plain"> </span><span class="token number">54</span><span class="token plain"> b6 </span><span class="token number">35</span><span class="token plain"> cf</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">mac</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token builtin" style="color:rgb(189, 147, 249)">bin</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">=</span><span class="token operator">&gt;</span><span class="token plain"> </span><span class="token number">10110100</span><span class="token plain"> </span><span class="token number">11010010</span><span class="token plain"> </span><span class="token number">01111010</span><span class="token plain"> </span><span class="token number">10110100</span><span class="token plain"> </span><span class="token number">10111101</span><span class="token plain"> </span><span class="token number">00110101</span><span class="token plain"> </span><span class="token number">11111110</span><span class="token plain"> </span><span class="token number">00100011</span><span class="token plain"> </span><span class="token number">11101101</span><span class="token plain"> </span><span class="token number">01011001</span><span class="token plain"> </span><span class="token number">01111110</span><span class="token plain"> </span><span class="token number">10111100</span><span class="token plain"> </span><span class="token number">11110000</span><span class="token plain"> </span><span class="token number">01111001</span><span class="token plain"> </span><span class="token number">11000001</span><span class="token plain"> </span><span class="token number">01001010</span><span class="token plain"> </span><span class="token number">00000110</span><span class="token plain"> </span><span class="token number">01101100</span><span class="token plain"> </span><span class="token number">01010001</span><span class="token plain"> </span><span class="token number">00101111</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">mac</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token builtin" style="color:rgb(189, 147, 249)">hex</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">=</span><span class="token operator">&gt;</span><span class="token plain"> b4 d2 7a b4 bd </span><span class="token number">35</span><span class="token plain"> fe </span><span class="token number">23</span><span class="token plain"> ed </span><span class="token number">59</span><span class="token plain"> 7e bc f0 </span><span class="token number">79</span><span class="token plain"> c1 4a </span><span class="token number">06</span><span class="token plain"> 6c </span><span class="token number">51</span><span class="token plain"> 2f</span><br></div></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_SAay" id="calculer-le-hotp">Calculer le HOTP<a href="https://lunik.tiwabbit.fr/blog/fr/understanding-totp#calculer-le-hotp" class="hash-link" aria-label="Lien direct vers Calculer le HOTP" title="Lien direct vers Calculer le HOTP" translate="no">​</a></h4>
<p>Conformément à la section <code>5.3</code> de la <a href="https://tools.ietf.org/html/rfc4226" target="_blank" rel="noopener noreferrer" class="">RFC 4226</a>.</p>
<h5 class="anchor anchorTargetStickyNavbar_SAay" id="trouver-le-décalage">Trouver le décalage<a href="https://lunik.tiwabbit.fr/blog/fr/understanding-totp#trouver-le-d%C3%A9calage" class="hash-link" aria-label="Lien direct vers Trouver le décalage" title="Lien direct vers Trouver le décalage" translate="no">​</a></h5>
<p>Nous devons d'abord trouver la valeur <code>offset</code> en obtenant les <code>4</code> bits les moins significatifs du <code>MAC</code> (Les <code>4</code> à droite)
en utilisation de <a href="https://fr.wikipedia.org/wiki/Op%C3%A9ration_bit_%C3%A0_bit#AND" target="_blank" rel="noopener noreferrer" class="">opération bit à bit AND</a></p>
<p>En <a href="https://www.python.org/" target="_blank" rel="noopener noreferrer" class="">Python</a> <code>&amp;</code> peut être utilisé pour faire une opération binaire <code>AND</code> entre deux nombres. Avec la valeur <code>0x0F</code> (en hexadécimal et équivalent à <code>00001111</code> en binaire) on peut extraire deux <code>4</code> derniers bits. Étant donné que <code>offset</code> est un entier stocké sur <code>4</code> bits, la valeur est comprise entre <code>0</code> et <code>15</code>. En <a href="https://www.python.org/" target="_blank" rel="noopener noreferrer" class="">Python</a>, nous pouvons utiliser <code>mac[-1]</code> pour obtenir le dernier octet de la liste d'octets converti en entier.</p>
<div class="language-python codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-python codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">offset </span><span class="token operator">=</span><span class="token plain"> mac</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"> </span><span class="token operator">&amp;</span><span class="token plain"> </span><span class="token number">0x0F</span><br></div></code></pre></div></div>
<div class="language-python codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-python codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">mac</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token builtin" style="color:rgb(189, 147, 249)">bin</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">10110100</span><span class="token plain"> </span><span class="token number">11010010</span><span class="token plain"> </span><span class="token number">01111010</span><span class="token plain"> </span><span class="token number">10110100</span><span class="token plain"> </span><span class="token number">10111101</span><span class="token plain"> </span><span class="token number">00110101</span><span class="token plain"> </span><span class="token number">11111110</span><span class="token plain"> </span><span class="token number">00100011</span><span class="token plain"> </span><span class="token number">11101101</span><span class="token plain"> </span><span class="token number">01011001</span><span class="token plain"> </span><span class="token number">01111110</span><span class="token plain"> </span><span class="token number">10111100</span><span class="token plain"> </span><span class="token number">11110000</span><span class="token plain"> </span><span class="token number">01111001</span><span class="token plain"> </span><span class="token number">11000001</span><span class="token plain"> </span><span class="token number">01001010</span><span class="token plain"> </span><span class="token number">00000110</span><span class="token plain"> </span><span class="token number">01101100</span><span class="token plain"> </span><span class="token number">01010001</span><span class="token plain"> </span><span class="token number">00101111</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">mac</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token builtin" style="color:rgb(189, 147, 249)">hex</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> b4 d2 7a b4 bd </span><span class="token number">35</span><span class="token plain"> fe </span><span class="token number">23</span><span class="token plain"> ed </span><span class="token number">59</span><span class="token plain"> 7e bc f0 </span><span class="token number">79</span><span class="token plain"> c1 4a </span><span class="token number">06</span><span class="token plain"> 6c </span><span class="token number">51</span><span class="token plain"> 2f</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">offset</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token builtin" style="color:rgb(189, 147, 249)">bin</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">=</span><span class="token operator">&gt;</span><span class="token plain"> </span><span class="token number">1111</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">offset</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token builtin" style="color:rgb(189, 147, 249)">hex</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">=</span><span class="token operator">&gt;</span><span class="token plain"> f</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">offset</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">dec</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">=</span><span class="token operator">&gt;</span><span class="token plain"> </span><span class="token number">15</span><br></div></code></pre></div></div>
<h5 class="anchor anchorTargetStickyNavbar_SAay" id="recherche-de-la-troncation-dynamique">Recherche de la troncation dynamique<a href="https://lunik.tiwabbit.fr/blog/fr/understanding-totp#recherche-de-la-troncation-dynamique" class="hash-link" aria-label="Lien direct vers Recherche de la troncation dynamique" title="Lien direct vers Recherche de la troncation dynamique" translate="no">​</a></h5>
<p>En utilisant le <code>offset</code> trouvé précédemment, nous allons extraire la <code>Troncation dynamique</code> du <code>MAC</code>. Nous devons récupérer les <code>4</code> octets à la position <code>offset</code>, <code>offset+1</code>, <code>offset+2</code> et <code>offset+3</code> dans la liste d'octets <code>MAC</code>.</p>
<p>Nous avons :</p>
<div class="language-python codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-python codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">dynamic_truncation </span><span class="token operator">=</span><span class="token plain"> mac</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">offset</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">offset</span><span class="token operator">+</span><span class="token number">3</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">+</span><span class="token number">1</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><br></div></code></pre></div></div>
<p>En <a href="https://www.python.org/" target="_blank" rel="noopener noreferrer" class="">Python</a>, la valeur après le <code>:</code> n'est pas incluse. Afin d'extraire la valeur <code>offset + 3</code>, nous devons mettre <code>(offset + 3) + 1</code></p>
<div class="language-python codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-python codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">offset</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token builtin" style="color:rgb(189, 147, 249)">bin</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">1111</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">offset</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token builtin" style="color:rgb(189, 147, 249)">hex</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> f</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">offset</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">dec</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">15</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">offset</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">dec</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token number">15</span><span class="token plain"> to </span><span class="token number">18</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">mac</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token builtin" style="color:rgb(189, 147, 249)">bin</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">10110100</span><span class="token plain"> </span><span class="token number">11010010</span><span class="token plain"> </span><span class="token number">01111010</span><span class="token plain"> </span><span class="token number">10110100</span><span class="token plain"> </span><span class="token number">10111101</span><span class="token plain"> </span><span class="token number">00110101</span><span class="token plain"> </span><span class="token number">11111110</span><span class="token plain"> </span><span class="token number">00100011</span><span class="token plain"> </span><span class="token number">11101101</span><span class="token plain"> </span><span class="token number">01011001</span><span class="token plain"> </span><span class="token number">01111110</span><span class="token plain"> </span><span class="token number">10111100</span><span class="token plain"> </span><span class="token number">11110000</span><span class="token plain"> </span><span class="token number">01111001</span><span class="token plain"> </span><span class="token number">11000001</span><span class="token plain"> </span><span class="token number">01001010</span><span class="token plain"> </span><span class="token number">00000110</span><span class="token plain"> </span><span class="token number">01101100</span><span class="token plain"> </span><span class="token number">01010001</span><span class="token plain"> </span><span class="token number">00101111</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">mac</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token builtin" style="color:rgb(189, 147, 249)">hex</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> b4 d2 7a b4 bd </span><span class="token number">35</span><span class="token plain"> fe </span><span class="token number">23</span><span class="token plain"> ed </span><span class="token number">59</span><span class="token plain"> 7e bc f0 </span><span class="token number">79</span><span class="token plain"> c1 4a </span><span class="token number">06</span><span class="token plain"> 6c </span><span class="token number">51</span><span class="token plain"> 2f</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">dynamic_truncation</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token builtin" style="color:rgb(189, 147, 249)">bin</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">=</span><span class="token operator">&gt;</span><span class="token plain"> </span><span class="token number">10010100</span><span class="token plain"> </span><span class="token number">00001100</span><span class="token plain"> </span><span class="token number">11011000</span><span class="token plain"> </span><span class="token number">1010001</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">dynamic_truncation</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token builtin" style="color:rgb(189, 147, 249)">hex</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">=</span><span class="token operator">&gt;</span><span class="token plain"> 4a </span><span class="token number">06</span><span class="token plain"> 6c </span><span class="token number">51</span><br></div></code></pre></div></div>
<h5 class="anchor anchorTargetStickyNavbar_SAay" id="extraire-les-31-bits">Extraire les 31 bits<a href="https://lunik.tiwabbit.fr/blog/fr/understanding-totp#extraire-les-31-bits" class="hash-link" aria-label="Lien direct vers Extraire les 31 bits" title="Lien direct vers Extraire les 31 bits" translate="no">​</a></h5>
<p>Enfin, nous allons extraire les <code>31</code> bits les moins significatifs de notre <code>Dynamic Truncation</code>
La solution serait de convertir la liste d'octets de résultat en une longueur non signée qui est de <code>32</code> bits avec le bit le plus significatif (à gauche) contenant la valeur signée (<code>+</code> ou <code>-</code>).
En utilisant la même astuce que précédemment, nous utilisons une <a href="https://fr.wikipedia.org/wiki/Op%C3%A9ration_bit_%C3%A0_bit#AND" target="_blank" rel="noopener noreferrer" class="">opération bit à bit AND</a> pour les extraire.
<code>0x7fffffff</code> (en hexadécimal et équivalent à <code>01111111 11111111 11111111 11111111</code> en binaire). Résultant en une valeur de <code>31</code> bits en ignorant le <code>0</code> en tête.</p>
<div class="language-python codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-python codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)"># https://docs.python.org/3/library/struct.html#struct.unpack</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">extract_31 </span><span class="token operator">=</span><span class="token plain"> struct</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">unpack</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">'&gt;L'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> dynamic_truncation</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token number">0</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"> </span><span class="token operator">&amp;</span><span class="token plain"> </span><span class="token number">0x7fffffff</span><br></div></code></pre></div></div>
<div class="language-python codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-python codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">dynamic_truncation</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token builtin" style="color:rgb(189, 147, 249)">bin</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">10010100</span><span class="token plain"> </span><span class="token number">00001100</span><span class="token plain"> </span><span class="token number">11011000</span><span class="token plain"> </span><span class="token number">1010001</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">dynamic_truncation</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token builtin" style="color:rgb(189, 147, 249)">hex</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> 4a </span><span class="token number">06</span><span class="token plain"> 6c </span><span class="token number">51</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">extract_31</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token builtin" style="color:rgb(189, 147, 249)">bin</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">=</span><span class="token operator">&gt;</span><span class="token plain"> </span><span class="token number">10010100</span><span class="token plain"> </span><span class="token number">00001100</span><span class="token plain"> </span><span class="token number">11011000</span><span class="token plain"> </span><span class="token number">1010001</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">extract_31</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token builtin" style="color:rgb(189, 147, 249)">hex</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">=</span><span class="token operator">&gt;</span><span class="token plain"> 4a </span><span class="token number">06</span><span class="token plain"> 6c </span><span class="token number">51</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">extract_31</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">dec</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">=</span><span class="token operator">&gt;</span><span class="token plain"> </span><span class="token number">1241934929</span><br></div></code></pre></div></div>
<h5 class="anchor anchorTargetStickyNavbar_SAay" id="chiffres-tronqués">Chiffres tronqués<a href="https://lunik.tiwabbit.fr/blog/fr/understanding-totp#chiffres-tronqu%C3%A9s" class="hash-link" aria-label="Lien direct vers Chiffres tronqués" title="Lien direct vers Chiffres tronqués" translate="no">​</a></h5>
<p>Maintenant que nous avons notre nombre final après avoir extrait les derniers <code>31</code> bits, nous devons cette fois tronquer la valeur décimale. Sur la base de la valeur <code>digits</code> configurée, nous voulons uniquement conserver les <code>X</code> derniers chiffres de la valeur décimale de <code>extract_31</code>.
<code>X</code> est la longueur du code <a href="https://fr.wikipedia.org/wiki/Mot_de_passe_%C3%A0_usage_unique_bas%C3%A9_sur_le_temps" target="_blank" rel="noopener noreferrer" class="">TOTP</a> que nous voulons et doit être comprise entre <code>6</code> et <code>10</code>.
<code>6</code> minimum en raison des exigences de sécurité et <code>10</code> maximum car la valeur maximale d'un entier signé <code>32</code> bits est <code>2147483647</code>, une valeur numérique <code>10</code>.</p>
<p>L'utilisation d'une longueur de <code>10</code> sur <code>9</code> n'ajoute pas beaucoup de sécurité car le premier chiffre ne peut prendre que les valeurs <code>0</code>, <code>1</code>, <code>2</code>.</p>
<div class="language-python codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-python codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">digits_count </span><span class="token operator">=</span><span class="token plain"> </span><span class="token number">6</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">hotp </span><span class="token operator">=</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">extract_31</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token operator">-</span><span class="token plain">digits_count</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><br></div></code></pre></div></div>
<div class="language-python codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-python codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">extract_31</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">dec</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">1241934929</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">digits_count</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">6</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">hotp </span><span class="token operator">=</span><span class="token operator">&gt;</span><span class="token plain"> </span><span class="token number">934929</span><br></div></code></pre></div></div>
<p>Dans le cas où <code>extract_31</code> est une valeur trop faible où le nombre de chiffres est inférieur au nombre <code>digits</code>, nous ajoutons des <code>0</code> au début à gauche du code <a href="https://en.wikipedia.org/wiki/HMAC-based_one-time_password" target="_blank" rel="noopener noreferrer" class="">HOTP</a> pour lui donner la bonne longueur.</p>
<div class="language-python codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-python codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">hotp </span><span class="token operator">=</span><span class="token plain"> hotp</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">zfill</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">digits_count</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></div></code></pre></div></div>
<div class="language-python codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-python codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">hotp</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">934929</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">hotp </span><span class="token operator">=</span><span class="token operator">&gt;</span><span class="token plain"> </span><span class="token number">934929</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="conclusion">Conclusion<a href="https://lunik.tiwabbit.fr/blog/fr/understanding-totp#conclusion" class="hash-link" aria-label="Lien direct vers Conclusion" title="Lien direct vers Conclusion" translate="no">​</a></h2>
<p>Maintenant, vous savez vraiment comment les codes <a href="https://fr.wikipedia.org/wiki/Mot_de_passe_%C3%A0_usage_unique_bas%C3%A9_sur_le_temps" target="_blank" rel="noopener noreferrer" class="">TOTP</a> sont générés. Comme on peut le voir, c'est assez simple et vous pouvez développer votre propre script pour les générer.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="code-complet">Code complet<a href="https://lunik.tiwabbit.fr/blog/fr/understanding-totp#code-complet" class="hash-link" aria-label="Lien direct vers Code complet" title="Lien direct vers Code complet" translate="no">​</a></h2>
<div class="language-python codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-python codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> base64</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> hmac</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> struct</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> time</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">hotp</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">counter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> key</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> digits_count</span><span class="token operator">=</span><span class="token number">6</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  bytes_counter </span><span class="token operator">=</span><span class="token plain"> struct</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">pack</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">'&gt;Q'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> counter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  key </span><span class="token operator">=</span><span class="token plain"> key </span><span class="token operator">+</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">'='</span><span class="token plain"> </span><span class="token operator">*</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token number">8</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">len</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">key</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">%</span><span class="token plain"> </span><span class="token number">8</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  bytes_key </span><span class="token operator">=</span><span class="token plain"> base64</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">b32decode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">key</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  mac </span><span class="token operator">=</span><span class="token plain"> hmac</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">new</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">bytes_key</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> bytes_counter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"SHA1"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">digest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  offset </span><span class="token operator">=</span><span class="token plain"> mac</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"> </span><span class="token operator">&amp;</span><span class="token plain"> </span><span class="token number">0x0F</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  dynamic_truncation </span><span class="token operator">=</span><span class="token plain"> mac</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">offset</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">offset</span><span class="token operator">+</span><span class="token number">4</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  extract_31 </span><span class="token operator">=</span><span class="token plain"> struct</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">unpack</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">'&gt;L'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> dynamic_truncation</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token number">0</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"> </span><span class="token operator">&amp;</span><span class="token plain"> </span><span class="token number">0x7fffffff</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">extract_31</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token operator">-</span><span class="token plain">digits_count</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">zfill</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">digits_count</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">totp</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">key</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  counter </span><span class="token operator">=</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">int</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">time</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">time</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">/</span><span class="token plain"> </span><span class="token number">30</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> hotp</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">counter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> key</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> __name__ </span><span class="token operator">==</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"__main__"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  key </span><span class="token operator">=</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">input</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Enter secret key : "</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">upper</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">print</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"TOTP code :"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> totp</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">key</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="références">Références<a href="https://lunik.tiwabbit.fr/blog/fr/understanding-totp#r%C3%A9f%C3%A9rences" class="hash-link" aria-label="Lien direct vers Références" title="Lien direct vers Références" translate="no">​</a></h2>
<ul>
<li class="">
<p><a href="https://tools.ietf.org/html/rfc6238" target="_blank" rel="noopener noreferrer" class="">TOTP: Time-Based One-Time Password Algorithm</a></p>
</li>
<li class="">
<p><a href="https://tools.ietf.org/html/rfc4226" target="_blank" rel="noopener noreferrer" class="">HOTP: An HMAC-Based One-Time Password Algorithm</a></p>
</li>
<li class="">
<p><a href="https://tools.ietf.org/html/rfc4648" target="_blank" rel="noopener noreferrer" class="">The Base16, Base32, and Base64 Data Encodings</a></p>
</li>
<li class="">
<p><a href="https://tools.ietf.org/html/rfc2104" target="_blank" rel="noopener noreferrer" class="">HMAC: Keyed-Hashing for Message Authentication</a></p>
</li>
<li class="">
<p><a href="https://tools.ietf.org/html/rfc3174" target="_blank" rel="noopener noreferrer" class="">US Secure Hash Algorithm 1 (SHA1)</a></p>
</li>
<li class="">
<p><a href="https://en.wikipedia.org/wiki/Multi-factor_authentication" target="_blank" rel="noopener noreferrer" class="">Multi-factor authentication</a></p>
</li>
<li class="">
<p><a href="https://fr.wikipedia.org/wiki/Mot_de_passe_%C3%A0_usage_unique_bas%C3%A9_sur_le_temps" target="_blank" rel="noopener noreferrer" class="">Mot de passe à usage unique basé sur le temps</a></p>
</li>
<li class="">
<p><a href="https://en.wikipedia.org/wiki/HMAC-based_one-time_password" target="_blank" rel="noopener noreferrer" class="">HMAC-based one-time password</a></p>
</li>
<li class="">
<p><a href="https://fr.wikipedia.org/wiki/Code_QR" target="_blank" rel="noopener noreferrer" class="">Code QR</a></p>
</li>
<li class="">
<p><a href="https://fr.wikipedia.org/wiki/SHA-1" target="_blank" rel="noopener noreferrer" class="">SHA-1</a></p>
</li>
<li class="">
<p><a href="https://fr.wikipedia.org/wiki/Op%C3%A9ration_bit_%C3%A0_bit#AND" target="_blank" rel="noopener noreferrer" class="">Opération bit à bit</a></p>
</li>
<li class="">
<p><a href="https://fr.wikipedia.org/wiki/Epoch" target="_blank" rel="noopener noreferrer" class="">epoch</a></p>
</li>
<li class="">
<p><a href="https://docs.python.org/3/library/hmac.html" target="_blank" rel="noopener noreferrer" class="">Python HMAC lib</a></p>
</li>
</ul>]]></content>
        <author>
            <name>Guillaume MARTINEZ</name>
            <uri>https://github.com/Lunik</uri>
        </author>
        <category label="security" term="security"/>
        <category label="2fa" term="2fa"/>
        <category label="totp" term="totp"/>
        <category label="two-factor" term="two-factor"/>
        <category label="authentication" term="authentication"/>
        <category label="otp" term="otp"/>
        <category label="hmac" term="hmac"/>
        <category label="hotp" term="hotp"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Gestion de certificats x509]]></title>
        <id>https://lunik.tiwabbit.fr/blog/fr/manage-x509-certs</id>
        <link href="https://lunik.tiwabbit.fr/blog/fr/manage-x509-certs"/>
        <updated>2022-02-06T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Présentation et gestion d'une authorité de certification racine]]></summary>
        <content type="html"><![CDATA[<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2022-02-06-manage-x509-certs/cover.png" alt="cover" class="img__Ss2"></p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="que-sont-les-certificats-x509-">Que sont les certificats x509 ?<a href="https://lunik.tiwabbit.fr/blog/fr/manage-x509-certs#que-sont-les-certificats-x509-" class="hash-link" aria-label="Lien direct vers Que sont les certificats x509 ?" title="Lien direct vers Que sont les certificats x509 ?" translate="no">​</a></h2>
<p><a href="https://fr.wikipedia.org/wiki/X.509" target="_blank" rel="noopener noreferrer" class="">D'après Wikipedia</a>, <a href="https://datatracker.ietf.org/doc/html/rfc5280" target="_blank" rel="noopener noreferrer" class="">x509</a> est une norme définissant le format des certificats de type clé publique. Ils sont utilisés dans de nombreux protocoles Internet, dont <a href="https://datatracker.ietf.org/doc/html/rfc8446" target="_blank" rel="noopener noreferrer" class="">TLS/SSL</a>, qui est à la base de <a href="https://datatracker.ietf.org/doc/html/rfc2818" target="_blank" rel="noopener noreferrer" class="">HTTPS</a> (le protocole de navigation sécurisé sur le Web).</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="but">But<a href="https://lunik.tiwabbit.fr/blog/fr/manage-x509-certs#but" class="hash-link" aria-label="Lien direct vers But" title="Lien direct vers But" translate="no">​</a></h2>
<p>Le but d'avoir ma propre autorité de certification (CA) me permet de générer des certificats auto-signés pour des utilisations non publiques. Mes services étant hébergés sur mon propre réseau privé m'empêchent d'obtenir des certificats gratuits de la populaire autorité certification <a href="https://letsencrypt.org/" target="_blank" rel="noopener noreferrer" class="">Let's Encrypt</a>.</p>
<p>Vu que j'héberge plus d'un service et que je veux que tous mes appareils (ordinateur portable, téléphone, ...) puissent y avoir accès sans avoir à installer de certificat toutes les 3 semaines (lorsque je mets à jour les noms d'hôtes par exemple). J'ai décidé de créer ma propre autorité de certification et de générer des certificats signés et validés par celle-là. De cette façon, je n'ai qu'à installer l'autorité de certification racine sur tous mes appareils pour que cela fonctionne.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="création-de-ma-propre-autorité-de-certification">Création de ma propre autorité de certification<a href="https://lunik.tiwabbit.fr/blog/fr/manage-x509-certs#cr%C3%A9ation-de-ma-propre-autorit%C3%A9-de-certification" class="hash-link" aria-label="Lien direct vers Création de ma propre autorité de certification" title="Lien direct vers Création de ma propre autorité de certification" translate="no">​</a></h2>
<p>Tout ce dont j'ai besoin est un environnement Linux et <a href="https://www.openssl.org/" target="_blank" rel="noopener noreferrer" class=""><code>openssl</code></a>.</p>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="génération-du-secret">Génération du secret<a href="https://lunik.tiwabbit.fr/blog/fr/manage-x509-certs#g%C3%A9n%C3%A9ration-du-secret" class="hash-link" aria-label="Lien direct vers Génération du secret" title="Lien direct vers Génération du secret" translate="no">​</a></h3>
<p>Tout d'abord je génère la clé privée avec la commande suivante :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">openssl genrsa </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-out</span><span class="token plain"> root-CA.key </span><span class="token number">4096</span><br></div></code></pre></div></div>
<p>Résultat :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">Generating RSA private key, </span><span class="token number">4096</span><span class="token plain"> bit long modulus</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token plain">.++</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token plain">++</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">e is </span><span class="token number">65537</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">0x10001</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></div></code></pre></div></div>
<p>J'ai maintenant une belle clé privée :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">-----BEGIN RSA PRIVATE KEY-----</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">MIIJKAIBAAKCAgEA2IxiR6U/B6Ypd1/3KG5Pxk/BY47HzHpBAHnEFsMHdcpCNNXO</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">GxqhUsIHBGMc0I2xa0WiyNJB4k5qGwL58J1TK/kKaW8yOOGajawvhjL/6bYXgN1I</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token plain">.</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">rcL3YJyl/m0mlYl80syPPViHM9TD7uwQi/M9DPeOGLwVuCYzpl3qAkQRaTwQc2Ev</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">5hffBNz+evhf2Q7iUCmWQFizIFlFpOCq1f/jvpleqf8ChG6EhNRgvAFIUMc</span><span class="token operator">=</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">-----END RSA PRIVATE KEY-----</span><br></div></code></pre></div></div>
<p><strong>Ce fichier doit être gardé secret et stocké de manière sécurisé hors ligne.</strong></p>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="génération-de-la-configuration-du-certificat">Génération de la configuration du certificat<a href="https://lunik.tiwabbit.fr/blog/fr/manage-x509-certs#g%C3%A9n%C3%A9ration-de-la-configuration-du-certificat" class="hash-link" aria-label="Lien direct vers Génération de la configuration du certificat" title="Lien direct vers Génération de la configuration du certificat" translate="no">​</a></h3>
<p>Maintenant que j'ai la partie secrète, je dois générer la partie publique : le <a href="https://datatracker.ietf.org/doc/html/rfc5280" target="_blank" rel="noopener noreferrer" class="">certificat x509</a>. En utilisant de la <a href="https://github.com/openssl/openssl/blob/master/apps/openssl.cnf" target="_blank" rel="noopener noreferrer" class="">configuration OpenSSL par défaut</a> :</p>
<div class="language-toml codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-toml codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">[ req ]</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">default_bits       = 4096</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">default_keyfile    = root-CA.key</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">encrypt_key        = no</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">utf8               = yes</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">distinguished_name = req_distinguished_name</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">prompt             = no</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">x509_extensions    = v3_ca</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">[ req_distinguished_name ]</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">countryName         = FR</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">stateOrProvinceName = France</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">localityName        = Paris</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">organizationName    = Example</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">commonName          = example.org</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">[ v3_ca ]</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">subjectKeyIdentifier = hash</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">basicConstraints     = critical,CA:true,pathlen:1</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">keyUsage             = critical,keyCertSign</span><br></div></code></pre></div></div>
<p>Cette configuration doit être conservée pour la prochaine fois que je dois regénérer le certificat racine. Gardez à l'esprit que ce certificat ne doit pas être modifié trop souvent, sinon cela rendrait l'objectif principal inutile.</p>
<p>Vous pouvez ajuster cette configuration en fonction de vos besoins.</p>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="génération-du-certificat-racine">Génération du certificat racine<a href="https://lunik.tiwabbit.fr/blog/fr/manage-x509-certs#g%C3%A9n%C3%A9ration-du-certificat-racine" class="hash-link" aria-label="Lien direct vers Génération du certificat racine" title="Lien direct vers Génération du certificat racine" translate="no">​</a></h3>
<p>En utilisant la configuration précédente, j'ai généré l'autorité de certification racine auto-signée :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">openssl req </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-x509</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-new</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-nodes</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-config</span><span class="token plain"> root-CA-openssl.cnf </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-key</span><span class="token plain"> root-CA.key </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-sha256</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-days</span><span class="token plain"> </span><span class="token number">1024</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-out</span><span class="token plain"> root-CA.crt</span><br></div></code></pre></div></div>
<p>Vérification du contenu du certificat :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">openssl x509 </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-in</span><span class="token plain"> root-CA.crt </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-noout</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-text</span><br></div></code></pre></div></div>
<p>Résultat :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">Certificate:</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    Data:</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        Version: </span><span class="token number">1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">0x0</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        Serial Number: </span><span class="token number">11676879669831540892</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">0xa20c9c31654a209c</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    Signature Algorithm: sha256WithRSAEncryption</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        Issuer: </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">C</span><span class="token operator">=</span><span class="token plain">FR, </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">ST</span><span class="token operator">=</span><span class="token plain">France, </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">L</span><span class="token operator">=</span><span class="token plain">Paris, </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">O</span><span class="token operator">=</span><span class="token plain">Example, </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">CN</span><span class="token operator">=</span><span class="token plain">example.org</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        Validity</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            Not Before: Feb  </span><span class="token number">6</span><span class="token plain"> </span><span class="token number">15</span><span class="token plain">:53:58 </span><span class="token number">2022</span><span class="token plain"> GMT</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            Not After </span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">:</span><span class="token plain"> Nov </span><span class="token number">26</span><span class="token plain"> </span><span class="token number">15</span><span class="token plain">:53:58 </span><span class="token number">2024</span><span class="token plain"> GMT</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        Subject: </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">C</span><span class="token operator">=</span><span class="token plain">FR, </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">ST</span><span class="token operator">=</span><span class="token plain">France, </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">L</span><span class="token operator">=</span><span class="token plain">Paris, </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">O</span><span class="token operator">=</span><span class="token plain">Example, </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">CN</span><span class="token operator">=</span><span class="token plain">example.org</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token plain">.</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        X509v3 extensions:</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            X509v3 Subject Key Identifier: </span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">                F1:FA:C4:50:A4:7F:53:D3:6C:D5:EF:48:72:24:B8:CE:08:10:3F:94</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            X509v3 Basic Constraints: critical</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">                CA:TRUE, pathlen:1</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            X509v3 Key Usage: critical</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">                Certificate Sign</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token plain">.</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><br></div></code></pre></div></div>
<p>Cette commande génère le fichier certificat et signe son contenu avec la clé privée.</p>
<p>J'ai maintenant un certificat d'autorité, je peux générer tous les certificats de mes applications et les signer avec.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="créer-des-certificats-pour-mes-applications">Créer des certificats pour mes applications<a href="https://lunik.tiwabbit.fr/blog/fr/manage-x509-certs#cr%C3%A9er-des-certificats-pour-mes-applications" class="hash-link" aria-label="Lien direct vers Créer des certificats pour mes applications" title="Lien direct vers Créer des certificats pour mes applications" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="génération-du-secret-1">Génération du secret<a href="https://lunik.tiwabbit.fr/blog/fr/manage-x509-certs#g%C3%A9n%C3%A9ration-du-secret-1" class="hash-link" aria-label="Lien direct vers Génération du secret" title="Lien direct vers Génération du secret" translate="no">​</a></h3>
<p>Comme pour l'autorité de certification racine, j'ai besoin de générer une clé secrète.</p>
<p>Je peux utiliser une commande identique à précédemment :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">openssl genrsa </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-out</span><span class="token plain"> my-app.key </span><span class="token number">2048</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="génération-de-la-configuration-openssl">Génération de la configuration openssl<a href="https://lunik.tiwabbit.fr/blog/fr/manage-x509-certs#g%C3%A9n%C3%A9ration-de-la-configuration-openssl" class="hash-link" aria-label="Lien direct vers Génération de la configuration openssl" title="Lien direct vers Génération de la configuration openssl" translate="no">​</a></h3>
<p>Je dois maintenant créer la configuration OpenSSL pour mon certificat en utilisant la <a href="https://github.com/openssl/openssl/blob/master/apps/openssl.cnf" target="_blank" rel="noopener noreferrer" class="">configuration OpenSSL par défaut</a> :</p>
<div class="language-toml codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-toml codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">[ req ]</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">default_bits       = 2048</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">default_keyfile    = my-app.key</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">encrypt_key        = no</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">utf8               = yes</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">distinguished_name = req_distinguished_name</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">req_extensions     = v3_req</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">prompt             = no</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">[ req_distinguished_name ]</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">countryName         = FR</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">stateOrProvinceName = France</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">localityName        = Paris</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">organizationName    = Example</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">commonName          = my-app.example.org</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">[v3_req]</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">subjectKeyIdentifier = hash</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">subjectAltName       = @alt_names</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">[ alt_names ]</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">DNS.1 = my-app.example.org</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">DNS.2 = extra.my-app.example.org</span><br></div></code></pre></div></div>
<p>Notez ici que le paramètre <code>subjectAltName</code> et les <code>alt_names</code> sont très importants. Désormais, chaque navigateur ou application sur téléphone nécessite que le nom d'hôte exposé par l'application Web soit spécifié dans cette section.</p>
<p>Vous pouvez toujours ajouter plusieurs noms alternatifs au certificat. Cela vous permet d'utiliser le même certificat pour plusieurs applications. <strong>Assurez-vous d'utiliser un certificat différent en fonction du niveau de sécurité dont vous avez besoin pour vos applications.</strong></p>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="génération-de-la-demande-de-certificat">Génération de la demande de certificat<a href="https://lunik.tiwabbit.fr/blog/fr/manage-x509-certs#g%C3%A9n%C3%A9ration-de-la-demande-de-certificat" class="hash-link" aria-label="Lien direct vers Génération de la demande de certificat" title="Lien direct vers Génération de la demande de certificat" translate="no">​</a></h3>
<p>Afin de générer un certificat signé par mon autorité de certification racine, je dois générer une demande de certificat.
À l'aide de la commande suivante, je peux générer la requête et la signer avec la clé privée de l'application :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">openssl req </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-sha256</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-new</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-key</span><span class="token plain"> my-app.key </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-config</span><span class="token plain"> my-app.cnf </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-out</span><span class="token plain"> my-app.csr</span><br></div></code></pre></div></div>
<p>Je peux vérifier le contenu de ma demande avec :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">openssl req </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-in</span><span class="token plain"> my-app.csr </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-noout</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-text</span><br></div></code></pre></div></div>
<p>Résultat :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">Certificate Request:</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    Data:</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        Version: </span><span class="token number">0</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">0x0</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        Subject: </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">C</span><span class="token operator">=</span><span class="token plain">FR, </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">ST</span><span class="token operator">=</span><span class="token plain">France, </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">L</span><span class="token operator">=</span><span class="token plain">Paris, </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">O</span><span class="token operator">=</span><span class="token plain">Example, </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">CN</span><span class="token operator">=</span><span class="token plain">my-app.example.org</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token plain">.</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="signer-mon-certificat-dapplication-avec-lautorité-de-certification-racine">Signer mon certificat d'application avec l'autorité de certification racine<a href="https://lunik.tiwabbit.fr/blog/fr/manage-x509-certs#signer-mon-certificat-dapplication-avec-lautorit%C3%A9-de-certification-racine" class="hash-link" aria-label="Lien direct vers Signer mon certificat d'application avec l'autorité de certification racine" title="Lien direct vers Signer mon certificat d'application avec l'autorité de certification racine" translate="no">​</a></h3>
<p>Enfin, je dois utiliser mon autorité de certification racine pour générer mon certificat d'application en fonction de la demande et garantir son authenticité.</p>
<p>J'ai seulement besoin d'utiliser la commande suivante :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">openssl x509 </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-req</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-CA</span><span class="token plain"> root-CA.crt </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-CAkey</span><span class="token plain"> root-CA.key </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-CAcreateserial</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-in</span><span class="token plain"> my-app.csr </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-days</span><span class="token plain"> </span><span class="token number">500</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-sha256</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-out</span><span class="token plain"> my-app.crt</span><br></div></code></pre></div></div>
<p>Pour vérifier le contenu du certificat nouvellement généré, je peux exécuter la commande suivante :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">openssl x509 </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-in</span><span class="token plain"> my-app.crt </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-noout</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-text</span><br></div></code></pre></div></div>
<p>Résultat :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">Certificate:</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    Data:</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        Version: </span><span class="token number">1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">0x0</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        Serial Number: </span><span class="token number">15807445207358136962</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">0xdb5f53aa27086282</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    Signature Algorithm: sha256WithRSAEncryption</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        Issuer: </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">C</span><span class="token operator">=</span><span class="token plain">FR, </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">ST</span><span class="token operator">=</span><span class="token plain">France, </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">L</span><span class="token operator">=</span><span class="token plain">Paris, </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">O</span><span class="token operator">=</span><span class="token plain">Example, </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">CN</span><span class="token operator">=</span><span class="token plain">example.org</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        Validity</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            Not Before: Feb  </span><span class="token number">6</span><span class="token plain"> </span><span class="token number">16</span><span class="token plain">:22:38 </span><span class="token number">2022</span><span class="token plain"> GMT</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            Not After </span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">:</span><span class="token plain"> Jun </span><span class="token number">21</span><span class="token plain"> </span><span class="token number">16</span><span class="token plain">:22:38 </span><span class="token number">2023</span><span class="token plain"> GMT</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        Subject: </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">C</span><span class="token operator">=</span><span class="token plain">FR, </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">ST</span><span class="token operator">=</span><span class="token plain">France, </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">L</span><span class="token operator">=</span><span class="token plain">Paris, </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">O</span><span class="token operator">=</span><span class="token plain">Example, </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">CN</span><span class="token operator">=</span><span class="token plain">my-app.example.org</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="vérification-de-la-chaîne-de-confiance-complète">Vérification de la chaîne de confiance complète<a href="https://lunik.tiwabbit.fr/blog/fr/manage-x509-certs#v%C3%A9rification-de-la-cha%C3%AEne-de-confiance-compl%C3%A8te" class="hash-link" aria-label="Lien direct vers Vérification de la chaîne de confiance complète" title="Lien direct vers Vérification de la chaîne de confiance complète" translate="no">​</a></h3>
<p>Maintenant que j'ai le certificat de mon application, je dois m'assurer que l'autorité de certification racine en valide l'authenticité.</p>
<p>En utilisant une dernière commande <code>openssl</code> :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">openssl verify </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-CAfile</span><span class="token plain"> root-CA.crt </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  my-app.crt</span><br></div></code></pre></div></div>
<p>Résultat :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">my-app.crt: OK</span><br></div></code></pre></div></div>]]></content>
        <author>
            <name>Guillaume MARTINEZ</name>
            <uri>https://github.com/Lunik</uri>
        </author>
        <category label="certificate" term="certificate"/>
        <category label="openssl" term="openssl"/>
        <category label="x509" term="x509"/>
        <category label="private_key" term="private_key"/>
        <category label="public_key" term="public_key"/>
        <category label="rsa" term="rsa"/>
        <category label="pem" term="pem"/>
        <category label="cert" term="cert"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Creation et exposition d'un service DNS publique]]></title>
        <id>https://lunik.tiwabbit.fr/blog/fr/create-public-dns-service</id>
        <link href="https://lunik.tiwabbit.fr/blog/fr/create-public-dns-service"/>
        <updated>2021-12-24T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[J'explique comment j'ai créé et exposé un service DNS publique]]></summary>
        <content type="html"><![CDATA[<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2021-12-24-create-public-dns-service/cover.png" alt="cover" class="img__Ss2"></p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="quest-ce-que-le-dns-">Qu'est-ce que le DNS ?<a href="https://lunik.tiwabbit.fr/blog/fr/create-public-dns-service#quest-ce-que-le-dns-" class="hash-link" aria-label="Lien direct vers Qu'est-ce que le DNS ?" title="Lien direct vers Qu'est-ce que le DNS ?" translate="no">​</a></h2>
<p>Le <a href="https://tools.ietf.org/html/rfc2929" target="_blank" rel="noopener noreferrer" class="">Domain Name System (DNS)</a> est un système qui fournit des noms lisibles par l'homme pour les ordinateurs, services et autres ressources connectés à Internet. Les enregistrements de base permettent de traduire un <a href="https://fr.wikipedia.org/wiki/Nom_de_domaine" target="_blank" rel="noopener noreferrer" class="">Nom de domaine</a> (que les humains peuvent comprendre) en une <a href="https://fr.wikipedia.org/wiki/Adresse_IP" target="_blank" rel="noopener noreferrer" class="">IP Address</a> (que l'ordinateur comprend pour le routage).</p>
<p><a href="https://tools.ietf.org/html/rfc2929" target="_blank" rel="noopener noreferrer" class="">DNS</a> est utilisé tout le temps, comme en ce moment, pour accéder à ce blog, votre ordinateur fait une requête <a href="https://tools.ietf.org/html/rfc2929" target="_blank" rel="noopener noreferrer" class="">DNS</a> pour traduire <code>lunik.tiwabbit.fr</code> en une [IP] [adresse-ip-wikipedia]. Ensuite, il a demandé la page Web à l'<a href="https://fr.wikipedia.org/wiki/Adresse_IP" target="_blank" rel="noopener noreferrer" class="">adresse IP</a> résolue par la requête <a href="https://tools.ietf.org/html/rfc2929" target="_blank" rel="noopener noreferrer" class="">DNS</a>.
Vous pouvez visualiser ce comportement en ouvrant la <a href="https://en.wikipedia.org/wiki/Web_development_tools" target="_blank" rel="noopener noreferrer" class="">console développeur</a> sur votre navigateur web :</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2021-12-24-create-public-dns-service/dns_safari_debug.jpg" alt="blog-dns-debug-through-developper-console" class="img__Ss2"></p>
<div class="theme-admonition theme-admonition-warning admonition_IZjC alert alert--warning"><div class="admonitionHeading_uVvU"><span class="admonitionIcon_HiR3"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>attention</div><div class="admonitionContent_bl22"><p>Toutes les adresses IP et les noms <a href="https://tools.ietf.org/html/rfc2929" target="_blank" rel="noopener noreferrer" class="">DNS</a> utilisés dans cet article de blog ne sont plus utilisés par mon projet. S'il vous plaît, ignorez-les.</p></div></div>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="faire-une-requête-dns">Faire une requête DNS<a href="https://lunik.tiwabbit.fr/blog/fr/create-public-dns-service#faire-une-requ%C3%AAte-dns" class="hash-link" aria-label="Lien direct vers Faire une requête DNS" title="Lien direct vers Faire une requête DNS" translate="no">​</a></h3>
<p>Vous pouvez effectuer une requête de base <a href="https://tools.ietf.org/html/rfc2929" target="_blank" rel="noopener noreferrer" class="">DNS</a> en utilisant <code>nslookup</code> sur votre terminal :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">nslookup</span><span class="token plain"> lunik.tiwabbit.fr</span><br></div></code></pre></div></div>
<p>Vous obtiendrez quelque chose comme :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">Nom </span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">:</span><span class="token plain"> lunik.tiwabbit.fr</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">Adresse </span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">:</span><span class="token plain"> </span><span class="token number">13.224</span><span class="token plain">.247.30</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">Nom </span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">:</span><span class="token plain"> lunik.tiwabbit.fr</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">Adresse </span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">:</span><span class="token plain"> </span><span class="token number">13.224</span><span class="token plain">.247.31</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">Nom </span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">:</span><span class="token plain"> lunik.tiwabbit.fr</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">Adresse </span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">:</span><span class="token plain"> </span><span class="token number">13.224</span><span class="token plain">.247.51</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">Nom </span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">:</span><span class="token plain"> lunik.tiwabbit.fr</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">Adresse </span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">:</span><span class="token plain"> </span><span class="token number">13.224</span><span class="token plain">.247.100</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="où-déployer-le-service-">Où déployer le service ?<a href="https://lunik.tiwabbit.fr/blog/fr/create-public-dns-service#o%C3%B9-d%C3%A9ployer-le-service-" class="hash-link" aria-label="Lien direct vers Où déployer le service ?" title="Lien direct vers Où déployer le service ?" translate="no">​</a></h2>
<p>J'ai décidé d'héberger mon service <a href="https://tools.ietf.org/html/rfc2929" target="_blank" rel="noopener noreferrer" class="">DNS</a> sur un fournisseur de cloud public nommé <a href="https://www.scaleway.com/fr/elements/" target="_blank" rel="noopener noreferrer" class="">Scaleway</a>.</p>
<p>Voici une vue globale de l'architecture :</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2021-12-24-create-public-dns-service/scaleway-arch.jpg" alt="scalway-architecture" class="img__Ss2"></p>
<p>J'ai décidé d'exposer deux serveurs publics <a href="https://tools.ietf.org/html/rfc2929" target="_blank" rel="noopener noreferrer" class="">DNS</a> un dans chaque région : France (Paris 1) et Pays-Bas (Amsterdam 1).</p>
<p>J'ai choisi ces deux régions car elles sont les seules à proposer des <a href="https://www.scaleway.com/fr/stardust-instances/" target="_blank" rel="noopener noreferrer" class="">instances Stardust</a>. Les serveurs <a href="https://tools.ietf.org/html/rfc2929" target="_blank" rel="noopener noreferrer" class="">DNS</a> ne nécessitent pas une tonne de ressources, cela me permet de réduire le coût du projet au minimum.</p>
<p>Les deux serveurs sont exposés avec des adresses publiques <code>flexible</code> <a href="https://fr.wikipedia.org/wiki/Adresse_IP" target="_blank" rel="noopener noreferrer" class="">IP</a> (une <a href="https://fr.wikipedia.org/wiki/IPv4" target="_blank" rel="noopener noreferrer" class="">v4</a> et une <a href="https://fr.wikipedia.org/wiki/IPv6" target="_blank" rel="noopener noreferrer" class="">v6</a> chacune) qui peuvent être résolues via deux entrées <a href="https://tools.ietf.org/html/rfc2929" target="_blank" rel="noopener noreferrer" class="">DNS</a> pour plus de commodité.</p>
<p>La sécurité était ma principale préoccupation, j'ai donc mis en place un groupe de sécurité sur mes instances me permettant de filtrer le trafic entrant et sortant.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="déploiement-de-linfrastructure">Déploiement de l'infrastructure<a href="https://lunik.tiwabbit.fr/blog/fr/create-public-dns-service#d%C3%A9ploiement-de-linfrastructure" class="hash-link" aria-label="Lien direct vers Déploiement de l'infrastructure" title="Lien direct vers Déploiement de l'infrastructure" translate="no">​</a></h2>
<p>Maintenant que je sais quelle architecture je veux pour le service. Je dois le déployer sur le fournisseur de cloud.
J'ai décidé d'utiliser <a href="https://www.scaleway.com/fr/terraform/" target="_blank" rel="noopener noreferrer" class="">Terraform</a> pour créer toutes les ressources et les lier ensemble.</p>
<p>ça a été assez simple de créer ma ressource en suivant la <a href="https://registry.terraform.io/providers/scaleway/scaleway/latest" target="_blank" rel="noopener noreferrer" class="">documentation Terraform</a>. Après 1 heure j'avais le code nécessaire. Il ne me restait plus qu'à l'appliquer.</p>
<p>Voici à quoi ressemblait le <code>plan</code> (tronqué) :</p>
<div class="language-hcl codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-hcl codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">Terraform will perform the following actions:</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)"># scaleway_instance_ip.france["tiwabbit-dns-01"] will be created</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  + </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">resource </span><span class="token keyword type variable" style="color:rgb(189, 147, 249);font-style:italic">"scaleway_instance_ip"</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"france"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      + </span><span class="token property">address</span><span class="token plain">         </span><span class="token punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token plain"> (known after apply)</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      + </span><span class="token property">id</span><span class="token plain">              </span><span class="token punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token plain"> (known after apply)</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      + </span><span class="token property">reverse</span><span class="token plain">         </span><span class="token punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"dns01.tiwabbit.fr"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      + </span><span class="token property">server_id</span><span class="token plain">       </span><span class="token punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token plain"> (known after apply)</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      + </span><span class="token property">zone</span><span class="token plain">            </span><span class="token punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"fr-par-1"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)"># scaleway_instance_security_group.france will be created</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  + </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">resource </span><span class="token keyword type variable" style="color:rgb(189, 147, 249);font-style:italic">"scaleway_instance_security_group"</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"france"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      + </span><span class="token property">description</span><span class="token plain">             </span><span class="token punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"dns"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      + </span><span class="token property">enable_default_security</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      + </span><span class="token property">external_rules</span><span class="token plain">          </span><span class="token punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      + </span><span class="token property">id</span><span class="token plain">                      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token plain"> (known after apply)</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      + </span><span class="token property">inbound_default_policy</span><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"drop"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      + </span><span class="token property">name</span><span class="token plain">                    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"public-dns"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      + </span><span class="token property">outbound_default_policy</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"accept"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      + </span><span class="token property">stateful</span><span class="token plain">                </span><span class="token punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      + </span><span class="token property">zone</span><span class="token plain">                    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"fr-par-1"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      + </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">inbound_rule</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">          + </span><span class="token property">action</span><span class="token plain">   </span><span class="token punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"accept"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">          + </span><span class="token property">ip</span><span class="token plain">       </span><span class="token punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"X.X.X.X"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">          + </span><span class="token property">port</span><span class="token plain">     </span><span class="token punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token plain"> </span><span class="token number">22</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">          + </span><span class="token property">protocol</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"TCP"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      + </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">inbound_rule</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">          + </span><span class="token property">action</span><span class="token plain">   </span><span class="token punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"accept"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">          + </span><span class="token property">ip_range</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"0.0.0.0/0"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">          + </span><span class="token property">port</span><span class="token plain">     </span><span class="token punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token plain"> </span><span class="token number">53</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">          + </span><span class="token property">protocol</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"UDP"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      + </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">inbound_rule</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">          + </span><span class="token property">action</span><span class="token plain">   </span><span class="token punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"accept"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">          + </span><span class="token property">ip_range</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"::/0"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">          + </span><span class="token property">port</span><span class="token plain">     </span><span class="token punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token plain"> </span><span class="token number">53</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">          + </span><span class="token property">protocol</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"UDP"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)"># scaleway_instance_server.france["tiwabbit-dns-01"] will be created</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  + </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">resource </span><span class="token keyword type variable" style="color:rgb(189, 147, 249);font-style:italic">"scaleway_instance_server"</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"france"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      + </span><span class="token property">enable_dynamic_ip</span><span class="token plain">                </span><span class="token punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      + </span><span class="token property">enable_ipv6</span><span class="token plain">                      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      + </span><span class="token property">id</span><span class="token plain">                               </span><span class="token punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token plain"> (known after apply)</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      + </span><span class="token property">image</span><span class="token plain">                            </span><span class="token punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"fr-par-1/5c8bbf4b-10f0-4cac-863b-4561781043ff"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      + </span><span class="token property">ip_id</span><span class="token plain">                            </span><span class="token punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token plain"> (known after apply)</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      + </span><span class="token property">ipv6_address</span><span class="token plain">                     </span><span class="token punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token plain"> (known after apply)</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      + </span><span class="token property">ipv6_gateway</span><span class="token plain">                     </span><span class="token punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token plain"> (known after apply)</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      + </span><span class="token property">ipv6_prefix_length</span><span class="token plain">               </span><span class="token punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token plain"> (known after apply)</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      + </span><span class="token property">name</span><span class="token plain">                             </span><span class="token punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"tiwabbit-dns-01"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      + </span><span class="token property">private_ip</span><span class="token plain">                       </span><span class="token punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token plain"> (known after apply)</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      + </span><span class="token property">public_ip</span><span class="token plain">                        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token plain"> (known after apply)</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      + </span><span class="token property">security_group_id</span><span class="token plain">                </span><span class="token punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"fr-par-1/dns"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      + </span><span class="token property">state</span><span class="token plain">                            </span><span class="token punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"started"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      + </span><span class="token property">type</span><span class="token plain">                             </span><span class="token punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"STARDUST1-S"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      + </span><span class="token property">zone</span><span class="token plain">                             </span><span class="token punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"fr-par-1"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      + </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">root_volume</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">          + </span><span class="token property">size_in_gb</span><span class="token plain">            </span><span class="token punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"10"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">          + </span><span class="token property">volume_id</span><span class="token plain">             </span><span class="token punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token plain"> (known after apply)</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">...</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">Plan: </span><span class="token number">8</span><span class="token plain"> to add, </span><span class="token number">0</span><span class="token plain"> to change, </span><span class="token number">0</span><span class="token plain"> to destroy.</span><br></div></code></pre></div></div>
<p>Après avoir terminé la création, voici ce que j'avais sur la console Scaleway :</p>
<p><strong>Instances :</strong>
<img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2021-12-24-create-public-dns-service/scaleway-console-instances.png" alt="scaleway-console-instances" class="img__Ss2"></p>
<p><strong>Volumes :</strong>
<img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2021-12-24-create-public-dns-service/scaleway-console-volumes.png" alt="scaleway-console-volumes" class="img__Ss2"></p>
<p><strong>[Adresses IP][adresse-ip-wikipedia] :</strong>
<img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2021-12-24-create-public-dns-service/scaleway-console-flexible-ips.png" alt="scaleway-console-flexible-ips" class="img__Ss2"></p>
<p><strong>Groupes de sécurité :</strong>
<img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2021-12-24-create-public-dns-service/scaleway-console-security-group.png" alt="scaleway-console-security-group" class="img__Ss2">
Ici, vous pouvez voir que je n'autorise le trafic entrant que sur le port <code>53</code> qui est celui utilisé par les serveurs <a href="https://tools.ietf.org/html/rfc2929" target="_blank" rel="noopener noreferrer" class="">DNS</a>. (La première règle avec le port <code>22</code> me permet de gérer le serveur depuis un emplacement privé en utilisant SSH)</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="installation-et-configuration-du-service">Installation et configuration du service<a href="https://lunik.tiwabbit.fr/blog/fr/create-public-dns-service#installation-et-configuration-du-service" class="hash-link" aria-label="Lien direct vers Installation et configuration du service" title="Lien direct vers Installation et configuration du service" translate="no">​</a></h2>
<p>Maintenant que j'ai deux nouveaux serveurs à ma disposition, je dois installer et configurer un service <a href="https://tools.ietf.org/html/rfc2929" target="_blank" rel="noopener noreferrer" class="">DNS</a> à faire tourner dessus.
Ils tournent avec <a href="https://getfedora.org/fr/" target="_blank" rel="noopener noreferrer" class="">Fedora 32</a> avec un <code>5.6</code> <a href="https://github.com/torvalds/linux" target="_blank" rel="noopener noreferrer" class="">Linux Kernel</a> :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">root@tiwabbit-dns-01 ~</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token comment" style="color:rgb(98, 114, 164)"># screenfetch</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">           /:-------------:</span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain">          root@tiwabbit-dns-01</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        :-------------------::        OS: Fedora </span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      :-----------/shhOHbmp---:</span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain">      Kernel: x86_64 Linux </span><span class="token number">5.6</span><span class="token plain">.6-300.fc32.x86_64</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    /-----------omMMMNNNMMD  ---:     Uptime: 18m</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">   :-----------sMMMMNMNMP.    ---:    Packages: </span><span class="token number">405</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  :-----------:MMMdP-------    ---</span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain">   Shell: </span><span class="token function" style="color:rgb(80, 250, 123)">bash</span><span class="token plain"> </span><span class="token number">5.0</span><span class="token plain">.11</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"> ,------------:MMMd--------    ---:   Disk: </span><span class="token number">1</span><span class="token plain">.0G / </span><span class="token number">9</span><span class="token plain">.6G </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token number">11</span><span class="token plain">%</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"> :------------:MMMd-------    .---:   CPU: AMD EPYC </span><span class="token number">7281</span><span class="token plain"> </span><span class="token number">16</span><span class="token plain">-Core @ </span><span class="token number">2</span><span class="token plain">.096GHz</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"> :----    oNMMMMMMMMMNho     .----:   RAM: 293MiB / 969MiB</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"> :--     .+shhhMMMmhhy++   .------/  </span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"> :-    -------:MMMd--------------:   </span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"> :-   --------/MMMd-------------</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain">    </span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"> :-    ------/hMMMy------------:     </span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"> :-- :dMNdhhdNMMNo------------</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain">      </span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"> :---:sdNMMMMNds:------------:       </span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"> :------:://:-------------::         </span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"> :---------------------://  </span><br></div></code></pre></div></div>
<p>Fait amusant les <a href="https://www.scaleway.com/fr/stardust-instances/" target="_blank" rel="noopener noreferrer" class="">instance Scaleway Stardust</a> fonctionne sur <a href="https://www.amd.com/fr/products/epyc" target="_blank" rel="noopener noreferrer" class="">AMD EPYC</a> <a href="https://fr.wikipedia.org/wiki/Syst%C3%A8me_sur_une_puce" target="_blank" rel="noopener noreferrer" class="">SoC</a> !</p>
<p>J'ai décidé d'utiliser le serveur <a href="https://bind9.net/" target="_blank" rel="noopener noreferrer" class="">Bind9</a> <a href="https://tools.ietf.org/html/rfc2929" target="_blank" rel="noopener noreferrer" class="">DNS</a> car il est déjà packagé dans de nombreuses distributions, il y a beaucoup de documentation et la communauté est importante.</p>
<p>J'utilise <a href="https://www.ansible.com/" target="_blank" rel="noopener noreferrer" class="">Ansible</a> pour déployer toute la pile : config linux de base, <a href="https://bind9.net/" target="_blank" rel="noopener noreferrer" class="">Bind9</a>, <a href="https://firewalld.org/" target="_blank" rel="noopener noreferrer" class="">Firewalld</a>, <a href="https://www.fail2ban.org/" target="_blank" rel="noopener noreferrer" class="">Fail2Ban</a></p>
<div class="theme-admonition theme-admonition-tip admonition_IZjC alert alert--success"><div class="admonitionHeading_uVvU"><span class="admonitionIcon_HiR3"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>astuce</div><div class="admonitionContent_bl22"><p>J'ai déjà parlé de <a href="https://firewalld.org/" target="_blank" rel="noopener noreferrer" class="">Firewalld</a> et de <a href="https://www.fail2ban.org/" target="_blank" rel="noopener noreferrer" class="">Fail2Ban</a> dans un autre article de blog : Sécurisation de mon point d'entré web des menaces externes</p></div></div>
<p>Mais pour les besoins de cet article de blog, je vais détailler les commandes <code>bash</code> équivalentes qui peuvent être utilisées.</p>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="installation-et-configuration-de-bind9">Installation et configuration de Bind9<a href="https://lunik.tiwabbit.fr/blog/fr/create-public-dns-service#installation-et-configuration-de-bind9" class="hash-link" aria-label="Lien direct vers Installation et configuration de Bind9" title="Lien direct vers Installation et configuration de Bind9" translate="no">​</a></h3>
<p>L'installation de <a href="https://bind9.net/" target="_blank" rel="noopener noreferrer" class="">Bind9</a> est assez simple. Comme il est déjà packagé, je n'ai qu'à faire une simple commande pour l'installer :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">root@tiwabbit-dns-01 ~</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token comment" style="color:rgb(98, 114, 164)"># dnf install bind bind-utils</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">Last metadata expiration check: </span><span class="token number">0</span><span class="token plain">:02:41 ago on Fri 05 Nov </span><span class="token number">2021</span><span class="token plain"> 09:49:15 AM UTC.</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">Dependencies resolved.</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"> Package                                                       Architecture                            Version                                               Repository                                Size</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">Installing:</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">bind</span><span class="token plain">                                                          x86_64                                  </span><span class="token number">32</span><span class="token plain">:9.11.28-1.fc32                                     updates                                  </span><span class="token number">2.0</span><span class="token plain"> M</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"> bind-utils                                                    x86_64                                  </span><span class="token number">32</span><span class="token plain">:9.11.28-1.fc32                                     updates                                  </span><span class="token number">233</span><span class="token plain"> k</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">Installing dependencies:</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"> bind-dnssec-doc                                               noarch                                  </span><span class="token number">32</span><span class="token plain">:9.11.28-1.fc32                                     updates                                   </span><span class="token number">46</span><span class="token plain"> k</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"> bind-libs                                                     x86_64                                  </span><span class="token number">32</span><span class="token plain">:9.11.28-1.fc32                                     updates                                   </span><span class="token number">90</span><span class="token plain"> k</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"> bind-libs-lite                                                x86_64                                  </span><span class="token number">32</span><span class="token plain">:9.11.28-1.fc32                                     updates                                  </span><span class="token number">1.1</span><span class="token plain"> M</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"> bind-license                                                  noarch                                  </span><span class="token number">32</span><span class="token plain">:9.11.28-1.fc32                                     updates                                   </span><span class="token number">16</span><span class="token plain"> k</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"> fstrm                                                         x86_64                                  </span><span class="token number">0.5</span><span class="token plain">.0-2.fc32                                          fedora                                    </span><span class="token number">28</span><span class="token plain"> k</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"> mariadb-connector-c                                           x86_64                                  </span><span class="token number">3.1</span><span class="token plain">.12-1.fc32                                         updates                                  </span><span class="token number">203</span><span class="token plain"> k</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"> mariadb-connector-c-config                                    noarch                                  </span><span class="token number">3.1</span><span class="token plain">.12-1.fc32                                         updates                                   </span><span class="token number">11</span><span class="token plain"> k</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"> policycoreutils-python-utils                                  noarch                                  </span><span class="token number">3.0</span><span class="token plain">-2.fc32                                            fedora                                    </span><span class="token number">83</span><span class="token plain"> k</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"> protobuf-c                                                    x86_64                                  </span><span class="token number">1.3</span><span class="token plain">.2-2.fc32                                          fedora                                    </span><span class="token number">35</span><span class="token plain"> k</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"> python3-bind                                                  noarch                                  </span><span class="token number">32</span><span class="token plain">:9.11.28-1.fc32                                     updates                                   </span><span class="token number">64</span><span class="token plain"> k</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">Installing weak dependencies:</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"> bind-dnssec-utils                                             x86_64                                  </span><span class="token number">32</span><span class="token plain">:9.11.28-1.fc32                                     updates                                  </span><span class="token number">128</span><span class="token plain"> k</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">Transaction Summary</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">Install  </span><span class="token number">13</span><span class="token plain"> Packages</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">Total download size: </span><span class="token number">4.0</span><span class="token plain"> M</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">Installed size: </span><span class="token number">10</span><span class="token plain"> M</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">Is this ok </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">y/N</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain">:</span><br></div></code></pre></div></div>
<p>Une fois installé, en utilisant la <a href="https://bind9.readthedocs.io/en/latest/reference.html" target="_blank" rel="noopener noreferrer" class="">documentation Bind9</a> j'ai mis la configuration suivante dans <code>/etc/named.conf</code> :</p>
<div class="language-bind9 codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-bind9 codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">acl "managment" {</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    X.X.X.X/32;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">};</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">acl "public" {</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    0.0.0.0/0;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    ::/0;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">};</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">options {</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  dump-file          "/etc/named/data/cache_dump.db";</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  statistics-file    "/etc/named/data/named_stats.txt";</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  memstatistics-file "/etc/named/data/named_mem_stats.txt";</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  secroots-file      "/etc/named/data/named.secroots";</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  recursing-file     "/etc/named/data/named.recursing";</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  listen-on port 53 { any; };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  listen-on-v6 port 53 { any; };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  allow-transfer { none; };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  max-cache-size 70%;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  allow-query-cache {</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    127.0.0.1;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    localhost;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    managment;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    public;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  allow-query {</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    127.0.0.1;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    localhost;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    managment;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    public;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  recursion yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  allow-recursion {</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    127.0.0.1;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    localhost;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    managment;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    public;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  dnssec-enable yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  dnssec-validation yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  prefetch 4 10;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  rate-limit {</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    ipv4-prefix-length 28;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    ipv6-prefix-length 56;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    responses-per-second 20;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    window 5;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    slip 3;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  managed-keys-directory "/var/named/dynamic";</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  geoip-directory        "/usr/share/GeoIP";</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  pid-file        "/run/named/named.pid";</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  session-keyfile "/run/named/session.key";</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  hostname "dns01.tiwabbit.fr";</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  server-id "dns01.tiwabbit.fr";</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  /* https://fedoraproject.org/wiki/Changes/CryptoPolicy */</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  include "/etc/crypto-policies/back-ends/bind.config";</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">};</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">statistics-channels {</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  inet 127.0.0.1 port 8053 allow { 127.0.0.1; };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">};</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">logging {</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  channel client_file {</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    file "/var/log/named/client.log" versions 3 size 5m;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    severity dynamic;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-time yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-category yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-severity yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  channel cname_file {</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    file "/var/log/named/cname.log" versions 3 size 5m;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    severity dynamic;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-time yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-category yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-severity yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  channel config_file {</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    file "/var/log/named/config.log" versions 3 size 5m;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    severity dynamic;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-time yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-category yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-severity yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  channel database_file {</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    file "/var/log/named/database.log" versions 3 size 5m;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    severity dynamic;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-time yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-category yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-severity yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  channel default_file {</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    file "/var/log/named/default.log" versions 3 size 5m;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    severity dynamic;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-time yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-category yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-severity yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  channel delegation-only_file {</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    file "/var/log/named/delegation-only.log" versions 3 size 5m;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    severity dynamic;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-time yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-category yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-severity yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  channel dispatch_file {</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    file "/var/log/named/dispatch.log" versions 3 size 5m;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    severity dynamic;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-time yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-category yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-severity yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  channel dnssec_file {</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    file "/var/log/named/dnssec.log" versions 3 size 5m;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    severity dynamic;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-time yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-category yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-severity yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  channel dnstap_file {</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    file "/var/log/named/dnstap.log" versions 3 size 5m;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    severity dynamic;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-time yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-category yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-severity yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  channel edns-disabled_file {</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    file "/var/log/named/edns-disabled.log" versions 3 size 5m;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    severity dynamic;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-time yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-category yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-severity yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  channel general_file {</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    file "/var/log/named/general.log" versions 3 size 5m;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    severity dynamic;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-time yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-category yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-severity yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  channel lame-servers_file {</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    file "/var/log/named/lame-servers.log" versions 3 size 5m;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    severity dynamic;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-time yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-category yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-severity yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  channel network_file {</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    file "/var/log/named/network.log" versions 3 size 5m;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    severity dynamic;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-time yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-category yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-severity yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  channel notify_file {</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    file "/var/log/named/notify.log" versions 3 size 5m;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    severity dynamic;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-time yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-category yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-severity yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  channel queries_file {</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    file "/var/log/named/queries.log" versions 3 size 5m;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    severity dynamic;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-time yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-category yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-severity yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  channel query-errors_file {</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    file "/var/log/named/query-errors.log" versions 3 size 5m;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    severity dynamic;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-time yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-category yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-severity yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  channel rate-limit_file {</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    file "/var/log/named/rate-limit.log" versions 3 size 5m;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    severity dynamic;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-time yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-category yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-severity yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  channel resolver_file {</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    file "/var/log/named/resolver.log" versions 3 size 5m;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    severity dynamic;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-time yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-category yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-severity yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  channel rpz_file {</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    file "/var/log/named/rpz.log" versions 3 size 5m;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    severity dynamic;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-time yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-category yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-severity yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  channel security_file {</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    file "/var/log/named/security.log" versions 3 size 5m;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    severity dynamic;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-time yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-category yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-severity yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  channel spill_file {</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    file "/var/log/named/spill.log" versions 3 size 5m;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    severity dynamic;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-time yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-category yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-severity yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  channel trust-anchor-telemetry_file {</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    file "/var/log/named/trust-anchor-telemetry.log" versions 3 size 5m;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    severity dynamic;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-time yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-category yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-severity yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  channel unmatched_file {</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    file "/var/log/named/unmatched.log" versions 3 size 5m;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    severity dynamic;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-time yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-category yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-severity yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  channel update_file {</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    file "/var/log/named/update.log" versions 3 size 5m;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    severity dynamic;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-time yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-category yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-severity yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  channel update-security_file {</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    file "/var/log/named/update-security.log" versions 3 size 5m;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    severity dynamic;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-time yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-category yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-severity yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  channel xfer-in_file {</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    file "/var/log/named/xfer-in.log" versions 3 size 5m;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    severity dynamic;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-time yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-category yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-severity yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  channel xfer-out_file {</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    file "/var/log/named/xfer-out.log" versions 3 size 5m;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    severity dynamic;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-time yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-category yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    print-severity yes;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  category client { client_file; default_debug; };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  category cname { cname_file; default_debug; };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  category config { config_file; default_debug; };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  category database { database_file; default_debug; };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  category default { default_file; default_debug; };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  category delegation-only { delegation-only_file; default_debug; };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  category dispatch { dispatch_file; default_debug; };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  category dnssec { dnssec_file; default_debug; };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  category dnstap { dnstap_file; default_debug; };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  category edns-disabled { edns-disabled_file; default_debug; };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  category general { general_file; default_debug; };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  category lame-servers { lame-servers_file; default_debug; };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  category network { network_file; default_debug; };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  category notify { notify_file; default_debug; };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  category queries { queries_file; default_debug; };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  category query-errors { query-errors_file; default_debug; };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  category rate-limit { rate-limit_file; default_debug; };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  category resolver { resolver_file; default_debug; };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  category rpz { rpz_file; default_debug; };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  category security { security_file; default_debug; };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  category spill { spill_file; default_debug; };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  category trust-anchor-telemetry { trust-anchor-telemetry_file; default_debug; };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  category unmatched { unmatched_file; default_debug; };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  category update { update_file; default_debug; };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  category update-security { update-security_file; default_debug; };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  category xfer-in { xfer-in_file; default_debug; };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  category xfer-out { xfer-out_file; default_debug; };</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">};</span><br></div></code></pre></div></div>
<p>Waouh c'est beaucoup !</p>
<p>Les lignes importantes à configurer sont :</p>
<h4 class="anchor anchorTargetStickyNavbar_SAay" id="listes-de-contrôle-daccès">Listes de contrôle d'accès<a href="https://lunik.tiwabbit.fr/blog/fr/create-public-dns-service#listes-de-contr%C3%B4le-dacc%C3%A8s" class="hash-link" aria-label="Lien direct vers Listes de contrôle d'accès" title="Lien direct vers Listes de contrôle d'accès" translate="no">​</a></h4>
<p>Les <a href="https://fr.wikipedia.org/wiki/Access_Control_List" target="_blank" rel="noopener noreferrer" class="">ACL</a>s permettent de choisir le comportement du service en fonction du client <a href="https://fr.wikipedia.org/wiki/Adresse_IP" target="_blank" rel="noopener noreferrer" class="">IP address</a>.</p>
<p>Jetons un œil à ma configuration :</p>
<div class="language-bind9 codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-bind9 codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">acl "managment" {</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    X.X.X.X/32;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">};</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">acl "public" {</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    0.0.0.0/0;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    ::/0;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">};</span><br></div></code></pre></div></div>
<p>Ici, je crée deux groupes <a href="https://fr.wikipedia.org/wiki/Access_Control_List" target="_blank" rel="noopener noreferrer" class="">ACL</a> : <code>public</code> et <code>managment</code>. Dans chacun de ces blocs <code>acl</code>, je peux mettre autant de <a href="https://fr.wikipedia.org/wiki/Adresse_IP#Agr%C3%A9gation_des_adresses" target="_blank" rel="noopener noreferrer" class="">CIDR</a> que je veux.
<code>public</code> contient l'<a href="https://fr.wikipedia.org/wiki/IPv4" target="_blank" rel="noopener noreferrer" class="">IPv4</a> et l'<a href="https://fr.wikipedia.org/wiki/IPv6" target="_blank" rel="noopener noreferrer" class="">IPv6</a> global <a href="https://fr.wikipedia.org/wiki/Adresse_IP#Agr%C3%A9gation_des_adresses" target="_blank" rel="noopener noreferrer" class="">CIDR</a>. <code>managment</code> contient une unique <a href="https://fr.wikipedia.org/wiki/Adresse_IP" target="_blank" rel="noopener noreferrer" class="">IP</a> <a href="https://fr.wikipedia.org/wiki/Adresse_IP#Agr%C3%A9gation_des_adresses" target="_blank" rel="noopener noreferrer" class="">CIDR</a> (celle utilisée pour configurer le service).</p>
<p>Vous pouvez réutiliser ces groupes <a href="https://fr.wikipedia.org/wiki/Access_Control_List" target="_blank" rel="noopener noreferrer" class="">ACL</a> dans d'autres parties de la configuration comme dans <code>allow-query</code>, <code>allow-query-cache</code>, <code>allow-recursion</code>.</p>
<h4 class="anchor anchorTargetStickyNavbar_SAay" id="comportement-des-requêtes">Comportement des requêtes<a href="https://lunik.tiwabbit.fr/blog/fr/create-public-dns-service#comportement-des-requ%C3%AAtes" class="hash-link" aria-label="Lien direct vers Comportement des requêtes" title="Lien direct vers Comportement des requêtes" translate="no">​</a></h4>
<p>J'ai choisi de n'implémenter que trois comportements de requête pour rester simple :</p>
<ul>
<li class=""><code>allow-query</code> définit qui est autorisé à interroger mon service <a href="https://tools.ietf.org/html/rfc2929" target="_blank" rel="noopener noreferrer" class="">DNS</a>. Si l'<a href="https://fr.wikipedia.org/wiki/Adresse_IP" target="_blank" rel="noopener noreferrer" class="">IP</a> du client n'est pas dans la liste, le serveur ne répondra pas.</li>
<li class=""><code>allow-query-cache</code> définit depuis quel client le serveur doit mettre en cache les réponses. Cela permet à la requête d'être résolue plus rapidement la prochaine fois.</li>
<li class=""><code>allow-recursion</code> définit qui peut faire des <a href="https://www.cloudflare.com/fr-fr/learning/dns/what-is-recursive-dns" target="_blank" rel="noopener noreferrer" class="">requêtes récursives</a>. <a href="https://www.cloudflare.com/fr-fr/learning/dns/what-is-recursive-dns" target="_blank" rel="noopener noreferrer" class="">Query recursion</a> est un mécanisme <a href="https://tools.ietf.org/html/rfc2929" target="_blank" rel="noopener noreferrer" class="">DNS</a> qui trouve l'<a href="https://fr.wikipedia.org/wiki/Adresse_IP" target="_blank" rel="noopener noreferrer" class="">IP</a> associé à une entrée <a href="https://tools.ietf.org/html/rfc2929" target="_blank" rel="noopener noreferrer" class="">DNS</a> en faisant tout les requêtes nécessaires une par une depuis les serveurs racine. Cela permet d'être indépendant lors de la résolution des requêtes (vous n'avez pas besoin de transmettre la requête à un autre serveur public <a href="https://tools.ietf.org/html/rfc2929" target="_blank" rel="noopener noreferrer" class="">DNS</a> comme <code>8.8.8.8</code> ou <code>1.1.1.1</code>)</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_SAay" id="prefetching">Prefetching<a href="https://lunik.tiwabbit.fr/blog/fr/create-public-dns-service#prefetching" class="hash-link" aria-label="Lien direct vers Prefetching" title="Lien direct vers Prefetching" translate="no">​</a></h4>
<p>Tout est dans le nom. Cette configuration permet au serveur de faire une requête <a href="https://tools.ietf.org/html/rfc2929" target="_blank" rel="noopener noreferrer" class="">DNS</a> par lui-même en prévision d'autres requêtes. Cela permet d'être plus rapide à répondre la plupart du temps si une entrée <a href="https://tools.ietf.org/html/rfc2929" target="_blank" rel="noopener noreferrer" class="">DNS</a> est demandée très souvent.</p>
<p>Chaque entrée <a href="https://tools.ietf.org/html/rfc2929" target="_blank" rel="noopener noreferrer" class="">DNS</a> a un <a href="https://fr.wikipedia.org/wiki/Time_to_Live" target="_blank" rel="noopener noreferrer" class="">Time To Live (ou TTL)</a>. Vous pouvez l'obtenir en utilisant <code>dig</code> :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">dig</span><span class="token plain"> lunik.tiwabbit.fr</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> </span><span class="token operator">&lt;&lt;</span><span class="token operator">&gt;&gt;</span><span class="token plain"> DiG </span><span class="token number">9.11</span><span class="token plain">.28-RedHat-9.11.28-1.fc32 </span><span class="token operator">&lt;&lt;</span><span class="token operator">&gt;&gt;</span><span class="token plain"> lunik.tiwabbit.fr</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> global options: +cmd</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> Got answer:</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> -</span><span class="token operator">&gt;&gt;</span><span class="token plain">HEADER</span><span class="token operator">&lt;&lt;-</span><span class="token plain"> opcode: QUERY, status: NOERROR, id: </span><span class="token number">41640</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> flags: qr rd ra</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> QUERY: </span><span class="token number">1</span><span class="token plain">, ANSWER: </span><span class="token number">4</span><span class="token plain">, AUTHORITY: </span><span class="token number">0</span><span class="token plain">, ADDITIONAL: </span><span class="token number">1</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> OPT PSEUDOSECTION:</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> EDNS: version: </span><span class="token number">0</span><span class="token plain">, flags:</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> udp: </span><span class="token number">1232</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> QUESTION SECTION:</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain">lunik.tiwabbit.fr.   IN  A</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> ANSWER SECTION:</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">lunik.tiwabbit.fr.  </span><span class="token number">66</span><span class="token plain">  IN  A </span><span class="token number">52.222</span><span class="token plain">.158.86</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">lunik.tiwabbit.fr.  </span><span class="token number">66</span><span class="token plain">  IN  A </span><span class="token number">52.222</span><span class="token plain">.158.38</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">lunik.tiwabbit.fr.  </span><span class="token number">66</span><span class="token plain">  IN  A </span><span class="token number">52.222</span><span class="token plain">.158.55</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">lunik.tiwabbit.fr.  </span><span class="token number">66</span><span class="token plain">  IN  A </span><span class="token number">52.222</span><span class="token plain">.158.103</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> Query time: </span><span class="token number">0</span><span class="token plain"> msec</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> SERVER: </span><span class="token number">10.194</span><span class="token plain">.3.3</span><span class="token comment" style="color:rgb(98, 114, 164)">#53(10.194.3.3)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> WHEN: Fri Nov 05 </span><span class="token number">10</span><span class="token plain">:13:42 UTC </span><span class="token number">2021</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> MSG SIZE  rcvd: </span><span class="token number">110</span><br></div></code></pre></div></div>
<p>Dans la <code>ANSWER SECTION</code> :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">lunik.tiwabbit.fr.  </span><span class="token number">66</span><span class="token plain">  IN  A </span><span class="token number">52.222</span><span class="token plain">.158.86</span><br></div></code></pre></div></div>
<p><code>66</code> est le <a href="https://fr.wikipedia.org/wiki/Time_to_Live" target="_blank" rel="noopener noreferrer" class="">TTL</a> de cette entrée <a href="https://tools.ietf.org/html/rfc2929" target="_blank" rel="noopener noreferrer" class="">DNS</a>. Cela signifie que dans <code>66</code> secondes, elle n'est plus valide et le client doit faire une autre demande pour obtenir la nouvelle <a href="https://fr.wikipedia.org/wiki/Adresse_IP" target="_blank" rel="noopener noreferrer" class="">IP</a> (la plupart du temps, cela ne change pas).</p>
<p>Dans ma configuration j'ai :</p>
<div class="language-bind9 codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-bind9 codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">prefetch 4 10;</span><br></div></code></pre></div></div>
<p>Si le serveur a mis en cache une entrée <a href="https://tools.ietf.org/html/rfc2929" target="_blank" rel="noopener noreferrer" class="">DNS</a> avec <code>4</code> secondes ou moins de <a href="https://fr.wikipedia.org/wiki/Time_to_Live" target="_blank" rel="noopener noreferrer" class="">TTL</a> restant alors il fera une requête <a href="https://tools.ietf.org/html/rfc2929" target="_blank" rel="noopener noreferrer" class="">DNS</a> pour actualiser celle mise en cache. <code>10</code> est un paramètre facultatif qui définit l'éligibilité de l'enregistrement pour la prélecture.</p>
<h4 class="anchor anchorTargetStickyNavbar_SAay" id="limitation-de-requêtes">Limitation de requêtes<a href="https://lunik.tiwabbit.fr/blog/fr/create-public-dns-service#limitation-de-requ%C3%AAtes" class="hash-link" aria-label="Lien direct vers Limitation de requêtes" title="Lien direct vers Limitation de requêtes" translate="no">​</a></h4>
<p>C'est peut-être l'un des paramètres les plus importants d'un serveur public <a href="https://tools.ietf.org/html/rfc2929" target="_blank" rel="noopener noreferrer" class="">DNS</a>. Le but de cette configuration est de limiter le nombre de réponses du serveur si un client demande plusieurs fois la même entrée <a href="https://tools.ietf.org/html/rfc2929" target="_blank" rel="noopener noreferrer" class="">DNS</a>. Il est très utile pour atténuer les <a href="https://www.cloudflare.com/fr-fr/learning/ddos/dns-amplification-ddos-attack" target="_blank" rel="noopener noreferrer" class="">attaques par amplification DNS</a>.</p>
<p>Voici la configuration que j'ai :</p>
<div class="language-bind9 codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-bind9 codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">rate-limit {</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  ipv4-prefix-length 28;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  ipv6-prefix-length 56;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  responses-per-second 20;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  window 5;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  slip 3;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">};</span><br></div></code></pre></div></div>
<p>Si un client demande plus de <code>20</code> fois la même entrée <a href="https://tools.ietf.org/html/rfc2929" target="_blank" rel="noopener noreferrer" class="">DNS</a> sur une période de <code>5</code> secondes, le serveur ignore <code>3</code> réponses avant de répondre (indéfiniment).
Pour empêcher les attaques via de large sous-réseaux, la limite de débit s'étend à un <code>/28</code> <a href="https://fr.wikipedia.org/wiki/Adresse_IP#IPv4" target="_blank" rel="noopener noreferrer" class="">sous-réseau IPv4</a> et à un <code>/56</code> <a href="https://fr.wikipedia.org/wiki/Adresse_IP#IPv6" target="_blank" rel="noopener noreferrer" class="">sous-réseau IPv6</a>.</p>
<h4 class="anchor anchorTargetStickyNavbar_SAay" id="journalisation">Journalisation<a href="https://lunik.tiwabbit.fr/blog/fr/create-public-dns-service#journalisation" class="hash-link" aria-label="Lien direct vers Journalisation" title="Lien direct vers Journalisation" translate="no">​</a></h4>
<p>j'ai fait le choix d'être très verbeux avec les logs c'est pourquoi j'ai configuré tous les canaux possibles.</p>
<p>Les plus intéressants sont</p>
<ul>
<li class=""><code>queries</code> qui journalise chaque requête résolue par le serveur :</li>
</ul>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)"># /var/log/named/queries.log</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">05-Nov-2021 </span><span class="token number">10</span><span class="token plain">:21:43.536 queries: info: client @0x7f76073dfe50 X.X.X.X</span><span class="token comment" style="color:rgb(98, 114, 164)">#14821 (mms-iad.sp-prod.net): query: mms-iad.sp-prod.net IN A +E(0)DV (10.70.2.235)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">05-Nov-2021 </span><span class="token number">10</span><span class="token plain">:21:43.545 queries: info: client @0x7f760793d450 X.X.X.X</span><span class="token comment" style="color:rgb(98, 114, 164)">#47583 (psja.isd.us): query: psja.isd.us IN MX +E(0)DV (10.70.2.235)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">05-Nov-2021 </span><span class="token number">10</span><span class="token plain">:21:43.547 queries: info: client @0x7f760759b400 X.X.X.X</span><span class="token comment" style="color:rgb(98, 114, 164)">#50020 (global.reputation.invincea.com): query: global.reputation.invincea.com IN A +E(0)DV (10.70.2.235)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">05-Nov-2021 </span><span class="token number">10</span><span class="token plain">:21:43.556 queries: info: client @0x7f76075dddc0 X.X.X.X</span><span class="token comment" style="color:rgb(98, 114, 164)">#38383 (forconzoomnyc233mmr.zoom.us): query: forconzoomnyc233mmr.zoom.us IN A + (10.70.2.235)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">05-Nov-2021 </span><span class="token number">10</span><span class="token plain">:21:43.566 queries: info: client @0x7f76077ba820 X.X.X.X</span><span class="token comment" style="color:rgb(98, 114, 164)">#39161 (ps-membership.us-ctkip-ps3.dell.com): query: ps-membership.us-ctkip-ps3.dell.com IN A + (10.70.2.235)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">05-Nov-2021 </span><span class="token number">10</span><span class="token plain">:21:43.618 queries: info: client @0x7f7607a9f2c0 X.X.X.X</span><span class="token comment" style="color:rgb(98, 114, 164)">#39161 (ps-membership.usgit.dell.com): query: ps-membership.usgit.dell.com IN A + (10.70.2.235)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">05-Nov-2021 </span><span class="token number">10</span><span class="token plain">:21:43.622 queries: info: client @0x7f76077fcbc0 X.X.X.X</span><span class="token comment" style="color:rgb(98, 114, 164)">#56424 (icn.intl-global-adns.alibabacloud.com): query: icn.intl-global-adns.alibabacloud.com IN A + (10.70.2.235)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">05-Nov-2021 </span><span class="token number">10</span><span class="token plain">:21:43.623 queries: info: client @0x7f760765f400 X.X.X.X</span><span class="token comment" style="color:rgb(98, 114, 164)">#38383 (forcon-zoomca193-123-14-158mmr.zoom.us): query: forcon-zoomca193-123-14-158mmr.zoom.us IN A + (10.70.2.235)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">05-Nov-2021 </span><span class="token number">10</span><span class="token plain">:21:43.635 queries: info: client @0x7f75f0ce5910 X.X.X.X</span><span class="token comment" style="color:rgb(98, 114, 164)">#56548 (sfc-idzwww.riotgames.roblox.com.ru): query: sfc-idzwww.riotgames.roblox.com.ru IN A + (10.70.2.235)</span><br></div></code></pre></div></div>
<ul>
<li class=""><code>rate-limit</code> qui enregistre tous les événements concernant le comportement de limitation de requêtes :</li>
</ul>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)"># /var/log/named/rate-limit.log</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">05-Nov-2021 </span><span class="token number">10</span><span class="token plain">:21:39.631 rate-limit: info: client @0x7f76077cdd80 X.X.X.X</span><span class="token comment" style="color:rgb(98, 114, 164)">#38383 (zoomff134-224-74-182mmrforcon.zoom.us): rate limit drop NXDOMAIN response to X.X.X.X/28 for zoom.us  (4ef96ce9)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">05-Nov-2021 </span><span class="token number">10</span><span class="token plain">:21:39.694 rate-limit: info: client @0x7f75f0cf3f10 X.X.X.X</span><span class="token comment" style="color:rgb(98, 114, 164)">#38383 (bisdtx-orgforcon.zoom.us): rate limit drop NXDOMAIN response to X.X.X.X/28 for zoom.us  (4ef96ce9)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">05-Nov-2021 </span><span class="token number">10</span><span class="token plain">:21:39.752 rate-limit: info: client @0x7f76077fcbc0 X.X.X.X</span><span class="token comment" style="color:rgb(98, 114, 164)">#38383 (kirklandwa-forcon.zoom.us): rate limit slip NXDOMAIN response to X.X.X.X/28 for zoom.us  (4ef96ce9)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">05-Nov-2021 </span><span class="token number">10</span><span class="token plain">:21:39.863 rate-limit: info: client @0x7f76077eab00 X.X.X.X</span><span class="token comment" style="color:rgb(98, 114, 164)">#38383 (friendsnrcforcon.zoom.us): rate limit drop NXDOMAIN response to X.X.X.X/28 for zoom.us  (4ef96ce9)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">05-Nov-2021 </span><span class="token number">10</span><span class="token plain">:21:39.942 rate-limit: info: client @0x7f76078e8610 X.X.X.X</span><span class="token comment" style="color:rgb(98, 114, 164)">#38383 (deltatrust-org-uk-forcon.zoom.us): rate limit drop NXDOMAIN response to X.X.X.X/28 for zoom.us  (4ef96ce9)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">05-Nov-2021 </span><span class="token number">10</span><span class="token plain">:21:40.857 rate-limit: info: client @0x7f7607a13120 X.X.X.X</span><span class="token comment" style="color:rgb(98, 114, 164)">#38383 (12mmrforcon.zoom.us): rate limit slip NXDOMAIN response to X.X.X.X/28 for zoom.us  (4ef96ce9)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">05-Nov-2021 </span><span class="token number">10</span><span class="token plain">:21:40.871 rate-limit: info: client @0x7f76076509a0 X.X.X.X</span><span class="token comment" style="color:rgb(98, 114, 164)">#38383 (datamarkgisforcon.zoom.us): rate limit drop NXDOMAIN response to X.X.X.X/28 for zoom.us  (4ef96ce9)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">05-Nov-2021 </span><span class="token number">10</span><span class="token plain">:21:40.891 rate-limit: info: client @0x7f7607866d60 X.X.X.X</span><span class="token comment" style="color:rgb(98, 114, 164)">#38383 (wvsd208-forcon.zoom.us): rate limit drop NXDOMAIN response to X.X.X.X/28 for zoom.us  (4ef96ce9)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">05-Nov-2021 </span><span class="token number">10</span><span class="token plain">:21:40.907 rate-limit: info: client @0x7f7607146a70 X.X.X.X</span><span class="token comment" style="color:rgb(98, 114, 164)">#38383 (zoomva198-251-217-184mmrforcon.zoom.us): rate limit slip NXDOMAIN response to X.X.X.X/28 for zoom.us  (4ef96ce9)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">05-Nov-2021 </span><span class="token number">10</span><span class="token plain">:21:40.968 rate-limit: info: client @0x7f760713b020 X.X.X.X</span><span class="token comment" style="color:rgb(98, 114, 164)">#38383 (zoomdvs185mmr-forcon.zoom.us): rate limit drop NXDOMAIN response to X.X.X.X/28 for zoom.us  (4ef96ce9)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">05-Nov-2021 </span><span class="token number">10</span><span class="token plain">:21:43.761 rate-limit: info: *stop limiting NXDOMAIN responses to X.X.X.X/28 </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">for</span><span class="token plain"> buffer.com  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">bc75c42e</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">05-Nov-2021 </span><span class="token number">10</span><span class="token plain">:21:43.761 rate-limit: info: *stop limiting error responses to X.X.X.X/28</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">05-Nov-2021 </span><span class="token number">10</span><span class="token plain">:21:43.761 rate-limit: info: *stop limiting NXDOMAIN responses to X.X.X.X/28 </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">for</span><span class="token plain"> restintergamma.nl  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">97dd2767</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">05-Nov-2021 </span><span class="token number">10</span><span class="token plain">:21:43.761 rate-limit: info: *stop limiting NXDOMAIN responses to X.X.X.X/28 </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">for</span><span class="token plain"> alibabacloud.com  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">d22fa033</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">05-Nov-2021 </span><span class="token number">10</span><span class="token plain">:21:43.761 rate-limit: info: *stop limiting NXDOMAIN responses to X.X.X.X/28 </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">for</span><span class="token plain"> dell.com  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">98e605b5</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">05-Nov-2021 </span><span class="token number">10</span><span class="token plain">:21:43.761 rate-limit: info: *stop limiting error responses to X.X.X.X/28</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">05-Nov-2021 </span><span class="token number">10</span><span class="token plain">:21:43.761 rate-limit: info: *stop limiting NXDOMAIN responses to X.X.X.X/28 </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">for</span><span class="token plain"> zoom.us  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">4ef96ce9</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="surveillance">Surveillance<a href="https://lunik.tiwabbit.fr/blog/fr/create-public-dns-service#surveillance" class="hash-link" aria-label="Lien direct vers Surveillance" title="Lien direct vers Surveillance" translate="no">​</a></h2>
<p>Je choisis d'utiliser <a href="https://www.datadoghq.com/" target="_blank" rel="noopener noreferrer" class="">Datadog</a> pour surveiller les serveurs <a href="https://tools.ietf.org/html/rfc2929" target="_blank" rel="noopener noreferrer" class="">DNS</a>.</p>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="installation-de-lagent-datadog">Installation de l'agent Datadog<a href="https://lunik.tiwabbit.fr/blog/fr/create-public-dns-service#installation-de-lagent-datadog" class="hash-link" aria-label="Lien direct vers Installation de l'agent Datadog" title="Lien direct vers Installation de l'agent Datadog" translate="no">​</a></h3>
<p>L'installation est assez simple avec <a href="https://www.ansible.com/" target="_blank" rel="noopener noreferrer" class="">Ansible</a> car ils fournissent un <a href="https://galaxy.ansible.com/datadog/datadog" target="_blank" rel="noopener noreferrer" class="">role galaxy</a>.
Je l'ai utilisé avec la configuration suivante :</p>
<div class="language-yaml codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-yaml codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token punctuation" style="color:rgb(248, 248, 242)">---</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">datadog_api_key</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"{{ vault_datadog_api_key }}"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">datadog_site</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"datadoghq.eu"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">datadog_agent_flavor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"datadog-agent"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">datadog_agent_major_version</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">7</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">datadog_enabled</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> yes</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">datadog_bind9_integration_version</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> 1.0.0</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">datadog_config</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">logs_enabled</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token boolean important">true</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">datadog_checks</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">bind9</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">init_config</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">instances</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> bind9</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token key atrule">url</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"http://127.0.0.1:{{ bind_statistics_port }}"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">logs</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">type</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> file</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token key atrule">path</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> /var/log/named/queries.log</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token key atrule">service</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> named</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token key atrule">source</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> bind9</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token key atrule">sourcecategory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> queries</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">type</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> file</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token key atrule">path</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> /var/log/named/rate</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">limit.log</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token key atrule">service</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> named</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token key atrule">source</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> bind9</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token key atrule">sourcecategory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> rate</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">limit</span><br></div></code></pre></div></div>
<p>J'ai activé les intégrations <a href="https://bind9.net/" target="_blank" rel="noopener noreferrer" class="">Bind9</a> et les journaux.</p>
<p>Une fois déployé, je peux voir mes agents via la console web <a href="https://www.datadoghq.com/" target="_blank" rel="noopener noreferrer" class="">Datadog</a> dans le panneau <code>Infrastructure</code> :</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2021-12-24-create-public-dns-service/datadog-host-map.png" alt="datadog-host-map" class="img__Ss2"></p>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="métriques-et-journaux-datadog">Métriques et journaux Datadog<a href="https://lunik.tiwabbit.fr/blog/fr/create-public-dns-service#m%C3%A9triques-et-journaux-datadog" class="hash-link" aria-label="Lien direct vers Métriques et journaux Datadog" title="Lien direct vers Métriques et journaux Datadog" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_SAay" id="métriques">Métriques<a href="https://lunik.tiwabbit.fr/blog/fr/create-public-dns-service#m%C3%A9triques" class="hash-link" aria-label="Lien direct vers Métriques" title="Lien direct vers Métriques" translate="no">​</a></h4>
<p>Vu que j'ai activé l'<a href="https://docs.datadoghq.com/fr/integrations/bind9" target="_blank" rel="noopener noreferrer" class="">intégration Bind9</a> dans la configuration de l'agent, je dois faire de même dans la console Web. Dans le panneau <code>Integrations</code>, recherchez <code>Bind9</code> et suivez le guide de configuration.</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2021-12-24-create-public-dns-service/datadog-bind9-integration-01.png" alt="datadog-bind-integration" class="img__Ss2"></p>
<p>Maintenant, je peux voir les métriques apparaître.</p>
<h4 class="anchor anchorTargetStickyNavbar_SAay" id="journaux">Journaux<a href="https://lunik.tiwabbit.fr/blog/fr/create-public-dns-service#journaux" class="hash-link" aria-label="Lien direct vers Journaux" title="Lien direct vers Journaux" translate="no">​</a></h4>
<p>Les journaux s'affichent déjà dans l'explorateur de journaux dans le panneau <code>Logs</code> :</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2021-12-24-create-public-dns-service/datadog-log-explorer.png" alt="datadog-log-explorer" class="img__Ss2"></p>
<p>Mais <a href="https://www.datadoghq.com/" target="_blank" rel="noopener noreferrer" class="">Datadog</a> ne sait pas comment interpréter ces journaux. Pour l'instant, il ne voit qu'une grande chaîne de caractères.
Si je veux analyser ces journaux, <a href="https://www.datadoghq.com/" target="_blank" rel="noopener noreferrer" class="">Datadog</a> doit les parser pour moi.</p>
<p>Dans le pipeline de journaux intégré <a href="https://www.datadoghq.com/" target="_blank" rel="noopener noreferrer" class="">Datadog</a> dans le panneau <code>Logs</code>, je peux définir une liste de modèles et d'actions pour parser le fichier journal produit par le service <a href="https://bind9.net/" target="_blank" rel="noopener noreferrer" class="">Bind9</a>. Sur certains logiciels plus populaires, <a href="https://www.datadoghq.com/" target="_blank" rel="noopener noreferrer" class="">Datadog</a> a déjà fait le travail pour vous, mais il semble que <a href="https://bind9.net/" target="_blank" rel="noopener noreferrer" class="">Bind9</a> soit une exception.</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2021-12-24-create-public-dns-service/datadog-log-pipeline-library.png" alt="datadog-pipeline-library" class="img__Ss2"></p>
<h5 class="anchor anchorTargetStickyNavbar_SAay" id="définition-des-journaux-danalyse-des-pipelines">Définition des journaux d'analyse des pipelines<a href="https://lunik.tiwabbit.fr/blog/fr/create-public-dns-service#d%C3%A9finition-des-journaux-danalyse-des-pipelines" class="hash-link" aria-label="Lien direct vers Définition des journaux d'analyse des pipelines" title="Lien direct vers Définition des journaux d'analyse des pipelines" translate="no">​</a></h5>
<p>J'ai d'abord créé un nouveau pipeline et utilisé des filtres prédéfinis : <code>source:bind9</code> et <code>sourcecategory:queries</code>.
Ces deux filtres sont déduits de la configuration de l'agent <a href="https://www.datadoghq.com/" target="_blank" rel="noopener noreferrer" class="">Datadog</a> précédente :</p>
<div class="language-yaml codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-yaml codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token key atrule">datadog_checks</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">bind9</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">...</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">logs</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">...</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">type</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> file</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token key atrule">path</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> /var/log/named/queries.log</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token key atrule">service</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> named</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token key atrule">source</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> bind9</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token key atrule">sourcecategory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> queries</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">...</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><br></div></code></pre></div></div>
<p>Maintenant que je vais uniquement parser les journaux à partir de la bonne source, j'ai besoin d'un <a href="https://docs.datadoghq.com/fr/logs/log_configuration/parsing" target="_blank" rel="noopener noreferrer" class="">parser Grok</a> pour parser la chaîne de journal.
Le <a href="https://docs.datadoghq.com/fr/logs/log_configuration/parsing" target="_blank" rel="noopener noreferrer" class="">parser Grok</a> définit des blocs dans la chaîne et les place dans des variables. Lorsque la ligne de journal est parsé, elle renvoie un objet <a href="https://tools.ietf.org/html/rfc8259" target="_blank" rel="noopener noreferrer" class="">JSON</a> magnifiquement formaté.</p>
<p>Les blocs sont définis par des expressions rationnelles "simplifiées" : <code>number</code>, <code>word</code>, <code>date</code>, <code>ip</code>, ...</p>
<p><a href="https://www.datadoghq.com/" target="_blank" rel="noopener noreferrer" class="">Datadog</a> me permet de le faire très simplement en ayant une vue d'analyse "en direct" où vous pouvez voir en temps réel quelle partie du journal est analysée par quel bloc.</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2021-12-24-create-public-dns-service/datadog-grok-parser.png" alt="datadog-grok-parser" class="img__Ss2"></p>
<p>Voici donc la règle finale de <a href="https://docs.datadoghq.com/fr/logs/log_configuration/parsing" target="_blank" rel="noopener noreferrer" class="">parsing Grok</a> pour les journaux <code>requêtes</code> :</p>
<div class="language-grok codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-grok codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">default %{number}-%{word}-%{number}\s+%{date("HH:mm:ss.SSS"):timestamp}\s+queries:\s+%{word:status}:\s+client\s+@%{word:client.data}\s+%{ip:client.ip}\#%{number:client.port}\s+\(%{hostname:query.hostname}\):\s+query:\s+%{hostname:query.fqdn}\s+%{word:query.location}\s+%{word:query.qcode}\s+.*\s+\(%{ip:server.ip}\).*</span><br></div></code></pre></div></div>
<p>Avec cet exemple :</p>
<div class="language-bind9 codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-bind9 codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">27-Oct-2021 16:53:43.594 queries: info: client @0x7fad52ee1fd0 127.0.0.1#64318 (google.fr): query: google.fr IN A +E(0) (10.69.86.243)</span><br></div></code></pre></div></div>
<p>Je reçois :</p>
<div class="language-json codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-json codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"status"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"info"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"query"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"qcode"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"A"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"location"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"IN"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"hostname"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"google.fr"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"fqdn"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"google.fr"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"client"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"ip"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"127.0.0.1"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"data"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"0x7fad52ee1fd0"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"port"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">64318</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"timestamp"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">1636131223594</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"server"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"ip"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"10.69.86.243"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></div></code></pre></div></div>
<p>Génial !</p>
<p><a href="https://www.datadoghq.com/" target="_blank" rel="noopener noreferrer" class="">Datadog</a> permet d'améliorer ce nouvel objet <a href="https://tools.ietf.org/html/rfc8259" target="_blank" rel="noopener noreferrer" class="">JSON</a> avec des métadonnées supplémentaires. Dans mon cas, puisque j'ai l'<a href="https://fr.wikipedia.org/wiki/Adresse_IP" target="_blank" rel="noopener noreferrer" class="">addresse IP</a> du client, je peux utiliser l'analyseur GeoIP pour trouver des métadonnées sur cette <a href="https://fr.wikipedia.org/wiki/Adresse_IP" target="_blank" rel="noopener noreferrer" class="">IP</a>. Maintenant, je peux déterminer le FAI, le pays et même la ville de ce client.</p>
<p>Voici un exemple :</p>
<div class="language-bind9 codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-bind9 codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">05-Nov-2021 14:07:16.442 queries: info: client @0x7f6b462b2900 X.X.X.X#38383 (zoom.us): query: zoom.us IN A + (10.70.2.235)</span><br></div></code></pre></div></div>
<div class="language-json codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-json codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"client"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain">  </span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"geoip"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> </span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token property">"as"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain">  </span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token property">"domain"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"online.net"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token property">"name"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"ONLINE S.A.S."</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token property">"number"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"AS12876"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token property">"route"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"51.15.0.0/16"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token property">"type"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"isp"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token property">"city"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token property">"name"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Paris"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token property">"continent"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token property">"code"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"EU"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token property">"name"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Europe"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token property">"country"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token property">"iso_code"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"FR"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token property">"name"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"France"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token property">"ipAddress"</span><span class="token plain"> </span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"X.X.X.X"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token property">"location"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token property">"latitude"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"48.85341"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string" style="color:rgb(255, 121, 198)">"longitude"</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"2.3488"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token property">"subdivision"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token property">"name"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Île-de-France"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token property">"timezone"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Europe/Paris"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="tableau-de-bord">Tableau de bord<a href="https://lunik.tiwabbit.fr/blog/fr/create-public-dns-service#tableau-de-bord" class="hash-link" aria-label="Lien direct vers Tableau de bord" title="Lien direct vers Tableau de bord" translate="no">​</a></h3>
<p>Je peux maintenant commencer la partie amusante de l'utilisation d'un service de surveillance : Make Dashboard and Graphs !</p>
<p>Voici ceux que j'ai créés :</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2021-12-24-create-public-dns-service/datadog-dashboard-01.png" alt="datadog-dashboard-overview" class="img__Ss2">
<img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2021-12-24-create-public-dns-service/datadog-dashboard-02.png" alt="datadog-dashboard-queries-by-code" class="img__Ss2">
<img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2021-12-24-create-public-dns-service/datadog-dashboard-03.png" alt="datadog-dashboard-client-by-location" class="img__Ss2"></p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="conclusion">Conclusion<a href="https://lunik.tiwabbit.fr/blog/fr/create-public-dns-service#conclusion" class="hash-link" aria-label="Lien direct vers Conclusion" title="Lien direct vers Conclusion" translate="no">​</a></h2>
<p>J'ai maintenant un serveur public <a href="https://tools.ietf.org/html/rfc2929" target="_blank" rel="noopener noreferrer" class="">DNS</a> pleinement opérationnel. Je peux maintenant faire des configurations avancées si je veux, comme bloquer certains noms de domaine (malware, trucs illégaux, ...).</p>
<p>Note : Si vous souhaitez rendre votre <a href="https://tools.ietf.org/html/rfc2929" target="_blank" rel="noopener noreferrer" class="">DNS</a> public accessible à tous, vous pouvez le publier sur <a href="https://public-dns.info/" target="_blank" rel="noopener noreferrer" class="">public-dns.info</a></p>]]></content>
        <author>
            <name>Guillaume MARTINEZ</name>
            <uri>https://github.com/Lunik</uri>
        </author>
        <category label="dns" term="dns"/>
        <category label="server" term="server"/>
        <category label="public" term="public"/>
        <category label="bind9" term="bind9"/>
        <category label="bind" term="bind"/>
        <category label="named" term="named"/>
        <category label="cloud" term="cloud"/>
        <category label="scaleway" term="scaleway"/>
        <category label="datadog" term="datadog"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Pourquoi la règle `W1203` est importante]]></title>
        <id>https://lunik.tiwabbit.fr/blog/fr/python-logging-fstring-interpolation</id>
        <link href="https://lunik.tiwabbit.fr/blog/fr/python-logging-fstring-interpolation"/>
        <updated>2021-10-13T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[`W1203: logging-fstring-interpolation` est une règle pylint avertissant sur un problème de performances potentiels]]></summary>
        <content type="html"><![CDATA[<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2021-10-13-python-logging-fstring-interpolation/cover.jpg" alt="cover" class="img__Ss2"></p>
<p>Si vous avez utilisé l'outil <a href="https://pylint.pycqa.org/" target="_blank" rel="noopener noreferrer" class="">pylint</a> pour vérifier le format de votre code Python, vous avez peut-être rencontré la règle <code>W1203 : logging-fstring-interpolation</code> mais vous n'avez pas vraiment compris pourquoi c'est important.</p>
<p>L'avertissement ressemble à :</p>
<div class="language-bash codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-bash codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">path/to/my/file.py:37:4: W1203: Use lazy % formatting </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">in</span><span class="token plain"> logging functions </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">logging-fstring-interpolation</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></div></code></pre></div></div>
<p>Il se trouve lorsque vous utilisez la <a href="https://docs.python.org/3/library/logging.html" target="_blank" rel="noopener noreferrer" class="">bibliothèque Python <code>logging</code></a>. La documentation <a href="https://pylint.pycqa.org/" target="_blank" rel="noopener noreferrer" class="">pylint</a> sur cette règle dit que vous ne devez pas utiliser de chaînes formatées de type <code>f-string</code>.</p>
<p>L'exemple donné est :</p>
<p><strong>Code problématique :</strong></p>
<div class="language-python codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-python codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> logging</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> sys</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">error</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">f'Python version: </span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">sys</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token string-interpolation interpolation">version</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)"># [logging-fstring-interpolation]</span><br></div></code></pre></div></div>
<p><strong>Code correct :</strong></p>
<div class="language-python codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-python codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> logging</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> sys</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">error</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">'Python version: %s'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> sys</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">version</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></div></code></pre></div></div>
<p><strong>Mais pourquoi utiliser la chaîne <code>f-string</code> dans le contexte de journalisation est une mauvaise idée et peut avoir un impact énorme sur les performances de votre application ??</strong></p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="la-bibliothèque-de-journalisation">La bibliothèque de journalisation<a href="https://lunik.tiwabbit.fr/blog/fr/python-logging-fstring-interpolation#la-biblioth%C3%A8que-de-journalisation" class="hash-link" aria-label="Lien direct vers La bibliothèque de journalisation" title="Lien direct vers La bibliothèque de journalisation" translate="no">​</a></h2>
<p>La <a href="https://docs.python.org/3/library/logging.html" target="_blank" rel="noopener noreferrer" class="">bibliothèque Python <code>logging</code></a> est la bibliothèque standard pour implémenter la journalisation dans une application ou un script. Il remplace l'instruction <code>print</code> traditionnelle.
Il permet d'avoir un format de sortie de journal unifié et de sélectionner le niveau de verbosité à la volée.</p>
<p>En utilisant la <a href="https://docs.python.org/3/library/logging.html" target="_blank" rel="noopener noreferrer" class="">bibliothèque <code>logging</code></a> vous pouvez affichez les journaux (sur la <code>stdout</code> ou dans un fichier) avec plusieurs niveaux comme : <code>info</code>, <code>warning</code>, <code>error</code>, <code>debug</code>, <a href="https://docs.python.org/3/library/logging.html#levels" target="_blank" rel="noopener noreferrer" class="">en savoir plus</a>.
Vous pouvez ensuite définir le niveau de verbosité des logs parmi l'un d'entre eux.</p>
<p>Par exemple, si vous avez décidé de ne vouloir que des logs utiles lors de l'exécution en production, vous définirez le niveau de log sur <code>error</code>. Seul les logs avec le niveau <code>error</code> ou <code>critical</code> seront affichées. Mais si vous êtes dans un environnement de développement, vous souhaiterez peut-être être au niveau de log <code>debug</code> pour afficher tous les logs possibles.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="quel-est-le-problème-alors-">Quel est le problème alors ?<a href="https://lunik.tiwabbit.fr/blog/fr/python-logging-fstring-interpolation#quel-est-le-probl%C3%A8me-alors-" class="hash-link" aria-label="Lien direct vers Quel est le problème alors ?" title="Lien direct vers Quel est le problème alors ?" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="exemple-complet">Exemple complet<a href="https://lunik.tiwabbit.fr/blog/fr/python-logging-fstring-interpolation#exemple-complet" class="hash-link" aria-label="Lien direct vers Exemple complet" title="Lien direct vers Exemple complet" translate="no">​</a></h3>
<p>Dans un environnement de production, si vous avez des logs de type <code>debug</code> qui appellent d'autres fonctions, ceux-ci seront interpolés même si elles ne seront jamais affichées.</p>
<p>Par exemple vous avez un code simple :</p>
<div class="language-python codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-python codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> logging</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> sys</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> datetime </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> datetime</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">logger </span><span class="token operator">=</span><span class="token plain"> logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">getLogger</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">handler </span><span class="token operator">=</span><span class="token plain"> logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">StreamHandler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">sys</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">stdout</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">logger</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">addHandler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">handler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># In production</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">logger</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">setLevel</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"INFO"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># In development</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># logger.setLevel("DEBUG")</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">handle_incoming_message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  logger</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">debug</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">f"[</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">datetime</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token string-interpolation interpolation">now</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">] New message received : '</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">message</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">'"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">len</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> __name__ </span><span class="token operator">==</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"__main__"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  total </span><span class="token operator">=</span><span class="token plain"> </span><span class="token number">0</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">for</span><span class="token plain"> i </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">in</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">range</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token number">10000000</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    total </span><span class="token operator">+=</span><span class="token plain"> handle_incoming_message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"my custom message"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  logger</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">info</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">f"The total is : </span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">total</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></div></code></pre></div></div>
<p>Vous appelez une fonction <code>handle_incoming_message</code> sur chaque message entrant reçu par votre application. Vous comptez le nombre de lettres dans le message et le renvoyez. Enfin, vous comptez le nombre total de lettres dans tous les messages.</p>
<p>Dans l'environnement de développement, vous souhaitez avoir une log de debug à chaque fois que vous recevez un message (à des fins de débogage). Mais vous ne vous souciez pas de ces logs lors de l'exécution en production.</p>
<p>L'exécution de ce code en développement a pris <code>116,40s</code> avec <code>10000001</code> ligne de logs affichées</p>
<p>L'exécution de ce code en production a pris <code>16,99s</code> avec uniquement une ligne de log (la dernière)</p>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="peut-on-optimiser-la-durée-du-script-en-production-">Peut-on optimiser la durée du script en production ?<a href="https://lunik.tiwabbit.fr/blog/fr/python-logging-fstring-interpolation#peut-on-optimiser-la-dur%C3%A9e-du-script-en-production-" class="hash-link" aria-label="Lien direct vers Peut-on optimiser la durée du script en production ?" title="Lien direct vers Peut-on optimiser la durée du script en production ?" translate="no">​</a></h3>
<p>Le changement de la ligne :</p>
<div class="language-python codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-python codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">logger</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">debug</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">f"[</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">datetime</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token string-interpolation interpolation">now</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">] New message received : '</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">message</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">'"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></div></code></pre></div></div>
<p>Par :</p>
<div class="language-python codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-python codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">logger</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">debug</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"[%s] New message received : '%s'"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> datetime</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">now</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></div></code></pre></div></div>
<p>Devrait produire exactement le même résultat mais en moins de temps.</p>
<p>L'exécution de ce code en développement a pris <code>112,81s</code> avec <code>10000001</code> ligne de logs affichées</p>
<p>L'exécution de ce code en production a pris <code>8,54s</code> avec uniquement une ligne de log (la dernière)</p>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="comment-avons-nous-gagné-du-temps-">Comment avons-nous gagné du temps ?<a href="https://lunik.tiwabbit.fr/blog/fr/python-logging-fstring-interpolation#comment-avons-nous-gagn%C3%A9-du-temps-" class="hash-link" aria-label="Lien direct vers Comment avons-nous gagné du temps ?" title="Lien direct vers Comment avons-nous gagné du temps ?" translate="no">​</a></h3>
<p>Comment le simple fait de changer le format de la chaîne de log peut-il nous permettre d'exécuter le même script en deux fois moins de temps ?</p>
<p>Dans la première solution :</p>
<div class="language-python codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-python codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">logger</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">debug</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">f"[</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">datetime</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token string-interpolation interpolation">now</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">] New message received : '</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">message</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">'"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></div></code></pre></div></div>
<p>Python appellera d'abord la fonction de format de chaîne pour faire le rendu de la chaîne, puis appellera le <code>logger.debug</code></p>
<p>Dans le deuxième exemple :</p>
<div class="language-python codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-python codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">logger</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">debug</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"[%s] New message received : '%s'"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> datetime</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">now</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></div></code></pre></div></div>
<p>Nous appelons directement le <code>logger.debug</code> avec plusieurs arguments. Dans l'algorithme de la fonction de logging, la fonction de format de chaîne sera appelée avec tous les arguments passés à la fonction <strong>uniquement si</strong> la log doit être affichée à l'utilisateur (selon le niveau de log).</p>
<p>En choisissant le deuxième code plutôt que l'autre, nous économisons un appel de fonction et ainsi du temps.
Dans l'exemple, l'appel qui prend du temps est <code>datetime.now()</code> mais vous devez imaginer que cet appel pourrait être un autre appel plus lent dans votre application !</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="conclusion">Conclusion<a href="https://lunik.tiwabbit.fr/blog/fr/python-logging-fstring-interpolation#conclusion" class="hash-link" aria-label="Lien direct vers Conclusion" title="Lien direct vers Conclusion" translate="no">​</a></h2>
<p>En utilisant les capacités de formatage de chaîne intégré <a href="https://docs.python.org/3/library/logging.html" target="_blank" rel="noopener noreferrer" class="">bibliothèque Python <code>logging</code></a>, vous pouvez gagner beaucoup de temps et rendre votre application ou votre script plus rapide et réactif.</p>
<p>Merci pylint pour l'avertissement.</p>]]></content>
        <author>
            <name>Guillaume MARTINEZ</name>
            <uri>https://github.com/Lunik</uri>
        </author>
        <category label="python" term="python"/>
        <category label="pylint" term="pylint"/>
        <category label="performance" term="performance"/>
        <category label="logging" term="logging"/>
        <category label="log" term="log"/>
        <category label="error" term="error"/>
        <category label="warning" term="warning"/>
        <category label="debug" term="debug"/>
        <category label="info" term="info"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Sécurisation de mon point d'entrée web]]></title>
        <id>https://lunik.tiwabbit.fr/blog/fr/secure-home-entrypoint</id>
        <link href="https://lunik.tiwabbit.fr/blog/fr/secure-home-entrypoint"/>
        <updated>2021-10-13T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[J'explique comment j'ai sécurisé mon point d'entré web des menaces externes]]></summary>
        <content type="html"><![CDATA[<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2021-10-13-secure-home-entrypoint/cover.jpg" alt="cover" class="img__Ss2"></p>
<p>J'héberge actuellement des services web privés accessibles depuis Internet. Afin de protéger ces applications, j'avais besoin d'un moyen plutôt sécurisé pour protéger l'accès à ces dernier.</p>
<p>Comme vous le savez peut-être déjà, il existe des tonnes de robots/bots qui analysent en permanence toutes les adresses IP publiques d'Internet à la recherche de potentielles vulnérabilités. Des ports ouverts, des services web non sécurisés ou des failles de sécurité.
Il existe des organisations privées qui permettent de découvrir ces vulnérabilités comme <a href="https://www.shodan.io/" target="_blank" rel="noopener noreferrer" class="">Shodan</a>. Dans mon cas particulier, c'est la seule information qu'ils ont pu collecter sur mon IP publique :</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2021-10-13-secure-home-entrypoint/shodan-private-gateway-summary.png" alt="Résumé de mon IP publique Showdan" class="img__Ss2"></p>
<p>Je dois donc exposer mes services et y accéder de n'importe où sur Internet sans trop de complexité tout en m'assurant que je suis le seul à pouvoir les utiliser et que personne d'autre ne puisse accéder à mes données.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="théorie">Théorie<a href="https://lunik.tiwabbit.fr/blog/fr/secure-home-entrypoint#th%C3%A9orie" class="hash-link" aria-label="Lien direct vers Théorie" title="Lien direct vers Théorie" translate="no">​</a></h2>
<p>J'utilise le <a href="https://en.wikipedia.org/wiki/Zero_trust_security_model" target="_blank" rel="noopener noreferrer" class="">modèle Zero trust security</a>. Donc, par défaut, personne ni aucun appareil n'est digne de confiance.</p>
<p>La première étape consiste à configurer le pare-feu pour supprimer tout le trafic entrant, fermer tous les ports réseau, désactiver la connexion pour tous les utilisateurs, supprimer tous les packages inutiles et exécuter les démons.</p>
<blockquote>
<p><strong>Avertissement :</strong> Vous devez être extrêmement prudent lorsque vous fermez tout ou vous pourriez être bloqué hors de votre réseau/serveur sans possibilité de récupérer l'accès.</p>
</blockquote>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="disposition">Disposition<a href="https://lunik.tiwabbit.fr/blog/fr/secure-home-entrypoint#disposition" class="hash-link" aria-label="Lien direct vers Disposition" title="Lien direct vers Disposition" translate="no">​</a></h2>
<p>Voici donc une vue grosse maille de ma configuration réseau :</p>
<p><strong>Internet</strong> --&gt; <strong>IP publique</strong> --&gt; <strong>Pare-feu</strong> --&gt; <strong>Serveur de passerelle</strong> --&gt; <strong>Service d'entrée</strong> --&gt; <strong>Réseau privé</strong></p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="mise-en-œuvre">Mise en œuvre<a href="https://lunik.tiwabbit.fr/blog/fr/secure-home-entrypoint#mise-en-%C5%93uvre" class="hash-link" aria-label="Lien direct vers Mise en œuvre" title="Lien direct vers Mise en œuvre" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="pas-à-pas">Pas à pas<a href="https://lunik.tiwabbit.fr/blog/fr/secure-home-entrypoint#pas-%C3%A0-pas" class="hash-link" aria-label="Lien direct vers Pas à pas" title="Lien direct vers Pas à pas" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_SAay" id="ip-publique">IP publique<a href="https://lunik.tiwabbit.fr/blog/fr/secure-home-entrypoint#ip-publique" class="hash-link" aria-label="Lien direct vers IP publique" title="Lien direct vers IP publique" translate="no">​</a></h4>
<p>Bon ici il n'y a pas grand chose à sécuriser. L'adresse IP est fournie de manière statique par mon <a href="https://fr.wikipedia.org/wiki/Fournisseur_d%27acc%C3%A8s_%C3%A0_Internet" target="_blank" rel="noopener noreferrer" class="">FAI</a> et est publiquement visible et accessible.</p>
<h4 class="anchor anchorTargetStickyNavbar_SAay" id="pare-feu">Pare-feu<a href="https://lunik.tiwabbit.fr/blog/fr/secure-home-entrypoint#pare-feu" class="hash-link" aria-label="Lien direct vers Pare-feu" title="Lien direct vers Pare-feu" translate="no">​</a></h4>
<p>Cet appareil est la première ligne de sécurité.</p>
<p>Comme mentionné précédemment, j'utilise le <a href="https://en.wikipedia.org/wiki/Zero_trust_security_model" target="_blank" rel="noopener noreferrer" class="">modèle Zero trust security</a>, donc la première étape consiste à supprimer tout le trafic entrant par défaut.
Maintenant, personne ne peut m'atteindre de l'extérieur, mais le trafic de retour ne le peut pas non plus. Lorsque je fais une requête à un service extérieur, les données renvoyées sont supprimées au niveau du pare-feu. Pas très utile en effet.</p>
<p>La deuxième étape consiste ensuite à autoriser le retour du trafic (tout en continuant à supprimer tout le reste du trafic). Je peux le faire avec une simple <a href="https://fr.wikipedia.org/wiki/Network_address_translation" target="_blank" rel="noopener noreferrer" class="">traduction d'adresse réseau ou NAT</a>. De cette façon, lorsqu'un serveur du réseau privé fait une requête à un service public, la réponse peut traverser le pare-feu en toute sécurité. Cela peut s'avérer utile si vous souhaitez mettre à jour des packages sur votre serveur !
Tous les pare-feu prennent en charge nativement <a href="https://fr.wikipedia.org/wiki/Network_address_translation" target="_blank" rel="noopener noreferrer" class="">NAT</a>, il n'est donc pas très difficile de l'activer.</p>
<p>Ensuite, je veux autoriser l'accès public à mes services qui exposent les ports <a href="https://tools.ietf.org/html/rfc2818" target="_blank" rel="noopener noreferrer" class="">HTTPS</a>, donc <code>443/tcp</code>. J'ai activé la <a href="https://fr.wikipedia.org/wiki/Redirection_de_port" target="_blank" rel="noopener noreferrer" class="">redirection de ports</a> sur mon pare-feu afin que lorsque le trafic entrant/la requête arrive sur le port <code>443</code> avec le protocole <a href="https://tools.ietf.org/html/rfc793" target="_blank" rel="noopener noreferrer" class="">TCP</a>, il soit transmis à mon serveur de passerelle au sein de mon réseau privé.</p>
<blockquote>
<p><strong>Remarque :</strong> Le port exposé par mon serveur de passerelle n'a aucun impact sur la règle de transfert. Cela pourrait être <code>443</code> pour être cohérent ou cela pourrait être <code>8888</code>. Ce n'est pas grave.</p>
</blockquote>
<h4 class="anchor anchorTargetStickyNavbar_SAay" id="serveur-de-passerelle">Serveur de passerelle<a href="https://lunik.tiwabbit.fr/blog/fr/secure-home-entrypoint#serveur-de-passerelle" class="hash-link" aria-label="Lien direct vers Serveur de passerelle" title="Lien direct vers Serveur de passerelle" translate="no">​</a></h4>
<p>Mon serveur de passerelle actuel est basé sur <a href="https://fr.wikipedia.org/wiki/Linux" target="_blank" rel="noopener noreferrer" class="">Linux</a>. La distribution utilisée dans mon cas n'est pas pertinente.</p>
<h5 class="anchor anchorTargetStickyNavbar_SAay" id="pare-feu-local">Pare-feu local<a href="https://lunik.tiwabbit.fr/blog/fr/secure-home-entrypoint#pare-feu-local" class="hash-link" aria-label="Lien direct vers Pare-feu local" title="Lien direct vers Pare-feu local" translate="no">​</a></h5>
<p>Il est livré avec <a href="https://firewalld.org/" target="_blank" rel="noopener noreferrer" class="">firewalld</a> pré-installé qui me permet d'avoir un pare-feu local sur mon serveur. Étant donné que ma passerelle reçoit du trafic du monde extérieur, je dois contrôler ce qui peut entrer et sortir de ce serveur.</p>
<p>Pour ma configuration, j'ai choisi de rester simple. J'autorise uniquement le trafic entrant depuis le port <code>443/tcp</code> (et <code>22/tcp</code> depuis mon réseau privé pour administrer le serveur avec <a href="https://tools.ietf.org/html/rfc4253" target="_blank" rel="noopener noreferrer" class="">SSH</a>). Ensuite, j'autorise le trafic sortant (comme le <a href="https://fr.wikipedia.org/wiki/Network_address_translation" target="_blank" rel="noopener noreferrer" class="">NAT</a>) pour le flux de retour.</p>
<p>Avec la ligne de commande <a href="https://firewalld.org/" target="_blank" rel="noopener noreferrer" class="">firewalld</a> suivante, je peux voir ma configuration actuelle :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">firewall-cmd </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--zone</span><span class="token plain"> public --list-all</span><br></div></code></pre></div></div>
<p>Je reçois :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">public </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">active</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  target: default</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  icmp-block-inversion: no</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  interfaces: eth0</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  sources: </span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  services: https </span><span class="token function" style="color:rgb(80, 250, 123)">ssh</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  ports: </span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  protocols: </span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  forward: no</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  masquerade: no</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  forward-ports: </span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  source-ports: </span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  icmp-blocks: </span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  rich rules: </span><br></div></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_SAay" id="service-ingress">Service Ingress<a href="https://lunik.tiwabbit.fr/blog/fr/secure-home-entrypoint#service-ingress" class="hash-link" aria-label="Lien direct vers Service Ingress" title="Lien direct vers Service Ingress" translate="no">​</a></h4>
<p>J'utilise <a href="https://www.nginx.com/" target="_blank" rel="noopener noreferrer" class="">NGINX</a> comme service Ingress. Il est exécuté sur mon serveur de passerelle.
Son objectif est d'acheminer et de filtrer le trafic <a href="https://tools.ietf.org/html/rfc2818" target="_blank" rel="noopener noreferrer" class="">HTTPS</a> entrant.</p>
<h5 class="anchor anchorTargetStickyNavbar_SAay" id="filtrer-le-trafic-indésirable">Filtrer le trafic indésirable<a href="https://lunik.tiwabbit.fr/blog/fr/secure-home-entrypoint#filtrer-le-trafic-ind%C3%A9sirable" class="hash-link" aria-label="Lien direct vers Filtrer le trafic indésirable" title="Lien direct vers Filtrer le trafic indésirable" translate="no">​</a></h5>
<p>La première étape consiste à filtrer tous les <a href="https://tools.ietf.org/html/rfc2818" target="_blank" rel="noopener noreferrer" class="">HTTPS</a> qui ne vont pas à mon service exposé. Une première étape simple consiste à supprimer par défaut toutes les requêtes entrantes. Dans une configuration du site par défaut <code>/etc/nginx/conf.d/default.conf</code>, j'ai :</p>
<div class="language-nginx codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-nginx codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token directive keyword" style="color:rgb(189, 147, 249);font-style:italic">server</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token directive keyword" style="color:rgb(189, 147, 249);font-style:italic">listen</span><span class="token directive">      </span><span class="token directive number">443</span><span class="token directive"> default_server ssl</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token directive keyword" style="color:rgb(189, 147, 249);font-style:italic">server_name</span><span class="token directive"> _</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token directive keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token directive">      </span><span class="token directive number">444</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></div></code></pre></div></div>
<p>La première ligne avec le mot clé <code>listen</code> indique à <a href="https://www.nginx.com/" target="_blank" rel="noopener noreferrer" class="">NGINX</a> d'écouter sur le port <code>443</code> et de commencer une connexion sécurisée avec le client.</p>
<p>Dans cette configuration, <code>server_name _;</code> correspond à tout les <a href="https://fr.wikipedia.org/wiki/Server_Name_Indication" target="_blank" rel="noopener noreferrer" class="">Server Name Identification ou SNI</a> (ou indéfinis) dans les requêtes entrantes.</p>
<p>La ligne <code>return 444;</code> renvoie le <a href="https://fr.wikipedia.org/wiki/Liste_des_codes_HTTP" target="_blank" rel="noopener noreferrer" class="">code HTTP</a> <code>444</code> qui indique à <a href="https://www.nginx.com/" target="_blank" rel="noopener noreferrer" class="">NGINX</a> de fermer la connexion immédiatement.</p>
<p>Comme j'utilise de l'<a href="https://tools.ietf.org/html/rfc2818" target="_blank" rel="noopener noreferrer" class="">HTTPS</a>, je dois fournir un <a href="https://fr.wikipedia.org/wiki/X.509" target="_blank" rel="noopener noreferrer" class="">certificat X.509</a> pour les communications <a href="https://tools.ietf.org/html/rfc8446" target="_blank" rel="noopener noreferrer" class="">TLS</a>. J'ai fait une petite blague sur celui-ci parce que bon ... si vous êtes un étranger essayant d'accéder à mes trucs privés <em>GTFO</em>. Cela me donne :</p>
<div class="language-nginx codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-nginx codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token directive keyword" style="color:rgb(189, 147, 249);font-style:italic">server</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token directive keyword" style="color:rgb(189, 147, 249);font-style:italic">listen</span><span class="token directive">      </span><span class="token directive number">443</span><span class="token directive"> default_server ssl</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token directive keyword" style="color:rgb(189, 147, 249);font-style:italic">server_name</span><span class="token directive"> _</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token directive keyword" style="color:rgb(189, 147, 249);font-style:italic">ssl_certificate</span><span class="token directive">     /etc/pki/tls/certs/go.fuck.yourself.now.crt</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token directive keyword" style="color:rgb(189, 147, 249);font-style:italic">ssl_certificate_key</span><span class="token directive"> /etc/pki/tls/private/go.fuck.yourself.now.key</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token directive keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token directive">      </span><span class="token directive number">444</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></div></code></pre></div></div>
<p>J'utilise actuellement une clé privée <a href="https://tools.ietf.org/html/rfc8017" target="_blank" rel="noopener noreferrer" class="">RSA</a> <code>4096</code> bits de long.</p>
<p>Maintenant, si j'essaie de faire une requête stupide à mon service d'entrée comme :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">curl</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--insecure</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--verbose</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--header</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Host: dumb.example.org"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  https://mygateway.local</span><br></div></code></pre></div></div>
<p>J'ai la réponse :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">*   Trying XXX.XXX.XXX.XXX</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token plain">.</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">* TCP_NODELAY </span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">set</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">* Connected to mygateway.local </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">XXX.XXX.XXX.XXX</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> port </span><span class="token number">443</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token comment" style="color:rgb(98, 114, 164)">#0)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">* ALPN, offering h2</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">* ALPN, offering http/1.1</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">* successfully </span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">set</span><span class="token plain"> certificate verify locations:</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">*   CAfile: /etc/ssl/cert.pem</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  CApath: none</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">* TLSv1.2 </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">OUT</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain">, TLS handshake, Client hello </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token number">1</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain">:</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">* TLSv1.2 </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">IN</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain">, TLS handshake, Server hello </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token number">2</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain">:</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">* TLSv1.2 </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">IN</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain">, TLS handshake, Certificate </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token number">11</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain">:</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">* TLSv1.2 </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">IN</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain">, TLS handshake, Server key exchange </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token number">12</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain">:</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">* TLSv1.2 </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">IN</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain">, TLS handshake, Server finished </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token number">14</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain">:</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">* TLSv1.2 </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">OUT</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain">, TLS handshake, Client key exchange </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token number">16</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain">:</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">* TLSv1.2 </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">OUT</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain">, TLS change cipher, Change cipher spec </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token number">1</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain">:</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">* TLSv1.2 </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">OUT</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain">, TLS handshake, Finished </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token number">20</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain">:</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">* TLSv1.2 </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">IN</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain">, TLS change cipher, Change cipher spec </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token number">1</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain">:</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">* TLSv1.2 </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">IN</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain">, TLS handshake, Finished </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token number">20</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain">:</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">* ALPN, server accepted to use http/1.1</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">* Server certificate:</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">*  subject: </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">C</span><span class="token operator">=</span><span class="token plain">FR</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">L</span><span class="token operator">=</span><span class="token plain">Paris</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">O</span><span class="token operator">=</span><span class="token plain">Wabbit</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">CN</span><span class="token operator">=</span><span class="token plain">go.fuck.yourself.now</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">emailAddress</span><span class="token operator">=</span><span class="token plain">admin@wabbit</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">*  start date: May </span><span class="token number">29</span><span class="token plain"> </span><span class="token number">15</span><span class="token plain">:55:36 </span><span class="token number">2021</span><span class="token plain"> GMT</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">*  expire date: May </span><span class="token number">29</span><span class="token plain"> </span><span class="token number">15</span><span class="token plain">:55:36 </span><span class="token number">2022</span><span class="token plain"> GMT</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">*  issuer: </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">C</span><span class="token operator">=</span><span class="token plain">FR</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">L</span><span class="token operator">=</span><span class="token plain">Paris</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">O</span><span class="token operator">=</span><span class="token plain">Wabbit</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">CN</span><span class="token operator">=</span><span class="token plain">wabbit</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">emailAddress</span><span class="token operator">=</span><span class="token plain">admin@wabbit</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">*  SSL certificate verify ok.</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token operator">&gt;</span><span class="token plain"> GET / HTTP/1.1</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token operator">&gt;</span><span class="token plain"> Host: dumb.example.org</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token operator">&gt;</span><span class="token plain"> User-Agent: curl/7.64.1</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token operator">&gt;</span><span class="token plain"> Accept: */*</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token operator">&gt;</span><span class="token plain"> </span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">* Empty reply from server</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">* Connection </span><span class="token comment" style="color:rgb(98, 114, 164)">#0 to host mygateway.local left intact</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">curl: </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token number">52</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> Empty reply from server</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">* Closing connection </span><span class="token number">0</span><br></div></code></pre></div></div>
<p>Mon serveur Ingress m'envoie le certificat avec le nom commun <code>go.fuck.yourself.now</code> pour une communication sécurisée. Mon client fait une requête <code>GET</code> sur le chemin d'URI <code>/</code> avec l'hôte <code>dumb.example.org</code>.</p>
<p>Étant donné que mon serveur Ingress n'est pas configuré pour accepter les demandes de service portant le nom <code>dumb.example.org</code>, il ferme la connexion sans avertissement et mon client reçoit une <code>Empty reply from server</code>.</p>
<h5 class="anchor anchorTargetStickyNavbar_SAay" id="améliorer-la-connexion-sécurisée">Améliorer la connexion sécurisée<a href="https://lunik.tiwabbit.fr/blog/fr/secure-home-entrypoint#am%C3%A9liorer-la-connexion-s%C3%A9curis%C3%A9e" class="hash-link" aria-label="Lien direct vers Améliorer la connexion sécurisée" title="Lien direct vers Améliorer la connexion sécurisée" translate="no">​</a></h5>
<p>Par défaut <a href="https://www.nginx.com/" target="_blank" rel="noopener noreferrer" class="">NGINX</a> est très ouvert en terme de protocoles et de chiffrement permettant d'établir une connexion sécurisée. Dans le fichier de configuration principal <a href="https://www.nginx.com/" target="_blank" rel="noopener noreferrer" class="">NGINX</a>, situé dans <code>/etc/nginx/nginx.conf</code>, dans la section <code>http</code>, j'ai remplacé les options <code>ssl_</code> par :</p>
<div class="language-nginx codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-nginx codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token directive keyword" style="color:rgb(189, 147, 249);font-style:italic">ssl_protocols</span><span class="token directive"> TLSv1.2 TLSv1.3</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token directive keyword" style="color:rgb(189, 147, 249);font-style:italic">ssl_prefer_server_ciphers</span><span class="token directive"> </span><span class="token directive boolean">on</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token directive keyword" style="color:rgb(189, 147, 249);font-style:italic">ssl_ciphers</span><span class="token directive">         HIGH:!aNULL:!MD5</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></div></code></pre></div></div>
<p>Maintenant, mon service Ingress n'autorisera que <a href="https://tools.ietf.org/html/rfc8446" target="_blank" rel="noopener noreferrer" class="">TLS</a> <code>1.2</code> minimum (jusqu'à <code>1.3</code>) avec uniquement des chiffrements <code>HIGH</code>, pas <code>NULL</code> et pas <code>MD5</code> pour établir des connexions sécurisées avec le client. Le <code>ssl_prefer_server_ciphers</code> pour que le client essaie les chiffrements avec l'ordre fourni par le service Ingress.</p>
<p><a href="https://www.ssi.gouv.fr/uploads/2017/02/security-recommendations-for-tls_v1.1.pdf" target="_blank" rel="noopener noreferrer" class="">Recommandations TLS supplémentaires</a></p>
<h5 class="anchor anchorTargetStickyNavbar_SAay" id="tout-logguer">Tout logguer<a href="https://lunik.tiwabbit.fr/blog/fr/secure-home-entrypoint#tout-logguer" class="hash-link" aria-label="Lien direct vers Tout logguer" title="Lien direct vers Tout logguer" translate="no">​</a></h5>
<p>Par défaut, <a href="https://www.nginx.com/" target="_blank" rel="noopener noreferrer" class="">NGINX</a> log toutes les requêtes dans le fichier <code>/var/log/nginx/access.log</code> et toutes les erreurs dans <code>/var/log/nginx/error.log</code>. J'ai vérifié si c'était le cas pour mon instance. Dans le fichier de configuration principal <code>/etc/nginx/nginx.conf</code>, j'ai :</p>
<div class="language-nginx codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-nginx codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token directive keyword" style="color:rgb(189, 147, 249);font-style:italic">error_log</span><span class="token directive"> /var/log/nginx/error.log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></div></code></pre></div></div>
<p>et :</p>
<div class="language-nginx codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-nginx codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token directive keyword" style="color:rgb(189, 147, 249);font-style:italic">log_format</span><span class="token directive">  main  </span><span class="token directive string" style="color:rgb(255, 121, 198)">'</span><span class="token directive string variable" style="color:rgb(189, 147, 249);font-style:italic">$remote_addr</span><span class="token directive string" style="color:rgb(255, 121, 198)"> - </span><span class="token directive string variable" style="color:rgb(189, 147, 249);font-style:italic">$remote_user</span><span class="token directive string" style="color:rgb(255, 121, 198)"> [</span><span class="token directive string variable" style="color:rgb(189, 147, 249);font-style:italic">$time_local]</span><span class="token directive string" style="color:rgb(255, 121, 198)"> "</span><span class="token directive string variable" style="color:rgb(189, 147, 249);font-style:italic">$request</span><span class="token directive string" style="color:rgb(255, 121, 198)">" '</span><span class="token directive"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token directive">                  </span><span class="token directive string" style="color:rgb(255, 121, 198)">'</span><span class="token directive string variable" style="color:rgb(189, 147, 249);font-style:italic">$status</span><span class="token directive string" style="color:rgb(255, 121, 198)"> </span><span class="token directive string variable" style="color:rgb(189, 147, 249);font-style:italic">$body_bytes_sent</span><span class="token directive string" style="color:rgb(255, 121, 198)"> "</span><span class="token directive string variable" style="color:rgb(189, 147, 249);font-style:italic">$http_referer</span><span class="token directive string" style="color:rgb(255, 121, 198)">" '</span><span class="token directive"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token directive">                  </span><span class="token directive string" style="color:rgb(255, 121, 198)">'"</span><span class="token directive string variable" style="color:rgb(189, 147, 249);font-style:italic">$http_user_agent</span><span class="token directive string" style="color:rgb(255, 121, 198)">" "</span><span class="token directive string variable" style="color:rgb(189, 147, 249);font-style:italic">$http_x_forwarded_for</span><span class="token directive string" style="color:rgb(255, 121, 198)">"'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token directive keyword" style="color:rgb(189, 147, 249);font-style:italic">access_log</span><span class="token directive">  /var/log/nginx/access.log  main</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></div></code></pre></div></div>
<p>Dans <code>/var/log/nginx/access.log</code>, je peux voir ma requête de test précédente :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">XXX.XXX.XXX.XXX - - </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token number">10</span><span class="token plain">/Oct/2021:15:55:36 +0000</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"GET / HTTP/1.1"</span><span class="token plain"> </span><span class="token number">444</span><span class="token plain"> </span><span class="token number">0</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"-"</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"curl/7.64.1"</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"-"</span><br></div></code></pre></div></div>
<h5 class="anchor anchorTargetStickyNavbar_SAay" id="exposer-un-service">Exposer un service<a href="https://lunik.tiwabbit.fr/blog/fr/secure-home-entrypoint#exposer-un-service" class="hash-link" aria-label="Lien direct vers Exposer un service" title="Lien direct vers Exposer un service" translate="no">​</a></h5>
<p>Maintenant que toutes mes connexions sont filtrées, je souhaite exposer mes services. Pour ce faire, j'ai ajouté un nouveau fichier de configuration dans <code>/etc/nginx/conf.d</code> avec le contenu suivant :</p>
<div class="language-nginx codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-nginx codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token directive keyword" style="color:rgb(189, 147, 249);font-style:italic">server</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token directive keyword" style="color:rgb(189, 147, 249);font-style:italic">listen</span><span class="token directive">      </span><span class="token directive number">443</span><span class="token directive"> ssl</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token directive keyword" style="color:rgb(189, 147, 249);font-style:italic">server_name</span><span class="token directive"> myapp.example.org</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token directive keyword" style="color:rgb(189, 147, 249);font-style:italic">ssl_certificate</span><span class="token directive">     /etc/pki/tls/certs/myapp.example.org.crt</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token directive keyword" style="color:rgb(189, 147, 249);font-style:italic">ssl_certificate_key</span><span class="token directive"> /etc/pki/tls/private/myapp.example.org.key</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token directive keyword" style="color:rgb(189, 147, 249);font-style:italic">location</span><span class="token directive"> /</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token directive keyword" style="color:rgb(189, 147, 249);font-style:italic">proxy_pass</span><span class="token directive"> https://myapp.local</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token directive keyword" style="color:rgb(189, 147, 249);font-style:italic">proxy_set_header</span><span class="token directive"> Host </span><span class="token directive variable" style="color:rgb(189, 147, 249);font-style:italic">$host</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token directive keyword" style="color:rgb(189, 147, 249);font-style:italic">proxy_set_header</span><span class="token directive"> X-Real-IP </span><span class="token directive variable" style="color:rgb(189, 147, 249);font-style:italic">$remote_addr</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token directive keyword" style="color:rgb(189, 147, 249);font-style:italic">proxy_set_header</span><span class="token directive"> X-Forwarded-For </span><span class="token directive variable" style="color:rgb(189, 147, 249);font-style:italic">$proxy_add_x_forwarded_for</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></div></code></pre></div></div>
<p>Si une demande arrive avec le <a href="https://fr.wikipedia.org/wiki/Server_Name_Indication" target="_blank" rel="noopener noreferrer" class="">SNI</a> <code>myapp.example.org</code>, elle est acceptée par le service Ingress. <a href="https://www.nginx.com/" target="_blank" rel="noopener noreferrer" class="">NGINX</a> va utiliser le certificat <code>myapp.example.org.crt</code> pour établir une connexion sécurisée avec le client. Ensuite, il transférera tout le trafic vers mon application privée sur <code>https://myapp.local</code> en utilisant la <a href="https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/" target="_blank" rel="noopener noreferrer" class="">configuration proxy d'NGINX</a>.</p>
<h5 class="anchor anchorTargetStickyNavbar_SAay" id="identification-des-clients">Identification des clients<a href="https://lunik.tiwabbit.fr/blog/fr/secure-home-entrypoint#identification-des-clients" class="hash-link" aria-label="Lien direct vers Identification des clients" title="Lien direct vers Identification des clients" translate="no">​</a></h5>
<p>Étant donné que je souhaite accéder à mes applications depuis n'importe où en dehors de mon réseau privé, je dois autoriser les requêtes entrantes de toutes les adresses IP publiques potentielles.
Mais je veux toujours pouvoir identifier mes appareils parmi toutes les IP publiques.</p>
<p>J'ai décidé d'implémenter l'authentification par [certificat client][certificat-client-wikipedia]. J'ai généré un <a href="https://fr.wikipedia.org/wiki/X.509" target="_blank" rel="noopener noreferrer" class="">certificat X.509</a> privé et unique pour chacun de mes appareils (PC, téléphone, ...) et je les ai installés.</p>
<p>J'ai ensuite configuré mon service Ingress pour demander le <a href="https://en.wikipedia.org/wiki/Client_certificate" target="_blank" rel="noopener noreferrer" class="">certificat client</a> lorsqu'un client souhaite accéder à un service exposé. En complétant la configuration précédente, j'obtiens :</p>
<div class="language-nginx codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-nginx codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token directive keyword" style="color:rgb(189, 147, 249);font-style:italic">server</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token directive keyword" style="color:rgb(189, 147, 249);font-style:italic">listen</span><span class="token directive">      </span><span class="token directive number">443</span><span class="token directive"> ssl</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token directive keyword" style="color:rgb(189, 147, 249);font-style:italic">server_name</span><span class="token directive"> myapp.example.org</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token directive keyword" style="color:rgb(189, 147, 249);font-style:italic">ssl_certificate</span><span class="token directive">     /etc/pki/tls/certs/myapp.example.org.crt</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token directive keyword" style="color:rgb(189, 147, 249);font-style:italic">ssl_certificate_key</span><span class="token directive"> /etc/pki/tls/private/myapp.example.org.key</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)"># make verification optional, so we can display a 403 message to those</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)"># who fail authentication</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token directive keyword" style="color:rgb(189, 147, 249);font-style:italic">ssl_verify_client</span><span class="token directive"> </span><span class="token directive boolean">on</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token directive keyword" style="color:rgb(189, 147, 249);font-style:italic">ssl_client_certificate</span><span class="token directive"> /etc/pki/tls/certs/users.example.org.crt</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token directive keyword" style="color:rgb(189, 147, 249);font-style:italic">location</span><span class="token directive"> /</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token directive keyword" style="color:rgb(189, 147, 249);font-style:italic">proxy_pass</span><span class="token directive"> https://myapp.local</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token directive keyword" style="color:rgb(189, 147, 249);font-style:italic">proxy_set_header</span><span class="token directive"> Host </span><span class="token directive variable" style="color:rgb(189, 147, 249);font-style:italic">$host</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token directive keyword" style="color:rgb(189, 147, 249);font-style:italic">proxy_set_header</span><span class="token directive"> X-Real-IP </span><span class="token directive variable" style="color:rgb(189, 147, 249);font-style:italic">$remote_addr</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token directive keyword" style="color:rgb(189, 147, 249);font-style:italic">proxy_set_header</span><span class="token directive"> X-Forwarded-For </span><span class="token directive variable" style="color:rgb(189, 147, 249);font-style:italic">$proxy_add_x_forwarded_for</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></div></code></pre></div></div>
<p><code>ssl_verify_client</code> force l'utilisateur à fournir un <a href="https://en.wikipedia.org/wiki/Client_certificate" target="_blank" rel="noopener noreferrer" class="">certificat client</a> pour l'authentification. Sinon, la connexion est fermée avec le code <code>400</code>.</p>
<p><code>ssl_certificate_key</code> fournit l'<a href="https://fr.wikipedia.org/wiki/Autorit%C3%A9_de_certification" target="_blank" rel="noopener noreferrer" class="">autorité de certification ou CA</a> qui a signé les certificats des clients.</p>
<p>Maintenant, si j'essaie de faire une demande sur <code>myapp.example.org</code> sans le <a href="https://en.wikipedia.org/wiki/Client_certificate" target="_blank" rel="noopener noreferrer" class="">certificat client</a> :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">curl</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--insecure</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--include</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  https://myapp.example.org</span><br></div></code></pre></div></div>
<p>Je reçois :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">HTTP/1.1 </span><span class="token number">400</span><span class="token plain"> Bad Request</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">Server: nginx/1.20.1</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">Date: Sun, </span><span class="token number">10</span><span class="token plain"> Oct </span><span class="token number">2021</span><span class="token plain"> </span><span class="token number">17</span><span class="token plain">:35:05 GMT</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">Content-Type: text/html</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">Content-Length: </span><span class="token number">237</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">Connection: close</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token operator">&lt;</span><span class="token plain">html</span><span class="token operator">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token operator">&lt;</span><span class="token plain">head</span><span class="token operator">&gt;</span><span class="token operator">&lt;</span><span class="token plain">title</span><span class="token operator">&gt;</span><span class="token number">400</span><span class="token plain"> No required SSL certificate was sent</span><span class="token operator">&lt;</span><span class="token plain">/title</span><span class="token operator">&gt;</span><span class="token operator">&lt;</span><span class="token plain">/head</span><span class="token operator">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token operator">&lt;</span><span class="token plain">body</span><span class="token operator">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token operator">&lt;</span><span class="token plain">center</span><span class="token operator">&gt;</span><span class="token operator">&lt;</span><span class="token plain">h</span><span class="token operator file-descriptor important">1</span><span class="token operator">&gt;</span><span class="token number">400</span><span class="token plain"> Bad Request</span><span class="token operator">&lt;</span><span class="token plain">/h</span><span class="token operator file-descriptor important">1</span><span class="token operator">&gt;</span><span class="token operator">&lt;</span><span class="token plain">/center</span><span class="token operator">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token operator">&lt;</span><span class="token plain">center</span><span class="token operator">&gt;</span><span class="token plain">No required SSL certificate was sent</span><span class="token operator">&lt;</span><span class="token plain">/center</span><span class="token operator">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token operator">&lt;</span><span class="token plain">hr</span><span class="token operator">&gt;</span><span class="token operator">&lt;</span><span class="token plain">center</span><span class="token operator">&gt;</span><span class="token plain">nginx/1.20.</span><span class="token operator file-descriptor important">1</span><span class="token operator">&lt;</span><span class="token plain">/center</span><span class="token operator">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token operator">&lt;</span><span class="token plain">/body</span><span class="token operator">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token operator">&lt;</span><span class="token plain">/html</span><span class="token operator">&gt;</span><br></div></code></pre></div></div>
<p>Le serveur Ingress rejette ma demande avec le code <code>400</code> car je n'ai pas fourni le <a href="https://en.wikipedia.org/wiki/Client_certificate" target="_blank" rel="noopener noreferrer" class="">certificat client</a> requis.</p>
<p>Essayons à nouveau en fournissant le <a href="https://en.wikipedia.org/wiki/Client_certificate" target="_blank" rel="noopener noreferrer" class="">certificat client</a> :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">curl</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--insecure</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--include</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--cert</span><span class="token plain"> lunik.pem </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  https://myapp.example.org</span><br></div></code></pre></div></div>
<p>Je reçois :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">HTTP/1.1 </span><span class="token number">302</span><span class="token plain"> Found</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">Server: nginx/1.20.1</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">Date: Sun, </span><span class="token number">10</span><span class="token plain"> Oct </span><span class="token number">2021</span><span class="token plain"> </span><span class="token number">17</span><span class="token plain">:35:36 GMT</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">Content-Type: text/plain</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">charset</span><span class="token operator">=</span><span class="token plain">utf-8</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">Content-Length: </span><span class="token number">30</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">Connection: keep-alive</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">Content-Language: en</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">Location: /login</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">Referrer-Policy: same-origin</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">Vary: Accept, Accept-Encoding</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">X-Content-Type-Options: nosniff</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">X-Frame-Options: deny</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">X-Xss-Protection: </span><span class="token number">1</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">mode</span><span class="token operator">=</span><span class="token plain">block</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">Found. Redirecting to /login</span><br></div></code></pre></div></div>
<p>Ca fonctionne !</p>
<h4 class="anchor anchorTargetStickyNavbar_SAay" id="fail2ban">Fail2ban<a href="https://lunik.tiwabbit.fr/blog/fr/secure-home-entrypoint#fail2ban" class="hash-link" aria-label="Lien direct vers Fail2ban" title="Lien direct vers Fail2ban" translate="no">​</a></h4>
<p>Maintenant que je peux accéder en toute sécurité à mes services privés, je veux toujours empêcher les utilisateurs ou les bots indésirables de faire du <a href="https://fr.wikipedia.org/wiki/Attaque_par_force_brute" target="_blank" rel="noopener noreferrer" class="">brute force</a> ou des <a href="https://fr.wikipedia.org/wiki/Attaque_par_d%C3%A9ni_de_service" target="_blank" rel="noopener noreferrer" class="">DDOS</a> sur mon serveur de passerelle.</p>
<p>J'utilise actuellement <a href="https://www.fail2ban.org/" target="_blank" rel="noopener noreferrer" class="">Fail2ban</a> pour bloquer ces comportements. Il analyse en permanence les logs du service Ingress pour identifier les demandes malveillantes faites par les clients publics.</p>
<p>J'ai créé un <code>filter</code> personnalisé qui correspond à toutes les demandes renvoyant un code <code>444</code>. Si vous vous souvenez bien, ce code est renvoyé par ma configuration <a href="https://www.nginx.com/" target="_blank" rel="noopener noreferrer" class="">NGINX</a> si le client demande un <a href="https://fr.wikipedia.org/wiki/Server_Name_Indication" target="_blank" rel="noopener noreferrer" class="">SNI</a> inconnu.
La configuration du filtre (<code>/etc/fail2ban/filter.d/nginx-444.conf</code>) ressemble à :</p>
<div class="language-toml codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-toml codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">[Definition]</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">failregex = ^&lt;HOST&gt;.*"(\w+).*" (444) .*$</span><br></div></code></pre></div></div>
<p>Ensuite, j'ai une <code>jail</code> qui implémente ce <code>filter</code>. Le fichier <code>/etc/fail2ban/jail.d/block-malicious-users.conf</code> contient :</p>
<div class="language-toml codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-toml codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">[DEFAULT]</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">ignoreip = 127.0.0.1 XXX.XXX.XXX.XXX YYY.YYY.YYY.YYY</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">findtime = 3600</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">bantime = 31536000</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">maxretry = 1</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">[nginx-444]</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">enabled = true</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">logpath  = /var/log/nginx/*.log</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"># Ban IP</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">action = %(banaction_allports)s </span><br></div></code></pre></div></div>
<p>Si <a href="https://www.fail2ban.org/" target="_blank" rel="noopener noreferrer" class="">Fail2ban</a> trouve dans le fichier <code>logpath</code>, au moins <code>maxretry</code> requêtes échouées dans une fenêtre de temps <code>findtime</code>. Il interdira l'IP pendant <code>bantime</code> secondes.</p>
<blockquote>
<p><strong>Remarques :</strong> J'ai ignoré l'adresse de l'hôte local, l'IP de mon PC d'administration (<code>XXX.XXX.XXX.XXX</code>) et l'IP publique de la passerelle <code>YYY.YYY.YYY.YYY</code> pour empêcher <a href="https://www.fail2ban.org/" target="_blank" rel="noopener noreferrer" class="">Fail2ban</a> de me bannir lorsque je teste la configuration.</p>
</blockquote>
<h5 class="anchor anchorTargetStickyNavbar_SAay" id="vérifier-les-ip-bannies">Vérifier les IP bannies<a href="https://lunik.tiwabbit.fr/blog/fr/secure-home-entrypoint#v%C3%A9rifier-les-ip-bannies" class="hash-link" aria-label="Lien direct vers Vérifier les IP bannies" title="Lien direct vers Vérifier les IP bannies" translate="no">​</a></h5>
<p>Je peux déjà voir des client banni des précédentes requêtes ayant échoué. Quand j'utilise la commande <a href="https://www.fail2ban.org/" target="_blank" rel="noopener noreferrer" class="">Fail2ban</a> de statuts :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">fail2ban-client status nginx-444</span><br></div></code></pre></div></div>
<p>J'ai :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">Status </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">for</span><span class="token plain"> the jail: nginx-444</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token operator">|</span><span class="token plain">- Filter</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token operator">|</span><span class="token plain">  </span><span class="token operator">|</span><span class="token plain">- Currently failed: </span><span class="token number">0</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token operator">|</span><span class="token plain">  </span><span class="token operator">|</span><span class="token plain">- Total failed: </span><span class="token number">3</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token operator">|</span><span class="token plain">  </span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">`</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">- File list:  /var/log/nginx/error.log /var/log/nginx/custom-access.log /var/log/nginx/access.log</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic"></span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">`</span><span class="token plain">- Actions</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">   </span><span class="token operator">|</span><span class="token plain">- Currently banned: </span><span class="token number">3</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">   </span><span class="token operator">|</span><span class="token plain">- Total banned: </span><span class="token number">3</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">   `- Banned IP list: XXX.XXX.XXX.XXX YYY.YYY.YYY.YYY ZZZ.ZZZ.ZZZ.ZZZ</span><br></div></code></pre></div></div>
<p>En vérifiant <a href="https://firewalld.org/" target="_blank" rel="noopener noreferrer" class="">firewalld</a> pour les règles de suppressions de paquets provenant de ces IP avec la commande :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">firewall-cmd </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--zone</span><span class="token plain"> public --list-all</span><br></div></code></pre></div></div>
<p>J'ai :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">public </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">active</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  target: default</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  icmp-block-inversion: no</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  interfaces: eth0</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  sources: </span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  services: dhcpv6-client https mdns </span><span class="token function" style="color:rgb(80, 250, 123)">ssh</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  ports: </span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  protocols: </span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  forward: no</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  masquerade: no</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  forward-ports: </span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  source-ports: </span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  icmp-blocks: </span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  rich rules: </span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  rule </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">family</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"ipv4"</span><span class="token plain"> </span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">source</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">address</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"XXX.XXX.XXX.XXX"</span><span class="token plain"> port </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">port</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"0-65535"</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">protocol</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"tcp"</span><span class="token plain"> reject </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">type</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"icmp-port-unreachable"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  rule </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">family</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"ipv4"</span><span class="token plain"> </span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">source</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">address</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"YYY.YYY.YYY.YYY"</span><span class="token plain"> port </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">port</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"0-65535"</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">protocol</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"tcp"</span><span class="token plain"> reject </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">type</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"icmp-port-unreachable"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  rule </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">family</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"ipv4"</span><span class="token plain"> </span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">source</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">address</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"ZZZ.ZZZ.ZZZ.ZZZ"</span><span class="token plain"> port </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">port</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"0-65535"</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">protocol</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"tcp"</span><span class="token plain"> reject </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">type</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"icmp-port-unreachable"</span><br></div></code></pre></div></div>
<p>Cela semble bon !</p>
<p>Je banni généralement environ <code>6,5</code> IP par jour :</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2021-10-13-secure-home-entrypoint/ban-rate-fail2ban.jpg" alt="Ban rate fail2ban" class="img__Ss2"></p>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="conclusion">Conclusion<a href="https://lunik.tiwabbit.fr/blog/fr/secure-home-entrypoint#conclusion" class="hash-link" aria-label="Lien direct vers Conclusion" title="Lien direct vers Conclusion" translate="no">​</a></h3>
<p>Sur chacune de mes couches j'ai implémenté :</p>
<ul>
<li class="">
<p><strong>Pare-feu :</strong></p>
<ul>
<li class="">Supprimer tout le trafic entrant</li>
<li class=""><a href="https://fr.wikipedia.org/wiki/Network_address_translation" target="_blank" rel="noopener noreferrer" class="">NAT</a></li>
<li class=""><a href="https://fr.wikipedia.org/wiki/Redirection_de_port" target="_blank" rel="noopener noreferrer" class="">Redirection de port</a> sur le port <code>443/tcp</code></li>
</ul>
</li>
<li class="">
<p><strong>Serveur passerelle :</strong></p>
<ul>
<li class="">Activer <a href="https://firewalld.org/" target="_blank" rel="noopener noreferrer" class="">Firewalld</a>
<ul>
<li class="">Supprimer tout le trafic entrant et sortant</li>
<li class="">Autoriser le trafic entrant sur le port '443/tcp'</li>
<li class="">Activer <a href="https://fr.wikipedia.org/wiki/Network_address_translation" target="_blank" rel="noopener noreferrer" class="">NAT</a> pour garder les paquets à jour</li>
</ul>
</li>
<li class="">Activer <a href="https://www.fail2ban.org/" target="_blank" rel="noopener noreferrer" class="">Fail2ban</a>
<ul>
<li class="">Interdire les IP qui demandent un <a href="https://fr.wikipedia.org/wiki/Server_Name_Indication" target="_blank" rel="noopener noreferrer" class="">SNI</a> inconnu</li>
</ul>
</li>
</ul>
</li>
<li class="">
<p><strong>Service Ingress :</strong></p>
<ul>
<li class="">Supprimer tout le trafic avec un <a href="https://fr.wikipedia.org/wiki/Server_Name_Indication" target="_blank" rel="noopener noreferrer" class="">SNI</a> inconnu</li>
<li class="">Utilisez uniquement des protocoles et des chiffrements sécurisés <a href="https://tools.ietf.org/html/rfc8446" target="_blank" rel="noopener noreferrer" class="">TLS</a></li>
<li class="">Appliquer [certificat client][certificat-client-wikipedia] pour l'authentification</li>
<li class="">Utilisez des <a href="https://fr.wikipedia.org/wiki/X.509" target="_blank" rel="noopener noreferrer" class="">certificats X.509</a> à l'état de l'art</li>
</ul>
</li>
</ul>]]></content>
        <author>
            <name>Guillaume MARTINEZ</name>
            <uri>https://github.com/Lunik</uri>
        </author>
        <category label="gateway" term="gateway"/>
        <category label="web" term="web"/>
        <category label="security" term="security"/>
        <category label="firewall" term="firewall"/>
        <category label="network" term="network"/>
        <category label="networking" term="networking"/>
        <category label="nginx" term="nginx"/>
        <category label="fail2ban" term="fail2ban"/>
        <category label="ssl" term="ssl"/>
        <category label="tls" term="tls"/>
        <category label="certificate" term="certificate"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Initialisation du blog]]></title>
        <id>https://lunik.tiwabbit.fr/blog/fr/init</id>
        <link href="https://lunik.tiwabbit.fr/blog/fr/init"/>
        <updated>2021-10-05T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[J'explique comment j'ai créé ce blog]]></summary>
        <content type="html"><![CDATA[<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2021-10-05-init/cover.png" alt="cover" class="img__Ss2"></p>
<p>Pour m'introduire, je ne suis pas un ingénieur web et je déteste le développement. Il y a beaucoup trop de Framework dans la nature (<a href="https://reactjs.org/" target="_blank" rel="noopener noreferrer" class="">ReactJS</a>, <a href="https://angular.io/" target="_blank" rel="noopener noreferrer" class="">Angular</a>, <a href="https://jquery.com/" target="_blank" rel="noopener noreferrer" class="">jquery</a>, ...). La programmation asynchrone de <a href="https://developer.mozilla.org/fr/docs/Web/JavaScript" target="_blank" rel="noopener noreferrer" class="">Javascript</a> n'est pas triviale à mettre en place et maintenir à l'échelle d'un site web complet. Sans parler de la gestion de dépendances qui est la goute qui fait déborder le vase (oui je parle de toi <code>npm</code>). Je ne suis pas non plus un web designer donc le <a href="https://tools.ietf.org/html/rfc1866" target="_blank" rel="noopener noreferrer" class="">HTML</a>/<a href="https://tools.ietf.org/html/rfc7993" target="_blank" rel="noopener noreferrer" class="">CSS</a> et moi, nous ne sommes pas copains (principalement parce que je ne  sais pas les utiliser à leurs plein potentiel).</p>
<p>C'est plus ou moins la raison pourquoi j'ai quitté le développement web et je suis devenu ingénieur SysOps.</p>
<div class="theme-admonition theme-admonition-danger admonition_IZjC alert alert--danger"><div class="admonitionHeading_uVvU"><span class="admonitionIcon_HiR3"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M5.05.31c.81 2.17.41 3.38-.52 4.31C3.55 5.67 1.98 6.45.9 7.98c-1.45 2.05-1.7 6.53 3.53 7.7-2.2-1.16-2.67-4.52-.3-6.61-.61 2.03.53 3.33 1.94 2.86 1.39-.47 2.3.53 2.27 1.67-.02.78-.31 1.44-1.13 1.81 3.42-.59 4.78-3.42 4.78-5.56 0-2.84-2.53-3.22-1.25-5.61-1.52.13-2.03 1.13-1.89 2.75.09 1.08-1.02 1.8-1.86 1.33-.67-.41-.66-1.19-.06-1.78C8.18 5.31 8.68 2.45 5.05.32L5.03.3l.02.01z"></path></svg></span>danger</div><div class="admonitionContent_bl22"><p>Cet article de blog est déprécié. Je l'ai laissé en ligne pour des raisons historiques.
Maintenant le blog est généré avec <a href="https://www.mkdocs.org/" target="_blank" rel="noopener noreferrer" class="">MKDocs</a>.</p></div></div>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="un-peu-de-théorie">Un peu de théorie<a href="https://lunik.tiwabbit.fr/blog/fr/init#un-peu-de-th%C3%A9orie" class="hash-link" aria-label="Lien direct vers Un peu de théorie" title="Lien direct vers Un peu de théorie" translate="no">​</a></h3>
<p>C'est un site static. Pas de code <a href="https://developer.mozilla.org/fr/docs/Web/JavaScript" target="_blank" rel="noopener noreferrer" class="">Javascript</a> alambiqué, de framework et autres <a href="https://fr.wikipedia.org/wiki/Syst%C3%A8me_de_gestion_de_contenu" target="_blank" rel="noopener noreferrer" class="">CMS</a>. Toutes les pages et les medias sont distribués via un service d'hébergement web basique que je détaillerais dans un autre articles prochainement.</p>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="comment-il-est-généré-">Comment il est généré ?<a href="https://lunik.tiwabbit.fr/blog/fr/init#comment-il-est-g%C3%A9n%C3%A9r%C3%A9-" class="hash-link" aria-label="Lien direct vers Comment il est généré ?" title="Lien direct vers Comment il est généré ?" translate="no">​</a></h3>
<p>Je ne voulais pas trop me faire des noeuds au cerveau en construisant la structure du site (<a href="https://tools.ietf.org/html/rfc1866" target="_blank" rel="noopener noreferrer" class="">HTML</a> &amp; company) et je voulais pouvoir me concentrer uniquement sur le contenu de ce blog. J'ai donc cherché un outil pour générer de jolie site à partir de ficher texte.</p>
<h4 class="anchor anchorTargetStickyNavbar_SAay" id="digression">Digression<a href="https://lunik.tiwabbit.fr/blog/fr/init#digression" class="hash-link" aria-label="Lien direct vers Digression" title="Lien direct vers Digression" translate="no">​</a></h4>
<p>Pas mal de monde connaissent déjà <a href="https://jekyllrb.com/" target="_blank" rel="noopener noreferrer" class="">Jekyll</a>. C'est un outil développé en <a href="https://www.ruby-lang.org/" target="_blank" rel="noopener noreferrer" class="">Ruby</a> qui fait le job. Il n'y a qu'à configurer deux/trois fichiers, écrire des articles au format texte, construire et ... voilà une super site internet.
Mais retournement de situation ! Je n'ai pas utiliser <a href="https://jekyllrb.com/" target="_blank" rel="noopener noreferrer" class="">Jekyll</a> parce que de mon point de vu, l'outil n'est pas adapté à mes besoins. Vous vous demandez pourquoi ? Voilà donc :</p>
<ul>
<li class="">Je n'y connais pas grand chose avec <a href="https://www.ruby-lang.org/" target="_blank" rel="noopener noreferrer" class="">Ruby</a> donc c'est plutôt difficile pour débugger</li>
<li class="">La gestion de dépendances de paquets <a href="https://www.ruby-lang.org/" target="_blank" rel="noopener noreferrer" class="">Ruby</a> sont une horreur</li>
<li class="">les plugins <a href="https://jekyllrb.com/" target="_blank" rel="noopener noreferrer" class="">Jekyll</a> sont (pour une majorité) développés par la communauté donc beaucoup d'entre eux sont incompatible les uns des autres, ont des bouts de documentation manquant ou alors ne fonctionne tout simplement pas.</li>
<li class="">J'ai déjà déployé un autre blog il y a quelques années avec <a href="https://jekyllrb.com/" target="_blank" rel="noopener noreferrer" class="">Jekyll</a> et je n'en ai pas un bon souvenir. Je le maintiens toujours, mais ce n'est pas trivial ...</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_SAay" id="quel-est-la-solution-">Quel est la solution ?<a href="https://lunik.tiwabbit.fr/blog/fr/init#quel-est-la-solution-" class="hash-link" aria-label="Lien direct vers Quel est la solution ?" title="Lien direct vers Quel est la solution ?" translate="no">​</a></h4>
<p>J'utilise <a href="https://getpelican.com/" target="_blank" rel="noopener noreferrer" class="">Pelican</a> !</p>
<p><img decoding="async" loading="lazy" src="https://lunik.tiwabbit.fr/blog/img/posts/2021-10-05-init/getpelican.jpg" alt="logo Pelican" class="img__Ss2"></p>
<p>C'est un outil tout simple de génération de site statique qui ne requiert que <a href="https://www.python.org/" target="_blank" rel="noopener noreferrer" class="">Python</a> pour fonctionner.
Il me permet d'écrire mon blog au format <a href="https://tools.ietf.org/html/rfc7763" target="_blank" rel="noopener noreferrer" class="">Markdown</a>. Les fichiers <a href="https://tools.ietf.org/html/rfc1866" target="_blank" rel="noopener noreferrer" class="">HTML</a> sont templaté via <a href="https://jinja.palletsprojects.com/" target="_blank" rel="noopener noreferrer" class="">Jinja</a>.
Etant un ingénieur SysOps, <a href="https://www.python.org/" target="_blank" rel="noopener noreferrer" class="">Python</a>, <a href="https://tools.ietf.org/html/rfc7763" target="_blank" rel="noopener noreferrer" class="">Markdown</a>, <a href="https://jinja.palletsprojects.com/" target="_blank" rel="noopener noreferrer" class="">Jinja</a> sont, parmi tant d'autres, des mots clés qui me font plaisir ! (Il vient même avec un <a href="https://www.gnu.org/software/make" target="_blank" rel="noopener noreferrer" class="">Makefile</a> !!)</p>
<p>Donc <a href="https://getpelican.com/" target="_blank" rel="noopener noreferrer" class="">Pelican</a> est un outil de génération de site statique <a href="https://tools.ietf.org/html/rfc1866" target="_blank" rel="noopener noreferrer" class="">HTML</a> via des fichiers <a href="https://tools.ietf.org/html/rfc7763" target="_blank" rel="noopener noreferrer" class="">Markdown</a> et des templates <a href="https://jinja.palletsprojects.com/" target="_blank" rel="noopener noreferrer" class="">Jinja</a>.</p>
<p>Super ?! Quand est ce qu'on commence ?!</p>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="mise-en-pratique">Mise en pratique<a href="https://lunik.tiwabbit.fr/blog/fr/init#mise-en-pratique" class="hash-link" aria-label="Lien direct vers Mise en pratique" title="Lien direct vers Mise en pratique" translate="no">​</a></h3>
<p>Je ne vais pas réinventer la roue, donc suivez le <a href="https://docs.getpelican.com/en/latest/quickstart.html" target="_blank" rel="noopener noreferrer" class="">guide de démarrage rapide Pelican</a> et revenez ici pour une description en profondeur de mon environnement pour ce blog.</p>
<h4 class="anchor anchorTargetStickyNavbar_SAay" id="pré-requis">Pré-requis<a href="https://lunik.tiwabbit.fr/blog/fr/init#pr%C3%A9-requis" class="hash-link" aria-label="Lien direct vers Pré-requis" title="Lien direct vers Pré-requis" translate="no">​</a></h4>
<p>I have <a href="https://www.python.org/" target="_blank" rel="noopener noreferrer" class="">Python</a> 3.9.6 installé sur mon PC et je fait tourner tout ça dans un <a href="https://docs.python.org/fr/3/library/venv.html" target="_blank" rel="noopener noreferrer" class="">VirtualEnv</a>.</p>
<p>Création du <a href="https://docs.python.org/fr/3/library/venv.html" target="_blank" rel="noopener noreferrer" class="">VirtualEnv</a> :</p>
<div class="language-text codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-text codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">python3 -m venv venv</span><br></div></code></pre></div></div>
<p>Rentrer dedans :</p>
<div class="language-text codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-text codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">source venv/bin/activate</span><br></div></code></pre></div></div>
<p>Installer les paquets requis :</p>
<div class="language-text codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-text codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">pip install "pelican[markdown]"</span><br></div></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_SAay" id="structure-des-fichiers">Structure des fichiers<a href="https://lunik.tiwabbit.fr/blog/fr/init#structure-des-fichiers" class="hash-link" aria-label="Lien direct vers Structure des fichiers" title="Lien direct vers Structure des fichiers" translate="no">​</a></h4>
<p>Voilà l'organisation actuelle des mes dossiers/fichiers (PI c'est celui par défaut fourni par la <a href="https://docs.getpelican.com/en/latest/settings.html" target="_blank" rel="noopener noreferrer" class="">configuration Pelican</a>):</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token builtin class-name" style="color:rgb(189, 147, 249)">.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">├── Makefile</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">├── content</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">│   ├── articles</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">│   │   ├── init-en.md</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">│   │   └── init-fr.md</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">│   ├── images</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">│   │   └── logo.png</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">│   └── pages</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">├── output</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">├── pelicanconf.py</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">├── publishconf.py</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">├── tasks.py</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">└── theme</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    └── flex</span><br></div></code></pre></div></div>
<ul>
<li class="">
<p>Le dossier <code>content</code> contient les articles, pages et medias rangés en trois dossiers :</p>
<ul>
<li class=""><code>articles</code> pour les posts du blog</li>
<li class=""><code>images</code> pour les médias</li>
<li class=""><code>pages</code> pour les pages supplémentaires du blog</li>
</ul>
</li>
<li class="">
<p>Le dossier <code>output</code> contient tous les fichiers statiques <a href="https://tools.ietf.org/html/rfc1866" target="_blank" rel="noopener noreferrer" class="">HTML</a> and <a href="https://tools.ietf.org/html/rfc7993" target="_blank" rel="noopener noreferrer" class="">CSS</a> générés après avoir buildé le site.</p>
</li>
<li class="">
<p>Le dossier <code>theme</code> contient le theme actuel du site. J'utilise actuellement le theme communautaire <a href="https://github.com/alexandrevicenzi/Flex" target="_blank" rel="noopener noreferrer" class="">Flex</a>.</p>
</li>
<li class="">
<p>Les fichiers <code>Makefile</code> et <code>tasks.py</code> sont auto-générés par <a href="https://getpelican.com/" target="_blank" rel="noopener noreferrer" class="">Pelican</a> lors de la création du projet avec le <a href="https://docs.getpelican.com/en/latest/quickstart.html" target="_blank" rel="noopener noreferrer" class="">guide de démarrage rapide Pelican</a>.</p>
</li>
<li class="">
<p>Le fichier <code>pelicanconf.py</code> contient les <a href="https://docs.getpelican.com/en/latest/settings.html" target="_blank" rel="noopener noreferrer" class="">paramètres par défaut Pelican</a>.</p>
</li>
<li class="">
<p>Et enfin <code>publishconf.py</code> contient les <a href="https://docs.getpelican.com/en/latest/settings.html" target="_blank" rel="noopener noreferrer" class="">paramètres spécifiques Pelican</a> utilisés lors de la publication du blog.</p>
</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_SAay" id="configuration-du-blog">Configuration du blog<a href="https://lunik.tiwabbit.fr/blog/fr/init#configuration-du-blog" class="hash-link" aria-label="Lien direct vers Configuration du blog" title="Lien direct vers Configuration du blog" translate="no">​</a></h4>
<p>J'utilise la configuration par défaut fournie par le <a href="https://docs.getpelican.com/en/latest/quickstart.html" target="_blank" rel="noopener noreferrer" class="">guide de démarrage rapide Pelican</a> et ai juste ajouté deux ou trois paramètres additionnels.</p>
<h4 class="anchor anchorTargetStickyNavbar_SAay" id="génération-du-blog">Génération du blog<a href="https://lunik.tiwabbit.fr/blog/fr/init#g%C3%A9n%C3%A9ration-du-blog" class="hash-link" aria-label="Lien direct vers Génération du blog" title="Lien direct vers Génération du blog" translate="no">​</a></h4>
<p>Maintenant que j'ai site complet, il faut que je le build.</p>
<p>Quand je développe pour ce blog (ou que j'écrit des articles), j'utilise la commande suivante :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">make</span><span class="token plain"> devserver</span><br></div></code></pre></div></div>
<p>Cela génère les pages du blog et les sert avec un petit serveur web local à l'adresse <a href="http://localhost:8000/" target="_blank" rel="noopener noreferrer" class="">http://localhost:8000</a>.</p>
<p>Une fois que je suis content de l'apparence du blog/articles, j'utilise la commande fournie pour générer une version publiable du site :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">make</span><span class="token plain"> publish</span><br></div></code></pre></div></div>
<p>Tous les fichiers du site se retrouvent générés dans le dossier <code>output</code> :</p>
<div class="language-shell codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-shell codeBlock_TAPP thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#F8F8F2"><span class="token plain">output</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">├── </span><span class="token number">404</span><span class="token plain">.html</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">├── archives.html</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">├── authors.html</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">├── categories.html</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">├── drafts</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">│   ├── init-fr.html</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">│   └── init.html</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">├── images</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">│   ├── getpelican.jpg</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">│   ├── getpelican.png</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">│   └── logo.png</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">├── index.html</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">├── tags.html</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">└── theme</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    └── </span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token plain">.</span><br></div></code></pre></div></div>
<p>La différence majeur entre ces deux commandes et que <code>publish</code> utilise la configure <code>publishconf.py</code> et <code>devserver</code> utilise uniquement <code>pelicanconf.py</code>.</p>
<h3 class="anchor anchorTargetStickyNavbar_SAay" id="conclusion">Conclusion<a href="https://lunik.tiwabbit.fr/blog/fr/init#conclusion" class="hash-link" aria-label="Lien direct vers Conclusion" title="Lien direct vers Conclusion" translate="no">​</a></h3>
<p>Maintenant que j'ai un environnement complet de build de mon blog et que j'ai besoin d'écrire un nouvel article, <code>make publish</code> et <em>tada</em>.</p>
<p>Dans un futur billet de blog, j'expliquerai comment j'héberge ces fichiers statiques pour les rendre accessibles sur internet.</p>]]></content>
        <author>
            <name>Guillaume MARTINEZ</name>
            <uri>https://github.com/Lunik</uri>
        </author>
        <category label="blog" term="blog"/>
        <category label="website" term="website"/>
        <category label="pelican" term="pelican"/>
        <category label="python" term="python"/>
        <category label="it" term="it"/>
        <category label="sysops" term="sysops"/>
    </entry>
</feed>