mTLS
Use mTLS profiles when client identity is established at TLS termination.
Runtime caveat (code-grounded)
- Gateway middleware does not parse/verify certificates itself for profile auth type
mtls. - Certificate validation is expected at ingress/TLS layer.
- Zerq still enforces profile checks, IP/method restrictions, and policy limits after ingress.
Required headers and behavior
X-Client-ID: identifies the calling app or partner integration.X-Profile-ID: selects the active policy/auth profile.Authorization: typically not required for mTLS profile auth itself.
Status-code mapping
403: IP restrictions, collection access deny, or profile mismatch405: method not allowed by profile429: policy/rate limits
401 for certificate failures usually comes from ingress/LB, not gateway middleware.
Example
curl -i https://gateway.example.com/orders/123 \
-H "X-Client-ID: acme-mobile" \
-H "X-Profile-ID: partner-prod" \
--cert client.pem --key client.key \
-H "Accept: application/json"
Expected outcomes: successful request returns 200; missing or untrusted cert should return 401; mapped policy deny should return 403.
Certificate example (test setup)
Create a client certificate and key for test traffic:
# 1) Private key
openssl genrsa -out client.key 2048
# 2) CSR (example subject values)
openssl req -new -key client.key -out client.csr \
-subj "/CN=acme-mobile/OU=partner-prod/O=ExampleCorp/C=US"
# 3) Sign with your CA
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key \
-CAcreateserial -out client.crt -days 365 -sha256
Practical mapping commonly used at the edge:
CN-> client identity (example:acme-mobile)OU-> profile identity (example:partner-prod)
Edge proxy forwarding example (nginx)
ssl_client_certificate /etc/nginx/certs/ca.crt;
ssl_verify_client on;
location / {
proxy_pass http://backend:8080;
proxy_set_header X-Client-ID $ssl_client_s_dn_cn;
proxy_set_header X-Profile-ID $ssl_client_s_dn_ou;
}
Use this pattern only behind trusted ingress where clients cannot spoof these headers directly.
Evidence to capture
- Policy decision records tied to
X-Client-IDandX-Profile-ID. - Authentication reason codes for denied requests (
401vs403). - Final profile-policy mapping used by the request.
Extra negative test
Use a valid Authorization token with a client ID not bound to the profile. Zerq should deny with 403 and log a client-profile mismatch.
Rollback checkpoint
If policy updates over-block traffic, restore the previous client/profile binding set and retest one approved path and one denied path before reapplying finer-grained rules.