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.
I'm using uwsgi-nginx-flask-docker container.
My Nginx configuration is as follows:
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;
}
}
When deploying this server on a local container, I'm getting SSL_CLIENT_S_DN
in flask.request.environ
, as expected.
On my Kubernetes cluster, the variable is just empty and no certificate demand is popped on the browser.
My service and deployment:
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"
I thought I had the same problem, turned out it was simply an error in my ca.crt Bad copy paste I guess, check to make sure your clients cert's signer is located in the ca.crt chain, if its not nginx will fail silently.
Kubernetes supports multiple means of authentication which are: X509, Static Token File, Bootstrap Tokens, Static Password File, Service Account Tokens and OpenID Connect Tokens.
Here is a link to a Blog post by Frederic Branczyk who explains how to setup X509 client certificates.
He creates a ClusterRole
with read-only permission for all pods and namespaces:
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
name: read-only-user
rules:
- apiGroups:
- ""
resources:
- pods
- namespaces
verbs:
- get
- list
- watch
Then granting a user these permissions in ClusterRoleBinding
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
The above
ClusterRoleBinding
gives the user named “brancz” the roles specified in theClusterRole
called “read-only-user”
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 kubeconfig
.
I hope this helps You.