Aller au contenu

Chapitre 7. Installation de Vault

Objectifs pédagogiques

Vérifier l'intégrité et l'origine d'un binaire. Situer le mode développement et ses limites. Préparer un hôte. Écrire une configuration mono-nœud complète et justifier chaque directive. Produire un certificat de laboratoire correct. Rédiger une unité systemd durcie. Établir une première connexion propre et lire l'état d'un serveur neuf.

Prérequis

Parties I et II, en particulier les hypothèses opérationnelles du chapitre 5 et la place du seal.

Cours

7.1 Se procurer Vault, et le vérifier

Vault est distribué sous forme d'un binaire unique par plateforme. Deux canaux propres : les dépôts de paquets officiels, qui installent binaire, utilisateur, répertoires et unité systemd, et le téléchargement direct. Ce cours montre le second, parce qu'il oblige à faire ce que le paquet fait pour vous, à commencer par la vérification. L'incident Codecov du chapitre 1 a montré ce qu'il en coûte d'exécuter un outil modifié en chemin.

[Laboratoire]. Remplacez <VERSION> par la version choisie ; ce cours est ancré sur la série 1.x.

# Le binaire, la liste des empreintes, et la signature de cette liste
curl -fsSLO https://releases.hashicorp.com/vault/<VERSION>/vault_<VERSION>_linux_amd64.zip
curl -fsSLO https://releases.hashicorp.com/vault/<VERSION>/vault_<VERSION>_SHA256SUMS
curl -fsSLO https://releases.hashicorp.com/vault/<VERSION>/vault_<VERSION>_SHA256SUMS.sig

# 1. La signature prouve que la liste vient bien de l'editeur.
#    La cle publique doit avoir ete importee au prealable, obtenue par un
#    canal de confiance et son empreinte verifiee.
gpg --verify vault_<VERSION>_SHA256SUMS.sig vault_<VERSION>_SHA256SUMS

# 2. L'empreinte prouve que le binaire telecharge est celui de la liste.
sha256sum -c vault_<VERSION>_SHA256SUMS --ignore-missing

unzip vault_<VERSION>_linux_amd64.zip
sudo install -o root -g root -m 0755 vault /usr/local/bin/vault
vault version

La double vérification a une logique qui resservira pour tout logiciel critique. L'empreinte seule prouve l'intégrité du téléchargement, pas son origine : un attaquant qui contrôle le canal de distribution sert un binaire modifié et sa liste d'empreintes assortie. La signature de la liste ferme cette porte. Le maillon restant est l'obtention initiale de la clé publique.

Le binaire n'a rien de secret et se pose en lecture pour tous ; ce sont ses données qui le seront.

7.2 Le mode développement

[Démonstration]

vault server -dev

Une commande, et tout fonctionne : serveur descellé, root token affiché, KV v2 monté sur secret/. Ce confort inverse un à un les trois comportements de sécurité par défaut. Le stockage est en mémoire : rien ne survit à l'arrêt. Le serveur démarre descellé. Le listener parle HTTP sans TLS. S'y ajoute le root token affiché dans le terminal et souvent exporté en variable d'environnement, donc lisible dans /proc.

L'usage légitime existe : explorer l'API, tester une syntaxe de policy, reproduire un comportement pour un rapport de bogue. Tout ce qui ne met en jeu aucune donnée réelle. Règle : le mode développement ne voit jamais un vrai secret, jamais un réseau partagé, jamais une démonstration avec des données d'entreprise.

7.3 Préparer l'hôte

Le processus n'a aucune raison de s'exécuter en root. [Production]

# Utilisateur systeme dedie : pas de shell de connexion,
# ce compte execute un service et rien d'autre
sudo useradd --system --home /etc/vault.d --shell /bin/false vault

sudo mkdir -p /etc/vault.d/tls /opt/vault/data /var/log/vault
sudo chown -R vault:vault /opt/vault /var/log/vault
sudo chown -R root:vault /etc/vault.d
sudo chmod 0750 /etc/vault.d /etc/vault.d/tls
sudo chmod 0700 /opt/vault/data

Le partage des rôles est délibéré. La configuration appartient à root et se donne en lecture au groupe : le service la lit sans pouvoir la réécrire, donc un processus compromis ne modifie pas sa propre configuration. Les données Raft appartiennent au compte de service seul, en 0700 : elles sont chiffrées, mais la défense en profondeur ne raisonne jamais « chiffré, donc permissions indifférentes ». Le répertoire d'audit doit être inscriptible, sous peine d'arrêt du service.

