summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--notes/create_self-signed_certificate_from_a_self-signed_CA.md434
-rw-r--r--notes/créer-un-certificat-auto-signé-depuis-un-CA-auto-signé.md435
-rw-r--r--notes/res/certificat-signed.svg1
-rw-r--r--notes/res/chain_of_trust.avifbin0 -> 13552 bytes
-rw-r--r--notes/res/chain_of_trust.pngbin0 -> 79824 bytes
-rw-r--r--notes/res/chaîne_de_certification.avifbin0 -> 14015 bytes
-rw-r--r--notes/res/chaîne_de_certification.pngbin0 -> 80455 bytes
7 files changed, 870 insertions, 0 deletions
diff --git a/notes/create_self-signed_certificate_from_a_self-signed_CA.md b/notes/create_self-signed_certificate_from_a_self-signed_CA.md
new file mode 100644
index 0000000..b3db87e
--- /dev/null
+++ b/notes/create_self-signed_certificate_from_a_self-signed_CA.md
@@ -0,0 +1,434 @@
+---
+pubDate = 2025-01-25T16:09:04
+tags = ['https', 'web', 'nginx', 'linux', 'cryptography']
+lang = "en"
+type = "note"
+
+[author]
+name = "ache"
+email = "ache@ache.one"
+
+[[alt_lang]]
+lang = "fr"
+url = "/notes/créer-un-certificat-auto-signé-depuis-un-CA-auto-signé"
+---
+
+# Obtaining a self-signed SSL certificate from our own Certificate Authority
+
+![Illustration of a self-signed certificate](res/certificat-signed.svg)
+
+In this blog post, we will create a self-signed TLS certificate, install it on an nginx server and on client systems.
+
+## Objectives of the TLS Protocol
+
+:::attention
+Generally, you do not want a self-signed certificate.
+If you want to obtain a valid certificate on the internet, then you need it to be verified by a trusted Certificate Authority (CA).
+In this case, [Let's Encrypt](https://letsencrypt.org/fr/) can certainly provide the certificate you need.
+:::
+
+TLS authentication is used to **verify that** the server you want to connect to (by its **domain name**) **is indeed the server** that has authority over that domain name.
+This may seem abstract, but there are several reasons why a domain name may not redirect to the correct server.
+
+- A lying DNS
+- A compromised router redirects you to the wrong server
+- A configuration error (on either the client or the server side)
+- ...
+
+Subsequently, TLS will handle encryption that ensures confidentiality and integrity.
+
+TLS is a protocol used as an overlay on many other protocols (FTP, IMAP, SMTP, ..., and even DNS!) to add security to them.
+
+## Certificate Chain (or Chain of Trust)
+
+We do not have a list of certificates issued on our computers. It would be too complicated to manage, heavy, difficult to update and ultimately unreliable.[^ct-logs]
+
+[^ct-logs]:
+ The role of _Certificate Transparency (CT) logs_ is to ensure that any suspicious behavior (at the level of certificate issuance) can be detected.
+ For more information, see <https://certificate.transparency.dev/>.
+
+<img src="res/chain-of-trust.png" class="big" alt="Schema of the Certificate Chain">
+
+On the contrary, we have only a relatively small list of certificates of trust on our computers (149 in my case).
+These are the root certificates.
+These certificates will delegate their role of identity verifier to others.
+These intermediate authorities then have the role of ensuring that the request for certification comes from the correct server and issuing a signed certificate (and of short duration, i.e., several days at most, up to a few months).
+
+In our case, we will pass the intermediate certificate step as we will never delegate our authority.
+
+:::info
+The certificates installed on your computer are selected by your operating system (for example, [that of Windows](https://ccadb.my.salesforce-sites.com/microsoft/IncludedCACertificateReportForMSFT)).
+Often, this delegates your trust to a certificate selection organization such as [Mozilla](https://wiki.mozilla.org/CA/Included_Certificates).
+:::
+
+### Under Arch Linux
+
+Arch Linux uses [p11-kit](https://github.com/p11-glue/p11-kit) to manage certificates.
+
+Just like on Ubuntu and Debian systems, the list of certificates is available in the PEM format in the `/etc/ssl/certs` directory.
+
+OpenSSL is the reference tool for TLS. You can use it to display a certificate as follows:
+
+```shell
+$ openssl x509 -noout -text -in $certificat
+```
+
+In the case of a website, you can query the certificate of a website with the following command:
+`
+
+```shell
+$ openssl s_client -connect ache.one:443 -verify_return_error </dev/null >/dev/null
+Connecting to 2001:41d0:601:1100::11dc
+depth=2 C=US, O=Internet Security Research Group, CN=ISRG Root X1
+verify return:1
+depth=1 C=US, O=Let's Encrypt, CN=R10
+verify return:1
+depth=0 CN=ache.one
+verify return:1
+DONE
+```
+
+One can add :
+
+- `-showcerts` to print the server certificat
+- `-servername` to set a SNI field
+- `-starttls` with `smtp`, `ldap`, `pop3`, `xmpp`... to verify that a TLS setup is compatible with StartTLS.
+-
+- We can also extract the certificate into a file as follows:
+
+ ```sh
+ $ openssl s_client -connect ache.one:443 -servername ache.one < /dev/null | \
+ openssl x509 -outform PEM > ache_one.cert
+ ```
+
+- To verify dates of a certificate :
+
+ ```shell
+ $ openssl x509 -in ache_one.cert -noout -dates # Pour un certificat que l'on possède localement
+ notBefore=Wen 16 15:27:33 2025 GMT
+ notAfter=Wen 30 15:27:33 2025 GMT
+ $ openssl s_client -servername ache.one -connect ache.one:443 2>/dev/null </dev/null | \
+ openssl x509 -noout -dates
+ ```
+
+## Créer le certificat racine
+
+Firstly, let's create a private key.
+We will use RSA with a 3072-bit key.
+
+```shell
+$ openssl genrsa -out root_ca.key 3072
+```
+
+To use elliptic curves, we will rather use `openssl ecparam -genkey` and select a curve from the available options `openssl ecparam -genkey -list_curves` (make sure to get informed about the support of the chosen curve).
+Then, we create the certificate and sign it.
+
+```shell
+$ openssl req -x509 -key local_ca.key -nodes -utf8 -days 3650 -out local_ca.cert -config local_ca.conf
+```
+
+With this configuration file :
+
+```toml
+[ req ]
+default_bits = 3072
+distinguished_name = x509_distinguished_name
+x509_extensions = x509_ext
+prompt = no
+
+[ x509_distinguished_name ]
+countryName = "FX"
+stateOrProvinceName = Pays des bisounours
+organizationName = ache
+organizationalUnitName = ache
+commonName = ache.local
+emailAddress = ache@ache.one
+
+[ x509_ext ]
+basicConstraints=critical,CA:TRUE
+subjectKeyIdentifier = hash
+authorityKeyIdentifier = keyid:always,issuer:always
+extendedKeyUsage=critical,serverAuth
+subjectAltName=email:ache@ache.one,DNS:local,DNS:ache.local
+# keyUsage = critical, digitalSignature, cRLSign, keyCertSign
+keyUsage = critical, digitalSignature, keyEncipherment, keyCertSign
+```
+
+Here, it's important to use `x509_extensions` instead of `req_extensions`, and the line `basicConstraints` specifies `CA:TRUE`.
+
+:::note
+It is possible to perform these two steps in one single command:
+
+```shell
+$ openssl req -x509 \
+ -sha256 -days 3650 \
+ -nodes \
+ -newkey rsa:3072 \
+ -subj "/CN=ache Root CA/C=FR/L=La grande ville" \
+ -keyout root_ca.key -out root_ca.cert
+```
+
+:::
+
+### Add the root certificate to the list of trusted certificates
+
+On the client side, we can already install the self-signed CA for the clients.
+For Arch Linux clients, this is done with the command `trust`.
+
+```shell
+# trust anchor --store root_ca.cert
+```
+
+One can verify if it is indeed on the list by checking its name.
+
+```shell
+$ trust list | rg -C 2 "ache"
+pkcs11:id=%F4%30%84%A6%0F%AD%AF%BB%6C%3A%2D%C6%1A%66%84%48%73%4E%CB%E7;type=cert
+ type: certificate
+ label: ache Root CA
+ trust: anchor
+ category: authority
+```
+
+:::warn
+We take this opportunity to make sure that the certificate is an authority certificate (category _authority_) and indeed that it is a certificate (type _certificate_).
+:::
+
+It will then be installed in the directory `/etc/ca-certificates/trust-source/`.
+To remove the certificate from the trusted certificates, we use the file generated in this directory.
+
+```shell
+# trust anchor --remove /etc/ca-certificates/trust-source/ache.dns.p11-kit
+```
+
+## Creation of the DNS Certificate
+
+Same as before, we start by creating a private key.
+
+### The Private Key
+
+```shell
+$ openssl genrsa -out website.key 3072
+```
+
+Then, we create a **signature request**.
+This allows us to configure the signature by the certification authority.
+
+### The Signature Request
+
+Normally, in the usual process, the Intermediate Certification Authority receives a signature request and initiates then the process of verifying the identity of the server that is requesting the signature.
+
+We can do this easily with OpenSSL:
+
+```shell
+$ openssl req -new -key website.key -out website.csr -utf8 -nameopt multiline,utf
+```
+
+:::info
+Here, I have added the parameters `-utf8 -nameopt multiline,utf8` so as to accept non-ASCII characters in the certification information (Company name, region ...).
+:::
+
+OpenSSL will then ask for the certification information interactively.
+This can be avoided either by filling in the data directly on the command line.
+
+```shell
+$ openssl req -new -out website.csr -sha256 -days 3650 -nodes -subj "/C=FR/ST=Centre/L=La grande Ville/O=NomDeLEntreprise/OU=/CN=CommonNameOrHostname"
+```
+
+Or by using a configuration file.
+This is what I chose to do in order to facilitate the re-creation of the certificate.
+
+```sh
+$ openssl req -new -key website.key -out website.csr -utf8 -nameopt multiline,utf8 -config website.conf
+```
+
+The configuration file looks like this:
+
+```toml
+[ req ]
+prompt = no
+default_bits = 3072
+default_md = sha256
+distinguished_name = server_distinguished_name
+req_extensions = v3_ext
+
+[ server_distinguished_name ]
+commonName = ache
+countryName = FR
+stateOrProvinceName = XXX
+emailAddress = ache@ache.one
+organizationName = ache local CA organization
+
+[ v3_ext ]
+basicConstraints = CA:FALSE
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+subjectAltName = @alt_names
+
+[ alt_names ]
+DNS.0 = website.ache.one
+DNS.1 = website_alt.ache.one
+```
+
+## Creating the final certificate
+
+There is only one step left: creating the final certificate.
+The following are required for this purpose:
+
+- Root certificate private key
+- Root certificate
+- The final certificate private key
+- The Certificate signing request (CSR)
+
+```shell
+$ openssl x509 -req -CA ../root_ca/root_ca.cert -CAkey ../root_ca/root_ca.key -in website.csr -out website.cert -days 10 -CAcreateserial -extensions v3_ext -extfile website.conf -sha256
+```
+
+## Configuring the certificate in nginx
+
+There is nothing magical about it.
+We add `ssl` to the `listen` and configure TLS.
+To do this, we need to indicate where the encryption key is located as well as the certificate.
+
+```text
+ listen [::]:443 ssl;
+ listen 443 ssl;
+ http2 on; # Not related to TLS
+
+ ssl_certificate /srv/www/website.cert; # managed by myself !
+ ssl_certificate_key /srv/website/cert/website.key;
+ ssl_stapling off; # Since it's a self-signed certificate. No need for OCSP stapling.
+ ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
+```
+
+It can be noticed that it is possible to pass the certificate chain also by concatenating the final certificate (first) with the root certificate.
+I do not know if this has a real advantage, but it is a common practice.
+
+## Certificate Update
+
+It is recommended to set up an automatic method for updating the certificate.
+I recommend a systemd timer that will check the validity of the certificate and renew it at regular intervals.
+
+`check-certificates.timer` :
+
+```toml
+# This timer unit is for refreshing local certificates everyday
+
+[Unit]
+Description=Refresh self-signed certificates regularly
+Requires=check-certificates.service
+
+
+[Timer]
+Unit=check-certificates.service
+OnUnitActiveSec=86400
+
+[Install]
+WantedBy=timers.target
+```
+
+And `check-certificates.service`
+
+```toml
+# This service unit is for refreshing local certificates if needed
+
+[Unit]
+Description=Refresh local certificates if needed
+Wants=check-certificates.timer
+
+[Service]
+Type=oneshot
+ExecStart=/usr/bin/check-certificates.sh
+
+[Install]
+WantedBy=multi-user.target
+```
+
+I thus created a Bash script to automate the verification of certificates and the updating of Nginx configuration files.
+
+:::details
+
+Content of the file `check-certificates.sh`
+
+::::summary
+
+```bash
+#!/bin/env bash
+
+# This script checks the validity of the certificates in the directory
+# ${CERTIFICATES_DIR} and renews them if necessary.
+#
+# It uses the local CA certificate and key to check the validity of the
+# certificates in the directory ${CERTIFICATES_DIR}.
+#
+# The script is intended to be run from a systemd timer every day.
+
+
+# TODO: Configure the following variables from cli arguments
+# TODO: Rewrite this shit in Python
+CERTIFICATES_DIR="/home/works/certs/"
+LOCAL_CA_CERT="${CERTIFICATES_DIR}/local_ca.cert"
+LOCAL_CA_KEY=$(echo "${LOCAL_CA_CERT}" | sed 's/.cert$/.key/')
+
+HAS_RENEW_CERT=""
+if [ ! -r "$LOCAL_CA_CERT" ]; then
+ echo "☠️ Please re-check that local CA cert \"$LOCAL_CA_CERT\" exists"
+ exit
+fi
+if [ ! -r "$LOCAL_CA_KEY" ]; then
+ echo "☠️ Please re-check that local CA key \"$LOCAL_CA_KEY\" exists"
+ exit
+fi
+
+date
+echo -e "Checking certificate validity (NotAfter field)\n"
+
+pushd ${CERTIFICATES_DIR} >/dev/null 2>/dev/null
+for cert in $(find -name "*.cert"); do
+ if openssl x509 -checkend 345600 -noout -in ${cert} > /dev/null; then
+ echo -e "✔️ $(basename ${cert}) will expire in more than 4 days"
+ else
+ echo -e "❌ $(basename ${cert}) will expire soon !"
+ if [ $(basename "$cert") = $(basename "$LOCAL_CA_CERT") ]; then
+ echo -e "\t⛔ I don't renew local CA certificate"
+ continue
+ fi
+
+ NEW_CSR=$(echo ${cert} | sed 's/.cert/.csr/')
+ CERT_KEY=$(echo ${cert} | sed 's/.cert/.key/')
+ CERT_CONFIG=$(echo ${cert} | sed 's/.cert/.conf/')
+
+ echo "Renewing ${cert}"
+ echo "Creating new CSR ($NEW_CSR)"
+ echo ${cert}
+ echo ${CERT_KEY}
+ echo ${CERT_CONFIG}
+
+ # Sign the new signing request
+ if openssl req -new -key "${CERT_KEY}" -out "${NEW_CSR}" -config "${CERT_CONFIG}"; then
+ echo "👍 CSR created"
+ else
+ echo "❌ Failled to create signing request!"
+ continue
+ fi
+
+ echo "Renewing certificate"
+ openssl x509 -req -CA "${LOCAL_CA_CERT}" -CAkey "${LOCAL_CA_KEY}" -in "${NEW_CSR}" -out "${cert}" -days 10 -CAcreateserial -extensions v3_ext -extfile "${CERT_CONFIG}" -sha256
+ if [ $? -eq 0 ]; then
+ HAS_RENEW_CERT="yes"
+ echo "✔️ Certificate renew"
+ else
+ echo "❌ Failled to renew certificate!"
+ fi
+ fi
+done
+
+echo -e "\nNo more certificate to check"
+if [ -n "$HAS_RENEW_CERT" ]; then
+ echo "🔃 Reload nginx configuration (and update certificates)"
+ nginx -s reload
+fi
+
+popd >/dev/null 2>/dev/null
+```
+
+::::
diff --git a/notes/créer-un-certificat-auto-signé-depuis-un-CA-auto-signé.md b/notes/créer-un-certificat-auto-signé-depuis-un-CA-auto-signé.md
new file mode 100644
index 0000000..27f82c2
--- /dev/null
+++ b/notes/créer-un-certificat-auto-signé-depuis-un-CA-auto-signé.md
@@ -0,0 +1,435 @@
+---
+pubDate = 2025-01-25T16:09:04
+tags = ['https', 'web', 'nginx', 'linux', 'cryptographie']
+lang = "fr"
+type = "note"
+
+[author]
+name = "ache"
+email = "ache@ache.one"
+
+[[alt_lang]]
+lang = "en"
+url = "/notes/create_self-signed_certificate_from_a_self-signed_CA"
+---
+
+# Obtenir un certificat auto-signé à partir de sa propre autorité de certification
+
+![Illustration d'un certificat auto-signé](res/certificat-signed.svg)
+
+Dans ce poste de blog, nous allons créer un certificat TLS autosigné, l'installer sur un serveur nginx et sur les systèmes clients.
+
+## Objectifs de TLS
+
+:::attention
+Généralement, vous ne souhaitez pas avoir un certificat autosigné.
+Si vous souhaitez obtenir un certificat valide sur internet, alors vous avez besoin qu'il soit validé par une autorité de certification.
+Dans ce cas, [Let's Encrypt](https://letsencrypt.org/fr/) peut très certainement vous délivrer le certificat dont vous avez besoin.
+:::
+
+L'authentification TLS sert à **attester que le** serveur que vous souhaitez contacter (par son **nom de domaine**) **correspond bien au serveur** ayant autorité sur ce nom de domaine.
+Cela peut paraître abstrait comme ça, mais il peut y avoir plusieurs raisons qui font que le nom de domaine ne redirige pas vers le bon serveur.
+
+- Un DNS menteur
+- Un routeur compromis vous redirige vers le mauvais serveur
+- Une erreur de configuration (coté client ou serveur)
+- ...
+
+Ensuite, TLS se chargera du chiffrement qui assurera la confidentialité et l'intégrité.
+
+TLS est un protocole utilisé comme surcouche à pleins d'autres protocoles (FTP, IMAP, SMTP, ..., et même DNS !) afin de leur rajouter une sécurité.
+
+## Chaîne de certification (ou chaîne de confiance)
+
+Nous n'avons pas la liste des certificats émis sur nos ordinateurs.
+Ça serait trop compliqué à gérer, trop lourd, difficile à mettre à jour et au final peu fiable.[^ct-logs]
+
+[^ct-logs]:
+ C'est le rôle cependant des _Certification Transparency (CT) logs_ qui assurent que tout comportement suspect (au niveau de l'émission de certificat) puisse être détecté.
+ Plus d'info à <https://certificate.transparency.dev/>.
+
+<img src="res/chaîne_de_certification.png" class="big" alt="Schéma de la chaîne de certification">
+
+Au contraire, on a une seulement une liste relative faible de certificats de confiance sur nos ordinateurs (149 chez moi).
+Ce sont les certificats d'autorité, ou racines.
+Ces certificats vont déléguer leur rôle de vérificateur d'identité à d'autres.
+Ces autorités intermédiaires ont alors pour rôle de s'assurer que la demande de certification émane bien du bon serveur et d'émettre un certificat signé (et de courte durée, c'est-à-dire quelques jours, au plus quelques mois).
+
+Dans notre cas, nous allons nous passez l'étape du certificat intermédiaire puisque nous n'allons jamais déléguer notre autorité.
+
+:::info
+Les certificats installés sur votre ordinateur sont sélectionnés par votre système d'exploitation (par exemple [celle de Windows](https://ccadb.my.salesforce-sites.com/microsoft/IncludedCACertificateReportForMSFT)).
+Souvent, celui-ci délègue votre confiance à un organisme de sélection de certificats comme [Mozilla](https://wiki.mozilla.org/CA/Included_Certificates).
+:::
+
+### Sous Arch Linux
+
+Arch Linux utilise [p11-kit](https://github.com/p11-glue/p11-kit) pour gérer les certificats.
+
+Tout comme sur les systèmes Ubuntu et Debian, la liste des certificats est disponible au format PEM dans le dossier `/etc/ssl/certs`.
+
+OpenSSL est l'outil de référence en matière de TLS.
+Vous pouvez l'utiliser pour afficher un certificat comme ceci.
+
+```shell
+$ openssl x509 -noout -text -in $certificat
+```
+
+Dans le cas d'un site web, on peut interroger le certificat d'un site web avec la commande suivante.
+
+```shell
+$ openssl s_client -connect ache.one:443 -verify_return_error </dev/null >/dev/null
+Connecting to 2001:41d0:601:1100::11dc
+depth=2 C=US, O=Internet Security Research Group, CN=ISRG Root X1
+verify return:1
+depth=1 C=US, O=Let's Encrypt, CN=R10
+verify return:1
+depth=0 CN=ache.one
+verify return:1
+DONE
+```
+
+On peut ajouter :
+
+- `-showcerts` pour afficher le certificat serveur
+- `-servername` pour mettre en place le SNI
+- `-starttls` avec `smtp`, `ldap`, `pop3`, `xmpp`... pour vérifier l'installation TLS sur un serveur avec un protocole compatible StartTLS.
+- On peut également extraire le certificat dans un fichier :
+
+ ```sh
+ $ openssl s_client -connect ache.one:443 -servername ache.one < /dev/null | \
+ openssl x509 -outform PEM > ache_one.cert
+ ```
+
+- Vérifier les dates de validité du certificat :
+
+ ```shell
+ $ openssl x509 -in ache_one.cert -noout -dates # Pour un certificat que l'on possède localement
+ notBefore=Wen 16 15:27:33 2025 GMT
+ notAfter=Wen 30 15:27:33 2025 GMT
+ $ openssl s_client -servername ache.one -connect ache.one:443 2>/dev/null </dev/null | \
+ openssl x509 -noout -dates
+ ```
+
+## Créer le certificat racine
+
+Premièrement, il faut créer une clé privée.
+Nous allons utilisez RSA avec une clé de 3072 bits.
+
+```shell
+$ openssl genrsa -out root_ca.key 3072
+```
+
+Pour utiliser les courbes elliptiques, on utilisera plutôt `openssl ecparam -genkey` en sélectionnant une courbe parmi celles disponibles `openssl ecparam -genkey -list_curves` (attention à bien se renseigner sur le support de la courbe choisie).
+
+Ensuite, on crée le certificat et on le signe :
+
+```shell
+$ openssl req -x509 -key local_ca.key -nodes -utf8 -days 3650 -out local_ca.cert -config local_ca.conf
+```
+
+Avec le fichier de configuration : 
+
+```toml
+[ req ]
+default_bits = 3072
+distinguished_name = x509_distinguished_name
+x509_extensions = x509_ext
+prompt = no
+
+[ x509_distinguished_name ]
+countryName = "FX"
+stateOrProvinceName = Pays des bisounours
+organizationName = ache
+organizationalUnitName = ache
+commonName = ache.local
+emailAddress = ache@ache.one
+
+[ x509_ext ]
+basicConstraints=critical,CA:TRUE
+subjectKeyIdentifier = hash
+authorityKeyIdentifier = keyid:always,issuer:always
+extendedKeyUsage=critical,serverAuth
+subjectAltName=email:ache@ache.one,DNS:local,DNS:ache.local
+# keyUsage = critical, digitalSignature, cRLSign, keyCertSign
+keyUsage = critical, digitalSignature, keyEncipherment, keyCertSign
+```
+
+Ici, ce qui est important dans l'utilisation de `x509_extensions` plutôt que `req_extensions` et la ligne `basicConstraints` spécifiant `CA:TRUE`.
+
+:::note
+Il est possible de faire ces deux étapes en une seule commande :
+
+```shell
+$ openssl req -x509 \
+ -sha256 -days 3650 \
+ -nodes \
+ -newkey rsa:3072 \
+ -subj "/CN=ache Root CA/C=FR/L=La grande ville" \
+ -keyout root_ca.key -out root_ca.cert
+```
+
+:::
+
+### Ajouter le certificat racine à la liste des certificats de confiance
+
+Coté client, on peut d’ores et déjà installer le CA autosigné chez les clients.
+Pour des clients Arch Linux ça se fait alors avec la commande `trust`.
+
+```shell
+# trust anchor --store root_ca.cert
+```
+
+On peut vérifier qu'il est bien dans la liste à partir de son nom.
+
+```shell
+$ trust list | rg -C 2 "ache"
+pkcs11:id=%F4%30%84%A6%0F%AD%AF%BB%6C%3A%2D%C6%1A%66%84%48%73%4E%CB%E7;type=cert
+ type: certificate
+ label: ache Root CA
+ trust: anchor
+ category: authority
+```
+
+:::warn
+On en profite pour bien vérifier que le certificat est un certificat d'autorité (catégorie _authority_) et biensûr que ce soit bien un certificat (type _certificate_).
+:::
+
+Il est alors installé dans le dossier `/etc/ca-certificates/trust-source/`.
+Pour supprimer le certificat des certificats de confiance, on utilise le fichier généré dans ce dossier.
+
+```shell
+# trust anchor --remove /etc/ca-certificates/trust-source/ache.dns.p11-kit
+```
+
+## Création du certificat DNS
+
+Idem, on commence par créer une clé privée.
+
+### La clé privée
+
+```shell
+$ openssl genrsa -out website.key 3072
+```
+
+Puis, on crée une **demande de signature**.
+Celle-ci permet de configurer la signature par l'autorité de certification.
+
+### La demande de signature
+
+Normalement, dans le processus normal, le CA intermédiaire reçoit une demande de signature et initie alors le processus de vérification de l'identité du serveur qui demande la signature.
+
+On peut le faire avec OpenSSL simplement :
+
+```shell
+$ openssl req -new -key website.key -out website.csr -utf8 -nameopt multiline,utf
+```
+
+:::info
+Ici, j'ai rajouté les paramètres `-utf8 -nameopt multiline,utf8` afin d’accepter les caractères non ASCII dans les informations de certification (Nom de l'entreprise, de la région ...).
+:::
+
+OpenSSL va alors nous demander les informations de certification en mode interactif.
+On peut éviter cela soit en remplissant les données directement en ligne de commande.
+
+```shell
+$ openssl req -new -out website.csr -sha256 -days 3650 -nodes -subj "/C=FR/ST=Centre/L=La grande Ville/O=NomDeLEntreprise/OU=/CN=CommonNameOrHostname"
+```
+
+Soit utiliser un fichier de configuration.
+C'est ce que j'ai choisi de faire afin de facilité la recréation du certificat.
+
+```sh
+$ openssl req -new -key website.key -out website.csr -utf8 -nameopt multiline,utf8 -config website.conf
+```
+
+Le fichier de configuration ressemble à ceci : 
+
+```toml
+[ req ]
+prompt = no
+default_bits = 3072
+default_md = sha256
+distinguished_name = server_distinguished_name
+req_extensions = v3_ext
+
+[ server_distinguished_name ]
+commonName = ache
+countryName = FR
+stateOrProvinceName = XXX
+emailAddress = ache@ache.one
+organizationName = ache local CA organization
+
+[ v3_ext ]
+basicConstraints = CA:FALSE
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+subjectAltName = @alt_names
+
+[ alt_names ]
+DNS.0 = website.ache.one
+DNS.1 = website_alt.ache.one
+```
+
+## Créer le certificat final
+
+Il ne reste plus qu'à créer le certificat.
+On a besoin pour cela de :
+
+- La clé du certificat racine
+- Le certificat racine
+- La clé du certificat final
+- La demande de signature
+
+```shell
+$ openssl x509 -req -CA ../root_ca/root_ca.cert -CAkey ../root_ca/root_ca.key -in website.csr -out website.cert -days 10 -CAcreateserial -extensions v3_ext -extfile website.conf -sha256
+```
+
+## Configuration du certificat dans nginx
+
+Il n'y a rien de bien sorcier.
+On rajoute `ssl` aux `listen` et on configure TLS.
+Pour cela, il faut indiquer où est la clé de chiffrement ainsi que le certificat.
+
+```text
+ listen [::]:443 ssl;
+ listen 443 ssl;
+ http2 on; # Not related to TLS
+
+ ssl_certificate /srv/www/website.cert; # managed by myself !
+ ssl_certificate_key /srv/website/cert/website.key;
+ ssl_stapling off; # Since it's a self-signed certificate. No need for OCSP stapling.
+ ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
+```
+
+On peut remarquer qu'il est possible de passer la chaîne de certificat également en concaténant le certificat final (en premier) avec le certificat racine.
+Je ne sais pas si cela a un réel avantage, mais c'est une pratique courante.
+
+## Mise à jour du certificat
+
+Il est conseillé de mettre en place une méthode automatique de mise à jour du certificat.
+Je recommande un timer systemd qui va vérifier la validité du certificat et le renouveler à intervalles réguliers.
+
+`check-certificates.timer` :
+
+```toml
+# This timer unit is for refreshing local certificates everyday
+
+[Unit]
+Description=Refresh self-signed certificates regularly
+Requires=check-certificates.service
+
+
+[Timer]
+Unit=check-certificates.service
+OnUnitActiveSec=86400
+
+[Install]
+WantedBy=timers.target
+```
+
+Et `check-certificates.service`
+
+```toml
+# This service unit is for refreshing local certificates if needed
+
+[Unit]
+Description=Refresh local certificates if needed
+Wants=check-certificates.timer
+
+[Service]
+Type=oneshot
+ExecStart=/usr/bin/check-certificates.sh
+
+[Install]
+WantedBy=multi-user.target
+```
+
+J'ai ainsi créé un script bash pour automatiser la vérification des certificats et la mise à jour des fichiers de configuration de Nginx.
+
+:::details
+
+Contenue du fichier `check-certificates.sh`
+
+::::summary
+
+```bash
+#!/bin/env bash
+
+# This script checks the validity of the certificates in the directory
+# ${CERTIFICATES_DIR} and renews them if necessary.
+#
+# It uses the local CA certificate and key to check the validity of the
+# certificates in the directory ${CERTIFICATES_DIR}.
+#
+# The script is intended to be run from a systemd timer every day.
+
+
+# TODO: Configure the following variables from cli arguments
+# TODO: Rewrite this shit in Python
+CERTIFICATES_DIR="/home/works/certs/"
+LOCAL_CA_CERT="${CERTIFICATES_DIR}/local_ca.cert"
+LOCAL_CA_KEY=$(echo "${LOCAL_CA_CERT}" | sed 's/.cert$/.key/')
+
+HAS_RENEW_CERT=""
+if [ ! -r "$LOCAL_CA_CERT" ]; then
+ echo "☠️ Please re-check that local CA cert \"$LOCAL_CA_CERT\" exists"
+ exit
+fi
+if [ ! -r "$LOCAL_CA_KEY" ]; then
+ echo "☠️ Please re-check that local CA key \"$LOCAL_CA_KEY\" exists"
+ exit
+fi
+
+date
+echo -e "Checking certificate validity (NotAfter field)\n"
+
+pushd ${CERTIFICATES_DIR} >/dev/null 2>/dev/null
+for cert in $(find -name "*.cert"); do
+ if openssl x509 -checkend 345600 -noout -in ${cert} > /dev/null; then
+ echo -e "✔️ $(basename ${cert}) will expire in more than 4 days"
+ else
+ echo -e "❌ $(basename ${cert}) will expire soon !"
+ if [ $(basename "$cert") = $(basename "$LOCAL_CA_CERT") ]; then
+ echo -e "\t⛔ I don't renew local CA certificate"
+ continue
+ fi
+
+ NEW_CSR=$(echo ${cert} | sed 's/.cert/.csr/')
+ CERT_KEY=$(echo ${cert} | sed 's/.cert/.key/')
+ CERT_CONFIG=$(echo ${cert} | sed 's/.cert/.conf/')
+
+ echo "Renewing ${cert}"
+ echo "Creating new CSR ($NEW_CSR)"
+ echo ${cert}
+ echo ${CERT_KEY}
+ echo ${CERT_CONFIG}
+
+ # Sign the new signing request
+ if openssl req -new -key "${CERT_KEY}" -out "${NEW_CSR}" -config "${CERT_CONFIG}"; then
+ echo "👍 CSR created"
+ else
+ echo "❌ Failled to create signing request!"
+ continue
+ fi
+
+ echo "Renewing certificate"
+ openssl x509 -req -CA "${LOCAL_CA_CERT}" -CAkey "${LOCAL_CA_KEY}" -in "${NEW_CSR}" -out "${cert}" -days 10 -CAcreateserial -extensions v3_ext -extfile "${CERT_CONFIG}" -sha256
+ if [ $? -eq 0 ]; then
+ HAS_RENEW_CERT="yes"
+ echo "✔️ Certificate renew"
+ else
+ echo "❌ Failled to renew certificate!"
+ fi
+ fi
+done
+
+echo -e "\nNo more certificate to check"
+if [ -n "$HAS_RENEW_CERT" ]; then
+ echo "🔃 Reload nginx configuration (and update certificates)"
+ nginx -s reload
+fi
+
+popd >/dev/null 2>/dev/null
+```
+
+::::
diff --git a/notes/res/certificat-signed.svg b/notes/res/certificat-signed.svg
new file mode 100644
index 0000000..63278d7
--- /dev/null
+++ b/notes/res/certificat-signed.svg
@@ -0,0 +1 @@
+<svg:svg xmlns:svg="http://www.w3.org/2000/svg" width="215" height="215" fill="none" version="1.1" viewBox="0 0 215.493 215.493"><svg:defs/><svg:path stroke="#1a1b1f" stroke-dasharray="6, 3" stroke-width="1.849" d="m 107.20009,8.8400154 21.80278,16.5838846 27.17395,-3.460579 10.58959,25.263491 25.26402,10.58993 -3.46058,27.173948 16.58369,21.80278 -16.58369,21.80277 3.46058,27.17395 -25.26402,10.5896 -10.58959,25.26402 -27.17395,-3.46057 -21.80278,16.58368 L 85.397306,188.16324 58.223357,191.62381 47.633766,166.35979 22.369741,155.77019 25.830318,128.59624 9.2466353,106.79347 25.830318,84.99069 22.369741,57.816742 47.633766,47.226812 58.223357,21.963321 85.397306,25.4239 Z" class="anim rev"><svg:animate attributeName="stroke-dashoffset" calcMode="linear" dur="2s" repeatCount="indefinite" values="18;0"/></svg:path><svg:path fill="#d6fff8" stroke="#1a1b1f" stroke-width="1.927" d="m 64.255208,45.81924 h 70.884212 l 18.08225,24.386957 V 165.80548 H 64.255208 Z" style="fill:#fff880;fill-opacity:1"/><svg:path stroke="#1a1b1f" stroke-width="1.927" d="m 134.84017,45.81924 v 24.79054 h 18.3815"/><svg:line x1="73.078" x2="128.958" y1="81.518" y2="81.518" stroke="#1a1b1f" stroke-width="1.927"/><svg:line x1="73.078" x2="110.577" y1="94.409" y2="94.409" stroke="#1a1b1f" stroke-width="1.927"/><script/><svg:path d="m 9.836065,2.0341911 c 0.112518,0.038276 0.222436,0.083805 0.329064,0.1363026 l 1.282734,0.6315458 c 0.348138,0.1714034 0.756137,0.1714034 1.104274,0 l 1.282734,-0.6315458 c 1.362589,-0.6708615 3.011025,-0.1101062 3.681887,1.2524821 l 0.07348,0.1623228 0.06282,0.1667409 0.460459,1.3536002 c 0.12497,0.3673712 0.413469,0.65587 0.78084,0.7808401 l 1.353601,0.4604596 c 1.437866,0.4891247 2.206973,2.0512594 1.717848,3.4891256 -0.03828,0.112518 -0.08381,0.222436 -0.136303,0.329064 l -0.631546,1.282734 c -0.171403,0.348138 -0.171403,0.756137 0,1.104274 l 0.631546,1.282734 c 0.670862,1.362589 0.110106,3.011025 -1.252482,3.681887 -0.106627,0.0525 -0.216545,0.09803 -0.329063,0.136303 L 18.89436,18.11352 c -0.367371,0.12497 -0.65587,0.413469 -0.78084,0.78084 l -0.460459,1.353601 c -0.489125,1.437866 -2.05126,2.206973 -3.489126,1.717848 -0.112518,-0.03828 -0.222436,-0.08381 -0.329064,-0.136303 L 12.552137,21.19796 c -0.348137,-0.171403 -0.756136,-0.171403 -1.104274,0 l -1.282734,0.631546 C 8.8025404,22.500368 7.1541036,21.939612 6.4832421,20.577024 6.4307448,20.470397 6.3852151,20.360479 6.3469394,20.247961 L 5.8864798,18.89436 C 5.7615097,18.526989 5.4730109,18.23849 5.1056397,18.11352 L 3.7520395,17.653061 c -1.4378662,-0.489125 -2.2069731,-2.05126 -1.7178484,-3.489126 0.038276,-0.112518 0.083805,-0.222436 0.1363026,-0.329064 l 0.6315458,-1.282734 c 0.1714034,-0.348137 0.1714034,-0.756136 0,-1.104274 L 2.1704937,10.165129 C 1.4996322,8.8025404 2.0603875,7.1541036 3.4229758,6.4832421 3.5296031,6.4307448 3.6395214,6.3852151 3.7520395,6.3469394 L 5.1056397,5.8864798 C 5.4730109,5.7615097 5.7615097,5.4730109 5.8864798,5.1056397 L 6.3469394,3.7520395 C 6.8360641,2.3141733 8.3981988,1.5450664 9.836065,2.0341911 Z M 15.46967,8.9696699 10.050399,14.388941 8.076166,12.019862 C 7.8109929,11.701654 7.3380694,11.658661 7.0198617,11.923834 6.701654,12.189007 6.658661,12.661931 6.923834,12.980138 l 2.5,3 c 0.2823364,0.338804 0.794645,0.362043 1.106496,0.05019 l 6,-6 c 0.292893,-0.2928931 0.292893,-0.7677669 0,-1.0606601 -0.292893,-0.2928932 -0.767767,-0.2928932 -1.06066,0 z" style="fill:#80b7ff;fill-opacity:1;stroke:none;stroke-width:.429579;stroke-dasharray:none;stroke-opacity:.46557" transform="matrix(2.1092 0 0 2.1092 102.13 114.153)"/></svg:svg> \ No newline at end of file
diff --git a/notes/res/chain_of_trust.avif b/notes/res/chain_of_trust.avif
new file mode 100644
index 0000000..a1b114a
--- /dev/null
+++ b/notes/res/chain_of_trust.avif
Binary files differ
diff --git a/notes/res/chain_of_trust.png b/notes/res/chain_of_trust.png
new file mode 100644
index 0000000..e27c0b2
--- /dev/null
+++ b/notes/res/chain_of_trust.png
Binary files differ
diff --git a/notes/res/chaîne_de_certification.avif b/notes/res/chaîne_de_certification.avif
new file mode 100644
index 0000000..7152fe6
--- /dev/null
+++ b/notes/res/chaîne_de_certification.avif
Binary files differ
diff --git a/notes/res/chaîne_de_certification.png b/notes/res/chaîne_de_certification.png
new file mode 100644
index 0000000..b0f5f5d
--- /dev/null
+++ b/notes/res/chaîne_de_certification.png
Binary files differ