Traefik is a modern reverse proxy and load balancer that makes deploying microservices easy. Traefik is natively compliant with Kubernetes, Docker and a lot of other cluster technologies.
Traefik allows the use of middlewares to tweak requests before they are sent to a service. There are several available middlewares in Traefik, some can modify the request, the headers, some are in charge of redirections and some add authentication.
This Post explains how to configure the BasicAuth-Middleware for Traefik 2 in Kubernetes. The BasicAuth-Middleware restricts access to services by prompting the user for a username and password.
There are multiple ways to enable and configure different Middlewares for Traefik. For the use with Kubernetes I will explain the File-Provider and the Kubernetes-Provider:
Configuration using File-Provider:
The File-Provider uses a YAML-Configuration-File that defines all the activated middlewares. The Following YAML shows my current Middleware File:
http:
middlewares:
sslheader:
headers:
customRequestHeaders:
X-Forwarded-Proto: "https"
compression:
compress:
excludedContentTypes:
- "text/event-stream"
To enable BasicAuth the file needs to be extended. First, we have to generate a user:password combination. The password must be hashed using MD5, SHA1, or BCrypt.
Generate a new user using the htpasswd
command:
echo $(htpasswd -nB user)
Now we can extend the configuration file:
http:
middlewares:
sslheader:
headers:
customRequestHeaders:
X-Forwarded-Proto: "https"
compression:
compress:
excludedContentTypes:
- "text/event-stream"
test-auth:
basicAuth:
users:
- "user:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/"
To activate BasicAuth make sure that the configuration is mounted inside your Traefik deployment. To do so, I use a Configuration-Map:
apiVersion: v1
data:
middleware.yaml: |
http:
middlewares:
sslheader:
headers:
customRequestHeaders:
X-Forwarded-Proto: "https"
compression:
compress:
excludedContentTypes:
kind: ConfigMap
metadata:
name: traefik-config
namespace: kube-system
---
And mount the volume inside the Traefik-Deployment:
# .... Deployment-Configs....
- image: traefik:v2.3.6
name: traefik
ports:
- name: http
containerPort: 80
hostPort: 80
- name: https
containerPort: 443
hostPort: 443
- name: admin
containerPort: 8080
hostPort: 8080
args:
- --configFile=/config/traefik.yaml
volumeMounts:
- mountPath: /config/traefik.yaml
name: traefik
subPath: traefik.yaml
- mountPath: /config/common/middleware.yaml
name: traefik
subPath: middleware.yaml
resources:
limits:
memory: 512Mi
cpu: "1"
livenessProbe:
httpGet:
port: 8082
path: /ping
readinessProbe:
httpGet:
port: 8082
path: /ping
volumes:
- name: traefik
configMap:
name: traefik-config
To enable the Taefik-Middleware for a route, add the following annotation to your ingress resource:
traefik.ingress.kubernetes.io/router.middlewares: test-auth@file
Configuration using Kubernetes-Provider:
The better way to enable and configure a BasicAuth-Middleware is by using the Kubernetes-Provider and custom CRD-resources.
First, we need to create a custom kind: Middleware
manifest to tell Traefik to enable the Middleware:
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: basic-auth-middleware
namespace: kube-system
spec:
basicAuth:
removeHeader: true
secret: basic-auth
The middleware links to a Kubernetes-Secret called test-auth
that holds the user:password
.
To generate the secret, run the following commands:
echo $(htpasswd -nB user) >> test-auth
kubectl create secret generic test-auth --from-file test-auth --namespace kube-system -o yaml --dry-run=client >> basic-auth-secret.yaml
This will generate the following File:
apiVersion: v1
data:
test-auth: dXNlcjokMnkkMDUkemV1Yzg0UmN0eFdJSE1MTC5RVzE4LnB3U256Wkp6UFYyT1JpSWF6ODNFU2JqSTMuZkRoUC4K
kind: Secret
metadata:
creationTimestamp: null
name: basic-auth
namespace: kube-system
Apply both manifests:
kubectl create -f basic-auth-middleware.yaml
kubectl create -f test-auth-secret.yaml
If you now open your Traefik-Dashboard you will see that Traefik found the test-auth-middleware
:
To enable BasicAuth for a specific route, use the name displayed in the Dashboard.
The Name consists out of <namespace>-<middleware-name>@kubernetescrd
.
For example, to enable the BasicAuth for the Traefik-Dashboard the ingress should be:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
kubernetes.io/ingress.class: traefik
traefik.ingress.kubernetes.io/router.entrypoints: https
traefik.ingress.kubernetes.io/router.tls: "true"
traefik.ingress.kubernetes.io/router.middlewares: kube-system-basic-auth-middleware@kubernetescrd
generation: 1
name: traefik
namespace: kube-system
spec:
rules:
- host: traefik.example.com
http:
paths:
- backend:
service:
name: traefik
port:
number: 8080
path: /
pathType: Prefix
tls:
- hosts:
- traefik.example.com
secretName: ingeress-tls