Nginx Ingress: passing client certificate info to backend

5/14/2020

I successfully implemented in my aks cluster an ingress with tls certification (https://docs.microsoft.com/en-us/azure/aks/ingress-own-tls), but I would like to pass the information contained in the client certificate to the backend. I did try adding to my ingress the annotation nginx.ingress.kubernetes.io/auth-tls-pass-certificate-to-upstream: "true", but the information seems to be missing in my request headers (I am simply printing the content of request.headers from my flask application). Other headers are correctly shown, e.g. X-Forwarded-Proto: https or X-Forwarded-Port: 443 .

Could somebody confirm the expected behaviour of the annotation?

Do I need to configure the backend somehow with tls as well?

EDIT

I did access the ingress pod, and in the nginx config I could not find any reference to ssl_client_s_dn, which I would expect to be the best candidate to pass the certificate info into an header.

I tried to assign some custom headers following the steps in https://github.com/kubernetes/ingress-nginx/tree/master/docs/examples/customization/custom-headers, but also this seems not to work.

-- Neo
flask
kubernetes
nginx-ingress

2 Answers

5/21/2020

you can pass annotations in nginx ingress' service this

   annotations:
    service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout: '60'
    service.beta.kubernetes.io/aws-load-balancer-proxy-protocol: "*"

if you want modify header based on ingress rule then you may also add annotations to ingress rules as well.

-- ANISH KUMAR MOURYA
Source: StackOverflow

5/22/2020

Which version of nginx-ingress are you using ?

At least with version 0.30 I'm able too see the client's certificate details passed to the backend properly.

The value of ssl_client_s_dn is being passed as Ssl-Client-Subject-Dn header with default nginx controller setup, no customization needed.

Here is the content of my default /etc/nginx/nginx.conf (converted from ConfigMap)

# Pass the extracted client certificate to the backend

        proxy_set_header ssl-client-cert        $ssl_client_escaped_cert;

        proxy_set_header ssl-client-verify      $ssl_client_verify;
        proxy_set_header ssl-client-subject-dn  $ssl_client_s_dn;
        proxy_set_header ssl-client-issuer-dn   $ssl_client_i_dn;

Request headers seen from backend perspective:

   ...
    "Ssl-Client-Issuer-Dn": "CN=example.com,O=example Inc.", 
    "Ssl-Client-Subject-Dn": "O=client organization,CN=client.example.com", 
    "Ssl-Client-Verify": "SUCCESS", 
    "User-Agent": "curl/7.58.0", 
    "X-Forwarded-Host": "httpbin.example.com", 
    "X-Scheme": "https", 
  }
}

You can always add your own custom headers, as explained here

Example:

apiVersion: v1
data:
  X-Client-Cert-Info: $ssl_client_s_dn
kind: ConfigMap
metadata:
...

which reflects at backend as:

    ...
    "X-Client-Cert-Info": "O=client organization,CN=client.example.com", 
    "X-Forwarded-Host": "httpbin.example.com", 
    "X-Scheme": "https", 
  }
}
-- Nepomucen
Source: StackOverflow