Ces chemins sont ceux du cours et du fil rouge : /etc/vault.d pour la configuration, /opt/vault/data pour le stockage, /var/log/vault pour l'audit.

7.4 La configuration, ligne à ligne

[Production], fichier /etc/vault.d/vault.hcl :

ui = true

storage "raft" {
  path    = "/opt/vault/data"
  node_id = "vault-core-01"
}

listener "tcp" {
  address       = "10.10.20.11:8200"
  tls_cert_file = "/etc/vault.d/tls/vault-core-01.crt"
  tls_key_file  = "/etc/vault.d/tls/vault-core-01.key"
}

api_addr      = "https://vault-core-01.astrea.lab:8200"
cluster_addr  = "https://10.10.20.11:8201"

disable_mlock = true

storage "raft". Le stockage intégré, y compris pour un mono-nœud. La justification n'est pas évidente : on pourrait se contenter d'un stockage fichier. Démarrer en Raft dès le premier jour épargne une migration de backend quand le cluster arrive (partie VIII) ; le nœud existant accueillera ses pairs sans déménagement. node_id fixe l'identité stable du nœud : un identifiant qui change, et Raft voit un inconnu.

listener "tcp". L'adresse d'écoute est celle de l'interface de service, pas 0.0.0.0 par réflexe. Écouter partout, c'est offrir l'API à toute interface présente et future. TLS est activé dès le laboratoire : s'habituer à http:// en laboratoire, c'est s'entraîner à la mauvaise configuration.

api_addr et cluster_addr. Deux adresses annoncées, à distinguer des adresses d'écoute. api_addr est l'adresse à laquelle les clients doivent joindre ce nœud, utilisée notamment pour les redirections en haute disponibilité. cluster_addr est celle qu'utiliseront les autres nœuds sur le port 8201. Sur un mono-nœud, ces valeurs semblent décoratives ; les fixer maintenant, c'est un cluster qui se formera sans surprise.

disable_mlock = true. La ligne qui étonne, et qui est la bonne pour la raison établie en section 5.7 : avec le stockage intégré, la recommandation documentée est de désactiver le verrouillage mémoire et l'échange au niveau de l'hôte. La directive n'a de sens qu'avec son autre moitié. [Production]

# Desactiver l'echange immediatement...
sudo swapoff -a
# ...et de facon permanente
sudo sed -i.bak '/\sswap\s/s/^/#/' /etc/fstab
free -h

Écrire disable_mlock = true sans supprimer l'échange cumule le pire des deux mondes : une mémoire qui peut paginer, sans verrou pour l'en empêcher, donc les clés de la barrière couchées au repos hors de sa protection.

ui = true. L'interface web n'est qu'un client de l'API et n'ouvre aucun droit supplémentaire. La laisser active est un choix de confort assumé, que certains environnements durcis inverseront.

Deux absences méritent un mot. Aucune strophe seal : le scellement est donc Shamir, comportement par défaut et choix de l'étape 0. Aucun bloc de télémétrie : la supervision arrive au chapitre 36, et le cours refuse les blocs recopiés sans être compris.

7.5 Le certificat TLS de laboratoire

En production, le certificat viendra de la PKI interne (chapitres 17 et 28). En attendant, un certificat auto-signé, correctement fait : nom exact, durée courte, et surtout des SAN complets, car c'est sur eux que les clients vérifient. [Laboratoire]

# Cle privee EC P-256 et certificat auto-signe, 90 jours
#   -nodes  : cle non chiffree (c'est un service qui la lit)
#   -addext : les SAN, nom DNS et adresse par lesquels les clients
#             joindront reellement ce serveur
sudo openssl req -x509 -nodes -newkey ec -pkeyopt ec_paramgen_curve:P-256 \
  -keyout /etc/vault.d/tls/vault-core-01.key \
  -out    /etc/vault.d/tls/vault-core-01.crt \
  -days 90 \
  -subj "/CN=vault-core-01.astrea.lab" \
  -addext "subjectAltName=DNS:vault-core-01.astrea.lab,IP:10.10.20.11"

sudo chown root:vault /etc/vault.d/tls/vault-core-01.*
sudo chmod 0640 /etc/vault.d/tls/vault-core-01.key
sudo chmod 0644 /etc/vault.d/tls/vault-core-01.crt

La durée de 90 jours force à pratiquer le renouvellement et prépare aux durées courtes du chapitre 17. La clé privée est lisible par le seul groupe de service : c'est un secret plein, quiconque la lit peut se faire passer pour le serveur. Le certificat embarque le nom DNS et l'adresse : un SAN incomplet produit ces erreurs de vérification que trop d'équipes résolvent en désactivant la vérification.

