Sécurisez vos secret avec HashiCorp Vault : avec le PaaS GCP
Mon 22 July 2024Introduction¶
HashiCorp Vault est un outil de gestion des secrets populaire qui permet de centraliser et de sécuriser les secrets sensibles tels que les mots de passe, les jetons d’API, les certificats et toute sorte de données confidentielles. C’est donc un outil d’exploitation qui devient très rapidement indispensable. À titre personnel, j’en ai en particulier besoin pour mon article sur la gestion des clés SSH.
Cependant même si l’éditeur de la solution le conseil de l’installer sur une plateforme IaaS (un cluster de machine), pour des raisons de coût je pense qu’on peut obtenir un très bon compromis sur une installation de type PaaS. * IaaS apporterait la possibilité d’isoler au maximum les secrets du reste de l’infrastructure et comme beaucoup d’autres infrastructures sont dépendantes de ce service, cela permet aussi de la relancer en premier en cas de gros crash. * PaaS lui évite les contraintes de gestion des mises à jour des serveurs, les pannes matérielles et offre une tarification à l’utilisation qui est très intéressante pour de petites infrastructures.
Il n’y a cependant pas beaucoup de documentation selon moi sur l’utilisation de Hashicorp Vault sur du PaaS. Voici ici une aide sur comment déployer la solution Hashicorp sur une infrastructure PaaS :
- CloudRun pour l’hébergement du compute et le lancement de container à la demande. Vous êtes facturé en fonction du temps d’exécution de vos conteneurs, de la mémoire qu’ils utilisent et du nombre de requêtes qu’ils traitent. Lorsqu’il n’y a pas de requêtes vers vos containers, ceux-ci sont coupés et vous n’êtes pas facturé.
- GCS pour le stockage des secrets et la base de données. Vous êtes facturé en fonction de la quantité de données stockées dans vos buckets (négligeable, ici, car nous n’allons pas avoir des secrets de plusieurs Go) et le trafic entrant et sortant de vos buckets, y compris les requêtes API, les téléchargements et les téléchargements. Il existe des frais distincts pour le trafic standard et le trafic par API.
- KMS pour le chiffrement des données sur le bucket (ce qu’on appelle “Seal” dans le language Vault). Vous êtes facturé pour chaque opération de chiffrement ou de déchiffrement effectuée à l’aide d’une clé KMS. Il existe différents tarifs pour les opérations de chiffrement symétrique et asymétrique.
En résumé, utiliser ces services permet de n’être facturé qu’as l’utilisation. Lectures de mot de passe au gestionnaire de secrets, décodage de flux, entraînera une facturation, mais si l’infrastructure “dort” elle ne coûtera rien.
Le schéma ci-dessous resume comment le service peut fonctionner sur du PaaS :

