# HashiCorp Vault

### Overview

HashiCorp Vault enables organizations to securely store and manage secrets, according to policies. Secrets can be API keys, passwords, or certificates, or other data objects where access is tightly regulated. The Veza integration connects to a **self-managed** or **cloud-hosted** Vault cluster to discover users, namespaces, and resources, including:

Principals

* HashiCorp Vault Alias

Resources:

* HashiCorp Vault Namespace
* HashiCorp Vault System Backend
* HashiCorp Vault Auth Method
* HashiCorp Vault Auth Method Subresource
* HashiCorp Vault Secrets Engine
* HashiCorp Vault Secrets Engine Subresource
* HashiCorp Vault KV2 Subkey (when KV2 key extraction is enabled)
* HashiCorp Vault Policy

The integration can show:

* Vault users with access to Vault secrets, and the path of authentication for those users.
* Identities with access via passwords, app roles, AWS IAM, and Okta
* All secrets and the users authorized for those secrets. See [notes and supported entities](#notes-and-supported-entities) for more details.

### Configuring HashiCorp Vault

Veza connects to HashiCorp Vault by assuming an application role in your environment. You will need to create an role `AppRole` that will be used for extraction. Then, attach it to a policy granting the required permissions for extraction.

You can do this by connecting to your server and running `vault` commands:

#### Create a policy for the Veza role

Create the policy to attach to the Veza AppRole. Paste the following policy into a text file and save it `veza-policy.hcl`.

<details>

<summary>Veza extraction policy for HashiCorp Vault (with nested namespace support)</summary>

The policy below includes support for nested namespaces up to 4 levels deep. HashiCorp Vault's `+` wildcard matches only one path segment, so each namespace depth level requires explicit path declarations.

{% hint style="info" %}
**For flat namespace structures**: If your Vault deployment uses only root-level namespaces (no nested namespaces), you can use the simplified policy shown below in the second expandable section. Most organizations with complex Vault deployments require the full nested namespace policy below.
{% endhint %}

```hcl
path "/sys/namespaces" {
  capabilities = ["list"]
}

# entities

path "/identity/entity/id" {
  capabilities = ["list"]
}

path "/identity/entity/id/*" {
  capabilities = ["read"]
}

# groups

path "/identity/group/id" {
  capabilities = ["list"]
}

path "/identity/group/id/*" {
  capabilities = ["read"]
}

# auth methods

path "/sys/auth" {
  capabilities = ["read"]
}

path "/auth/+/role" {
  capabilities = ["list"]
}

path "/auth/+/role/*" {
  capabilities = ["read"]
}

path "/auth/+/roles" {
  capabilities = ["list"]
}

path "/auth/+/roles/*" {
  capabilities = ["read"]
}

path "/auth/+/users" {
  capabilities = ["list"]
}

path "/auth/+/users/*" {
  capabilities = ["read"]
}

path "/auth/+/groups" {
  capabilities = ["list"]
}

path "/auth/+/groups/*" {
  capabilities = ["read"]
}

# policies

path "/sys/policies/acl" {
  capabilities = ["list"]
}

path "/sys/policies/acl/*" {
  capabilities = ["read"]
}

# secrets engines

path "/sys/mounts" {
  capabilities = ["read"]
}

path "/+/metadata/*" { # kv2
  capabilities = ["list", "read"]
}

path "/+/subkeys/*" { # kv2 subkeys (required for KV2 key extraction)
  capabilities = ["read"]
}

path "/+/roles" { # aws, azure
  capabilities = ["list"]
}

path "/+/roles/*" { # aws, azure
  capabilities = ["read"]
}

path "/+/rolesets" { # gcp
  capabilities = ["list"]
}

path "/+/rolesets/*" { # gcp
  capabilities = ["read"]
}

path "/+/static-accounts" { # gcp
  capabilities = ["list"]
}

path "/+/impersonated-accounts" { # gcp
  capabilities = ["list"]
}

# namespaces
# --- From /sys/namespaces ---
path "+/sys/namespaces" {
  capabilities = ["list"]
}
path "+/+/sys/namespaces" {
  capabilities = ["list"]
}
path "+/+/+/sys/namespaces" {
  capabilities = ["list"]
}

# --- From /identity/entity/id ---
path "+/identity/entity/id" {
  capabilities = ["list"]
}
path "+/+/identity/entity/id" {
  capabilities = ["list"]
}
path "+/+/+/identity/entity/id" {
  capabilities = ["list"]
}

# --- From /identity/entity/id/* ---
path "+/identity/entity/id/*" {
  capabilities = ["read"]
}
path "+/+/identity/entity/id/*" {
  capabilities = ["read"]
}
path "+/+/+/identity/entity/id/*" {
  capabilities = ["read"]
}

# --- From /identity/group/id ---
path "+/identity/group/id" {
  capabilities = ["list"]
}
path "+/+/identity/group/id" {
  capabilities = ["list"]
}
path "+/+/+/identity/group/id" {
  capabilities = ["list"]
}

# --- From /identity/group/id/* ---
path "+/identity/group/id/*" {
  capabilities = ["read"]
}
path "+/+/identity/group/id/*" {
  capabilities = ["read"]
}
path "+/+/+/identity/group/id/*" {
  capabilities = ["read"]
}

# --- From /sys/auth ---
path "+/sys/auth" {
  capabilities = ["read"]
}
path "+/+/sys/auth" {
  capabilities = ["read"]
}
path "+/+/+/sys/auth" {
  capabilities = ["read"]
}

# --- From /auth/+/role ---
path "+/auth/+/role" {
  capabilities = ["list"]
}
path "+/+/auth/+/role" {
  capabilities = ["list"]
}
path "+/+/+/auth/+/role" {
  capabilities = ["list"]
}

# --- From /auth/+/role/* ---
path "+/auth/+/role/*" {
  capabilities = ["read"]
}
path "+/+/auth/+/role/*" {
  capabilities = ["read"]
}
path "+/+/+/auth/+/role/*" {
  capabilities = ["read"]
}

# --- From /auth/+/roles ---
path "+/auth/+/roles" {
  capabilities = ["list"]
}
path "+/+/auth/+/roles" {
  capabilities = ["list"]
}
path "+/+/+/auth/+/roles" {
  capabilities = ["list"]
}

# --- From /auth/+/roles/* ---
path "+/auth/+/roles/*" {
  capabilities = ["read"]
}
path "+/+/auth/+/roles/*" {
  capabilities = ["read"]
}
path "+/+/+/auth/+/roles/*" {
  capabilities = ["read"]
}

# --- From /auth/+/users ---
path "+/auth/+/users" {
  capabilities = ["list"]
}
path "+/+/auth/+/users" {
  capabilities = ["list"]
}
path "+/+/+/auth/+/users" {
  capabilities = ["list"]
}

# --- From /auth/+/users/* ---
path "+/auth/+/users/*" {
  capabilities = ["read"]
}
path "+/+/auth/+/users/*" {
  capabilities = ["read"]
}
path "+/+/+/auth/+/users/*" {
  capabilities = ["read"]
}

# --- From /auth/+/groups ---
path "+/auth/+/groups" {
  capabilities = ["list"]
}
path "+/+/auth/+/groups" {
  capabilities = ["list"]
}
path "+/+/+/auth/+/groups" {
  capabilities = ["list"]
}

# --- From /auth/+/groups/* ---
path "+/auth/+/groups/*" {
  capabilities = ["read"]
}
path "+/+/auth/+/groups/*" {
  capabilities = ["read"]
}
path "+/+/+/auth/+/groups/*" {
  capabilities = ["read"]
}

# --- From /sys/policies/acl ---
path "+/sys/policies/acl" {
  capabilities = ["list"]
}
path "+/+/sys/policies/acl" {
  capabilities = ["list"]
}
path "+/+/+/sys/policies/acl" {
  capabilities = ["list"]
}

# --- From /sys/policies/acl/* ---
path "+/sys/policies/acl/*" {
  capabilities = ["read"]
}
path "+/+/sys/policies/acl/*" {
  capabilities = ["read"]
}
path "+/+/+/sys/policies/acl/*" {
  capabilities = ["read"]
}

# --- From /sys/mounts ---
path "+/sys/mounts" {
  capabilities = ["read"]
}
path "+/+/sys/mounts" {
  capabilities = ["read"]
}
path "+/+/+/sys/mounts" {
  capabilities = ["read"]
}

# --- From /+/metadata/* ---
path "+/+/metadata/*" { # kv2
  capabilities = ["list", "read"]
}
path "+/+/+/metadata/*" { # kv2
  capabilities = ["list", "read"]
}
path "+/+/+/+/metadata/*" { # kv2
  capabilities = ["list", "read"]
}

# --- From /+/subkeys/* ---
path "+/+/subkeys/*" { # kv2 subkeys
  capabilities = ["read"]
}
path "+/+/+/subkeys/*" { # kv2 subkeys
  capabilities = ["read"]
}
path "+/+/+/+/subkeys/*" { # kv2 subkeys
  capabilities = ["read"]
}

# --- From /+/roles ---
path "+/+/roles" { # aws, azure
  capabilities = ["list"]
}
path "+/+/+/roles" { # aws, azure
  capabilities = ["list"]
}
path "+/+/+/+/roles" { # aws, azure
  capabilities = ["list"]
}

# --- From /+/roles/* ---
path "+/+/roles/*" { # aws, azure
  capabilities = ["read"]
}
path "+/+/+/roles/*" { # aws, azure
  capabilities = ["read"]
}
path "+/+/+/+/roles/*" { # aws, azure
  capabilities = ["read"]
}

# --- From /+/rolesets ---
path "+/+/rolesets" { # gcp
  capabilities = ["list"]
}
path "+/+/+/rolesets" { # gcp
  capabilities = ["list"]
}
path "+/+/+/+/rolesets" { # gcp
  capabilities = ["list"]
}

# --- From /+/rolesets/* ---
path "+/+/rolesets/*" { # gcp
  capabilities = ["read"]
}
path "+/+/+/rolesets/*" { # gcp
  capabilities = ["read"]
}
path "+/+/+/+/rolesets/*" { # gcp
  capabilities = ["read"]
}

# --- From /+/static-accounts ---
path "+/+/static-accounts" { # gcp
  capabilities = ["list"]
}
path "+/+/+/static-accounts" { # gcp
  capabilities = ["list"]
}
path "+/+/+/+/static-accounts" { # gcp
  capabilities = ["list"]
}

# --- From /+/impersonated-accounts ---
path "+/+/impersonated-accounts" { # gcp
  capabilities = ["list"]
}
path "+/+/+/impersonated-accounts" { # gcp
  capabilities = ["list"]
}
path "+/+/+/+/impersonated-accounts" { # gcp
  capabilities = ["list"]
}
```

{% hint style="warning" %}
**Understanding path segments**: The policy above supports namespaces with up to 3 path segments (e.g., `admin/engineering/us-east`). Each `+` in a path matches exactly one segment.

* `/sys/namespaces` matches the root namespace
* `+/sys/namespaces` matches one segment (e.g., `admin`)
* `+/+/sys/namespaces` matches two segments (e.g., `admin/engineering`)
* `+/+/+/sys/namespaces` matches three segments (e.g., `admin/engineering/us-east`)

If your organization has deeper namespace hierarchies, add additional path entries with more `+` wildcards to match your structure.
{% endhint %}

</details>

<details>

<summary>Simplified policy for flat namespace structures (root-level only)</summary>

If your Vault deployment does not use nested namespaces, you can use this simplified policy:

```hcl
path "/sys/namespaces" {
  capabilities = ["list"]
}

# entities

path "/identity/entity/id" {
  capabilities = ["list"]
}

path "/identity/entity/id/*" {
  capabilities = ["read"]
}

# groups

path "/identity/group/id" {
  capabilities = ["list"]
}

path "/identity/group/id/*" {
  capabilities = ["read"]
}

# auth methods

path "/sys/auth" {
  capabilities = ["read"]
}

path "/auth/+/role" {
  capabilities = ["list"]
}

path "/auth/+/role/*" {
  capabilities = ["read"]
}

path "/auth/+/roles" {
  capabilities = ["list"]
}

path "/auth/+/roles/*" {
  capabilities = ["read"]
}

path "/auth/+/users" {
  capabilities = ["list"]
}

path "/auth/+/users/*" {
  capabilities = ["read"]
}

path "/auth/+/groups" {
  capabilities = ["list"]
}

path "/auth/+/groups/*" {
  capabilities = ["read"]
}

# policies

path "/sys/policies/acl" {
  capabilities = ["list"]
}

path "/sys/policies/acl/*" {
  capabilities = ["read"]
}

# secrets engines

path "/sys/mounts" {
  capabilities = ["read"]
}

path "/+/metadata/*" { # kv2
  capabilities = ["list", "read"]
}

path "/+/subkeys/*" { # kv2 subkeys (required for KV2 key extraction)
  capabilities = ["read"]
}

path "/+/roles" { # aws, azure
  capabilities = ["list"]
}

path "/+/roles/*" { # aws, azure
  capabilities = ["read"]
}

path "/+/rolesets" { # gcp
  capabilities = ["list"]
}

path "/+/rolesets/*" { # gcp
  capabilities = ["read"]
}

path "/+/static-accounts" { # gcp
  capabilities = ["list"]
}

path "/+/impersonated-accounts" { # gcp
  capabilities = ["list"]
}
```

</details>

#### Troubleshooting nested namespace permissions

If extraction fails with `403 Forbidden: permission denied` errors when accessing nested namespaces:

1. **Verify namespace depth**: Count the levels in your namespace paths (e.g., `admin/engineering/us-east` is 3 levels)
2. **Check policy coverage**: Ensure the policy includes path entries matching your namespace depth
3. **Test with explicit paths**: If wildcards don't work, try creating explicit paths for specific namespaces
4. **Review AppRole placement**: The AppRole must be created at the root level or appropriately scoped to access child namespaces

Add the policy to Vault, adjusting the name and path of the saved policy as needed:

```shell
vault policy write veza-extraction-policy path/to/veza-policy.hcl
```

#### Create an Application Role

Enable [AppRole](https://developer.hashicorp.com/vault/docs/auth/approle) authentication and create the role:

```shell
vault auth enable approle
```

The response should be: `Success! Enabled approle auth method at: approle/`

Create the AppRole, and attach the policy you created:

```shell
vault write auth/approle/role/veza-extraction-role token_policies=veza-extraction-policy
```

The response will include the path to the app role: `Success! Data written to: auth/approle/role/veza-extraction-role`

Get the role ID and secret ID (sensitive):

```shell
vault read /auth/approle/role/veza-extraction-role/role-id
```

This returns the `role_id`, e.g. `10d51ce2-16bd-444b-4330-8fdcebfeda98`

Get the secret ID:

```shell
vault write -f /auth/approle/role/veza-extraction-role/secret-id
```

Copy the `secret_id`, e.g. `16f03071-3ea6-2505-7bcc-153683766133`.

### Configuring HashiCorp Vault on the Veza Platform

To enable the integration:

1. In Veza, go to the **Integrations** page.
2. Click *Add Integration* and pick HashiCorp Vault as the type of integration to add. Click **Next** under the list of integrations.
3. Enter the required information and *Save* the configuration

| Field                          | Notes                                                                                                                                                                                                         |
| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Insight Point                  | Choose whether to use the default data plane or a deployed Insight Point.                                                                                                                                     |
| Cluster Id                     | ID of the cluster to connect to.                                                                                                                                                                              |
| Cluster URL                    | URL of the cluster to connect to.                                                                                                                                                                             |
| Auth Role ID                   | Vault `role_id`                                                                                                                                                                                               |
| Auth Secret ID                 | Vault role `secret_id`                                                                                                                                                                                        |
| Extract KV2 Subkeys (Optional) | When enabled, extracts individual key names from KV2 secrets. This provides more granular visibility into secret structure. Requires additional `read` permission on `/+/subkeys/*` paths (see policy above). |

#### Identity Mappings

If your users can log into Vault with single sign-on, you will need to specify this relationship in a [Custom Identity Mapping](/4yItIzMvkpAvMVFAamTf/integrations/configuration/custom-identity-mappings.md). For example, you can connect Okta Users to matching HashiCorp Aliases by adding a mapping configuration on the Okta integration. Pick HashiCorp Vault as the destination data source, using Alias *Unique ID* as the mapping property.

### Notes and Supported Entities

#### HashiCorp Vault Cluster

Represents a top-level HashiCorp Vault Cluster. A Vault cluster is a set of Vault servers that share the same data storage backend, clustered for high availability and scaling.

#### HashiCorp Vault Namespace

Namespaces in Vault provide a way to partition resources and delegate management of those resources.

The root namespace is named `admin`. Namespaces can be nested.

#### HashiCorp Vault Group

Groups can be nested and can have a policy attached. Groups are a way to organize and manage entities (such as users or machines) in Vault.

Group memberships defined in one namespace referencing an entity from another namespace are not supported.

#### HashiCorp Vault Alias

Aliases represent principals that can access Vault resources. These are identities that can be used for authentication and authorization purposes in Vault.

#### HashiCorp Vault System Backend

Represents the API used to perform system actions such as creating namespaces. The system backend is a built-in secrets engine in Vault that allows management of system-level functionality.

#### HashiCorp Vault Auth Method

Authentication methods in Vault are the components used to authenticate clients and map them to internal entities. Veza currently supports vault authentication methods:

* AppRole
* AWS
* Google Cloud Platform
* Microsoft Azure
* Okta
* Token
* Userpass

Contact our support team if your organization uses an alternative auth method.

#### HashiCorp Vault Auth Method Subresource

Can have a policy attached. Auth method subresources are specific configurations or resources within an authentication method, such as roles or bindings.

#### HashiCorp Vault Secrets Engine

Secrets engines in Vault are the components that store and manage secrets and other sensitive data. Veza currently supports the following secrets engines:

* Key/Value Store (v2)
* AWS
* Microsoft Azure
* GCP

#### HashiCorp Vault Secrets Engine Subresource

Alternatively called secrets. Some resources are not as sensitive, such as roles generated dynamically. Secrets engine subresources are specific configurations or resources within a secrets engine, such as key-value pairs or roles.

**KV2 Key Extraction**: When the "Extract KV2 Subkeys" option is enabled for the integration, Veza will extract the individual key names within each KV2 secret, providing more granular visibility into the structure of your secrets without retrieving their values. This feature requires the `read` capability on `/+/subkeys/*` paths in the Vault policy.

#### HashiCorp Vault KV2 Subkey

KV2 Subkeys represent individual keys within a KV2 (Key/Value version 2) secret. This entity type is only created when the "Extract KV2 Subkeys" option is enabled on the integration.

Note that Veza extracts only the key names and structure—never the actual secret values to provide visibility into secret organization while maintaining security.

**Attributes:**

* **Subkey Name**: The name of the key within the secret (e.g., `username`, `password`, `api_key`)
* **Parent Secret Path**: The path to the parent KV2 secret that contains this key
* **Created At**: The timestamp when the parent secret was created

KV2 Subkeys are connected to their parent Secrets Engine Subresource via a "Has key" relationship.

#### HashiCorp Vault Policy

Policy consists of statements that can allow or deny access to resources. Statements consist of a path (can include wildcards) and capabilities. Longer prefix paths take precedence over shorter ones. Policies in Vault are used to govern the access permissions of entities to various resources.

Entities in Vault can have a policy attached.

#### Namespaces

Namespaces are path-based and can be nested. Parent namespaces can define policies related to child namespaces. Namespaces provide a way to partition resources and allow delegated management of those resources in Vault.

#### Effective Permissions and Cross-Service Connections

Veza generates effective permissions between principals (HashiCorp Vault Alias) and resources (Namespaces, System Backend, Auth Method, Auth Method Subresource, Secrets Engine, Secrets Engine Subresource, KV2 Subkey, Policy). Veza also shows connections between Vault namespaces, Vault namespace and cluster, Vault namespace and IdPs, and Vault namespace and existing integrations.

When KV2 key extraction is enabled, effective permissions are calculated at the granular subkey level, allowing you to see which users have access to specific keys within KV2 secrets.

#### Limitations

Two Vault authorization concepts are not supported at present:

* Templated Policies A policy may contain a set of variables. For instance, take the following policy clause:

  ```txt
  path "secret/data/{{identity.entity.id}}/*" {
  capabilities = ["create", "update", "patch", "read", "delete"]
  }
  ```

  This allows each user access to a user-specific area. Veza doesn't currently resolve these templates to show access to secrets.
* External Namespace Group Memberships

  Group memberships can be defined across different namespaces, independent of their hierarchy. An entity defined in one namespace can be referenced in a group in another namespace. Veza does not currently fetch policies across namespaces.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.veza.com/4yItIzMvkpAvMVFAamTf/integrations/integrations/hashicorp-vault.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
