Traefik¶
Traefik is an open-source Application Proxy that makes publishing your services a fun and easy experience. It receives requests on behalf of your system and identifies which components are responsible for handling them, and routes them securely.
This tutorial shows how Traefik's ForwardAuth middleware can be configured to delegate authorization decisions to the Generic Auth Server.
Setup¶
Prerequisites¶
- A Kubernetes cluster
- Helm to install Traefik and the Generic Auth Server
- kubectl to interact with the cluster
Setup a cluster¶
Create a local cluster with kind.
KIND_IMAGE=kindest/node:v1.31.1
# create cluster
kind create cluster --image $KIND_IMAGE --wait 1m
Install Traefik¶
Install Traefik on the cluster.
# install traefik
helm install traefik --namespace traefik --create-namespace \
--wait --repo https://traefik.github.io/charts traefik \
--values - <<EOF
service:
type: ClusterIP
tolerations:
- key: node-role.kubernetes.io/control-plane
operator: Equal
effect: NoSchedule
EOF
Deploy the Generic Auth Server¶
Now deploy the Generic Auth Server.
# deploy the generic auth server
helm install generic-auth-server --namespace kyverno --create-namespace \
--wait --repo https://eddycharly.github.io/generic-auth-server \
generic-auth-server
Configure the ForwardAuth middleware¶
The ForwardAuth middleware will delegate authorization decisions to the Generic Auth Server.
# configure the forward auth middleware
kubectl apply -n traefik -f - <<EOF
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: auth
spec:
forwardAuth:
address: http://generic-auth-server.kyverno.svc.cluster.local:9081/auth
EOF
Notice that the middleware uses the Generic Auth Server url we deployed earlier:
[...]
forwardAuth:
address: http://generic-auth-server.kyverno.svc.cluster.local:9081/auth
[...]
Deploy a sample application¶
We will use the whoami
sample application that can be used to test HTTP requests and helps to show quickly how we can play with the request and response attributes.
# create the demo namespace
kubectl create ns demo
# deploy the httpbin application
kubectl apply -n demo -f - <<EOF
kind: Deployment
apiVersion: apps/v1
metadata:
name: whoami
labels:
app: whoami
spec:
replicas: 1
selector:
matchLabels:
app: whoami
template:
metadata:
labels:
app: whoami
spec:
containers:
- name: whoami
image: traefik/whoami
ports:
- name: web
containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: whoami
spec:
ports:
- name: web
port: 80
targetPort: web
selector:
app: whoami
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: whoami-ingress
annotations:
traefik.ingress.kubernetes.io/router.middlewares: traefik-auth@kubernetescrd
spec:
rules:
- host: foo.bar.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: whoami
port:
name: web
EOF
Notice that the ingress references our middleware using annotations:
[...]
annotations:
traefik.ingress.kubernetes.io/router.middlewares: traefik-auth@kubernetescrd
[...]
Create an AuthorizationPolicy¶
In summary the policy below does the following:
- Checks if the incoming request contains the header
x-force-authorized
with the valueenabled
ortrue
- Allows the request if it has the header or denies it if not
# deploy authorization policy
kubectl apply -f - <<EOF
apiVersion: generic.kyverno.io/v1alpha1
kind: AuthorizationPolicy
metadata:
name: demo-policy.example.com
spec:
variables:
- name: force_authorized
expression: >
object.Header("x-force-authorized")
- name: allowed
expression: >
"enabled" in variables.force_authorized || "true" in variables.force_authorized
authorizations:
- expression: >
variables.allowed
? auth
.Response(200)
: auth
.Response(401)
.WithBody("bye")
.WithHeader("reason", "not allowed")
EOF
Testing¶
At this point we have deployed and configured Traefik, the Generic Auth Server, a sample application, and an authorization policy.
Start an in-cluster shell¶
Let's start a pod in the cluster with a shell to call into the sample application.
# run an in-cluster shell
kubectl run -i -t busybox --image=alpine --restart=Never -n demo
Install curl¶
We will use curl to call into the sample application but it's not installed in our shell, let's install it in the pod.
# install curl
apk add curl
Call into the sample application¶
Now we can send requests to the sample application and verify the result.
The following request will return 401
(denied by our policy):
curl -s -w "\nhttp_code=%{http_code}" http://traefik.traefik.svc.cluster.local \
-H "Host: foo.bar.com"
The following request will return 200
(allowed by our policy):
curl -s -w "\nhttp_code=%{http_code}" http://traefik.traefik.svc.cluster.local \
-H "Host: foo.bar.com" \
-H "x-force-authorized: true"
Wrap Up¶
Congratulations on completing the tutorial!
This tutorial demonstrated how to configure Traefik’s ForwardAuth middleware to utilize the Generic Auth Server as an external authorization service.