<p>My web server backend enforces a client-side certificate. This worked great until I moved my deployment to a Kubernetes cluster. My guess is that the forwarding rules are not passing on the certificate request from the server to the browser.</p>

<p>I'm using <a href="https://github.com/tiangolo/uwsgi-nginx-flask-docker" rel="nofollow noreferrer">uwsgi-nginx-flask-docker container</a>.</p>

<p>My Nginx configuration is as follows:</p>

<pre><code>server {
    listen 8000 ssl;
    location / {
        try_files $uri @app;
    }
    location @app {
        include uwsgi_params; uwsgi_param SSL_CLIENT_S_DN $ssl_client_s_dn;

        uwsgi_pass unix:///tmp/uwsgi.sock;
        uwsgi_read_timeout 300;

        ssl_certificate     /app/cert.pem;
        ssl_certificate_key /app/key.pem;
        ssl_password_file   /app/password.pass;

        ssl_client_certificate  /app/client-ca.crt;
        ssl_verify_client off;
        ssl_verify_depth 2;
    }
    location /static {
        alias /app/static;
    }
}
</code></pre>

<p>When deploying this server on a local container, I'm getting <code>SSL_CLIENT_S_DN</code> in <code>flask.request.environ</code>, as expected.</p>

<p>On my Kubernetes cluster, the variable is just empty and no certificate demand is popped on the browser.</p>

<p>My service and deployment:</p>

<pre><code>apiVersion: v1
kind: Service
metadata:
  name: my-server
spec:
  selector:
    app: my-server
  type: LoadBalancer
  loadBalancerIP: XX.XX.XXX.XXX
  ports:

  - protocol: TCP
    port: 8000
    targetPort: 8000

---

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-server
  labels:
    app: my-server
spec:
  replicas: 1
  strategy:
    type: RollingUpdate
  selector:
    matchLabels:
      app: my-server
  template:
    metadata:
      labels:
        app: my-server
    spec:
      restartPolicy: Always
      hostname: my-server
      containers:

      - name: my-server
        image: asia.gcr.io/my-project/my-server:latest
        imagePullPolicy: Always
        ports:
        - name: LISTEN_PORT
          value: "8000 ssl"
</code></pre>

Mugen
<p>Kubernetes supports <a href="https://kubernetes.io/docs/admin/authentication/" rel="nofollow noreferrer">multiple means of authentication</a> which are: <a href="https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certs" rel="nofollow noreferrer">X509</a>, <a href="https://kubernetes.io/docs/reference/access-authn-authz/authentication/#static-token-file" rel="nofollow noreferrer">Static Token File</a>, <a href="https://kubernetes.io/docs/reference/access-authn-authz/authentication/#bootstrap-tokens" rel="nofollow noreferrer">Bootstrap Tokens</a>, <a href="https://kubernetes.io/docs/reference/access-authn-authz/authentication/#static-password-file" rel="nofollow noreferrer">Static Password File</a>, <a href="https://kubernetes.io/docs/reference/access-authn-authz/authentication/#service-account-tokens" rel="nofollow noreferrer">Service Account Tokens</a> and <a href="https://kubernetes.io/docs/reference/access-authn-authz/authentication/#openid-connect-tokens" rel="nofollow noreferrer">OpenID Connect Tokens</a>.</p>

<p><a href="https://brancz.com/2017/10/16/kubernetes-auth-x509-client-certificates/" rel="nofollow noreferrer">Here</a> is a link to a Blog post by <a href="https://github.com/brancz" rel="nofollow noreferrer">Frederic Branczyk</a> who explains how to setup X509 client certificates.</p>

<p>He creates a <code>ClusterRole</code> with read-only permission for all pods and namespaces:</p>

<pre><code>apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
  name: read-only-user
rules:
- apiGroups:
  - ""
  resources:
  - pods
  - namespaces
  verbs:
  - get
  - list
  - watch
</code></pre>

<p>Then granting a user these permissions in <code>ClusterRoleBinding</code></p>

<pre><code>apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: read-only-users
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: read-only-user
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: brancz
</code></pre>

<blockquote>
  <p>The above <code>ClusterRoleBinding</code> gives the user named “brancz” the roles specified in the <code>ClusterRole</code> called “read-only-user”</p>
</blockquote>

<p>You can also have a look at the automation script that he uses to generate the client certificates, signs them with cluster's CA and generates a <code>kubeconfig</code>.</p>

<p>I hope this helps You.</p>
