How would you design Vault policies to follow least privilege for a team of microservices, and what's a common anti-pattern to avoid?
Quick Answer
Write narrow, path-scoped policies per service (or per service-role) granting only the specific secret paths and capabilities (read, create, update, list) each one genuinely needs, and bind those policies to auth method roles scoped to that service's identity (e.g. its Kubernetes service account). A common anti-pattern is a single broad policy — e.g. granting read access to secret/* — shared across many services for convenience, which means a single compromised service can read every other service's secrets.
Detailed Answer
Vault policies are written in HCL, granting specific capabilities (read, create, update, delete, list, sudo, deny) on specific path patterns, and a token's effective permissions are the union of every policy attached to it. Good least-privilege design scopes each policy as narrowly as the service's actual needs: a payments service's policy should grant access to secret/data/payments/* and the specific database role it uses, not a broad secret/data/*.
Those narrow policies are then bound to an auth method role tied to the service's actual runtime identity — for Kubernetes workloads, the Kubernetes auth method binds a policy to a specific Kubernetes service account (and optionally namespace), so only pods running as that service account can authenticate into a token carrying that policy; for CI, an AppRole per pipeline/service serves the same purpose.
The anti-pattern that shows up repeatedly in real environments: teams under time pressure grant a single shared, broad policy (often literally path "secret/*" { capabilities = ["read"] }) to many services 'temporarily' to unblock a launch, and it never gets narrowed afterward because doing so risks breaking something nobody wants to touch. The consequence is that compromising any one of those services (a dependency vulnerability, a leaked token) gives an attacker read access to every other service's secrets too, turning a single-service compromise into an organization-wide secrets breach. Vault's own audit log and policy-review tooling (or third-party policy linting) should be used periodically to catch and narrow overly broad grants before they're needed in anger.
Code Example
path "secret/data/payments/*" {
capabilities = ["read"]
}
path "database/creds/payments-role" {
capabilities = ["read"]
}Interview Tip
Give the concrete failure story — one compromised service reading every other service's secrets due to a shared broad policy — rather than just reciting 'least privilege' as a buzzword.