Set Up Mutual TLS (mTLS) with Vault’s PKI Secrets Engine

Mutual TLS (mTLS) is a security mechanism that requires both the client and the server to verify each other’s identities using digital certificates. In contrast to one-way TLS, where only the server’s identity is validated, mTLS adds an extra layer of security by ensuring mutual authentication. Vault’s PKI secrets engine streamlines the management of these certificates by enabling automated issuance, renewal, and revocation, making the process more efficient and secure.

In this post, you’ll learn how to set up Vault’s PKI secrets engine to generate certificates for mTLS and integrate those certificates with your NGINX server.

Prerequisites

Installing Vault CLI on Linux –
Using a package manager (Ubuntu/Debian)
Run the following commands:
$ curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
$ sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
$ sudo apt update && sudo apt install vault

Start the Vault development server –
$ vault server -dev

Set the Vault address –
Open a new terminal window and configure the Vault server address to enable communication via the CLI.
$ export VAULT_ADDR='http://127.0.0.1:8200'


Generate mTLS Certificates with Vault

Step 1: Activate the PKI Secrets Engine
Run the following command to enable the PKI secrets engine:
$ vault secrets enable pki

If successful, you’ll see:
Success! Enabled the pki secrets engine at: pki/

Step 2: Adjust the PKI Secrets Engine Settings
Now, set the maximum lease duration for the certificates:
$ vault secrets tune -max-lease-ttl=8760h pki

Upon success, you should get:
Success! Tuned the secrets engine at: pki/

Step 3: Create a root certificate
$ vault write pki/root/generate/internal common_name="shortcut.com" ttl=8760h

This command generates a root certificate with a validity period of 8760 hours. You should see an output similar to:


Step 4: Set up the Certificate Revocation List (CRL) and define the URLs for issuing certificates

$ vault write pki/config/urls \
issuing_certificates="http://127.0.0.1:8200/v1/pki/ca" \
crl_distribution_points="http://127.0.0.1:8200/v1/pki/crl"

After running this command, you should see an output similar to


Step 5: Create a Certificate Role
Use the following command to create a role for issuing certificates:

$ vault write pki/roles/shortcut-role \
allowed_domains="test.shortcut.com" \
allow_subdomains=true \
max_ttl="72h"

Step 6: Generate Client and Server Certificates

  • Client Certificate:
$ vault write pki/issue/shortcut-role \
common_name="client.test.shortcut.com" \
ttl="72h" > client_cert.json

Note: The certificates are stored in key-value pairs in client_cert.json. Copy the certificate’s value and private key and store them in two different files named as client.crt and client.key respectively.

  • Server Certificate:
$ vault write pki/issue/shortcut-role \
common_name="server.test.shortcut.com" \
ttl="72h" > server_cert.json

Note: The certificates are stored in key-value pairs in server_cert.json. Copy the certificate’s value and private key and store them in two different files named as server.crt and server.key respectively.

Step 7: Retrieve the Root Certificate
Run this command to download the root CA certificate:
$ vault read -field=certificate pki/cert/ca > ca.pem


Set Up NGINX for mTLS Authentication

Step 1: Install NGINX
Ensure NGINX is installed on your machine. If it isn’t, run the following commands:
$ sudo apt update
$ sudo apt install nginx

Step 2: Update NGINX Configuration for mTLS
Open the NGINX configuration file—usually located at /etc/nginx/sites-available/default—and modify it to enable mutual TLS:

server {
listen 443 ssl;
server_name server.test.shortcut.com;

ssl_certificate /path/to/server.crt;
ssl_certificate_key /path/to/server.key;
ssl_client_certificate /path/to/ca.pem;
ssl_verify_client on;

location / {
root /var/www/html;
index index.html;
}
}
  • server.crt and server.key: These were generated earlier and saved in the server_cert.json file.
  • ca.pem: This is the root CA certificate you retrieved previously.

Step 3: Apply the Configuration
Restart NGINX to implement the changes:
$ sudo systemctl restart nginx

Step 4: Test mTLS with the Client
To verify the setup, use the curl command with the client certificate, key, and CA certificate:

$ curl --cert client.crt --key client.key --cacert ca.pem https://server.test.shortcut.com
  • client.crt and client.key: These were obtained from the client_cert.json file.

If the command runs successfully, mTLS is correctly configured, and your NGINX server is now secured with certificates issued by Vault.

Leave a comment