Verify your TPM auth method configuration
Enterprise
Appropriate Vault Enterprise license required
You can authenticate to Vault using the TPM auth method with a software TPM (swtpm), which emulates TPM 2.0 hardware without a physical chip or nested virtualization.
If you are not familiar with TPM auth, refer to the TPM auth method overview for how it works, and Set up the TPM auth method for configuration reference.
Before you start
- You must have Vault Enterprise or HCP Vault Dedicated v2.2.0+.
- You must have UTM installed to run a Linux VM.
- You must have Vagrant and the Vagrant SCP plugin installed.
- You must have Vault Enterprise installed on both the Linux
VM (to run
vault tpm attestandvault login) and your host OS
Step 1: Set up the software vTPM
Start a new Linux VM and install swtpm on the Linux VM, independent of Vault. These steps were tested on Ubuntu 24.04.
Connect to the Vagrant VM.
$ vagrant sshVerify the routing configuration for the VM.
$ ip route show default via 10.0.2.2 dev enp0s2 proto dhcp src 10.0.2.15 metric 100 ...snip...Make sure there is a route to
10.0.2.2. This ensures the Vault certificate you install matchesVAULT_ADDR.Write the swtpm set up script.
$ tee swtpm-setup.sh <<'EOF' #!/usr/bin/env bash set -euo pipefail STATE_DIR="/var/lib/swtpm/tpm0" echo "== 1. Kernel support check ==" if ! lsmod | grep -q '^tpm_vtpm_proxy'; then sudo modprobe tpm_vtpm_proxy || { echo "ERROR: tpm_vtpm_proxy module not available/loadable on this kernel." echo "Some cloud/minimal VM kernels strip this out or block module loading." echo "If it won't load here, the fallback is swtpm in socket/TCTI mode" echo "(no /dev/tpmN needed), IF the product supports pointing at a" echo "TCTI/socket instead of a device file." exit 1 } fi echo "tpm_vtpm_proxy module loaded." echo "== 2. Install packages ==" if command -v apt >/dev/null; then sudo apt update sudo apt install -y swtpm swtpm-tools tpm2-tools tpm-udev elif command -v dnf >/dev/null; then sudo dnf install -y swtpm swtpm-tools tpm2-tools echo "NOTE: on RHEL/Rocky, confirm tpm udev rules exist under /usr/lib/udev/rules.d/" echo "(look for a tpm*.rules file); if absent, permissions in step 7 below are" echo "your safety net regardless." else echo "Unsupported package manager — install swtpm, swtpm-tools, tpm2-tools manually." exit 1 fi echo "== 3. Ensure tss user/group exists ==" getent group tss >/dev/null || sudo groupadd -r tss getent passwd tss >/dev/null || sudo useradd -r -g tss -d /var/lib/tpm -s /sbin/nologin tss echo "== 4. Add accounts that need device access to the tss group ==" echo "Adding current user ($(whoami)) now. Also add whatever account the OTHER" echo "PRODUCT runs as, or it will get Permission Denied on the TPM device:" echo " sudo usermod -aG tss <product-service-account>" sudo usermod -aG tss "$(whoami)" echo "== 5. Provision TPM state (EK + EK cert) BEFORE first launch ==" # This has to happen before swtpm ever starts, or the TPM comes up with nothing # to authenticate with. NOTE: --tpmstate here takes a bare path — no "dir=" — # that backend-selector syntax is only for the daemon invocation in step 6. sudo mkdir -p "$STATE_DIR" sudo swtpm_setup \ --tpm2 \ --tpmstate "$STATE_DIR" \ --create-ek-cert \ --create-platform-cert \ --overwrite echo "== 6. Launch swtpm (chardev interface, kernel vtpm-proxy) ==" sudo pkill -f "swtpm chardev --vtpm-proxy" 2>/dev/null || true sleep 1 sudo swtpm chardev \ --vtpm-proxy \ --tpm2 \ --tpmstate dir="$STATE_DIR" \ --log level=1 & sleep 2 # vtpm-proxy assigns the device number dynamically, so detect what actually # showed up rather than assuming /dev/tpm0. DEV_PATH=$(ls -1 /dev/tpm[0-9]* 2>/dev/null | grep -v 'rm' | sort -V | head -1 || true) RM_DEV_PATH=$(ls -1 /dev/tpmrm[0-9]* 2>/dev/null | sort -V | head -1 || true) if [ -z "$DEV_PATH" ]; then echo "ERROR: no /dev/tpmN device appeared. Check swtpm output above." exit 1 fi echo "Device: ${DEV_PATH}" echo "Resource-managed device: ${RM_DEV_PATH:-none found — proceeding on ${DEV_PATH} only}" echo "== 7. Fix device permissions ==" # Being a real kernel-registered chip, standard udev tpm rules should catch # this automatically — but force it anyway rather than assume. sudo chown tss:tss "$DEV_PATH" sudo chmod 660 "$DEV_PATH" if [ -n "$RM_DEV_PATH" ]; then sudo chown tss:tss "$RM_DEV_PATH" sudo chmod 660 "$RM_DEV_PATH" fi ls -l "$DEV_PATH" 2>/dev/null [ -n "$RM_DEV_PATH" ] && ls -l "$RM_DEV_PATH" echo "== 8. Send TPM2_Startup ==" # A real kernel-registered chip may auto-send this on probe; harmless either # way, so send it and don't let an "already started" response kill the script. sudo tpm2_startup -c -T "device:${DEV_PATH}" || echo "(Already started, or non-fatal — continuing.)" echo "== 9. Baseline verification ==" # Prefer the resource-managed device if we got one — that's what the other # product and any concurrent tooling should actually be pointed at. VERIFY_DEV="${RM_DEV_PATH:-$DEV_PATH}" echo "Verifying against: ${VERIFY_DEV}" echo "-- fixed properties --" sudo tpm2_getcap properties-fixed -T "device:${VERIFY_DEV}" echo "-- PCR banks --" sudo tpm2_pcrread -T "device:${VERIFY_DEV}" echo "-- Endorsement Key --" sudo tpm2_createek -T "device:${VERIFY_DEV}" -c /tmp/ek.ctx -u /tmp/ek.pub sudo tpm2_readpublic -T "device:${VERIFY_DEV}" -c /tmp/ek.ctx EOFChange the permissions on the file.
$ chmod +x swtpm-setup.shRun the script to install and configure swtpm.
$ ./swtpm-setup.shThe swtpm package is ready, and replicates a physical TPM from a bare metal server.
Update your active group in the current shell session.
$ newgrp tssYou will run TPM configuration commands from this terminal.
Step 2: Enroll the TPM and configure Vault
Retrieve the relevant information from swtpm to configure Vault.
From the terminal session of your Ubuntu VM, export the EK from the Linux VM.
$ tpm2_readpublic -c 0x81010001 -f pem -o ek.pem -T device:/dev/tpmrm0Vault identifies this TPM as
sha256-<hex>of the DER-encoded EK public key.Read the certificate.
$ cat ek.pemCopy the full PEM output, including the
BEGIN/END PUBLIC KEYlines.Switch to the terminal session where you exported the
VAULT_ADDRenvironment variable.Export the certificate as an environment variable.
$ export EK_PEM='-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvneMK6d4EH/UNgnMeVtV .............example............. 6/faxJnLwWo2kD+nzPTJZcHnQiHUpu2oCcF0FdZvL89E+URUy8UVedK2VqyUG4Fo 3QIDAQAB -----END PUBLIC KEY-----'Write the certificate to the Vault identity plugin and save the output as an environment variable.
$ TPM_ID=$(vault write -field=id identity/tpm tpm_ek_public_key="$EK_PEM") && \ echo $TPM_IDYou use the TPM ID to configure the TPM auth method role.
Enable the TPM auth method.
$ vault auth enable tpmWrite the TPM auth method configuration.
$ vault write auth/tpm/config \ ca_lifetime="8760h" \ ca_soft_expiry="720h" \ default_cert_ttl="168h"Create a role for the TPM auth method.
$ vault write auth/tpm/role/my-role \ tpm_ids="$TPM_ID" \ token_ttl="1h" \ token_policies="default"Use the
defaultpolicy for simplicity to demonstrate authentication using the TPM auth method. In a production environment, you would write a Vault policy scoped using the principle of least privilege for the workload(s) authenticating to Vault.
Step 3: Authenticate to Vault with the TPM auth method
Now that you have Vault configured for the TPM auth method, you will log in and get a Vault token.
From the terminal session where you exported the
VAULT_ADDRenvironment variable, change to the directory with the Vagrantfile.$ cd ~/learn-vault-tpmCopy the Vault dev server's CA certificate to the Linux VM.
$ vagrant scp $(echo $VAULT_CACERT) :~/Switch to the terminal session of your Ubuntu VM.
Export the Vault environment variables.
$ export VAULT_CACERT=/home/vagrant/vault-ca.pem \ VAULT_ADDR=https://10.0.2.2:8200 \ VAULT_SKIP_VERIFY=110.0.2.2is the default gateway address for UTM NAT networks.Authenticate the workload to Vault.
$ vault tpm attest -tpm-state-dir=./private -role-name=my-roleA successful run prints a certificate expiry and writes
ak.blob,app.blob,ca_chain.pem,client.crt, andclient-key.jsoninto./private:Attestation successful. Certificate valid until: <timestamp>Log in with the issued certificate.
$ vault login -method=tpm -tpm-state-dir=./private role_name=my-roleThe Ubuntu VM authenticates to Vault using the swtpm device and Vault's TPM auth method.
Example output:
Success! You are now authenticated. The token information displayed below is already stored in the token helper. You do NOT need to run "vault login" again. Future Vault requests will automatically use this token. Key Value --- ----- token hvs.CAESIGZFGMHXSl...EXAMPLE....m05TVo0bjE token_accessor leEZXvkjYb76cPJPd5bHAWTE token_duration 1h token_renewable true token_policies ["default"] identity_policies [] policies ["default"] token_meta_tpm_id sha256-f8de35485292c5a382cb033920a28607a434b8d3fa366ed75a39b4ec80bf7a6e token_meta_authority_key_id b5:9c:70:e9:a0:67:2c:8e:62:08:99:c7:ad:03:46:d5:3f:d3:6f:c0 token_meta_common_name vagrant token_meta_role_name my-role token_meta_serial_number 142903966480012384510302558029086613401474387319 token_meta_subject_key_id bb:b9:b5:20:58:11:e4:d3:c0:02:c5:b9:e4:37:42:03:b8:d5:27:f7The
policiesattached to the token come from the TPM role you created earlier in this guide, and thetoken_durationfrom the TPM auth method configuration.
Summary
In this guide, you installed a vTPM (swtpm) in a Linux VM to replicate a physical TPM. You then added the ID from the vTPM to Vault, configured the TPM auth method, and logged in using the vTPM.