7.6 Le service systemd, durci

Chaque directive de durcissement renvoie au chapitre 5 : tout ce qui réduit ce que le processus peut faire réduit ce qu'un processus compromis pourra faire. [Production], fichier /etc/systemd/system/vault.service :

[Unit]
Description=HashiCorp Vault
Wants=network-online.target
After=network-online.target
ConditionFileNotEmpty=/etc/vault.d/vault.hcl

[Service]
User=vault
Group=vault
ExecStart=/usr/local/bin/vault server -config=/etc/vault.d/vault.hcl
ExecReload=/bin/kill --signal HUP $MAINPID
KillSignal=SIGINT
Restart=on-failure
RestartSec=5

# Confinement : reduire ce que le processus peut voir et faire
ProtectSystem=full
ProtectHome=read-only
PrivateTmp=yes
PrivateDevices=yes
NoNewPrivileges=yes

# Pas de vidage memoire, et assez de descripteurs
LimitCORE=0
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target

Les lignes qui portent le sens. User et Group appliquent le moindre privilège à l'exécution. KillSignal=SIGINT donne l'arrêt propre que Vault attend. ProtectSystem et ProtectHome rendent le système en lecture seule pour le processus : un Vault compromis ne réécrit ni binaires ni configurations. NoNewPrivileges interdit toute acquisition ultérieure de privilèges. LimitCORE=0 traduit l'hypothèse « la mémoire ne se retrouve pas sur disque », dans la même famille que la suppression de l'échange. Aucune capacité de verrouillage mémoire n'est accordée : une unité cohérente n'accorde pas un privilège que la configuration a décidé de ne pas utiliser.

sudo systemctl daemon-reload
sudo systemctl enable --now vault
journalctl -u vault -n 20 --no-pager

Le journal doit montrer le serveur démarré, en écoute, et scellé. Il tourne, mais ne fonctionne pas encore : c'est l'état attendu.

7.7 Première connexion

[Laboratoire], depuis le poste d'administration :

export VAULT_ADDR="https://vault-core-01.astrea.lab:8200"
export VAULT_CACERT="$HOME/vault-core-01.crt"
vault status

VAULT_CACERT désigne l'autorité avec laquelle vérifier le serveur : c'est la façon correcte de parler à un serveur au certificat non public. La façon incorrecte a un nom, VAULT_SKIP_VERIFY, et aucune place dans ce cours : elle recrée le profil intercepteur du chapitre 5. Quant à VAULT_TOKEN, la variable existe, et le chapitre 1 a montré où finissent les variables d'environnement ; vault login range le token dans un fichier aux permissions utilisateur.

La sortie sur un serveur neuf :

Key                Value
---                -----
Seal Type          shamir
Initialized        false
Sealed             true
Storage Type       raft
HA Enabled         true

Initialized false : la hiérarchie de clés n'existe pas encore. Sealed true : l'état sûr est l'état initial. L'équivalent API :

curl --cacert "$VAULT_CACERT" "$VAULT_ADDR/v1/sys/health"

Le code HTTP dit tout sans lire le corps : 200 pour un serveur actif, 429 pour un standby, 501 pour un serveur non initialisé, 503 pour un serveur scellé. Des codes supplémentaires existent pour les états de réplication Enterprise. Notre serveur répond 501.

Exemple : le journal d'installation d'Astrea

Chaque décision est consignée avec sa justification, parce qu'un choix non documenté sera un jour corrigé par quelqu'un qui en ignorait la raison.

  • Binaire vérifié, signature et empreinte, avant installation.
  • Stockage Raft dès le mono-nœud, pour éviter une migration à l'arrivée du cluster.
  • Écoute liée à 10.10.20.11 : l'API n'est pas offerte aux interfaces d'administration.
  • TLS actif avec certificat de laboratoire de 90 jours, SAN complets, remplacement prévu par la PKI interne.
  • disable_mlock = true et échange supprimé de la table de montage, contrôle croisé au TP 1.
  • Unité systemd durcie, LimitCORE=0.
  • Accès SSH restreint à deux comptes nominatifs : la liste des root est la liste d'accès aux secrets.

Restent ouverts et datés : l'initialisation, l'audit à activer dans la foulée, la supervision.

Architecture : l'étape 0

   admin-01 (10.10.10.21)                    vault-core-01 (10.10.20.11)
   poste d'administration                    +---------------------------+
        |                                    |  vault (user systeme)     |
        |  HTTPS, certificat verifie         |  listener :8200 (TLS)     |
        +----------------------------------->|  [scelle, non initialise] |
                                             |  /etc/vault.d/  (config)  |
                                             |  /opt/vault/data (raft)   |
                                             |  /var/log/vault (audit)   |
                                             |  :8201 (inutilise)        |
                                             +---------------------------+

