Short answer: Yes—use the full chain (leaf + intermediates), not just the leaf. Don’t include the root CA in the chain you send.
Here’s how it applies in the three common Kong TLS cases:
- Clients → Kong (mTLS client-auth)
- The client must present its leaf cert + intermediate(s) during the handshake.
- Kong must trust the issuing CA (configure trusted CA(s) for client verification).
- If you only send the leaf, you’ll hit errors like “unable to get local issuer certificate.”
Example (client side):
# build a fullchain for the client cert (no root)
cat client.crt intermediate.crt > client-fullchain.crt
# test against Kong (mTLS)
curl --cert client-fullchain.crt --key client.key https://kong.example.com/secure
- Kong → Upstream (mTLS to your backend)
- In Kong, create a Certificate whose
certfield is full chain (leaf + intermediates) andkeyis the private key. - Attach it to the service via
client_certificate. - Ensure the upstream trusts the issuing CA.
Kong (DB mode, gist):
# upload cert+key (cert must be full chain)
POST /certificates
{ "cert": "<PEM fullchain>", "key": "<PEM key>" }
# bind to service
PATCH /services/{id}
{ "client_certificate": "<certificate_id>" }
- Kong’s server cert (TLS termination at Kong)
- Serve a full chain so browsers/clients validate without needing to have the intermediate locally.
- If using Kong Ingress, put the full chain in
tls.crtof the Kubernetes secret.
Quick checks & common pitfalls
- Do not include the root CA in the chain you send.
- Order matters:
leaffirst, then each intermediate in order up to (but excluding) the root. - If you see “No required SSL certificate was sent” → the client didn’t present a cert at all.
- If you see “certificate verify failed” / “unable to get local issuer certificate” → chain or trust store problem (usually missing intermediate).
If you tell me which direction you’re doing mTLS (client→Kong or Kong→upstream) and how you deploy (Docker / KIC / bare-metal), I’ll give you the exact Kong config block to drop in.