---
title: "HashiCorp Vault Transit Secrets Engine"
description: "When using the HashiCorp Vault integration with the Enterprise Stack Key Management Service, the Enterprise Stack can leverage HashiCorp Vault's Transit Secrets Engine to hook into the \"cryptography as a service\" or…"
stack: "Enterprise Stack (commercial) — version 0.21.0"
stack_version: "0.21.0"
stack_comparison: https://docs.walt.id/community-vs-enterprise.md
canonical_url: https://docs.walt.id/enterprise-stack/services/key-management-service/hashicorp-vault
generated: 2026-07-20
---
# HashiCorp Vault Transit Secrets Engine

When using the HashiCorp Vault integration with the Enterprise Stack Key Management Service, the Enterprise Stack
can leverage HashiCorp Vault's [Transit Secrets Engine](https://developer.hashicorp.com/vault/docs/secrets/transit) to
hook into the "cryptography as a service" or "encryption as a service" features provided
by [HashiCorp Vault](https://developer.hashicorp.com/vault). With that, services like issuer or credential-status can
sign credentials
whilst keeping the secrets (signing keys) in an external secure environment.

## HashiCorp Vault Setup

If you are new to HashiCorp Vault, make sure to check out the
guides [here](https://developer.hashicorp.com/vault/tutorials/getting-started/getting-started-intro).
The rest of this document assumes you already know how Vault works and have a transit secrets engine setup and
running.

### Setting Up Authentication Method

Once you have the HashiCorp Server up and running and enabled the transit secrets engine mentioned above, we need to
either enable AppRole Authentication or User/Pass Authentication to use HashiCorp Vault with the walt.id Enterprise
Stack.

#### Setup Policy

Before enabling and configuring authentication methods, a policy must be created to define the permissions and actions
that authenticated users or roles are allowed to perform.

**Create The Policy File**

```bash
echo 'path "transit/*" {
  capabilities = ["create", "update", "read", "delete", "list"]
}' > transit-policy.hcl

```

**Check the Client Configuration**

If you are configuring vault locally make sure that the client is configured to
communicate via HTTP. This can be achieved by setting the `VAULT_ADDR` environment
variable.

```bash
export VAULT_ADDR=https://127.0.0.1:8200
```

**Upload the Policy**

```bash
vault policy write transit-policy transit-policy.hcl
# Expected result:
# Success! Uploaded policy: transit-policy
```

#### Setup Auth Method

**Option: AppRole Auth**

To enable AppRole auth you have two options, the Web UI of HashiCorp Vault or the CLI:

**Option: Web UI**

1. Navigate to `Access`.
2. Choose `Authentication Methods`.
3. Click on `Enable new method`.
4. Select `Generic / AppRole`.
5. Click `Enable method`.

_Please note: You might want to disable lockout: select the created approle method,
press "Configure", scroll to "User lockout configuration" and select "Disable lockout for this mount"._

**Option: CLI**

In the CLI enter:

```bash
vault auth enable approle
```

_Please note: You might want to disable lockout: Use the `disable_lockout` parameter._

#### Configure AppRole

**Add a Role**

```bash
vault write auth/approle/role/my-role token_type=batch
# Additional parameters can include:
# secret_id_ttl, token_num_uses, token_ttl, token_max_ttl, secret_id_num_uses
```

**Show Role ID**

```bash
vault read auth/approle/role/my-role/role-id
# Save the value of role_id for later use.
```

**Issue a Secret ID**

```bash
vault write -f auth/approle/role/my-role/secret-id
# Save the value of secret_id for later use.
```

**Associate Policy with AppRole**

```bash
vault write auth/approle/role/my-role token_policies="transit-policy"
# Expected result:
# Success! Data written to: auth/approle/role/my-role
```

If you already have a token policy with the AppRole:

```bash
vault write auth/approle/role/my-role token_policies="existing-policy,transit-policy"
```

**Option: User/Pass Auth**

**Option: CLI**

**Enable Userpass**

```bash
vault auth enable userpass
# Alternatively with a custom path
vault auth enable -path=<path> userpass
# Expected result:
# Success! Enabled userpass auth method at: userpass/
```

**Add User**

```bash
vault write auth/<userpass:path>/users/myuser password=mypassword policies=mypolicy
# Creates user "myuser", password "mypassword", associated with "mypolicy".
# Example policy: transit-policy (see above).
```

## KMS Service Setup in the Enterprise Stack

### Setup Key Service

In the following section, we will setup a KMS service inside of a tenant. If you don't have a tenant yet, you can learn
how to create one [here](https://docs.walt.id/enterprise-stack/administration/tenants/create.md).

When configuring the KMS service, you can set default access credentials for the Enterprise API to authenticate with
HashiCorp Vault. This means that whenever you call the key generation endpoint without specifying any authentication
credentials for HashiCorp Vault, the system will automatically use the default credentials you provided during setup.

**Option: Without Access Credentials**

**Option: CURL**

Endpoint: `/v1/{target}/resource-api/services/create` | [API Reference](https://enterprise.sandbox.walt.id/swagger/index.html#/Service%20%7C%20Resource/post_v1__target__resource_api_services_create)

**Example Request**

```bash
curl -X 'POST' \
  'https://{orgID}.enterprise-sandbox.waltid.dev/v1/{target}/resource-api/services/create' \
  -H 'accept: */*' \
  -H 'Authorization: Bearer {yourToken}' \
  -H 'Content-Type: application/json' \
  -d '{
  "type": "kms"
}'
```

**Body**

```json
{
  "type": "kms"
}
```

**Path Parameters**

- `orgID`: - When performing operations within an organization, it is essential to use the organization's Base URL or
  another valid host alias. For example, if your organization is named `test`, your default Base URL will
  be `test.enterprise-sandbox.waltid.dev` when using the sandbox environment.
- `target`: _resourceIdentifier_ - The target indicates the organization + tenant in which to create the new KMS service
  and the service's
  ID (`{organizationID}.{tenantID}.[NewKmsServiceID]`), e.g. `waltid.tenant1.kms1`

**Body Parameters**

- `type`: _serviceType_ - Specifies the type of service to create. In our case `kms`

---

**Response Codes**

- `201` - Service created successfully.

**Option: With Access Credentials**

Coming soon

### Key Creation

Use `backend: "tse"` to create keys in the HashiCorp Vault Transit Secrets Engine. The Enterprise API accepts walt.id
`keyType` values and maps them to the matching Vault Transit key type before calling Vault.

| walt.id `keyType` | Vault Transit key type |
|---|---|
| `Ed25519` | `ed25519` |
| `secp256r1` | `ecdsa-p256` |
| `secp384r1` | `ecdsa-p384` |
| `secp521r1` | `ecdsa-p521` |
| `RSA` | `rsa-2048` |
| `RSA3072` | `rsa-3072` |
| `RSA4096` | `rsa-4096` |

`secp256k1` is not supported by the TSE integration. See the HashiCorp Vault Transit Secrets Engine key types [full list](https://developer.hashicorp.com/vault/docs/secrets/transit#key-types) for the provider-side names.

**Option: Without Default Access Credentials**

**Option: CURL**

Endpoint:`/v1/{target}/kms-service-api/keys/generate` | [API Reference](https://enterprise.sandbox.walt.id/swagger/index.html#/Service%20%7C%20Key%20Management/post_v1__target__kms_service_api_keys_generate)

**Example Request**

**Option: AppRole Auth**

```bash
curl -X 'POST' \
  'https://{orgID}.enterprise-sandbox.waltid.dev/v1/{target}/kms-service-api/keys/generate' \
  -H 'accept: */*' \
  -H 'Authorization: Bearer {yourToken}' \
  -H 'Content-Type: application/json' \
  -d '{
  "backend": "tse",
  "keyType": "Ed25519",
  "config": {
    "server": "http://127.0.0.1:8200/v1/transit",
    "auth": {
      "roleId": "6823b3c7-60f7-db0b-c663-7359f17c0c30",
      "secretId": "aba4f28b-524c-db63-bae2-67a0e094f46a"
    }
  }
}'
```

**Body**

```json
{
  "backend": "tse",
  "keyType": "Ed25519",
  "config": {
    "server": "http://127.0.0.1:8200/v1/transit",
    "auth": {
      "roleId": "6823b3c7-60f7-db0b-c663-7359f17c0c30",
      "secretId": "aba4f28b-524c-db63-bae2-67a0e094f46a"
    }
  }
}
```

**Path Parameters**

- `orgID`: - When performing operations within an organization, it is essential to use the organization's Base URL or
  another valid host alias. For example, if your organization is named `test`, your default Base URL will
  be `test.enterprise-sandbox.waltid.dev` when using the sandbox environment.
- `target`: _resourceIdentifier_ - The target indicates the organization + tenant + kmsService in which to create the
  new key and the key's ID (`{organizationID}.{tenantID}.{kmsServiceID}.[newKeyID]`), e.g. `waltid.tenant1.kms1.key1`

**Body Parameters**

- `backend`: _String_ - in our case `tse` indicating the key will be managed by HashiCorp Vault.
- `keyType`: _String_ - the algorithm used to generate the key. For Vault TSE, use one of `Ed25519`, `secp256r1`, `secp384r1`, `secp521r1`, `RSA`, `RSA3072`, or `RSA4096`.
- `config`
    - `server`: _URL_ - The endpoint of your Vault instance. Following the structure of
      `https://<yourHost>/v1/<pathOfTransitEngine>`, e.g. "https://vault.walt.id/v1/transit". By default the transit
      engine will live at /transit.
    - `auth`:
    - **AppRole Auth:**
        - `roleId`: _String_ - The Role ID for AppRole authentication.
        - `secretId`: _String_ - The Secret ID for AppRole authentication.
    - **User/Pass Auth:**
        - `username`: _String_ - The username for user/pass authentication.
        - `password`: _String_ - The password for user/pass authentication.
    - **AccessToken Auth (Deprecated):**
        - `accessKey`: _String_ - The access token for token-based authentication.
    - `namespace`: _String_ (optional) - The namespace within the Vault instance.

**Option: User/Pass Auth**

```bash
curl -X 'POST' \
  'https://{orgID}.enterprise-sandbox.waltid.dev/v1/{target}/kms-service-api/keys/generate' \
  -H 'accept: */*' \
  -H 'Authorization: Bearer {yourToken}' \
  -H 'Content-Type: application/json' \
  -d '{
  "backend": "tse",
  "keyType": "Ed25519",
  "config": {
    "server": "http://127.0.0.1:8200/v1/transit",
    "auth": {
      "username": "myuser",
      "password": "mypassword"
    }
  }
}'
```

**Body**

```json
{
  "backend": "tse",
  "keyType": "Ed25519",
  "config": {
    "server": "http://127.0.0.1:8200/v1/transit",
    "auth": {
      "username": "myuser",
      "password": "mypassword"
    }
  }
}
```

**Path Parameters**

- `orgID`: - When performing operations within an organization, it is essential to use the organization's Base URL or
  another valid host alias. For example, if your organization is named `test`, your default Base URL will
  be `test.enterprise-sandbox.waltid.dev` when using the sandbox environment.
- `target`: _resourceIdentifier_ - The target indicates the organization + tenant + kmsService in which to create the
  new key and the key's ID (`{organizationID}.{tenantID}.{kmsServiceID}.[newKeyID]`), e.g. `waltid.tenant1.kms1.key1`

**Body Parameters**

- `backend`: _String_ - in our case `tse` indicating the key will be managed by HashiCorp Vault.
- `keyType`: _String_ - the algorithm used to generate the key. For Vault TSE, use one of `Ed25519`, `secp256r1`, `secp384r1`, `secp521r1`, `RSA`, `RSA3072`, or `RSA4096`.
- `config`
    - `server`: _URL_ - The endpoint of your Vault instance. Following the structure of
      `https://<yourHost>/v1/<pathOfTransitEngine>`, e.g. "https://vault.walt.id/v1/transit". By default the transit
      engine will live at /transit.
    - `auth`:
    - **AppRole Auth:**
        - `roleId`: _String_ - The Role ID for AppRole authentication.
        - `secretId`: _String_ - The Secret ID for AppRole authentication.
    - **User/Pass Auth:**
        - `username`: _String_ - The username for user/pass authentication.
        - `password`: _String_ - The password for user/pass authentication.
    - **AccessToken Auth (Deprecated):**
        - `accessKey`: _String_ - The access token for token-based authentication.
    - `namespace`: _String_ (optional) - The namespace within the Vault instance.

**Response Codes**

- `201` - Key created successfully.

**Option: With Default Access Credentials**

**Option: CURL**

Endpoint:`/v1/{target}/kms-service-api/keys/generate` | [API Reference](https://enterprise.sandbox.walt.id/swagger/index.html#/Service%20%2F%20Key%20Management/post_v1__target__kms_service_api_keys_generate)

**Example Request**

```bash
curl -X 'POST' \
  'https://{orgID}.enterprise-sandbox.waltid.dev/v1/{target}/kms-service-api/keys/generate' \
  -H 'accept: */*' \
  -H 'Authorization: Bearer {yourToken}' \
  -H 'Content-Type: application/json' \
  -d '{
  "backend": "tse",
  "keyType": "Ed25519"
}'
```

**Body**

```json
{
  "backend": "tse",
  "keyType": "Ed25519"
}
```

**Path Parameters**

- `orgID`: - When performing operations within an organization, it is essential to use the organization's Base URL or
  another valid host alias. For example, if your organization is named `test`, your default Base URL will
  be `test.enterprise-sandbox.waltid.dev` when using the sandbox environment.
- `target`: _resourceIdentifier_ - The target indicates the organization + tenant + kmsService in which to create the
  new key and the key's ID (`{organizationID}.{tenantID}.{kmsServiceID}.[newKeyID]`), e.g. `waltid.tenant1.kms1.key1`

**Body Parameters**

- `backend`: _String_ - in our case `tse` indicating the key will be managed by HashiCorp Vault.
- `keyType`: _String_ - the algorithm used to generate the key. For Vault TSE, use one of `Ed25519`, `secp256r1`, `secp384r1`, `secp521r1`, `RSA`, `RSA3072`, or `RSA4096`.

**Response Codes**

- `201` - Key created successfully.