Sécurité : ce qu'une installation décide déjà

La chaîne d'approvisionnement. Le binaire vérifié, la clé publique obtenue proprement, et la même exigence appliquée aux mises à jour. Un attaquant qui place son binaire a tout, immédiatement et silencieusement.

La surface de l'hôte. Cette machine ne fait que Vault. Chaque service cohabitant, chaque compte supplémentaire, chaque outil pratique installé est un chemin de plus vers la mémoire du processus. La troisième frontière n'a que la sobriété pour défense.

Les habitudes de laboratoire. TLS vérifié dès le premier jour, pas de token en variable d'environnement, pas d'écoute sur toutes les interfaces. Les gestes appris ici seront reproduits en production.

Erreurs fréquentes

Faire durer le mode développement. Il héberge bientôt de vrais secrets, en mémoire, sans TLS, root token dans l'historique (section 7.2).

VAULT_SKIP_VERIFY comme solution aux erreurs TLS. L'erreur signale un SAN manquant ou une autorité absente. La désactiver installe le profil intercepteur au cœur des pratiques (sections 7.5 et 7.7).

Écouter sur toutes les interfaces. L'adresse d'écoute se choisit ; la surface se déclare (section 7.4).

Désactiver le verrouillage mémoire sans toucher à l'échange, ou l'inverse. Les deux réglages forment un couple ; l'un sans l'autre laisse la mémoire paginer, clés comprises (section 7.4).

Exécuter Vault en root. Un processus root compromis, c'est l'hôte entier, donc tout (sections 7.3 et 7.6).

Laisser la configuration et la clé TLS lisibles largement. La clé du listener permet l'usurpation du serveur ; la configuration révèle l'architecture (sections 7.3 et 7.5).

Négliger node_id et les adresses annoncées. Tout semble marcher sur un mono-nœud ; à l'arrivée du cluster, identités instables et redirections fausses (section 7.4).

Mise en pratique : l'audit d'une configuration fautive

Sans machine. Une configuration trouvée en l'état sur un serveur candidat à la production. Réponses commentées en fin de partie.

  1. Identifiez les six défauts, classés par gravité décroissante, et dites pour chacun quelle frontière ou quelle exigence il abandonne.
  2. Proposez la correction de chacun, en distinguant ce qui se règle dans le fichier de ce qui se règle en dehors.
  3. Deux de ces défauts ne produiront aucun symptôme avant la partie VIII. Nommez-les et expliquez le coût de leur report.
storage "raft" {
  path = "/opt/vault/data"
}

listener "tcp" {
  address     = "0.0.0.0:8200"
  tls_disable = true
}

api_addr = "http://127.0.0.1:8200"

Le service est lancé par nohup vault server -config=vault.hcl & dans une session root, et la machine dispose de 4 Go d'échange actif.

Questions de compréhension

  1. Pourquoi la vérification exige-t-elle empreinte et signature ? Que couvre chacune, et quel maillon reste à votre charge ?
  2. Citez les trois inversions de sécurité du mode développement et son périmètre d'usage légitime.
  3. Justifiez le choix de Raft dès le mono-nœud, et le rôle de node_id.
  4. Distinguez adresse d'écoute, api_addr et cluster_addr : qui utilise chacune ?
  5. Énoncez le couple de réglages mémoire recommandé, et ce que produit chacune des deux incohérences possibles.
  6. Reliez trois directives de durcissement systemd à un élément précis du modèle du chapitre 5.
  7. Pourquoi VAULT_CACERT est-il la bonne réponse là où VAULT_SKIP_VERIFY est la mauvaise ?
  8. Que signifie la réponse 501, et citez les trois autres codes avec leur signification.

Synthèse

Installer proprement, c'est appliquer le modèle avant l'initialisation. Un binaire dont l'origine et l'intégrité sont prouvées. Un hôte préparé au moindre privilège. Une configuration dont chaque ligne se justifie : Raft dès le premier nœud avec une identité stable, un listener TLS lié à son interface, des adresses annoncées correctes, et le couple cohérent verrouillage mémoire désactivé avec échange supprimé. Un service confiné, sans vidage mémoire ni privilège superflu. Une CLI qui vérifie le serveur au lieu d'apprendre à l'ignorer. Le serveur obtenu répond 501 : il n'est rien encore. Déclenche le TP 1 (énoncé en partie XV).