De plus en plus menacée, la sécurité informatique est devenue un enjeu majeur pour les entreprises désireuses de consolider leurs anciennes architectures et moderniser leurs nouvelles. Des méthodes et des outils existent pour renforcer la sécurité des données : Vault apporte une réponse technique pour le stockage, et l’accès à vos secrets. Découvrez comment l’installer et l’exploiter !
Outil utilisé : Vault/hashicorp v0.6.1
Site du projet : https://www.vaultproject.io/
Qu’est-ce que Vault?
Vault permet de stocker des secrets de manière sécurisée, tels que vos mots de passe, vos clés privées, vos identifiants de connexion... Il permet d’en contrôler l’accès, mais aussi de renforcer l’authentification à des ressources (génération de mots de base d’accès tournant pour vos bases de données, ssh avec OTP...)
C’est un produit sous licence publique Mozilla écrit en Go qui offre ses services via un interfaçage RESTs. Mais Vault est-il sécurisé ? La gestion de la mémoire en Go et la libre consultation du code source sont des points positifs d’autant plus qu’il a été audité par le groupe iSEC/NCC (auditeur de TrueCrypt et OpenSSL)[ISEC].
1. Installation
L’objectif est de renforcer l’usage des secrets dans une architecture trois tiers existante (projetA), composée de trois machines : un apache avec SSL, une application et une base de données MySQL.
Actuellement, il n’existe aucun paquet officiel Vault. Vous pouvez donc faire votre propre paquet ou l’installer manuellement avec cette procédure.
1.1 Préparer le système à recevoir Vault
1. Créez un utilisateur « vault » dédié. Téléchargez et installez le binaire pour votre plateforme et créez les répertoires pour la configuration et les données.
% adduser --no-create-home --disabled-login vault
% wget -O - https://releases.hashicorp.com/vault/0.6.1/vault_0.6.1_linux_amd64.zip | funzip > /usr/bin/vault && chmod +x /usr/bin/vault
% mkdir /etc/vault; mkdir /var/lib/vault ; chown vault /var/lib/vault ; chmod 700 /var/lib/vault
2. Ajoutez au binaire la capacité de verrouiller une zone mémoire pour éviter que le système vide des pages mémoire dans la swap et expose vos secrets.
% setcap cap_ipc_lock=+ep /usr/bin/vault
3. Facilitez la gestion de votre service avec systemd.
# /lib/systemd/system/vault.service
[Unit]
Description=Vault daemon
After=network.target
[Service]
ExecStart=/usr/bin/vault server -config=/etc/vault/vault.conf
ExecStop=
User=vault
Group=vault
[Install]
WantedBy=multi-user.target
Avant de démarrer Vault, il faut créer les certificats serveurs pour bénéficier du TLS.
1.2 Créer votre infrastructure de certificats
Si vous ne pouvez pas acheter un certificat signé par une autorité de certification(AC) connue, il faudra suivre cette procédure.
Créons une AC qui permettra de signer notre certificat serveur et de la distribuer aux clients. Pour faciliter l’administration en local, l’ajout de l’extension (subjectAltName) avec l’IP 127.0.0.1 sera pratique.
1. Ajoutez à votre configuration openssl une extension (localisation variant suivant les distributions, sous Debian /etc/ssl/openssl.cnf) :
[SANVAULT]
subjectAltName=IP:127.0.0.1
2. Lancez la création de l’AC et du certificat serveur. Choisissez un mot de passe robuste pour votre clé privée d’AC pour assurer la sécurité des certificats et garantir le transport des secrets !
# Génération d’une autorité de certificat(AC) pour 10 ans
% openssl req -new -sha256 -x509 -extensions v3_ca -keyout ca.key -out ca_vault.crt -days 3650
# renforcer la protection de la clé privée de votre AC
% chown root:root ca.key && chmod 400 ca.key
# Création d’une clé privée sans mot de passe pour vault avec un csr (CN=nom de machine)
% openssl req -out vault.csr -new -newkey rsa:2048 -nodes -keyout vault.key -reqexts SANVAULT -config /etc/ssl/openssl.cnf
# Signature de votre certificat avec votre autorité de certificat
% openssl x509 -req -days 3650 -in vault.csr -out vault.pem -CA ca_vault.crt -CAkey ca.key -CAcreateserial -extfile /etc/ssl/openssl.cnf -extensions SANVAULT
Vault est intransigeant avec la conformité des certificats utilisés. Sans certificat serveur avec une AC associée et enregistrée sur votre système, vous devrez rajouter des paramètres supplémentaires aux clients (-tls-skip-verify) qui affaibliraient la sécurité. Utiliser Vault en production, sans chiffrer le transport est absurde.
3. Distribuez votre certificat d’autorité (ca_vault.crt) à vos clients et à votre serveur, puis mettez à jour la base des certificats de confiance.
# (suivant distribution) ajout de notre autorité de certificat et mise à jour des CA de confiance
cp ca_vault.crt /usr/local/share/ca-certificates/ && update-ca-certificate
1.3 Le fichier de configuration
1. Écrivez un fichier de configuration avec le module de stockage de secret « File ». Il existe d’autres modules notamment pour les bases de données et ainsi que ceux qui supportent la haute disponibilité, comme consul, zookeeper ou etcd.
# /etc/vault/vault.conf
# Écoute sur le port TCP 8200 sur toutes les IPs en TLS
listener "tcp" {
address = "0.0.0.0:8200"
tls_cert_file = "/etc/vault/vault.pem"
tls_key_file = "/etc/vault/vault.key"
}
# module de stockage
backend "file" {
path = "/var/lib/vault"
}
Vault stocke ses secrets et son arborescence sous cette forme : les branches sont des répertoires et les feuilles sont des fichiers contenant les secrets. Donc aucun secret ne doit être stocké dans le chemin. De plus, avec le module « File », la lecture/écriture d’un secret passe par l’ouverture/fermeture systématique des fichiers. Il est donc mal adapté aux fortes charges.
2. Activez au redémarrage et démarrez Vault :
% systemctl enable vault.service
% systemctl start vault.service
1.4 Initialisation de la clé de chiffrement
Lors du 1er démarrage, Vault va créer une clé de chiffrement qui permettra de chiffrer les secrets. Elle est protégée par le mécanisme du partage de clé de Shamir, qui permet de diviser le secret en plusieurs parties nécessitant un minimum de participants pour la révéler (cérémonie des clés).
1. Initialisez-le (ici avec 5 clés dont 3 suffisent pour le desceller) :
% vault init -key-shares=5 -key-threshold=3
Unseal Key 1 (hex) : 330d9e8c517aa493ca37ef7ba4f73abf3c1ef6b0e1011be6eaf56640823e559f01
…
Initial Root Token: 1bfde3d3-e1c2-1e2a-3c57-1fb92890361d
2. Distribuez judicieusement les « Unseal key » aux différentes personnes de votre organisation pour garantir une bonne ségrégation des droits.
Le « root token » donnera les pleins pouvoirs pour configurer les futurs droits d’accès.
3. Descellez la clé de chiffrement. Trois participants minimums devront entrer leur clé (hex ou base64) :
% vault unseal Mw2ejFF6pJPKN+97pPc6vzwe9rDhARvm6vVmQII+VZ8B
% vault unseal 738ceaaef7b8dd133e00d33d31c533634e372e294591a5f89779a092cfc67ef603
% vault unseal 7f3rxTLTmij/Z+gMrfYYgJ45LsJ/3Qw9R5nNHwLhcWAF
Vault a maintenant déchiffré et chargé en mémoire la clé de chiffrement. Désormais, vous pouvez vous authentifier et créer vos premiers secrets !
2. Stocker des secrets
1. Authentifiez-vous avec le root token.
% vault auth 1bfde3d3-e1c2-1e2a-3c57-1fb92890361d
Pour l’organisation, la génération et la classification de secrets (« stockage logique »), Vault utilise un système d’arborescence, comme un système de fichiers, où les chemins racines se montent et se démontent.
% vault mounts
Path Type Default TTL Max TTL Description
cubbyhole/ cubbyhole n/a n/a per-token private secret storage
secret/ generic system system generic secret storage
sys/ system n/a n/a system endpoints used for control, policy and debugging
Le chemin détermine l’URL REST d’accès à l’information et sa classification. Chaque type de module possède les propriétés présentées dans la partie description avec leur durée de vie respective.
Vous pouvez ajouter des points de montage personnalisés, par exemple avec le module « generic » :
% vault mount -path=mypassword -max-lease-ttl=87600h generic
Successfully mounted 'generic' at 'mypassword'!
Contrairement à un système de fichiers Linux, le démontage d’un chemin entraîne la destruction de tous ses secrets.
2.1 Stockage de la clé de déchiffrement SSL de notre certificat apache
1. Stockez votre mot de passe de déchiffrement de votre clé privée SSL relatif au projetA et lisez-le :
vault write secret/projetA/web apache_priv_key=secret
Success! Data written to: secret/projetA/web
% vault read secret/projetA/web
Key Value
--- -----
refresh_interval 720h0m0s
apache_priv_key secret
Le refresh_interval informe le client de la durée de rafraîchissement du secret, grâce au module « generic », c’est indicatif. Il a un grand intérêt lorsque l’on utilise un système de rotation des secrets (MySQL, OTP...), pour la récupération du nouveau mot de passe valide.
2. Modifiez votre configuration apache pour lire le mot de passe de chiffrement de clé privée SSL à partir d’un script (paramètre SSLPassPhraseDialog) :
# configuration apache ssl ...
...
SSLPassPhraseDialog exec:/path/get_passwd_from_vault.sh
...
3. Écrivez le script correspondant :
#!/usr/bin/env bash
export VAULT_TOKEN="un_token_dédié"
vault read -field=apache_priv_key secret/projetA/web
Ne mettez pas votre « root-token » dans le script, car il a accès à tous les secrets. Nous verrons par la suite comment créer des tokens avec des accès restreints.
2.2 Générer des comptes MySQL tournants
2.2.1 Configuration du module
L’objectif du module est de fournir à Vault un utilisateur MySQL avec les droits nécessaires pour générer/détruire à la volée des identifiants/mots de passe pour un type de profil donné (lecture, écriture…), souhaité pour notre application.
1. Créez un utilisateur « vault_gen » sur votre MySQL avec les droits nécessaires pour ajouter/supprimer des utilisateurs et leur attribuer des droits sur la base de données «projetA» :
mysql> CREATE USER 'vault_gen'@'localhost' IDENTIFIED BY 'secret';
mysql> GRANT ALL PRIVILEGES ON projetA.* TO 'vault_gen'@'localhost' WITH GRANT OPTION;
mysql> GRANT CREATE USER ON *.* TO 'vault_gen'@'localhost';
2. Montez le module MySQL sur le point de montage « mysql.projetA ». Il sera dédié à notre instance MySQL, et les identifiants seront à renouveler toutes les 10 minutes :
% vault mount -path=projetA.mysql -description="mysql projet A" -default-lease-ttl=10m mysql
3. Configurez le module avec votre utilisateur MySQL « vault_gen ».
% vault write projetA.mysql/config/connection
connection_url="vault_gen:secret@tcp(127.0.0.1:3306)/projetA"
4. Créez les profils de compte désirés comme « lecture, écriture et dba ». Observez ci-dessous un exemple pour la lecture seule à adapter pour vos autres comptes (droit après le « GRANT »).
# remplacer % par localhost si l’application est sur la même machine que le MySQL
% vault write projetA.mysql/roles/lecture sql="CREATE USER '{{name}}'@'%' IDENTIFIED BY '{{password}}';
GRANT SELECT ON projetA.* TO '{{name}}'@'%';"
La création des rôles est entièrement personnalisable grâce aux modèles et aux variables « {{name}} »/« {{password}} », ainsi que les requêtes SQL. Il est tout à fait possible de rajouter d’autres instructions SQL dans la chaîne.
Pour supprimer un rôle, il suffit de détruire la branche correspondante :
% vault delete projetA.mysql/roles/lecture
La suppression d’un rôle et le démontage du module ne coupent pas les connexions MySQL existantes (pas de « kill »).
2.2.2 Générer des identifiants de connexion
1. Récupérez les identifiants générés par Vault dans le MySQL :
% vault read projetA.mysql/creds/lecture
…
password 5b65ee31-14f1-3488-ad7c-fe0d51096830
username lect-root-1435be
2. Connectez-vous au MySQL pour tester le couple username/password :
% mysql -ulect-root-1435be -p5b65ee31-14f1-3488-ad7c-fe0d51096830 -B -N -e"show grants"
GRANT USAGE ON *.* TO 'lect-root-1435be'@'localhost' IDENTIFIED BY PASSWORD <secret>
GRANT SELECT ON `projetA`.* TO 'lect-root-1435be'@'localhost'
Pour utiliser ces identifiants tournants, des modifications dans votre application seront nécessaires : en faisant une requête REST directement (exemple ci-dessous avec curl) ou en utilisant une bibliothèque dédiée au langage (hvac pour python, Spring Cloud Vault pour java, etc.) :
% curl -s -H "X-Vault-Token: TOKEN" "https://127.0.0.1:8200/v1/projetA.mysql/creds/ecriture" | python -m json.tool
…
"password": "1a2bd102-2af4-a284-601f-893deac80ef4",
"username": "ecri-root-760038"
…
Si d’autres modules à explorer existent, il n'est pas possible de tous les traiter ici. Lorsque l’on centralise les secrets, le plus important est d’en contrôler strictement les accès, regardons la procédure à suivre.
3. Contrôler l’accès à vos secrets
Il y a deux techniques essentielles pour contrôler l'accès aux secrets : les tokens avec leurs modules d'authentification et les politiques de droit.
3.1 Comprendre les tokens
Les mécanismes d’authentification reposent sur le composant « token ». Il est représenté par un uuid, créé aléatoirement. Il est rattaché à une ou plusieurs politiques de droits, une structure de données qui permettent de les représenter sous la forme d’arbre ainsi que d’autres propriétés (durée de vie, nombre d’utilisation...). Il est plus pratique et flexible d’utiliser un module d’authentification que de créer des tokens manuellement, car il le fera pour vous. Néanmoins, il est important d’en comprendre le fonctionnement, car ils sont toujours manipulés.
La première manipulation de token est l’authentification que nous avons utilisée pour administrer Vault :
% vault auth TOKEN_ROOT
Une fois authentifié(e), on peut consulter les propriétés de son token :
% vault token-lookup
…
id 2dfb381f-3bd1-9ff1-2753-37c6d1c3356a << le token
policies [default] << liste des droits pour le token
…
ttl 35988 << durée restante avant expiration
Enfin, si on souhaite les créer, les renouveler et les détruire, découvrez cinq manipulations courantes.
3.1.1. 5 manipulations courantes de tokens
1. Comment créer un token « root » ? Ce type de token n’expire jamais. Il doit être créé pour un nombre restreint de personnes et ne jamais être mis dans une application.
% vault token-create -display-name="Bob admin" -policy="root"
2. Comment créer une hiérarchie de token ? En créant initialement la racine avec un token orphelin. Par défaut, le token est renouvelable. Il a une durée de vie fixée à « default_lease_ttl ».
% vault token-create -display-name="AdminClient1" -policy="default" -orphan
3. Comment créer un token avec une durée de vie limitée à 10 heures, renouvelable jusqu’à « default_lease_ttl »?
% vault token-create -display-name="adminClient2" -policy="default" -ttl=10h
4. Comment renouveler un token ? Vous devez le renouveler avant son expiration.
% vault token-renew -increment 10h
…
token_duration 10h0m0s
5. Comment révoquer un token ? Soit avec sa valeur, soit via son accesseur afin de révoquer des droits sans les avoir.
% vault token-create -orphan -renewable=true -display-name="AdminClient1" -policy="default" -ttl=10h
…
token 9c93ee42-aa6b-d62f-6bb4-a0ed5ff65eb2
token_accessor a46d5538-1a9b-94c0-9e41-2bcd90d662fc
# les 2 commandes ci-dessous révoquent le même token
% vault token-revoke 9c93ee42-aa6b-d62f-6bb4-a0ed5ff65eb2
% vault token-revoke -accessor a46d5538-1a9b-94c0-9e41-2bcd90d662fc
Tous les tokens possèdent une ou plusieurs « policy » qui déterminent les politiques d’accès aux données. Créons en maintenant pour nos besoins.
3.2 Politique d’accès
Ils déterminent les permissions sur les secrets ou l’administration : lecture et écriture des différentes branches. Une permission se configure à l’aide de la syntaxe HCL ou json.
On décrit le chemin d’accès, avec éventuellement des jokers, puis leurs politiques et/ou leurs capacités. Une politique est un ensemble de capacités. Par défaut, il existe deux politiques de droits, lisibles ainsi :
# pour les lister
% vault policies
default
root
# pour consulter la politique « default »
% vault policies default
path "auth/token/lookup-self" {
…
Par défaut rien n’est autorisé. C’est la politique « default » qui permet de manipuler son propre token et son cagibi personnel (cubbyhole) : elle est automatiquement appliquée sauf à root qui a tous les droits.
3.2.1 Les droits pour votre script apache SSL
1. Définissez une politique pour que votre script apache ait accès en lecture au mot de passe SSL et appliquez-la avec la commande policy-write :
# fichier lecture_web.hcl
path "secret/projetA/web" { policy = "read" }
% vault policy-write lecture_web lecture_web.hcl
Policy 'lecture_web' written.
2. Ajoutez une politique pour administrer ces secrets :
# admin_projeta.hcl
path "secret/projetA/*" { policy = "write" }
On peut faire des politiques plus complexes comme supprimer n’importe quel token, verrouiller les secrets en cas d’intrusion et contrôler les politiques de sécurité :
# admin_securite
path "/auth/token/revoke*" { policy = "write" }
path "/sys/seal*" { policy = "sudo" }
path "/sys/policy*" { policy = "read" }
Ici, l’utilisation du droit sudo pour le scellement est nécessaire, car il est réservé à « root ».
3.2.2 Les droits pour votre MySQL
1. Donnez les droits de configuration sur le module MySQL à vos administrateurs.
# dba_projeta
path "/projetA.mysql/*" { policy = "write" }
2. N’oubliez pas de protéger tous les accès au compte MySQL créé (écriture, lecture...).
# app_db_projeta
path "/projetA.mysql/auth/creds/ecriture" { policy = "read" }
Les politiques de droits sont dynamiques. Elles sont lues à chaque requête : inutile de recréer un token. De plus, on peut donner des droits sur des chemins qui n’existent pas encore.
Nous l’avons vu, manipuler les tokens est une tâche fastidieuse. Pour y palier, des modules existants génèrent, gèrent et appliquent les politiques de droit aux tokens.
3.3 Les modules d’authentification
Ils sont nombreux, du GitHub au LDAP d’entreprise. Présentons le module « userpass » pour authentifier des personnes et le module « approle », orienté machines/applications.
3.3.1 Authentifiez des personnes
1. Activez le module une première fois et créez des utilisateurs adaptés à vos précédentes politiques de droits (un échantillon ci-dessous).
# activation du module (à faire qu’une fois)
% vault auth-enable userpass
% vault write auth/userpass/users/denis password='robustless' policies=admin_projeta
% vault write auth/userpass/users/theary password='secret' policies=admin_securite
% vault write auth/userpass/users/teddy password='bear' policies=dba_projeta,admin_projeta
2. Authentifiez-vous à l’aide de la commande auth et vos couples utilisateurs/mots de passe pour recevoir votre token.
% vault auth -method=userpass username=theary
L'authentification des personnes réussie, il s'agit de faire de même avec les applications/machines.
3.3.2 Authentifier des machines et des applications
Le module « approle » permet de créer des rôles pour vos machines et vos applications : on l’utilisera pour authentifier notre script pour apache.
1. Activez le module une seule fois :
% vault auth-enable approle
2. Créez le rôle « web_projeta » sur lequel on associe notre politique de droits « lecture_web » et on y affecte une restriction d’IP pour renforcer la sécurité.
% vault write auth/approle/role/web_projeta secret_id_ttl=0 token_ttl=24h bound_cidr_list="172.17.0.0/24" policies="lecture_web"
3. Récupérez l’identifiant de votre rôle :
% vault read auth/approle/role/web_projeta/role-id
Key Value
--- -----
role_id 046edfd1-edbf-9310-4c80-270cb7fd1282
4. Récupérez votre « secret-id » qui est une sécurité supplémentaire. Elle associe à un rôle, un uuid confidentiel. Cela empêche la fuite de secret, lorsque l’on connaît juste le nom de l’application.
% vault write -f auth/approle/role/applicationA/secret-id
Key Value
--- -----
secret_id 915a1259-d26e-e832-bd30-8ba088e701cf
secret_id_accessor f5d6cfd4-4067-21c6-bbc7-de9e7cacbbf0
5. Modifiez le script apache ainsi :
export VAULT_TOKEN=`vault write -field=token auth/approle/login role_id=046edfd1-edbf-9310-4c80-270cb7fd1282 secret_id=915a1259-d26e-e832-bd30-8ba088e701cf`
Vous pouvez utiliser le même principe pour vos applications. Maintenant pour faire face à un incident de sécurité, on doit auditer notre gestionnaire de secret.
4. Gardez le contrôle
Pour détecter toutes activités anormales, il faut l’interconnecter avec un produit de surveillance qui est facilité par le format json des logs (Elasticsearch/watch) :
# dans un fichier
% vault audit-enable file path=/var/log/vault.log
# via syslog
% vault audit-enable syslog
Rassurez-vous, toutes les actions sont loggées avec des tokens et les secrets hachés en SHA256.
Conclusion
Vault est un outil complet et moderne adapté à tout type d’architecture moyennant quelques modifications logicielles. La mise à disposition du code source et les audits réalisés par des professionnels sont rassurants.
C’est un logiciel récent qui évolue, il est donc à installer avec un suivi régulier des mises à jour. De plus, on pourrait lui reprocher un manque de fonctionnalités pour les entreprises (HSM et interface d’administration) absentes dans la version communautaire. Néanmoins, il offre de nombreuses fonctionnalités puissantes adaptées à tous.