Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save ptesny/d3fbbad2e7b6896d951ee95ea5e07447 to your computer and use it in GitHub Desktop.
Save ptesny/d3fbbad2e7b6896d951ee95ea5e07447 to your computer and use it in GitHub Desktop.
Mutual TLS easy with SAP BTP, Kyma runtime and BTP destinations

2.2 mTLS gateways with custom business domains

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

Create a cacert bundle

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

Configure a Virtual Service for x509 client authentication.

The API rules do not yet support the x509 client certificate authentication. Thus, we need configure a VirtualService to allow for the x509 client certificate communication, as follows:
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

Authorization policy httpbin-x509-policy

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

Troubleshooting

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)


Additional resources

S/4HANA Cloud APIs with ClientCertificateAuthentication. | SAP Blogs

Export Certificates and Private Key from a PKCS#12 File with OpenSSL

What is mutual TLS (mTLS)?

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/

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment