Vault policies are how you control who can do what inside Vault, and they’re a lot more powerful than just "read" or "write."

Let’s see Vault policies in action. Imagine we have a secret at secret/myapp/database. We want to grant a specific role, let’s call it app-db-reader, read-only access to this secret, but only if the request comes from a specific network or has a particular tag.

First, we need to define the policy. We’ll call it app-db-reader-policy:

path "secret/myapp/database" {
  capabilities = ["read"]
  # Optional: Add conditions for finer-grained access
  # For example, if using AppRole auth, you might add:
  # conditions = [
  #   {
  #     key    = "role_id"
  #     type   = "string"
  #     value  = "your-specific-role-id"
  #   }
  # ]
}

path "secret/myapp/database/*" {
  # Deny any other access to sub-paths if you want to be strict
  capabilities = ["deny"]
}

Now, we can associate this policy with an authentication method. Let’s say we’re using AppRole. We’d create a role for our application:

vault write auth/approle/role/app-db-reader \
  token_policies="app-db-reader-policy" \
  token_ttl=30m \
  token_max_ttl=1h \
  bind_secret_id=true

When an application authenticates with AppRole using the app-db-reader role ID and secret ID, it will receive a token with the app-db-reader-policy attached. This token will only be able to read the secret at secret/myapp/database. Any attempt to list, create, update, or delete will be denied. If the conditions were specified and not met, the read operation would also fail.

The core problem Vault policies solve is managing secrets securely in dynamic environments. Traditional approaches often involve static access controls that are hard to update and prone to errors. Vault policies allow you to define access based on who is requesting, what they are requesting, and under what conditions, all in a declarative and versionable way.

Vault policies are hierarchical. A policy can grant access to a specific path, like secret/myapp/database, or to a broader path, like secret/myapp/*, which would grant access to all secrets under myapp. The most specific path wins. If a path is listed multiple times with different capabilities, Vault will union the capabilities unless a deny is present, in which case the deny overrides.

Think about how you’d grant read access to secret/myapp/database and write access to secret/myapp/audit_logs. You’d have two separate stanzas in your policy:

path "secret/myapp/database" {
  capabilities = ["read"]
}

path "secret/myapp/audit_logs" {
  capabilities = ["create", "update", "delete"]
}

The capabilities are the verbs: create, read, update, delete, and list. You can also use sudo which bypasses certain checks, but this is highly discouraged for regular use. The deny capability is powerful and explicitly prevents any operations on a given path.

A common pattern is to grant broad access and then use deny rules to restrict it further. For instance, you might grant read access to all of secret/ and then deny read access to secret/sensitive/* for a specific role.

path "secret/*" {
  capabilities = ["read"]
}

path "secret/sensitive/*" {
  capabilities = ["deny"]
}

This approach is useful when you have a general pattern of access but need to carve out specific exceptions.

The most surprising true thing about Vault policies is that they can be evaluated against the context of the request, not just the identity of the requester. This means you can write policies that depend on metadata associated with the token itself, such as the IP address it originated from, the CIDR block it belongs to, or even custom metadata attached when the token was issued. This allows for extremely dynamic and context-aware access control, moving beyond simple role-based access. For example, you could grant access to a secret only if the token was generated with a specific meta field, or if the request comes from a particular network segment defined in the token’s metadata.

The next concept you’ll likely run into is managing these policies effectively as your organization scales, which often leads to exploring policy templating or using external systems to generate policies.

Want structured learning?

Take the full Vault course →