Intégration HashiCorp Vault
GGScout prend en charge l'intégration avec HashiCorp Vault pour collecter et surveiller vos secrets, y compris Vault Community Edition et Vault Enterprise (self-hosted et HashiCorp Cloud Dedicated). Ce guide vous aidera à mettre en place et configurer l'intégration.
Fonctionnalités prises en charge
Disponibles sur toutes les éditions (Community et Enterprise) :
- Moteurs de secrets KV1 et KV2
- Collecte de plusieurs versions de secrets
- Filtrage basé sur les chemins
- Authentification par token
- Type de montage explicite facultatif (
kv-v1/kv-v2) pour ignorer la détection automatiquesys/*
Disponibles uniquement sur Vault Enterprise et HashiCorp Cloud Dedicated (HCD) :
- Prise en charge des namespaces
Prise en charge de HashiCorp Cloud Dedicated
GGScout prend entièrement en charge les environnements HashiCorp Cloud Dedicated (HCD). Lorsque vous utilisez HCD, les namespaces sont automatiquement inclus dans le resource_id exporté, suivant le modèle de l'API Vault décrit dans la documentation HashiCorp.
Filtrage par namespace
Restreindre l'accès aux namespaces (Enterprise et HCD uniquement)
Les namespaces sont une fonctionnalité de Vault Enterprise et HCD. Avec ces éditions, vous pouvez limiter les namespaces auxquels ggscout accède à l'aide du paramètre de configuration namespaces :
[sources.vault]
type = "hashicorpvault"
vault_address = "${VAULT_ADDR}"
fetch_all_versions = true
namespaces = ["admin", "prod", "shared"] # Only fetch from these namespaces
Si le paramètre namespaces n'est pas spécifié, ggscout récupérera les secrets de tous les namespaces accessibles. Utilisez ce paramètre pour limiter la portée de la collecte de secrets et améliorer les performances.
Filtrage au niveau des ressources
Vous pouvez également filtrer les secrets par namespace directement dans vos modèles d'inclusion/exclusion. Le namespace devient une partie du chemin de la ressource, ce qui permet un filtrage précis :
# Include all secrets from the 'admin' namespace, 'kv' mount, under 'my_app' path
[[sources.vault.include]]
resource_ids = ["admin/kv/my_app/*"]
# Include secrets from multiple namespaces
[[sources.vault.include]]
resource_ids = ["admin/kv/*", "dev/secrets/*", "prod/database/*"]
# Exclude test secrets from all namespaces
[[sources.vault.exclude]]
resource_ids = ["*/test/*", "*/temp/*"]
Le filtrage fonctionne de manière transparente avec la structure de namespace, où le format du resource_id suit : namespace/mount/path
Configuration
Pour configurer GGScout afin qu'il fonctionne avec HashiCorp Vault, ajoutez la configuration suivante à votre fichier ggscout.toml :
Authentification par token
[sources.vault]
type = "hashicorpvault"
vault_address = "${VAULT_ADDR}"
fetch_all_versions = true
mode = "read"
env = "production"
owner = "devops-team@example.com"
auth.auth_mode = "token"
auth.token = "${VAULT_TOKEN}"
# Optional: Limit to specific namespaces (Vault Enterprise and HCD only)
namespaces = ["admin", "prod", "shared"]
# Standard filtering (works on all editions including Vault Community Edition)
[[sources.vault.include]]
resource_ids = ["app/*", "database/*", "api-key"]
# Namespace-aware filtering (Vault Enterprise and HCD only)
[[sources.vault.include]]
resource_ids = ["admin/kv/my_app/*", "prod/secrets/database/*"]
[[sources.vault.exclude]]
resource_ids = ["*/test/*", "*/temp/*", "dev/old-secret"]
Configuration HashiCorp Cloud Dedicated
Pour les environnements HashiCorp Cloud Dedicated, la configuration est identique, mais le filtrage fonctionne automatiquement avec les namespaces :
[sources.vault_hcd]
type = "hashicorpvault"
vault_address = "${HCD_VAULT_ADDR}"
fetch_all_versions = true
mode = "read"
env = "production"
owner = "devops-team@example.com"
auth.auth_mode = "token"
auth.token = "${HCD_VAULT_TOKEN}"
# Optional: Limit to specific namespaces
namespaces = ["admin", "prod", "shared"]
# Namespace-specific filtering
[[sources.vault_hcd.include]]
resource_ids = [
"admin/kv/my_app/*", # All secrets in admin namespace, kv mount, my_app path
"prod/database/credentials/*", # Database credentials in prod namespace
"shared/api-keys/*" # Shared API keys across teams
]
[[sources.vault_hcd.exclude]]
resource_ids = [
"*/test/*", # Exclude test secrets from all namespaces
"dev/temp/*", # Exclude temporary secrets in dev namespace
"*/legacy/*" # Exclude legacy secrets from all namespaces
]
Authentification Kubernetes
[sources.vault]
type = "hashicorpvault"
vault_address = "${VAULT_ADDR}"
fetch_all_versions = true
mode = "read"
env = "production"
owner = "devops-team@example.com"
auth.auth_mode = "k8s"
auth.k8s.service_account = "${KUBERNETES_SERVICE_ACCOUNT}"
auth.k8s.namespace = "${KUBERNETES_NAMESPACE}"
auth.k8s.role = "${KUBERNETES_ROLE}"
[[sources.vault.include]]
resource_ids = ["app/*", "database/*", "api-key"]
[[sources.vault.exclude]]
resource_ids = ["test/*", "temp/*", "old-secret"]
Paramètres de configuration
| Paramètre | Description | Requis | Valeur par défaut |
|---|---|---|---|
type | Doit être défini sur "hashicorpvault" | Oui | |
vault_address | L'adresse de votre serveur Vault | Oui | |
fetch_all_versions | Indique s'il faut collecter toutes les versions des secrets | Oui | |
namespaces | Liste des namespaces Vault à récupérer (Vault Enterprise et HCD uniquement). Si non spécifié, récupère depuis tous les namespaces accessibles | Non | Tous les namespaces accessibles |
mount_type | Type de moteur de secrets du ou des montages épinglés : "kv-v1" ou "kv-v2". Lorsqu'il est défini, ggscout utilise le type déclaré et ignore la détection de montage sys/*. Ne s'applique que lorsque include/path épingle le ou les montages. | Non | Détecté automatiquement |
auth.auth_mode | Mode d'authentification (ex. : "token", "k8s") | Oui | |
mode | Mode d'intégration (l'un de : "read", "write", "read/write") | Non | "read" |
env | Environnement par défaut des secrets de cette source. GitGuardian déduit un environnement par secret et se rabat sur cette valeur | Non | |
owner | Propriétaire de cette source (un e-mail, généralement d'un employé ou d'une équipe) | Non | |
[[sources.<name>.include]] | Table de modèles de resource_id à inclure (voir ci-dessous) | Non | |
[[sources.<name>.exclude]] | Table de modèles de resource_id à exclure (voir ci-dessous) | Non |
GitGuardian déduit l'environnement de chaque secret Vault d'abord à partir de son chemin (namespace, montage KV et dossiers, lus comme des composants entiers, le plus profond l'emporte), puis à partir des clés custom_metadata de KV v2 telles que env ou environment, et n'utilise env que lorsque ni l'un ni l'autre n'en nomme un.
Avec des paramètres supplémentaires selon le mode d'authentification choisi :
Pour l'authentification par token :
| Paramètre | Description | Requis | Valeur par défaut |
|---|---|---|---|
auth.token | Le token d'authentification Vault | Oui |
Pour l'authentification Kubernetes :
| Paramètre | Description | Requis | Valeur par défaut |
|---|---|---|---|
auth.k8s.service_account | Le compte de service Kubernetes | Oui | |
auth.k8s.namespace | Le namespace Kubernetes | Oui | |
auth.k8s.role | Le rôle Kubernetes | Oui |
Variables d'environnement
VAULT_ADDR: L'adresse de votre serveur Vault (ex. :http://localhost:8200)
Pour l'authentification par token :
VAULT_TOKEN: Votre token d'authentification Vault
Pour l'authentification Kubernetes :
KUBERNETES_SERVICE_ACCOUNT: Le compte de service KubernetesKUBERNETES_NAMESPACE: Le namespace KubernetesKUBERNETES_ROLE: Le rôle Kubernetes
Ignorer la détection de montage avec mount_type
ggscout détecte automatiquement la version du moteur KV de chaque montage, donc ceci est facultatif — voir Politiques Vault requises ci-dessous pour comprendre pourquoi aucun accès à sys/* n'est nécessaire. Déclarer le type avec mount_type ignore entièrement la détection, ce qui est utile lorsque votre token se voit refuser l'accès à sys/* ou lorsque vous souhaitez éviter des appels supplémentaires à chaque exécution planifiée :
[sources.vault]
type = "hashicorpvault"
vault_address = "${VAULT_ADDR}"
mount_type = "kv-v1" # or "kv-v2"
auth.auth_mode = "token"
auth.token = "${VAULT_TOKEN}"
# mount_type only applies when an include pattern (or the deprecated `path`) pins the mount:
[[sources.vault.include]]
resource_ids = ["secret/app/*"]
mount_type ne prend effet que lorsqu'un montage est épinglé par un modèle include (ou le path déprécié). Si aucun montage n'est épinglé, ggscout se rabat sur la détection automatique. La valeur s'applique à chaque montage épinglé par les filtres, utilisez-la donc lorsque ces montages partagent la même version de moteur.
Politiques Vault requises
GGScout a besoin de l'autorisation de lire les secrets que vous souhaitez inventorier. Il détecte automatiquement le type et la version du moteur KV (en utilisant la même recherche par chemin que la CLI vault kv), de sorte que l'octroi de sys/mounts n'est pas requis.
L'étendue nécessaire de la politique dépend de si vous collectez un montage entier ou si vous vous limitez à un path spécifique. Pour les modes d'écriture (mode = "write" ou "read/write"), accordez également create et update sur les chemins data.
Collecter un montage entier
L'option la plus simple — accordez l'accès à l'ensemble du montage :
# KV2
path "secret/metadata/*" { capabilities = ["read", "list"] }
path "secret/data/*" { capabilities = ["read"] }
# KV1
path "secret/*" { capabilities = ["read", "list"] }
Se limiter à un chemin spécifique (moindre privilège)
Lorsque vous définissez un path (ou un filtre d'inclusion), accordez l'accès uniquement à ce chemin. GGScout le collecte, que le chemin soit un dossier de secrets ou un secret unique — aucun accès au reste du montage (ou à sys/mounts) n'est nécessaire.
Un dossier — chaque secret sous un chemin, ex. path = "secret/app/team" :
# KV2
path "secret/metadata/app/team" { capabilities = ["list"] }
path "secret/metadata/app/team/*" { capabilities = ["read", "list"] }
path "secret/data/app/team/*" { capabilities = ["read"] }
Un secret unique, ex. path = "secret/app/db-creds" :
# KV2
path "secret/metadata/app/db-creds" { capabilities = ["read"] }
path "secret/data/app/db-creds" { capabilities = ["read"] }
Pour KV1, supprimez les segments data/ et metadata/ (ex. path "secret/app/team/*").
Pour HashiCorp Cloud Dedicated et Enterprise (avec namespaces)
Lorsque vous utilisez HCD ou Vault Enterprise avec des namespaces, les politiques sont limitées au namespace où elles sont créées. Chaque namespace possède son propre espace de politiques, et vous créez des politiques au sein de namespaces spécifiques plutôt que d'utiliser des caractères génériques pour correspondre à plusieurs namespaces.
Pour les politiques spécifiques aux namespaces, vous créeriez des politiques au sein de chaque namespace :
# Policy created within the 'admin' namespace for KV2 secrets
path "kv/data/*" {
capabilities = ["read", "list"]
}
path "kv/metadata/*" {
capabilities = ["read", "list"]
}
# Policy for specific paths within a namespace using the + wildcard
path "kv/data/my_app/+/config" {
capabilities = ["read", "list"]
}
path "kv/metadata/my_app/+/config" {
capabilities = ["read", "list"]
}
Lorsque vous travaillez avec des namespaces, les politiques sont créées et gérées au sein de la portée de chaque namespace. Le caractère générique + peut être utilisé au sein des segments de chemin comme documenté dans la documentation HashiCorp Vault Policies, mais les caractères génériques de politique inter-namespaces ne sont pas pris en charge. Pour plus d'informations sur les namespaces, consultez la documentation HashiCorp Vault Namespace.
Bonnes pratiques
- Utilisez des variables d'environnement pour les valeurs sensibles comme
auth.token - Tirez parti du filtrage par namespace dans les environnements Vault Enterprise et HCD pour contrôler précisément quels secrets sont collectés
- Envisagez d'utiliser des restrictions de chemin pour limiter la portée de la collecte de secrets
- Activez
fetch_all_versionspour suivre les modifications de vos secrets au fil du temps - Utilisez un compte de service dédié avec les permissions minimales requises
- Pour les environnements HCD, profitez de l'inclusion automatique du namespace dans les resource_ids pour un filtrage granulaire
- Utilisez des modèles de caractères génériques comme
*/test/*pour exclure les secrets de test dans tous les namespaces