TPM auth method (API)
Enterprise
This feature requires Vault Enterprise(opens in new tab).
The TPM auth method allows clients that hold a TPM (Trusted Platform Module) device to authenticate using TLS client certificates backed by hardware attestation.
Before a TPM can authenticate, it must be enrolled via the identity/tpm endpoint
in the same namespace as the TPM auth method is mounted in, and the TPM
auth method must be configured with at least one role.
The examples below assume the TPM auth method is mounted at the /auth/tpm
path in Vault.
Configure
Set the internal CA parameters for the TPM auth backend. The backend manages its own CA that it uses to issue and verify client certificates. The first write to the configure endpoint initializes the CA. Subsequent writes update the CA rotation parameters and may rotate the active CA if the new settings require it.
| Method | Path |
|---|---|
POST | /auth/tpm/config |
Parameters
ca_lifetime(duration: "8760h")– How long each CA certificate is valid once it becomes the active CA. The backend always pre-generates a Next CA before the Active CA expires to avoid gaps in signing capability. Accepts a Go duration string (e.g."8760h","365d") or an integer number of seconds.ca_soft_expiry(duration: "720h")– Sets a soft expiry for the active CA, after which the CA stops signing new certificates. When the time remaining on the active CA drops below the soft expiry window, Vault retires the active CA and promotes the pre-generated next CA. The soft expiry duration must be less thanca_lifetime / 2. Accepts a Go duration string or an integer number of seconds.default_cert_ttl(duration: "")– Default lifetime for client certificates issued by thegentpmcertendpoint when the role does not specifycert_ttl. When unset or0, the effective TTL falls back toca_soft_expiry. Vault always caps the actual certificate lifetime by the remaining validity of the signing CA.
Sample payload
{
"ca_lifetime": "8760h",
"ca_soft_expiry": "720h",
"default_cert_ttl": "168h"
}
Sample request
$ curl \
--header "X-Vault-Token: ${VAULT_TOKEN}" \
--request POST \
--data @payload.json \
${VAULT_ADDR}/v1/auth/tpm/config
Sample response
{
"data": {
"ca_lifetime": 31536000,
"ca_soft_expiry": 2592000,
"default_cert_ttl": 604800
}
}
Read configuration
Return the current CA configuration.
| Method | Path |
|---|---|
GET | /auth/tpm/config |
Sample request
$ curl \
--header "X-Vault-Token: ${VAULT_TOKEN}" \
${VAULT_ADDR}/v1/auth/tpm/config
Sample response
{
"data": {
"ca_lifetime": 31536000,
"ca_soft_expiry": 2592000,
"default_cert_ttl": 0
}
}
Create or update role
Creates or updates a named role. Roles define which TPM devices (by individual ID or by group membership) may obtain client certificates and authenticate against this mount, and also govern the Vault token parameters issued on successful login.
At least one of tpm_ids or tpmgroup_ids is required.
| Method | Path |
|---|---|
POST | /auth/tpm/role/:name |
Parameters
name(string: <required>)– Name of the role. Used in API paths and stored in lower-case.tpm_ids(array: [] or comma-delimited string: "")– List of TPM record IDs (EK SHA-256 hashes in the formsha256-<hex>) authorized to use the role. You can enroll TPMs using theidentity/tpmendpoint.tpmgroup_ids(array: [] or comma-delimited string: "")– List of TPM group IDs whose members are authorized to use the role. Vault evaluates group membership at login time.display_name(string: "")– The display name attached to tokens issued when authenticating with the role. Defaults to the role name if not set.cert_ttl(duration: "")– Lifetime for client certificates issued by thegentpmcertendpoint for the role. Zero means inherit the globaldefault_cert_ttlfrom config, falling back toca_soft_expiry. Accepts a Go duration string or an integer number of seconds.
alias_metadata(map<string|string>: nil)- Map of arbitrary string to arbitrary string that pre-populates the custom metadata of new entity aliases created at login.token_ttl(integer: 0 or string: "")- The incremental lifetime for generated tokens. This current value of this will be referenced at renewal time.token_max_ttl(integer: 0 or string: "")- The maximum lifetime for generated tokens. This current value of this will be referenced at renewal time.token_policies(array: [] or comma-delimited string: "")- List of token policies to encode onto generated tokens. Depending on the auth method, this list may be supplemented by user/group/other values.policies(array: [] or comma-delimited string: "")- DEPRECATED: Please use thetoken_policiesparameter instead. List of token policies to encode onto generated tokens. Depending on the auth method, this list may be supplemented by user/group/other values.
token_bound_cidrs(array: [] or comma-delimited string: "")- List of CIDR blocks; if set, specifies blocks of IP addresses which can authenticate successfully, and ties the resulting token to these blocks as well.token_explicit_max_ttl(integer: 0 or string: "")- If set, will encode an explicit max TTL onto the token. This is a hard cap even iftoken_ttlandtoken_max_ttlwould otherwise allow a renewal.token_no_default_policy(bool: false)- If set, thedefaultpolicy will not be set on generated tokens; otherwise it will be added to the policies set intoken_policies.token_num_uses(integer: 0)- The maximum number of times a generated token may be used (within its lifetime); 0 means unlimited. If you require the token to have the ability to create child tokens, you will need to set this value to 0.token_period(integer: 0 or string: "")- The maximum allowed period value when a periodic token is requested from this role.token_type(string: "")- The type of token that should be generated. Can beservice,batch, ordefaultto use the mount's tuned default (which unless changed will beservicetokens). For token store roles, there are two additional possibilities:default-serviceanddefault-batchwhich specify the type to return unless the client requests a different type at generation time. For machine based authentication cases, you should usebatchtype tokens.
Sample payload
{
"tpm_ids": ["sha256-abc123..."],
"display_name": "my-device",
"token_ttl": "1h",
"token_policies": ["default", "my-policy"]
}
Sample request
$ curl \
--header "X-Vault-Token: ${VAULT_TOKEN}" \
--request POST \
--data @payload.json \
${VAULT_ADDR}/v1/auth/tpm/role/my-role
Sample response
{
"data": {
"name": "my-role",
"display_name": "my-device",
"tpm_ids": ["sha256-abc123..."],
"tpmgroup_ids": [],
"cert_ttl": 0,
"token_ttl": 3600,
"token_max_ttl": 0,
"token_policies": ["default", "my-policy"]
}
}
Read role
Return the configuration of an existing role.
| Method | Path |
|---|---|
GET | /auth/tpm/role/:name |
Parameters
name(string: <required>)– Name of the role.
Sample request
$ curl \
--header "X-Vault-Token: ${VAULT_TOKEN}" \
${VAULT_ADDR}/v1/auth/tpm/role/my-role
Sample response
{
"data": {
"name": "my-role",
"display_name": "my-role",
"tpm_ids": ["sha256-abc123..."],
"tpmgroup_ids": [],
"cert_ttl": 0,
"token_ttl": 3600,
"token_max_ttl": 0,
"token_policies": ["default"]
}
}
List roles
List all configured role names.
| Method | Path |
|---|---|
LIST | /auth/tpm/role |
Sample request
$ curl \
--header "X-Vault-Token: ${VAULT_TOKEN}" \
--request LIST \
${VAULT_ADDR}/v1/auth/tpm/role
Sample response
{
"data": {
"keys": ["my-role", "another-role"]
}
}
Delete role
Delete a named role.
| Method | Path |
|---|---|
DELETE | /auth/tpm/role/:name |
Parameters
name(string: <required>)– Name of the role to delete.
Sample request
$ curl \
--header "X-Vault-Token: ${VAULT_TOKEN}" \
--request DELETE \
${VAULT_ADDR}/v1/auth/tpm/role/my-role
Begin TPM certificate issuance
Phase 1 of the two-phase TPM attestation protocol. The client submits its Endorsement Key (EK) public key and Attestation Key (AK) parameters. Vault verifies that the EK corresponds to a TPM enrolled under the given role, then generates an encrypted credential challenge using the EK.
| Method | Path |
|---|---|
POST | /auth/tpm/role/:role_name/gentpmcert/begin |
Parameters
role_name(string: <required>)– Name of the role to issue a certificate for.ek_public_key(string: <required>)– PEM-encoded RSA or EC public key for the TPM's Endorsement Key. Vault derives the TPM ID assha256-<hex(SHA-256(DER bytes))>and matches the ID against the enrolled TPM records.ak_params(string: <required>)– Base64-encoded JSON object containing the public TPM 2.0 parameters of the Attestation Key. The object has the following fields:Field Type Description publicbytesAK canonical encoding (TPM2B_PUBLIC / TPMT_PUBLIC). create_databytesTPMS_CREATION_DATA structure for the AK. create_attestationbytesTPMS_ATTEST structure for the AK. create_signaturebytesTPMT_SIGNATURE over create_attestation.use_tcsd_activation_formatboolSet when the trousers daemon (tcsd) is used.
Sample request
$ curl \
--request POST \
--data @payload.json \
${VAULT_ADDR}/v1/auth/tpm/role/my-role/gentpmcert/begin
Sample response
The encrypted_credentials value is a base64-encoded JSON blob containing a
TPM2 EncryptedCredential structure clients must pass to the
TPM2_ActivateCredential command using the AK handle and the EK handle. The
TPM returns the raw secret bytes if and only if the AK was created on the same
TPM as the EK.
{
"data": {
"challenge_id": "dGVzdGNoYWxsZW5nZQ==",
"encrypted_credentials": "base64-encoded-credential-blob..."
}
}
The challenge expires after 5 minutes. Vault only keeps one active challenge
per TPM. Submitting a new /begin request for the same EK invalidates any
previous challenge. Vault rate limits requests from the same EK to one every
10 seconds.
Finish TPM certificate issuance
Phase 2 of the two-phase TPM attestation protocol. The client submits the decrypted challenge response (proving hardware possession) along with a CSR and key certification parameters (proving the application key was created on the same TPM). Vault verifies all inputs and, if successful, issues a client certificate signed by the active CA.
| Method | Path |
|---|---|
POST | /auth/tpm/role/:role_name/gentpmcert/finish |
Parameters
role_name(string: <required>)– Name of the role the certificate is being issued for. Must match the role supplied to/begin.ek_public_key(string: <required>)– PEM-encoded EK public key. Must match the key used in the corresponding/begincall.challenge_id(string: <required>)– Thechallenge_idvalue returned by the/begincall.challenge_response(string: <required>)– Base64-encoded raw bytes returned by the TPM'sTPM2_ActivateCredentialcommand. Must equal the secret generated during/begin.csr(string: <required>)– PEM-encoded PKCS#10 Certificate Signing Request for the application key. The key in the CSR must be TPM-resident (seekey_certification).key_certification(string: <required>)– Base64-encoded JSON object containing the TPM certification parameters that prove the application key (matching the CSR) was created inside the same TPM. The object has the following fields:Field Type Description publicbytesApplication key canonical encoding (TPMT_PUBLIC). create_databytesTPMS_CREATION_DATA structure for the key. create_attestationbytesTPMS_ATTEST structure for the key. create_signaturebytesTPMT_SIGNATURE over create_attestation, signed by the AK.
Sample request
$ curl \
--request POST \
--data @payload.json \
${VAULT_ADDR}/v1/auth/tpm/role/my-role/gentpmcert/finish
Sample response
{
"data": {
"certificate": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----",
"ca_chain": [
"-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----"
]
}
}
The issued certificate embeds two OtherName SAN extensions:
| OID suffix | Value |
|---|---|
1.3.6.1.4.1.55813.1.1.1 | TPM ID (sha256-<hex>) derived from the EK public key. |
1.3.6.1.4.1.55813.1.1.2 | Role name used during issuance. |
Vault verifies both values at login time.
Login
Authenticate using a TPM-backed client certificate obtained from the
gentpmcert endpoints. You must present the
certificate as the TLS client certificate on the connection. Vault
verifies the chain against its internal CA, checks the TPM ID and role-name
OtherName SANs, confirms the TPM is enrolled, and checks role authorization
before issuing a token.
| Method | Path |
|---|---|
POST | /auth/tpm/login |
Parameters
role_name(string: <required>)– The name of the role to authenticate against. Must match the role name embedded in the OtherName SAN of the client certificate.
Sample payload
{
"role_name": "my-role"
}
Sample request
cURL does not support TPM-embedded private keys. To call the login endpoint. We recommend using an appropriate code library or the Vault CLI:
$ vault login -method=cert -tpm-state-dir=/private -role_name=my-role
### Sample response
```json
{
"auth": {
"client_token": "00000000-0000-0000-0000-000000000000",
"policies": ["default", "my-policy"],
"metadata": {
"role_name": "my-role",
"common_name": "tpm-client",
"serial_number": "123456789",
"subject_key_id": "aa:bb:cc:...",
"authority_key_id": "dd:ee:ff:...",
"tpm_id": "sha256-abc123..."
},
"lease_duration": 3600,
"renewable": true
}
}
Vault sets the token alias name to the TPM ID (sha256-<hex>), which allows
consistent entity mapping across certificate rotations.