Let's opt for a dedicated DNS entry for the purpose of mTLS communications, namely:
apiVersion: dns.gardener.cloud/v1alpha1
kind: DNSEntry
metadata:
annotations:
dns.gardener.cloud/class: garden
name: quovadis-azure-dns-entry-mtls
namespace: azure-dns
spec:
dnsName: '*.mtls.quovadis-********.com'
targets:
- 20.**.***.***
ttl: 600
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
labels:
app.kubernetes.io/name: quovadis-azure-dns-gateway-mtls
name: quovadis-azure-dns-gateway-mtls
namespace: azure-dns
spec:
selector:
istio: ingressgateway
servers:
- hosts:
- '*.mtls.quovadis-********.com'
port:
name: quovadis-https
number: 443
protocol: HTTPS
tls:
credentialName: quovadis-azure-tls-secret
mode: MUTUAL
- hosts:
- '*.mtls.quovadis-*******.com'
port:
name: quovadis-http
number: 80
protocol: HTTP
As aforementioned, the cacert bundle is composed of two public x509 certificates, namely the client's x509 issuer certificate and the root CA certificate.
$ cat poster-quovadis-cacert.pem | base64
LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUdhRENDQkZDZ0F3SUJBZ0lUY0FBQUFBV2FYN3FEWCsxMzZBQUFBQUFBQ0Y0SlRiTzhBTll0V1FUeDBQVnJaS0p1KzhmY0lhVXA3TVZCSVZaCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0=
kind: Secret
apiVersion: v1
metadata:
name: quovadis-azure-tls-secret-cacert
namespace: istio-system
data:
cacert: >-
LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUdhRENDQkZDZ0F3SUJBZ0lUY0FBQUFBV2FYN3FEWCsxMzZBQUFBQUFBQ0Y0SlRiTzhBTll0V1FUeDBQVnJaS0p1KzhmY0lhVXA3TVZCSVZaCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0=
type: Opaque
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: httpbin-x509
namespace: quovadis
spec:
gateways:
- quovadis-azure-dns-gateway-mtls.azure-dns.svc.cluster.local
hosts:
- httpbin-x509.mtls.quovadis-*******.com
http:
- corsPolicy:
allowHeaders:
- Authorization
- Content-Type
- '*'
allowMethods:
- GET
- POST
- PUT
- DELETE
- PATCH
allowOrigins:
- regex: .*
headers:
request:
set:
X-CLIENT-SSL-CN: '%DOWNSTREAM_PEER_SUBJECT%'
X-CLIENT-SSL-ISSUER: '%DOWNSTREAM_PEER_ISSUER%'
X-CLIENT-SSL-SAN: '%DOWNSTREAM_PEER_URI_SAN%'
test: 'true'
x-forwarded-host: httpbin-x509.mtls.quovadis-******.com
match:
- uri:
regex: /.*
route:
- destination:
host: httpbin
port:
number: 8000
weight: 100
timeout: 300s
Please observe that the below policy is restricted to workloads against a custom azure-dns/quovadis-azure-dns-gateway-mtls gateway with the PolicyTargetReference mechanism.
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: httpbin-x509-policy
namespace: quovadis
spec:
action: ALLOW
rules:
- to:
- operation:
hosts:
- httpbin-x509.mtls.quovadis-******.com
when:
- key: request.headers[X-Client-Ssl-Cn]
values:
- >-
CN=poster-quovadis
(P000000),L=<sap ias tenant>.accounts400.ondemand.com,OU=8e1affb2-62a1-43cc-a687-*****,OU=Canary,OU=SAP
Cloud Platform Clients,O=SAP SE,C=DE
targetRef:
group: gateway.networking.k8s.io
kind: Gateway
name: quovadis-azure-dns-gateway-mtls
a. SSL: no alternative certificate subject name matches target host name
$ curl --key poster-quovadis.key --cert poster-quovadis.crt https://httpbin-x509.mtls.quovadis-*********.com/headers
curl: (60) SSL: no alternative certificate subject name matches target host name 'httpbin-x509.mtls.quovadis-********.com'
More details here: https://curl.se/docs/sslcerts.html
curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.
As explained here, the above error implies that the hostname from the URL doesn't match certificate's altnames (which means it is not a subject alternative name in the certificate)
b. With SAP Approuter. Hostname/IP does not match certificate's altnames
/app/node_modules/@sap/approuter/lib/middleware/error-handler.js DEBUG: stack: VError: error while forwarding request to https://httpbin-x509.mtls.quovadis-********.com/headers: Hostname/IP does not match certificate's altnames: Host: httpbin-x509.mtls.quovadis-********.com. is not in the cert's altnames: DNS:*.btp.quovadis-*******.com, DNS:*.quovadis-*********.com at returnGateWayError (/app/node_modules/@sap/approuter/lib/middleware/request-handler.js:271:13)
c. How do I know mTLS is working ?
Just look for x-forwarded-client-cert
(XFCC) request header, for instance:
"X-Forwarded-Client-Cert": "Hash=8c5007a39120e597707e4ed8cd2ee34b2940e0a21d046ec6b0c1687c4d4741ac;Cert=\"-----BEGIN%20CERTIFICATE-----%0AMIIF8TCCA9mgAwIBAgIQSmSVJYGM%2F5ZswXFF%2Fku%2BrjANBgkqhkiG9w0BAQsFADCB%0AgDELMAkGA1UEBhMCREUxFDASBgNVBAcMC0VVMTAtQ2FuYXJ5MQ
############################ truncated #############################
u%2FW%0AtLi9rwrGaLvswUwRd0O8v98b4dyeZ13PNVVCKrxMC433%2B9jI8A%3D%3D%0A-----END%20CERTIFICATE-----%0A\";Subject=\"CN=poster-quovadis (P000000),L=***.accounts400.ondemand.com,OU=8e1affb2-62a1-43cc-a687-********,OU=Canary,OU=SAP Cloud Platform Clients,O=SAP SE,C=DE\";URI=,By=spiffe://cluster.local/ns/default/sa/httpbin;Hash=6c15e418d985ad43386656b1c9aa69306703121e25bbc1ac51d33d19d70b191e;Subject=\"\";URI=spiffe://cluster.local/ns/istio-system/sa/istio-ingressgateway-service-account"
According to istio documentation when mTLS is enabled, the proxy injects the X-Forwarded-Client-Cert header to the upstream request in the backend.
That XFCC header presence is evidence that mTLS traffic is working.
Worth mentioning, with istio/kubernetes, the format of the URI field of the forwarded X.509 certificate is as follows:
spiffe://<domain>/ns/<namespace>/sa/<serviceaccount>
This enables the istio services to establish and accept connections with other SPIFFE-compliant systems.
(SPIFFE stands for Secure Production Identity Framework for Everyone)
S/4HANA Cloud APIs with ClientCertificateAuthentication. | SAP Blogs
Export Certificates and Private Key from a PKCS#12 File with OpenSSL
Secure Application Communications with Mutual TLS and Istio | Istio docs
Secure service-service communication with Istio |Medium Blogs
Service Mesh by example — how we did it | Medium Blogs
https://istio.io/latest/docs/ops/deployment/architecture/