Introduction

When Vault's PKI secrets engine issues certificates, the certificate's Issuer Common Name (CN) and Subject Alternative Names (SANs) must be consistent and correctly configured. A mismatch between the Issuer CN and the SANs can cause certificate validation failures in clients that perform strict hostname verification, leading to TLS connection failures for services using Vault-issued certificates.

Symptoms

  • TLS connections fail with certificate name mismatch errors
  • Certificate inspection shows Issuer CN different from SAN DNS entries
  • Client applications reject Vault-issued certificates during TLS handshake
  • openssl verify returns error 62: hostname mismatch
  • Error message: x509: certificate is valid for vault.internal, not app.example.com

Common Causes

  • PKI role configured with allowed_domains that does not match the certificate request
  • Certificate issued without SANs, relying only on CN which is deprecated in modern clients
  • enforce_hostnames=true on the role blocking valid SAN entries
  • Issuing certificate chain has a different CN than the intermediate CA
  • Multiple PKI issuers in the mount with different CN configurations

Step-by-Step Fix

  1. 1.Inspect the issued certificate: Check the CN and SAN fields.
  2. 2.```bash
  3. 3.vault write pki_int/issue/my-role \
  4. 4.common_name="app.example.com" \
  5. 5.ttl="72h" | jq -r '.data.certificate' | openssl x509 -noout -text | grep -A2 "Subject:|DNS:"
  6. 6.`
  7. 7.Update the PKI role configuration: Ensure allowed domains match the expected SANs.
  8. 8.```bash
  9. 9.vault write pki_int/roles/my-role \
  10. 10.allowed_domains="example.com,*.example.com" \
  11. 11.allow_subdomains=true \
  12. 12.allow_bare_domains=true \
  13. 13.allow_glob_domains=true \
  14. 14.enforce_hostnames=false \
  15. 15.server_flag=true
  16. 16.`
  17. 17.Re-issue the certificate with correct SANs: Generate a new certificate.
  18. 18.```bash
  19. 19.vault write pki_int/issue/my-role \
  20. 20.common_name="app.example.com" \
  21. 21.alt_names="app.example.com,app.internal" \
  22. 22.ttl="72h"
  23. 23.`
  24. 24.Deploy the new certificate: Update the service with the corrected certificate.
  25. 25.```bash
  26. 26.kubectl create secret tls app-tls \
  27. 27.--cert=cert.pem --key=key.pem \
  28. 28.--dry-run=client -o yaml | kubectl apply -f -
  29. 29.`
  30. 30.Verify the certificate validates correctly: Check the new certificate.
  31. 31.```bash
  32. 32.echo | openssl s_client -connect app.example.com:443 -servername app.example.com 2>/dev/null | openssl x509 -noout -subject -issuer
  33. 33.`

Prevention

  • Configure PKI roles with allowed_domains that cover all expected certificate hostnames
  • Always include SANs (Subject Alternative Names) in issued certificates, not just CN
  • Use allow_subdomains=true and allow_bare_domains=true for flexible domain coverage
  • Test certificate issuance and validation as part of the PKI role setup process
  • Monitor certificate issuance for SAN validation errors
  • Document the PKI role configuration requirements in a certificate management runbook