Aller au contenu
Sécurité medium

Vault : policies et contrôle d'accès (ACL)

16 min de lecture

logo vault

Une fois authentifié, Vault détermine les permissions via les policies. Chaque policy définit des capabilities (read, write, delete…) sur des paths (secret/data/*, auth/token/…).

Vault applique un modèle deny by default : sans policy explicite, tout accès est refusé. Quand plusieurs règles peuvent correspondre à un path :

  1. Vault choisit d’abord la règle la plus spécifique (priority matching)
  2. Si exactement le même pattern est défini dans plusieurs policies attachées au token, les capabilities se cumulent
  3. La capability deny reste toujours prioritaire
  • Vault installé et démarré
  • Accès root ou admin pour créer des policies

Vault inclut deux policies intégrées :

La policy root donne un accès total à Vault. Le token root doit être réservé à l’initialisation ou aux situations d’urgence.

La policy default est attachée à la plupart des tokens par défaut. Elle fournit généralement un socle minimal pour que le token puisse se consulter et gérer certaines opérations de base (cubbyhole, renouvellement…).

Une policy est écrite en HCL (HashiCorp Configuration Language) ou JSON :

# Policy pour l'équipe développement
path "secret/data/dev/*" {
capabilities = ["create", "read", "update", "delete", "list"]
}
path "secret/data/shared/config" {
capabilities = ["read"]
}
path "secret/metadata/dev/*" {
capabilities = ["list", "read", "delete"]
}
CapabilityDescriptionVerbes HTTP
createCréer une nouvelle entréePOST/PUT
readLire une entréeGET
updateModifier une entrée existantePOST/PUT
deleteSupprimer une entréeDELETE
listLister les entréesLIST
patchModification partielle (si l’endpoint le supporte)PATCH
sudoAccès aux paths protégés (root-protected)-
denyRefuser explicitement (prioritaire sur tout)-

Avec le moteur KV v2, les paths sont structurés ainsi :

PathUsage
secret/data/*Lecture/écriture des secrets
secret/metadata/*Métadonnées, versions, suppression soft
secret/delete/*Suppression soft de versions
secret/undelete/*Restauration de versions
secret/destroy/*Suppression définitive

Priority matching : comment Vault choisit la règle

Section intitulée « Priority matching : comment Vault choisit la règle »

Quand plusieurs patterns peuvent correspondre à un path, Vault applique une logique de priorité pour déterminer lequel utiliser.

  1. Si le premier wildcard (+ ou *) apparaît plus tôt dans le path, la règle est moins prioritaire
  2. Une règle finissant par * est moins prioritaire qu’une sans wildcard
  3. Plus il y a de segments +, plus la priorité baisse
  4. Une règle plus courte est moins prioritaire
  5. En dernier recours : comparaison lexicographique
# Règle générale : lecture sur tout secret/*
path "secret/*" {
capabilities = ["read"]
}
# Règle spécifique : deny sur prod
path "secret/data/prod/*" {
capabilities = ["deny"]
}

Pour le path secret/data/prod/app :

  • Les deux patterns matchent
  • secret/data/prod/* est plus spécifique (wildcard plus tard)
  • Vault applique deny → accès refusé

L’union ne se produit que si le même pattern exact existe dans plusieurs policies attachées au token :

# Policy A
path "secret/data/shared/*" {
capabilities = ["read"]
}
# Policy B
path "secret/data/shared/*" {
capabilities = ["list"]
}

Si un token a les deux policies, il obtient ["read", "list"] sur ce path.

PatternSignification
*Glob de suffixe — matche tout le reste du path
+Matche un seul segment de chemin
PatternCorrespond àNe correspond pas à
secret/data/dev/*secret/data/dev/a, secret/data/dev/a/b/csecret/data/dev
secret/data/apps/+secret/data/apps/a, secret/data/apps/bsecret/data/apps/a/b
secret/data/+/configsecret/data/prod/configsecret/data/a/b/config
  1. Créer le fichier HCL

    Fenêtre de terminal
    cat > dev-policy.hcl << 'EOF'
    # Accès complet à secret/dev/*
    path "secret/data/dev/*" {
    capabilities = ["create", "read", "update", "delete", "list"]
    }
    path "secret/metadata/dev/*" {
    capabilities = ["list", "read", "delete"]
    }
    # Lecture seule sur shared
    path "secret/data/shared/*" {
    capabilities = ["read", "list"]
    }
    EOF
  2. Charger la policy dans Vault

    Fenêtre de terminal
    vault policy write dev-policy dev-policy.hcl

    Sortie :

    Success! Uploaded policy: dev-policy
  3. Vérifier

    Fenêtre de terminal
    vault policy read dev-policy

Pour les policies simples :

Fenêtre de terminal
vault policy write staging-readonly - << 'EOF'
path "secret/data/staging/*" {
capabilities = ["read", "list"]
}
EOF
Fenêtre de terminal
# Lister toutes les policies
vault policy list
# Lire une policy
vault policy read dev-policy
# Supprimer une policy
vault policy delete dev-policy
Fenêtre de terminal
vault write auth/userpass/users/alice policies="dev-policy,staging-readonly"
Fenêtre de terminal
vault write auth/approle/role/ci-app \
policies="ci-deploy-policy" \
secret_id_ttl=10m \
token_ttl=20m
Fenêtre de terminal
vault token create -policy="dev-policy" -policy="staging-readonly"
Fenêtre de terminal
# Créer un token avec la policy
vault token create -policy="dev-policy" -field=token

Puis testez avec ce token :

Fenêtre de terminal
export VAULT_TOKEN="<token>"
# Doit réussir (dev/*)
vault kv put secret/dev/myapp password="test"
# Doit échouer (pas de permission)
vault kv put secret/prod/myapp password="test"

Sortie attendue pour l’échec :

Error writing data to secret/data/prod/myapp: Error making API request.
Code: 403. Errors:
* 1 error occurred:
* permission denied

Vérifiez les capabilities d’un token sur un path :

Fenêtre de terminal
# Avec le token actuel
vault token capabilities secret/data/dev/myapp
# Avec un token spécifique
vault token capabilities <token> secret/data/dev/myapp

Sortie :

create, delete, list, read, update

Certaines commandes CLI supportent -output-policy pour afficher les permissions nécessaires à une opération :

Fenêtre de terminal
vault kv get -output-policy secret/apps/webapp

Sortie :

path "secret/data/apps/webapp" {
capabilities = ["read"]
}

Utile pour construire vos policies de manière incrémentale.

Vault peut utiliser l’identité de l’utilisateur dans les paths grâce aux templated policies :

# Chaque utilisateur accède à son propre espace
path "secret/data/users/{{identity.entity.name}}/*" {
capabilities = ["create", "read", "update", "delete", "list"]
}

L’utilisateur alice pourra accéder à secret/data/users/alice/* mais pas à secret/data/users/bob/*.

VariableDescription
{{identity.entity.id}}ID unique de l’entité
{{identity.entity.name}}Nom de l’entité
{{identity.entity.aliases.<mount>.id}}ID d’alias pour un auth method
{{identity.groups.ids.<group_id>.name}}Nom d’un groupe par ID
{{identity.groups.names.<group_name>.id}}ID d’un groupe par nom

Les policies peuvent restreindre quels paramètres peuvent être envoyés à un endpoint.

Autorise uniquement certains paramètres :

path "secret/data/limited/*" {
capabilities = ["create", "update"]
# Seuls ces champs peuvent être écrits
allowed_parameters = {
"data" = {
"username" = []
"password" = []
}
}
}

Interdit certains paramètres (prioritaire sur allowed_parameters) :

path "secret/data/apps/*" {
capabilities = ["create", "update"]
# Tout est autorisé sauf ces champs
denied_parameters = {
"data" = {
"admin_token" = []
}
}
}

Exige la présence de certains paramètres :

path "pki/issue/my-role" {
capabilities = ["create", "update"]
# Le common_name est obligatoire
required_parameters = ["common_name"]
}
# dev-policy.hcl - Développeur
# Accès complet à l'environnement de dev
path "secret/data/dev/*" {
capabilities = ["create", "read", "update", "delete", "list"]
}
path "secret/metadata/dev/*" {
capabilities = ["list", "read"]
}
# Lecture seule sur staging
path "secret/data/staging/*" {
capabilities = ["read", "list"]
}
# Pas d'accès à prod (deny by default)

Un pipeline de build n’a généralement besoin que de chiffrer :

# ci-build-policy.hcl - Pipeline de build
# Chiffrement uniquement (pas de déchiffrement)
path "transit/encrypt/ci-key" {
capabilities = ["update"]
}
# Lecture des configs non sensibles
path "secret/data/build/config" {
capabilities = ["read"]
}

Un pipeline de déploiement a besoin de déchiffrer et lire les secrets :

# ci-deploy-policy.hcl - Pipeline de déploiement
# Lecture des secrets de déploiement
path "secret/data/deploy/*" {
capabilities = ["read"]
}
# Déchiffrement (pas de chiffrement)
path "transit/decrypt/ci-key" {
capabilities = ["update"]
}
# Accès aux certificats PKI
path "pki/issue/deploy-role" {
capabilities = ["create", "update"]
}
# admin-policy.hcl - Admin sans être root
# Gestion des policies
path "sys/policies/acl/*" {
capabilities = ["create", "read", "update", "delete", "list"]
}
# Gestion des auth methods (activer/désactiver)
path "sys/auth/*" {
capabilities = ["create", "read", "update", "delete", "list", "sudo"]
}
# Configuration des auth methods
path "auth/*" {
capabilities = ["create", "read", "update", "delete", "list"]
}
# Gestion des secrets engines
path "sys/mounts/*" {
capabilities = ["create", "read", "update", "delete", "list"]
}
# Accès à tous les secrets
path "secret/*" {
capabilities = ["create", "read", "update", "delete", "list"]
}
policies/
├── team-backend.hcl
├── team-frontend.hcl
├── team-devops.hcl
└── team-security.hcl
policies/
├── env-dev.hcl
├── env-staging.hcl
└── env-prod.hcl

Un utilisateur peut avoir plusieurs policies :

Fenêtre de terminal
vault write auth/userpass/users/alice \
password="..." \
policies="team-backend,env-dev,env-staging"

Les capabilities se cumulent pour les mêmes patterns.

SymptômeCause probableSolution
permission deniedPolicy manquante ou pattern non couvertvault token capabilities <path>
invalid policyErreur de syntaxe HCLValider avec vault policy write
Capabilities inattenduesPriority matching → mauvaise règle sélectionnéeVérifier les wildcards
Wildcard ne marche pas* pas en fin de path, ou + vs *Revoir la syntaxe
KV v2 access deniedPath sans /data/Ajouter /data/ au path
Policy modifiée sans effetToken émis avant modificationLes tokens gardent leurs policies d’émission
Fenêtre de terminal
# Token actuel
vault token lookup
# Token spécifique
vault token lookup <token>
Fenêtre de terminal
vault kv get -output-policy secret/myapp
  1. Deny by default : sans policy explicite, tout est refusé
  2. Priority matching : la règle la plus spécifique s’applique en premier
  3. Union conditionnelle : les capabilities se cumulent uniquement sur le même pattern dans plusieurs policies
  4. KV v2 paths : secret/data/*, secret/metadata/*, etc.
  5. Wildcards : * (suffixe uniquement, fin de path), + (un segment)
  6. Templates : {{identity.entity.id}} — préférez les IDs aux noms
  7. deny prioritaire : toujours évalué en dernier, gagne toujours
  8. Moindre privilège : séparez les rôles (build ≠ deploy, dev ≠ prod)

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn