Istio MTLS configuration: client validation

Istio MTLS

Istio supports MTLS to authenticate clients. This is configured using a Gateway resource. There’s great documentation on the configuration steps here. However, what’s not quite clear is how to validate client identity using the subjectAltName (SAN) presented in the client certificate. In the example from Istio documentation, any client who presents a certificate using a given CA is accepted which is not desired in certain cases e.g. server exposed to multiple clients in the same network but accepts traffic only from specific clients.

Starting from the example here, MTLS client validation is done by adding tls.subjectAltNames

kind: Gateway
... <snip> ...
     mode: MUTUAL
     credentialName: httpbin-credential

The caveat is, Istio validates only the SAN and not the Common Name (CN).

To create a CSR with SANs, do

openssl req -nodes -newkey rsa:2048 -subj "/ organization" -out -pubkey -new -keyout -sha256 -config ssl.cnf

where ssl.cnf is

[ CA_default ]
copy_extensions = copy

req_extensions = v3_req
distinguished_name = req_distinguished_name


[ v3_req ]
# Extensions to add to a certificate request
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName =

To sign the client certificate, do

openssl x509 -req -in -CA -CAkey -CAcreateserial -out -days 3650 -sha256 -extfile ssl-ext.cnf

where ssl-ext.cnf is

basicConstraints = CA:FALSE
subjectAltName =

and CA certificate/key are generated from

openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=example Inc./' -keyout -out

Server certificates installed installed in Gateway.tls.credentialName are generated from

openssl req -out -newkey rsa:2048 -nodes -keyout -subj "/ organization"
openssl x509 -req -days 365 -CA -CAkey -set_serial 0 -in -out

The credential contains

$ kubectl describe secrets/httpbin-credential -n istio-system

... <snip> ...

ca.crt:   1046 bytes
tls.crt:  1054 bytes
tls.key:  1708 bytes

To test (against the httpbin server in the example), run

curl -vvv --resolve "$SECURE_INGRESS_PORT:$INGRESS_HOST" \
--cacert --cert --key \