Using single-sign-on oauth2 across many sites in Kubernetes
You have a set of web resources (a kibana dashboard, a grafana dashboard, a few other misc ones). You are setting them all up with ‘basic’ auth because its simple, and secretly hoping no-one guesses “MyS3cret”. You, my friend, are doing it wrong. Let me explain.
It turns out there is a protocol called ‘oauth2’. You have probably seen this on many sites (e.g. ‘sign in with Google’/’GitHub’ etc). As a consumer, you should always do that when you can. Its much better to have one strong setup (your Google one) than many weak ones. When you ‘sign in with Google’ it doesn’t actually share your password or profile, it just does authentication.
Now, how can we translate that into the misc set of web pages that we run in our system? This is super simple but it wasn’t well documented and took me a bit to figure out how to do it well.
First, lets create a small yaml file, ‘oauth2-values.yaml’. Fill it in like so. You will need to get the clientID and clientSecret. I am using Google (so https://console.cloud.google.com/apis/credentials), but there are other sites like GitHub, GitLab, etc you can use, and ample instructions online for this. In the Google case, allow redirect URI of ‘oauth2.MYDOMAIN/oauth2/callback‘
config: clientID: "xxxxx.apps.googleusercontent.com" clientSecret: "yyyyyyy" # Create a new cookieSecret with the following command # python -c 'import os,base64; print base64.b64encode(os.urandom(16))' cookieSecret: "zzzzz==" configFile: |- pass_basic_auth = false pass_access_token = true set_authorization_header = true pass_authorization_header = true image: repository: "quay.io/pusher/oauth2_proxy" tag: "v3.1.0" pullPolicy: "IfNotPresent" extraArgs: provider: "google" email-domain: "MYDOMAIN" cookie-domain: "MYDOMAIN" upstream: "file:///dev/null" http-address: "0.0.0.0:4180" ingress: enabled: true annotations: ingress.kubernetes.io/ssl-redirect: 'true' kubernetes.io/ingress.class: nginx kubernetes.io/tls-acme: "true" certmanager.k8s.io/cluster-issuer: letsencrypt nginx.ingress.kubernetes.io/proxy-body-size: 100m path: / hosts: - oauth2.MYDOMAIN - oauth2.MYDOMAIN tls: - secretName: oauth2-noc-tls hosts: - oauth2.MYDOMAIN - oauth2.MYDOMAIN
Now we are going to install an ‘oauth2 proxy’. We will run *1* for our entire domain, and it will allow anyone with our domain to access.
helm install -f oauth2-values.yaml --name oauth2 --namespace oauth2 stable/oauth2-proxy
OK, now we just need to add 2 annotation lines to every ingress:
nginx.ingress.kubernetes.io/auth-signin: https://oauth2.MYDOMAIN/oauth2/start?rd=$http_host$request_uri nginx.ingress.kubernetes.io/auth-url: https://oauth2.MYDOMAIN/oauth2/auth
And boom we are done. I’m assuming you are already using the excellent cert-manager so your site is TLS protected. Now you have strong sign-on, and, more usefuly, single-sign-on.
The key is that ‘cookie-domain’ above. It means we are using a single oauth2-proxy protecting the entire domain, and, once one site is signed in, all sites are signed in. So great!
Even better, if you use Multi-Factor-Authenticaation it fits in with it. Rarely type a password again, prevent needing passwords for new sites, and be more secure. What’s not to love!