Voici maintenant comment installer HashiCorp Vault sur Cloud Run en utilisant un backend de stockage Cloud Storage (GCS) et un chiffrement Cloud Key Management Service (KMS) sur GCP.
Prérequis¶
Avant de commencer, vous devez avoir les éléments suivants :
- Un compte GCP avec les permissions appropriées
- Gcloud SDK installé et configuré (inclus dans la CLI de la cloud-console GCP)
- Terraform (inclus dans la CLI de la cloud-console GCP)
Étape 1 : Créer un service de compte¶
Pour que notre application puisse interagir avec les APIs dans GCP (accès aux objets du bucket, KMS, …). Il sera utilisé par notre service CloudRUN et nous lui donnerons les droits en respectant scrupuleusement le principe des moindres-privilèges.
# service_account.tf
# Create a new service account
resource "google_service_account" "vault_sa" {
account_id = "vault-${var.environment}-kapable-info-sa"
}
Étape 2 : Confirgurer une Clé KMS¶
On initialise maintenant une clé KMS qui sera elle utilisé par hashicorp pour chiffrer les secrets avant de les déposer dans le bucket. Cette clé appelé “seal”, dans le verbiage Vault est une sécurité permettant de ne pas avoir “en clair” les données dans le bucket.
L’utilisation d’un service comme KMS pour ce chiffrement permet de ne pas avoir a “imprimer”/”stocker” des “unseal-key”, ces chaines de caractères demandés au lancement de Vault pour décoder les données présente dans Vault.
Voici le code terraform permettant de générer une tel clé dans GCP et de la rendre accessible a notre service-account préalablement généré.
# kms.tf
# Generate random string for each ressource name
resource "random_id" "vault_kms" {
byte_length = 8
}
# A keyring to store our keys
resource "google_kms_key_ring" "vault" {
name = "${var.environment}-vault-${random_id.vault_kms.hex}"
location = "europe-west1"
project = var.project
}
# The crypto-key ressources
resource "google_kms_crypto_key" "vault-key" {
name = "${var.environment}-vault-${random_id.vault_kms.hex}"
key_ring = google_kms_key_ring.vault.id
version_template {
algorithm = "GOOGLE_SYMMETRIC_ENCRYPTION"
protection_level = "SOFTWARE"
}
# If we lost this key, then we won't be able to read our data
lifecycle {
prevent_destroy = true
}
}
# Allow our application service account to use this key
data "google_iam_policy" "seal" {
binding {
role = "roles/cloudkms.cryptoKeyEncrypterDecrypter"
members = [
"serviceAccount:${google_service_account.vault_sa.email}",
]
}
}
# Atach policy to our key
resource "google_kms_key_ring_iam_policy" "seal" {
key_ring_id = google_kms_key_ring.vault.id
policy_data = data.google_iam_policy.seal.policy_data
}
Étape 3 : Configurer un bucket de stockage¶
Voici mon code standard pour la création d’un bucket de stockage
# bucket.tf
# Define vars
locals {
buckets = {
vault = { name = "vault" }
}
}
# Generate random string for each ressource name
resource "random_id" "vault_bucket" {
byte_length = 8
}
# Create buckets
resource "google_storage_bucket" "buckets" {
for_each = local.buckets
name = "${var.environment}-data-${each.key}-${random_id.vault_bucket.hex}"
location = "europe-west1"
force_destroy = true
public_access_prevention = "enforced"
}
# Allow our application service account to use this bucket
data "google_iam_policy" "data" {
binding {
role = "roles/storage.admin"
members = [
"serviceAccount:${google_service_account.vault_sa.email}",
]
}
}
# Atach policy to our key
resource "google_storage_bucket_iam_policy" "policy" {
for_each = local.buckets
bucket = google_storage_bucket.buckets[each.key].name
policy_data = data.google_iam_policy.data.policy_data
}
Étape 4 : Générer un fichier de configuration pour le container¶
Voici le fichier de configuration qui sera utilisé par le service Vault :
# vault-server.hcl
default_max_request_duration = "90s"
disable_clustering = false
disable_mlock = true
ui = true
log_file = "/dev/stdout"
listener "tcp" {
address = "[::]:8200"
cluster_address = "[::]:8201"
tls_disable = "true"
}
# Utilisation du KMS Vault
seal "gcpckms" {
key_ring = "${key_ring}"
crypto_key = "${crypto_key}"
region = "${region}"
}
# Utilisation du stockage GCS
storage "gcs" {
ha_enabled = "true"
}
On injecte ensuite le fichier ci-dessus dans le service GCP Secret Manager :
# config.tf
# Generate random string for each ressource name
resource "random_id" "config" {
byte_length = 8
}
# Secret to store config file
resource "google_secret_manager_secret" "vault_config" {
secret_id = "${var.environment}-vault-config-${random_id.vault-config.hex}"
labels = {
app = "vault"
environment = var.environment
}
replication {
user_managed {
replicas {
location = "europe-west1"
}
}
}
}
# Inject config into our secret and complete config-file with KMS values
resource "google_secret_manager_secret_version" "vault_config" {
secret = google_secret_manager_secret.vault_config.id
secret_data = templatefile("${path.module}/vault-server.hcl", {
key_ring = google_kms_key_ring.vault.name
crypto_key = google_kms_crypto_key.vault-key.name
region = google_kms_key_ring.vault.location
})
}
# Atach policy to our secret
data "google_iam_policy" "vault_config" {
binding {
role = "roles/secretmanager.secretAccessor"
members = [
"serviceAccount:${google_service_account.vault_sa.email}",
]
}
}
resource "google_secret_manager_secret_iam_policy" "vault_config" {
project = var.project
secret_id = google_secret_manager_secret.vault_config.id
policy_data = data.google_iam_policy.vault_config.policy_data
}
Étape 5 : Configurer le lancement de notre container¶
Maintenant il est possible d’enfin lancer notre container pour cela on utilise un module perso et on prend soin de surcharger l’entrypoint du container. En effet par défaut le container utilise un mode “dev” pour se lancer.
module "vault_service" {
source = "../modules/http-container"
project = var.project
fqdn = var.environment != "prod" ? "vault-${var.environment}.kapable.info" : "vault.kapable.info"
docker_image = "hashicorp/vault"
allways_on = false
container_port = 8200
cpus = 2
memory = 2000
command = ["/bin/vault"]
args = ["server", "-config", "/etc/vault/config.hcl"]
container_env = {
SKIP_SETCAP = 1
GOOGLE_PROJECT = var.project
GOOGLE_STORAGE_BUCKET = google_storage_bucket.buckets["vault"].name
VAULT_LOG_LEVEL = "info"
SKIP_CHOWN = 1
VAULT_ADDR = "http://127.0.0.1"
VAULT_API_ADDR = "http://127.0.0.1"
}
volumes = {
config = {
secret_id = google_secret_manager_secret.vault_config.id
secret_version = google_secret_manager_secret_version.vault_config.version
secret_file = "config.hcl"
mount_path = "/etc/vault"
}
}
depends_on = [google_kms_key_ring_iam_policy.seal]
}
Étape 6 : Initialiser le Vault¶
- Créez un répertoire pour stocker vos fichiers de configuration Vault.
- Téléchargez le binaire Vault depuis https://developer.hashicorp.com/vault/install.
- Déplacez le binaire Vault dans le répertoire que vous avez créé à l’étape 1.
- Initialisez Vault en exécutant la commande suivante : ̀`` vault operator init -key-shares=1 -key-threshold=1 ``` Suivez les instructions à l’écran pour enregistrer les clés de déverrouillage et le jeton racine.
Conclusion¶
Ce guide vous a montré comment déployer et configurer Hashicorp Vault sur Cloud Run en utilisant un backend de stockage Cloud Storage (GCS) et un chiffrement Cloud Key Management Service (KMS) sur GCP.
Avantages de cette approche :
- Simplicité: Déploiement et gestion simplifiés via Cloud Run et Terraform.
- Évolution: Échelle automatique en fonction de la demande.
- Sécurité: Chiffrement des secrets avec KMS et isolation des conteneurs.
- Coût: Paiement à la consommation pour une optimisation des coûts.
Points importants à retenir:
- Assurez-vous de suivre scrupuleusement les instructions de sécurité pour protéger vos secrets.
- Utilisez des politiques IAM strictes pour limiter l’accès à vos ressources GCP.
- Surveillez l’utilisation de vos ressources et ajustez la configuration de votre infrastructure en fonction de vos besoins.
En conclusion, l’hébergement de Hashicorp Vault sur Cloud Run avec un backend de stockage GCS et un chiffrement KMS sur GCP offre une solution simple, évolutive et sécurisée pour la gestion des secrets de vos applications.
Cloud Ops Chronicles