Sometimes you just want to expose some services that don't have any authentication mechanism. Many users have this issue, especially with Kubernetes, because it is damn easy to expose any service over ingress and also to have HTTPS by default with Let's Encrypt. The missing piece could be authentication in the application you want to expose. In this case, we can always leverage external authentication from GitHub, Google, and many others via OAuth. This is where OAuth2 Proxy comes into place. It's a reverse proxy that provides external authentication and it's relatively easy to set up.
- Package Kubernetes Applications with Helm
- AWS Cost Savings by Utilizing Kubernetes Ingress with Classic ELB
- Get Automatic HTTPS with Let's Encrypt and Kubernetes Ingress
Check out the related posts above for ingress and automatic HTTPS setup. Those are the requirements. First, we need to register the new OAuth application. I will use GitHub, so let's create one at https://github.com/settings/applications/new:
Replace with your domain name. As you can see, callback URL has added
/oauth2 at the end. Write down the auth details after you click on register application. Let's also generate a cookie secret. You probably have python installed, so you could just run a python command instead of running it in a Docker container:
⚡ docker run -ti --rm python:3-alpine \ python -c 'import secrets,base64; print(base64.b64encode(base64.b64encode(secrets.token_bytes(16))));'
You can deploy OAuth2 Proxy now. Use Helm to make things easier:
⚡ helm install --name authproxy \ --namespace=ingress \ --set config.clientID=<YOUR_CLIENT_ID> \ --set config.clientSecret=<YOUR_SECRET> \ --set config.cookieSecret=<GENERATED_COOKIE_SECRET> \ --set extraArgs.provider=github \ --set extraArgs.email-domain="*" \ stable/oauth2-proxy ⚡ kubectl get pods --selector=app=oauth2-proxy -n ingress NAME READY STATUS RESTARTS AGE authproxy-oauth2-proxy-cdb4f675b-wvdg5 1/1 Running 0 1m
NOTE: For GitHub, you can restrict access by
github-team="", which can be accompanied with
email-domain="*" from the above example. You can find more info here for GitHub provider.
You are done with the setup. Let's test it now.
For testing purposes I will deploy Kibana because it doesn't have authentication:
⚡ helm install --name kibana-test \ --set service.externalPort=5601 \ stable/kibana ⚡ kubectl get pods --selector=app=kibana NAME READY STATUS RESTARTS AGE kibana-test-66b88f77bc-vcwl4 1/1 Running 0 1m
There is a small catch now. Not sure if this is a bug or by design. You need to create two ingress resources for both services (Kibana and OAuth2 Proxy), but to be available on the same FQDN. Otherwise you will end up with auth loop and GitHub will block you for some time. I didn't have time to dig further into it.
Kibana path will be on
\ and OAuth2 on
\oauth2, same domain. This part is what configures Nginx ingress to route requests to auth service first:
nginx.ingress.kubernetes.io/auth-url: "https://$host/oauth2/auth" nginx.ingress.kubernetes.io/auth-signin: "https://$host/oauth2/start?rd=$request_uri"
And you will add above annotations to Kibana ingress only.
I could create ingress resources with Helm directly, but it will be easier for you to understand if I do it manually. Let's create both ingress resources with kubectl:
⚡ cat <<EOF | kubectl create -f - apiVersion: extensions/v1beta1 kind: Ingress metadata: name: kibana-test annotations: kubernetes.io/ingress.class: nginx kubernetes.io/tls-acme: "true" nginx.ingress.kubernetes.io/auth-url: "https://\$host/oauth2/auth" nginx.ingress.kubernetes.io/auth-signin: "https://\$host/oauth2/start?rd=\$request_uri" spec: rules: - host: kibana.test.akomljen.com http: paths: - backend: serviceName: kibana-test servicePort: 5601 path: / tls: - hosts: - kibana.test.akomljen.com secretName: kibana-tls --- apiVersion: extensions/v1beta1 kind: Ingress metadata: name: authproxy-oauth2-proxy namespace: ingress annotations: kubernetes.io/ingress.class: nginx kubernetes.io/tls-acme: "true" spec: rules: - host: kibana.test.akomljen.com http: paths: - backend: serviceName: authproxy-oauth2-proxy servicePort: 80 path: /oauth2 tls: - hosts: - kibana.test.akomljen.com secretName: kibana-tls EOF
kibana.test.akomljen.com will be accessible through HTTPS. Open the URL you configured as ingress host for Kibana, and you should be prompted with GitHub login screen:
If you want to add more services to OAuth Proxy, you could edit its ingress and add another host.
Cloud Native tools again make things easier. People just love when you can quickly come with the things working and OAuth Proxy is no different. Some basic security is definitely easier. Stay tuned for the next one.