Guides

mTLS Admin Setup

How to configure mutual TLS for the RA's admin and client endpoints.

mTLS Admin Setup

The RA protects its admin (/api/v1/*) and client (/api/client/*) endpoints with mutual TLS (mTLS). Both the RA and the caller must present valid certificates signed by the same CA.

Overview

Admin tool / uPKI CLI
        │
        │  HTTPS (client cert = admin cert, signed by uPKI CA)
        ▼
  uPKI RA :8000
        │  verifies client cert against ca.crt
        │  (rejects if not signed by the same CA)

Step 1 — Obtain an admin client certificate

Using uPKI CLI:

upki-cli generate \
  --host 127.0.0.1 \
  --cn "admin.example.internal" \
  --profile admin

This issues a certificate with clientAuth extended key usage, signed by the CA.

Alternatively, request it via ZMQ directly:

{
  "TASK": "generate",
  "params": {
    "cn": "admin.example.internal",
    "profile": "admin"
  }
}

Step 2 — Configure the HTTP client

For curl:

curl --cert admin.crt \
     --key admin.key \
     --cacert ca.crt \
     https://upki-ra:8000/api/v1/health

For Python (httpx / requests):

import httpx

client = httpx.Client(
    cert=("admin.crt", "admin.key"),
    verify="ca.crt"
)
response = client.get("https://upki-ra:8000/api/v1/health")

Step 3 — Verify access

# Should return 200 OK
curl -s \
  --cert admin.crt \
  --key admin.key \
  --cacert ca.crt \
  https://upki-ra:8000/api/v1/health

Without a valid client certificate:

curl --cacert ca.crt https://upki-ra:8000/api/v1/health
# → 403 Forbidden or TLS handshake error

Certificate profiles

Endpoint typeRecommended profileExtended Key Usage
Admin APIadminclientAuth
Client APIuser or laptopclientAuth
RA itselfra (auto-issued)serverAuth, clientAuth

Revoking admin access

To revoke an admin certificate:

{
  "TASK": "revoke",
  "params": {
    "dn": "/CN=admin.example.internal",
    "reason": "cessationOfOperation"
  }
}

Then regenerate the CRL:

{
  "TASK": "generate_crl",
  "params": {}
}

The RA reads the CRL on startup and on certificate validation — revoked certificates are rejected immediately after the CRL is updated.

Docker compose with mTLS admin

If running the RA behind Traefik and wanting to protect admin routes further, add a Traefik middleware for mTLS passthrough:

labels:
  - "traefik.http.routers.upki-ra-admin.rule=Host(`ra.example.internal`) && PathPrefix(`/api/v1`)"
  - "traefik.http.routers.upki-ra-admin.tls=true"
  - "traefik.http.routers.upki-ra-admin.tls.certresolver=upki"
  - "traefik.http.routers.upki-ra-admin.middlewares=strip-admin"

The RA itself handles mTLS verification for the /api/v1/* routes — Traefik only needs to forward the client certificate headers.

Copyright © 2026