-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathblog.html
295 lines (274 loc) · 20.4 KB
/
blog.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
<!DOCTYPE html>
<html lang="fr">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<title>Gitoyen</title>
<link rel="stylesheet" href="/theme/css/main.css">
<link href="https://gitoyen.net/feeds/all.rss.xml" type="application/rss+xml" rel="alternate" title="Gitoyen RSS Feed">
<script src="/theme/scripts/jquery-2.1.4.min.js"></script>
<script src="/theme/scripts/jquery.sticky.js"></script>
<script src="/theme/scripts/mine.js"></script>
<!--[if IE]>
<script src="https://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
</head>
<body id="index" class="home">
<header id="banner">
<div id="headerContainer">
<div id="logo">
<a href="/index.html"></a>
</div>
<div class="burger">
<ul>
<li></li>
<li></li>
<li></li>
</ul>
</div>
<nav>
<ul>
<li >
<a href="/">Accueil</a>
</li>
<li >
<a href="/gitoyen.html">Gitoyen</a>
</li>
<li >
<a href="/services-de-gitoyen.html">Nos Services</a>
</li>
<li >
<a href="/cote-technique.html">Côté technique</a>
</li>
<li class="active">
<a href="/blog.html">Blog</a>
</li>
<li >
<a href="/contact.html">Contact</a>
</li>
<li class="icon twitter"><a href="https://twitter.com/gitoyen"> </a></li>
<li class="icon rss"><a href="https://gitoyen.net/feeds/all.rss.xml"> </a></li>
</ul>
</nav>
</div>
</header><!-- /#banner -->
<div class="cacheMenu"></div>
<div class="container">
<aside id="featured">
<article>
<h1 class="entry-title"><a href="/blog/yet-another-tutorial-about-lets-encrypt.html">Yet another tutorial about Let's Encrypt</a></h1>
<footer class="post-info">
<abbr class="published" title="2016-03-07T20:00:00+01:00">
Published: Mon 07 March 2016
</abbr>
<address class="vcard author">
By <a class="url fn" href="/author/gitoyen.html">gitoyen</a>
</address>
<p>In <a href="/category/tech.html">Tech</a>.</p>
<p>tags: <a href="/tag/https.html">https</a> <a href="/tag/letsencrypt.html">letsencrypt</a> </p>
</footer><!-- /.post-info --><p><img alt="Logo Let's Encrypt" src="//letsencrypt.org/images/letsencrypt-logo-horizontal.svg"/></p>
<p>Voilà 1 million de certificats <a href="//letsencrypt.org/">Let's Encrypt</a> délivrés (les certificats délivrés par <a href="https://crt.sh/?Identity=%25&iCAID=7395">Let's Encrypt</a>); La littérature sur le sujet ne manque pas, mais je vais quand même en apporter une de plus, pour la partie compilation :-)</p>
<p>Pour rappel, Let's Encrypt, est un projet porté par l' « Internet Security Research Group » (ISRG), qui vise à automatiser, rendre accessible à tous, de manière ouverte et gratuite, des certificats SSL</p>
<h2 id="generation">Génération</h2>
<p>Nous allons ici, ne pas utiliser le client officiel; Principalement parce qu'il intègre trop de fonctionnalités (serveur web intégré, …), mais aussi parce qu'il ne réponds pas vraiment aux besoins de cet article (arborescence flexible, serveur nginx, …; et que c'est plus facile à lire un script de 200 lignes qu'un énorme client…)</p>
<p>Le client que nous allons utiliser est donc le <a href="https://github.com/diafygi/acme-tiny">acme-tiny</a> (écrit en python). Lors de mes pérégrinations sur la toile (oui ok ça fait un peu vieillot, j'aurais pu dire « alors que je surfais sur le web », … :-D), je suis tombé sur ce script <a href="https://github.com/lukas2511/letsencrypt.sh">letsencrypt.sh</a>. Le coté FQDN à un endroit, et le rechargement lorsque les AltNames changent sont des features appréciables. Après c'est du bash, donc comme vous voulez :)</p>
<h3>Création des certificats</h3>
<p>De mon coté, j'ai opté pour une arborescence de ce type (certificats générés dans un répertoire dédié, avec un utilisateur dédié).</p>
<div class="highlight"><pre><span></span>$ mkdir -p /etc/letsencrypt/<span class="o">{</span>certs,challenges,csr,pem,private<span class="o">}</span>
/etc/letsencrypt/
├── certs
├── challenges
├── csr
├── pem
└── private
</pre></div>
<p>Il suffit donc alors de :</p>
<ul>
<li>Créer une clé pour le domaine en question</li>
<li>Créer une demande de signature (CSR) en y incluant les noms DNS alternatifs</li>
<li>Lancer le client (qui va se charger de créer un challenge) et signer si le challenge est ok.</li>
<li>Télécharger et concaténer le certificat obtenu avec le certificat intermédiaire de Let's Encrypt</li>
</ul>
<p>Le challenge sert ici à ce que let's encrypt vérifie que nous contrôlons bien le
domaine pour lequel nous demandons un certificat. Il faut d'ailleurs ajouter à
la configuration du serveur web, l'endroit où seront stockés ces challenges.</p>
<div class="highlight"><pre><span></span><span class="k">location</span> <span class="s">/.well-known/acme-challenge/</span> <span class="p">{</span>
<span class="kn">alias</span> <span class="s">/etc/letsencrypt/challenges/gitoyen.net/</span><span class="p">;</span>
<span class="kn">try_files</span> <span class="nv">$uri</span> <span class="p">=</span><span class="mi">404</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
<p>Coté certificat intermédiaire, ils sont disponibles sur le site de <a href="https://letsencrypt.org/certificates/">Let's Encrypt</a>.</p>
<p>Bon donc du coup ça donne cela dans un mini-script (pas super beau…)</p>
<div class="highlight"><pre><span></span><span class="ch">#!/bin/bash</span>
<span class="c1"># bootstrap letsencrypt</span>
<span class="nv">account</span><span class="o">=</span><span class="nv">$1</span>
<span class="nv">cert</span><span class="o">=</span><span class="nv">$2</span>
<span class="nv">dns</span><span class="o">=</span><span class="nv">$3</span>
mkdir -p /etc/letsencrypt/<span class="o">{</span>certs,challenges,csr,pem,private<span class="o">}</span>
<span class="nb">pushd</span> /etc/letsencrypt
<span class="k">if</span> <span class="o">[[</span> ! -f <span class="s2">"./private/</span><span class="si">${</span><span class="nv">account</span><span class="si">}</span><span class="s2">.key"</span> <span class="o">]]</span><span class="p">;</span> <span class="k">then</span>
openssl genrsa <span class="m">4096</span> > <span class="s2">"./private/</span><span class="si">${</span><span class="nv">account</span><span class="si">}</span><span class="s2">.key"</span>
<span class="k">fi</span>
<span class="k">if</span> <span class="o">[[</span> ! -f ./pem/intermediate.pem <span class="o">]]</span><span class="p">;</span> <span class="k">then</span>
wget -O - https://letsencrypt.org/certs/lets-encrypt-x1-cross-signed.pem > ./pem/intermediate.pem
<span class="k">fi</span>
<span class="nb">echo</span> <span class="s2">"##### </span><span class="si">${</span><span class="nv">cert</span><span class="si">}</span><span class="s2"> #####"</span>
<span class="k">if</span> <span class="o">[[</span> ! -f <span class="s2">"./private/</span><span class="si">${</span><span class="nv">cert</span><span class="si">}</span><span class="s2">.key"</span> <span class="o">]]</span><span class="p">;</span> <span class="k">then</span>
openssl genrsa <span class="m">4096</span> > <span class="s2">"./private/</span><span class="si">${</span><span class="nv">cert</span><span class="si">}</span><span class="s2">.key"</span>
<span class="k">fi</span>
mkdir -p <span class="s2">"./challenges/</span><span class="si">${</span><span class="nv">cert</span><span class="si">}</span><span class="s2">"</span>
openssl req -new -sha256 -key <span class="s2">"./private/</span><span class="si">${</span><span class="nv">cert</span><span class="si">}</span><span class="s2">.key"</span> -subj <span class="s2">"/"</span> -reqexts SAN -config <<span class="o">(</span>cat /etc/ssl/openssl.cnf <<span class="o">(</span><span class="nb">printf</span> <span class="s2">"[SAN]\nsubjectAltName=%s"</span> <span class="s2">"</span><span class="si">${</span><span class="nv">dns</span><span class="si">}</span><span class="s2">"</span><span class="o">))</span> > <span class="s2">"./csr/</span><span class="si">${</span><span class="nv">cert</span><span class="si">}</span><span class="s2">.csr"</span>
acme_tiny.py --account-key <span class="s2">"./private/</span><span class="si">${</span><span class="nv">account</span><span class="si">}</span><span class="s2">.key"</span> --csr <span class="s2">"./csr/</span><span class="si">${</span><span class="nv">cert</span><span class="si">}</span><span class="s2">.csr"</span> --acme-dir <span class="s2">"/etc/letsencrypt/challenges/</span><span class="si">${</span><span class="nv">cert</span><span class="si">}</span><span class="s2">/"</span> > <span class="s2">"./certs/</span><span class="si">${</span><span class="nv">cert</span><span class="si">}</span><span class="s2">.crt"</span>
cat <span class="s2">"./certs/</span><span class="si">${</span><span class="nv">cert</span><span class="si">}</span><span class="s2">.crt"</span> ./pem/intermediate.pem > <span class="s2">"./pem/</span><span class="si">${</span><span class="nv">cert</span><span class="si">}</span><span class="s2">.pem"</span>
<span class="nb">popd</span>
</pre></div>
<p>Qu'il suffit de lancer comme ceci (pour l'exemple je génère un certificate
asral.fr avec comme domaines gérés gitoyen.net et planet.gitoyen.net (oui de la pub au passage))</p>
<div class="highlight"><pre><span></span>$ bash bootstrap-letsencrypt.sh asrall gitoyen.net <span class="s1">'DNS:gitoyen.net,DNS:planet.gitoyen.net'</span>
<span class="c1">##### gitoyen.net #####</span>
Parsing account key...
Parsing CSR...
Registering account...
Already registered!
Verifying planet.gitoyen.net...
planet.gitoyen.net verified!
Verifying gitoyen.net...
gitoyen.net verified!
Signing certificate...
Certificate signed!
</pre></div>
<p>Plutôt cool non? Il suffit alors d'adapter la configuration du serveur web, pour
prendre en compte ces certificats. Et passer tout en HTTPS! (dans notre cas,
c'est un nginx en reverse proxy qui gère le SSL et forward en HTTP sur une IP
privée).</p>
<div class="highlight"><pre><span></span><span class="c1"># Gitoyen</span>
<span class="k">server</span> <span class="p">{</span>
<span class="kn">server_name</span> <span class="s">gitoyen.net</span> <span class="s">planet.gitoyen.net</span><span class="p">;</span>
<span class="kn">rewrite</span> <span class="s">^(.*)</span> <span class="s">https://</span><span class="nv">$host$1</span> <span class="s">permanent</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1"># Gitoyen SSL</span>
<span class="c1"># DNS:gitoyen.net,DNS:planet.gitoyen.net</span>
<span class="k">server</span> <span class="p">{</span>
<span class="kn">listen</span> <span class="mi">443</span><span class="p">;</span>
<span class="kn">ssl</span> <span class="no">on</span><span class="p">;</span>
<span class="kn">client_max_body_size</span> <span class="s">20M</span><span class="p">;</span>
<span class="kn">server_name</span> <span class="s">gitoyen.net</span> <span class="s">planet.gitoyen.net</span> <span class="s">asrall.sebian.fr</span><span class="p">;</span>
<span class="kn">ssl_certificate</span> <span class="s">/etc/letsencrypt/pem/gitoyen.net.pem</span><span class="p">;</span>
<span class="kn">ssl_certificate_key</span> <span class="s">/etc/letsencrypt/private/gitoyen.net.key</span><span class="p">;</span>
<span class="kn">ssl_session_timeout</span> <span class="mi">5m</span><span class="p">;</span>
<span class="kn">ssl_protocols</span> <span class="s">TLSv1</span> <span class="s">TLSv1.1</span> <span class="s">TLSv1.2</span><span class="p">;</span>
<span class="kn">ssl_ciphers</span> <span class="s">ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA</span><span class="p">;</span>
<span class="kn">ssl_session_cache</span> <span class="s">shared:SSL:50m</span><span class="p">;</span>
<span class="kn">ssl_prefer_server_ciphers</span> <span class="no">on</span><span class="p">;</span>
<span class="kn">ssl_dhparam</span> <span class="s">/etc/letsencrypt/dh4096.pem</span><span class="p">;</span>
<span class="kn">ssl_ecdh_curve</span> <span class="s">secp384r1</span><span class="p">;</span>
<span class="kn">add_header</span> <span class="s">Strict-Transport-Security</span> <span class="s">max-age=15768000</span><span class="p">;</span>
<span class="kn">resolver</span> <span class="mi">127</span><span class="s">.0.0.1</span><span class="p">;</span>
<span class="kn">location</span> <span class="s">/.well-known/acme-challenge/</span> <span class="p">{</span>
<span class="kn">alias</span> <span class="s">/etc/letsencrypt/challenges/gitoyen.net/</span><span class="p">;</span>
<span class="kn">try_files</span> <span class="nv">$uri</span> <span class="p">=</span><span class="mi">404</span><span class="p">;</span>
<span class="p">}</span>
<span class="kn">location</span> <span class="s">/</span> <span class="p">{</span>
<span class="kn">proxy_pass</span> <span class="s">http://10.41.1.143</span><span class="p">;</span>
<span class="kn">proxy_set_header</span> <span class="s">Host</span> <span class="nv">$host</span><span class="p">;</span>
<span class="kn">proxy_set_header</span> <span class="s">X-Forwarded-For</span> <span class="nv">$proxy_add_x_forwarded_for</span><span class="p">;</span>
<span class="kn">proxy_set_header</span> <span class="s">X-Real-IP</span> <span class="nv">$remote_addr</span><span class="p">;</span>
<span class="kn">proxy_set_header</span> <span class="s">X-Forwarded-Proto</span> <span class="s">https</span><span class="p">;</span>
<span class="kn">proxy_set_header</span> <span class="s">X-Forwarded-Ssl</span> <span class="no">on</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></div>
<p>Pour la génération du dhparams (4096 bits c'est bien)</p>
<div class="highlight"><pre><span></span>openssl dhparam -out dh4096.pem 4096
</pre></div>
<p>Et vous voila donc avec une super config et du HTTPS automatisé, on peut aller
faire un tour sur <a href="https://tls.imirhil.fr/https/gitoyen.net">imirhil</a> pour un
check de la conf et bien sûr pour pouvoir briller en société…</p>
<h2 id="supervision">Supervision</h2>
<p>Bon c'est bien beau, mais avec tout ça les certificats sont valables que 90j
(oui mort à CertPatrol :-() mais pour le coup il va donc falloir superviser
tout cela.</p>
<h3>Via Certificate Monitor</h3>
<p>Si vous utilisez le sympa <a href="https://certificatemonitor.org/">certificatemonitor</a> (<a href="https://github.com/RaymiiOrg/certificate-expiry-monitor">code source</a>) de Raymii, il suffit alors d'ajouter vos FQDN dans l'interface. Et ainsi recevoir une notification avant l'expiration de vos certificats.</p>
<h3>Via Checkmk</h3>
<p>Sinon si vous avez déjà une bonne veille supervision à base de nagios ou checkmk ou compatible, il suffit d'ajouter les checks via le script <code>check_http</code>.</p>
<p>Dans la conf <code>main.mk</code> de checkmk:</p>
<div class="highlight"><pre><span></span># /etc/checkmk/main.mk
legacy_checks = [
## Gitoyen
( ( "check-certificate!gitoyen.net", "Certificate Gitoyen - Letsencrypt", True), ['baloo.sebian.fr']),
( ( "check-certificate!planet.gitoyen.net", "Certificate Planet Gitoyen - Letsencrypt", True), ['baloo.sebian.fr']),
]
</pre></div>
<p>Et ne pas oublier la <code>check_command</code> associée (on émet un warning lorsque que le certificat expire à J-30 et un critical à J-7)</p>
<div class="highlight"><pre><span></span><span class="err">#</span><span class="x"> /etc/checkmk/conf.d/commands_extra.mk</span>
<span class="x">define command </span><span class="err">{</span><span class="x"></span>
<span class="x"> command_name check-certificate</span>
<span class="x"> command_line </span><span class="p">$</span><span class="nv">USER1</span><span class="p">$</span><span class="x">/check_http -H </span><span class="p">$</span><span class="nv">ARG1</span><span class="p">$</span><span class="x"> -C 30,7 --sni</span>
<span class="x">}</span>
</pre></div>
<h2 id="renouvellement">Renouvellement</h2>
<p>Il existe des scripts de renouvellement automatique:</p>
<ul>
<li><a href="https://github.com/octopuce/octopuce-goodies/tree/master/letsencrypt-renew">letsencrypt-renew</a></li>
<li><a href="https://github.com/lukas2511/letsencrypt.sh">letsencrypt.sh</a></li>
</ul>
<p>Mais je ne sais pas encore quoi en penser, pour le moment je réagit lorsque que
le check passe en warning avec ce mini script bash.</p>
<div class="highlight"><pre><span></span><span class="ch">#!/bin/bash</span>
<span class="nv">account</span><span class="o">=</span><span class="s1">'asrall'</span>
<span class="nv">certs</span><span class="o">=</span><span class="s1">'gitoyen.net planet.gitoyen.net'</span>
<span class="nb">pushd</span> /etc/letsencrypt
<span class="k">for</span> cert in <span class="nv">$certs</span>
<span class="k">do</span>
<span class="nb">echo</span> <span class="s2">"##### </span><span class="si">${</span><span class="nv">cert</span><span class="si">}</span><span class="s2"> #####"</span>
acme_tiny.py --account-key ./private/labriqueinternet.key --csr ./csr/<span class="si">${</span><span class="nv">cert</span><span class="si">}</span>.csr --acme-dir /etc/letsencrypt/challenges/<span class="si">${</span><span class="nv">cert</span><span class="si">}</span>/ > ./certs/<span class="si">${</span><span class="nv">cert</span><span class="si">}</span>.crt
cat ./certs/<span class="si">${</span><span class="nv">cert</span><span class="si">}</span>.crt ./pem/intermediate.pem > ./pem/<span class="si">${</span><span class="nv">cert</span><span class="si">}</span>.pem
<span class="k">done</span>
<span class="nb">popd</span>
systemctl restart nginx
</pre></div>
<h2 id="chocolat">Chocolat</h2>
<p>Même si le modèle des CA et bancal, il n'y a plus de raison maintenant de ne pas proposer du HTTPS partout!</p> </article>
</aside><!-- /#featured -->
<section class="m3y">
<h1>Autres articles</h1>
<hr />
<ol id="posts-list" class="hfeed">
<li>
<article class="hentry">
<header>
<h1>
<a href="/blog/pytest-fixture.html" rel="bookmark" title="Permalink to Pytest Fixture">
Pytest Fixture
</a>
</h1>
</header>
<div class="entry-content">
<footer class="post-info">
<abbr class="published" title="2015-04-14T00:00:00+02:00">
Published: Tue 14 April 2015
</abbr>
<address class="vcard author">
By <a class="url fn" href="/author/gitoyen.html">gitoyen</a>
</address>
<p>In <a href="/category/tuto.html">tuto</a>.</p>
<p>tags: <a href="/tag/python.html">python</a> <a href="/tag/dev.html">dev</a> </p>
</footer><!-- /.post-info --> <p>I am a huge fan of python (one of the best language in my toolbox). And
when it comes to tests, <a href="http://pytest.org/">pytest</a> is <em>THE</em> library to use.</p>
<p>I also use <a href="http://flask.pocoo.org/">Flask</a> a lot, so today I will show you
some of my snippets.</p>
<p>This create an app fixture which will ...</p>
<a class="readmore" href="/blog/pytest-fixture.html">read more</a>
</div><!-- /.entry-content -->
</article>
</li>
</ol><!-- /#posts-list -->
</section><!-- /#content -->
</div>
<footer id="contentinfo">
<a href="#">Mentions légales</a>
</footer>
</body>
</html>