Last update:
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.
Related posts:
- 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
Installation
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-org=""
and 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.
Testing
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.
Summary
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.