Add kubernetes examples + better document methods of applying authentication

Closes #33
This commit is contained in:
Thom Seddon
2020-04-24 14:22:29 +01:00
parent 3a66191314
commit 9abf5645b7
36 changed files with 1029 additions and 54 deletions

View File

@ -0,0 +1,10 @@
# Kubernetes
These examples show how to deploy traefik-forward-auth alongside traefik v1.7.
The "seperate pod" examples show traefik-forward-auth in it's own pod and leave the deployment of traefik as an exercise for the user (e.g. if using helm).
The "single pod" examples show traefik and traefik-forward-auth in a single pod.
Please see the README's in each example for more details.

View File

@ -0,0 +1,16 @@
# Kubernetes - Advanced Separate Pod Example
This is an advanced example of how to deploy traefik-forward-auth in it's own pod. This example is a good starting point for those who already have traefik deployed (e.g. using helm).
This example uses [Individual Authentication](https://github.com/thomseddon/traefik-forward-auth/blob/master/README.md#individual-ingress-authentication-in-kubernetes) to selectively apply forward authentication to each individual ingress, a simple example "whoami" application (deployment, service and ingress) is included for completeness.
This example leverages kustomise to define Secrets and ConfigMaps, example deployment:
```
# Deploy traefik-forward-auth
kubectl apply -k traefik-forward-auth
# Deploy example whoami app
kubectl apply -k whoami
```

View File

@ -0,0 +1,3 @@
resources:
- traefik-forward-auth
- whoami

View File

@ -0,0 +1,65 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: traefik-forward-auth
labels:
app: traefik-forward-auth
spec:
replicas: 1
selector:
matchLabels:
app: traefik-forward-auth
strategy:
type: Recreate
template:
metadata:
labels:
app: traefik-forward-auth
spec:
terminationGracePeriodSeconds: 60
containers:
- image: thomseddon/traefik-forward-auth:2
name: traefik-forward-auth
ports:
- containerPort: 4181
protocol: TCP
env:
- name: CONFIG
value: "/config"
- name: DOMAIN
value: "example.com"
# Remove COOKIE_DOMAIN if not using auth host mode
- name: COOKIE_DOMAIN
value: "example.com"
# Remove AUTH_HOST if not using auth host mode
- name: AUTH_HOST
value: "auth.example.com"
- name: LOG_LEVEL
value: "info"
- name: PROVIDERS_GOOGLE_CLIENT_ID
valueFrom:
secretKeyRef:
name: secrets
key: google-client-id
- name: PROVIDERS_GOOGLE_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: secrets
key: google-client-secret
- name: COOKIE_SECRET
valueFrom:
secretKeyRef:
name: secrets
key: cookie-secret
volumeMounts:
- name: configs
mountPath: /config
subPath: traefik-forward-auth.ini
volumes:
- name: configs
configMap:
name: configs
- name: secrets
secret:
secretName: secrets

View File

@ -0,0 +1,17 @@
#
# NOTE: This is only needed if you are using auth-host mode
#
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: traefik-forward-auth
labels:
app: traefik-forward-auth
spec:
rules:
- host: auth.example.com
http:
paths:
- backend:
serviceName: traefik-forward-auth
servicePort: auth-http

View File

@ -0,0 +1,22 @@
commonLabels:
app: traefik-forward-auth
resources:
- deployment.yaml
- service.yaml
- ingress.yaml # Only needed for auth-host mode
#
# Configs
#
configMapGenerator:
- name: configs
files:
- traefik-forward-auth.ini
#
# Secrets
#
secretGenerator:
- name: secrets
env: traefik-forward-auth.env

View File

@ -0,0 +1,14 @@
apiVersion: v1
kind: Service
metadata:
name: traefik-forward-auth
labels:
app: traefik-forward-auth
spec:
type: ClusterIP
selector:
app: traefik-forward-auth
ports:
- name: auth-http
port: 4181
targetPort: 4181

View File

@ -0,0 +1,3 @@
google-client-id=client-id
google-client-secret=client-secret
cookie-secret=something-random

View File

@ -0,0 +1,8 @@
rule.example_public.action=allow
rule.example_public.rule=Host("stats.example.com") && PathPrefix("/api/public")
rule.example_api.action=allow
rule.example_api.rule=Host("api.example.com") && Headers("X-API-Authorization", "a-long-api-key")
rule.example_api_query.action=allow
rule.example_api_query.rule=Host("api.example.com") && && Query("api_key=a-long-api-key")

View File

@ -0,0 +1,19 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: whoami
labels:
app: whoami
spec:
replicas: 1
selector:
matchLabels:
app: whoami
template:
metadata:
labels:
app: whoami
spec:
containers:
- image: containous/whoami
name: whoami

View File

@ -0,0 +1,16 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: whoami
labels:
app: whoami
annotations:
kubernetes.io/ingress.class: traefik
spec:
rules:
- host: whoami.example.com
http:
paths:
- backend:
serviceName: whoami
servicePort: http

View File

@ -0,0 +1,7 @@
commonLabels:
app: whoami
resources:
- deployment.yaml
- service.yaml
- ingress.yaml

View File

@ -0,0 +1,14 @@
apiVersion: v1
kind: Service
metadata:
name: whoami
labels:
app: whoami
spec:
type: ClusterIP
ports:
- name: http
port: 80
selector:
app: whoami

View File

@ -0,0 +1,18 @@
# Kubernetes - Advanced Single Pod Example
This is an advanced example of how to deploy traefik and traefik-forward-auth in a single pod. This example is a good starting point for those who already have a manually defined traefik config (e.g. not using helm).
This example uses [Universal Authentication](https://github.com/thomseddon/traefik-forward-auth/blob/master/README.md#universal-authentication) to apply authentication for the entire `https` entrypoint.
This example also includes SSL via traefik acme/lesencrypt, auth host mode, exposes the traefik dashboard and leverages kustomise. No special config if required for your applications, but a simple example "whoami" application (deployment, service and ingress) is included for completeness.
Example deployment:
```
# Deploy traefik+traefik-forward-auth
kubectl apply -k traefik
# Deploy whoami app
kubectl apply -k whoami
```

View File

@ -0,0 +1,8 @@
rule.example_public.action=allow
rule.example_public.rule=Host("stats.example.com") && PathPrefix("/api/public")
rule.example_api.action=allow
rule.example_api.rule=Host("api.example.com") && Headers("X-API-Authorization", "a-long-api-key")
rule.example_api_query.action=allow
rule.example_api_query.rule=Host("api.example.com") && && Query("api_key=a-long-api-key")

View File

@ -0,0 +1,169 @@
################################################################
# Global configuration
################################################################
# Enable debug mode
#
# Optional
# Default: false
#
# debug = true
# Log level
#
# Optional
# Default: "ERROR"
#
logLevel = "INFO"
# Entrypoints to be used by frontends that do not specify any entrypoint.
# Each frontend can specify its own entrypoints.
#
# Optional
# Default: ["http"]
#
defaultEntryPoints = ["http", "https"]
# If set to true invalid SSL certificates are accepted for backends.
# This disables detection of man-in-the-middle attacks so should only be used on secure backend networks.
#
# Optional
# Default: false
#
insecureSkipVerify = true
################################################################
# Entrypoints configuration
################################################################
# Entrypoints definition
#
# Optional
# Default:
[entryPoints]
[entryPoints.http]
address = ":80"
compress = true
[entryPoints.http.redirect]
entryPoint = "https"
[entryPoints.https]
address = ":443"
compress = true
[entryPoints.https.tls]
[entryPoints.https.auth.forward]
address = "http://127.0.0.1:4181"
authResponseHeaders = ["X-Forwarded-User"]
[entryPoints.traefik]
address = ":8080"
################################################################
# Traefik logs configuration
################################################################
# Traefik logs
# Enabled by default and log to stdout
#
# Optional
#
[traefikLog]
format = "json"
# Sets the filepath for the traefik log. If not specified, stdout will be used.
# Intermediate directories are created if necessary.
#
# Optional
# Default: os.Stdout
#
# filePath = "log/traefik.log"
# Format is either "json" or "common".
#
# Optional
# Default: "common"
#
# format = "common"
################################################################
# Access logs configuration
################################################################
# Enable access logs
# By default it will write to stdout and produce logs in the textual
# Common Log Format (CLF), extended with additional fields.
#
# Optional
#
# [accessLog]
# Sets the file path for the access log. If not specified, stdout will be used.
# Intermediate directories are created if necessary.
#
# Optional
# Default: os.Stdout
#
# filePath = "/path/to/log/log.txt"
# Format is either "json" or "common".
#
# Optional
# Default: "common"
#
# format = "common"
################################################################
# API and dashboard configuration
################################################################
# Enable API and dashboard
[api]
# Name of the related entry point
#
# Optional
# Default: "traefik"
#
# entryPoint = "traefik"
# Enabled Dashboard
#
# Optional
# Default: true
#
# dashboard = false
################################################################
# Ping configuration
################################################################
# Enable ping
[ping]
# Name of the related entry point
#
# Optional
# Default: "traefik"
#
# entryPoint = "traefik"
################################################################
# Docker configuration backend
################################################################
# Enable Kubernetes configuration backend
[kubernetes]
[acme]
KeyType = "RSA4096"
email = "you@example.com"
storage = "/acme/acme.json"
entryPoint = "https"
onHostRule = true
acmeLogging = true
[acme.httpChallenge]
entryPoint = "http"

View File

@ -0,0 +1,92 @@
#
# Traefik + Traefik Forward Auth Deployment
#
apiVersion: apps/v1
kind: Deployment
metadata:
name: traefik
labels:
app: traefik
spec:
replicas: 1
selector:
matchLabels:
app: traefik
strategy:
type: Recreate
template:
metadata:
labels:
app: traefik
spec:
serviceAccountName: traefik
terminationGracePeriodSeconds: 60
containers:
- image: traefik:1.7.12
name: traefik
args:
- --configfile=/config/traefik.toml
ports:
- name: http
containerPort: 80
hostPort: 80
protocol: TCP
- name: https
containerPort: 443
hostPort: 443
protocol: TCP
- name: dash
containerPort: 8080
protocol: TCP
volumeMounts:
- mountPath: /config
name: configs
- mountPath: /acme
name: acme
- image: thomseddon/traefik-forward-auth:2
name: traefik-forward-auth
ports:
- containerPort: 4181
protocol: TCP
env:
- name: CONFIG
value: "/config"
- name: COOKIE_DOMAIN
value: "example.com"
- name: DOMAIN
value: "example.com"
- name: AUTH_HOST
value: "auth.example.com"
- name: LOG_LEVEL
value: "info"
- name: PROVIDERS_GOOGLE_CLIENT_ID
valueFrom:
secretKeyRef:
name: secrets
key: google-client-id
- name: PROVIDERS_GOOGLE_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: secrets
key: google-client-secret
- name: COOKIE_SECRET
valueFrom:
secretKeyRef:
name: secrets
key: cookie-secret
volumeMounts:
- name: configs
mountPath: /config
subPath: traefik-forward-auth.ini
volumes:
- name: configs
configMap:
name: configs
- name: secrets
secret:
secretName: secrets
- name: acme
persistentVolumeClaim:
claimName: traefik-acme

View File

@ -0,0 +1,36 @@
#
# Auth Ingress
#
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: traefik-forward-auth
labels:
app: traefik
spec:
rules:
- host: auth.example.com
http:
paths:
- backend:
serviceName: traefik-forward-auth
servicePort: auth-http
---
#
# Dash Ingress
#
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: traefik-dashboard
labels:
app: traefik
spec:
rules:
- host: traefik.example.com
http:
paths:
- backend:
serviceName: traefik-dashboard
servicePort: dashboard-http

View File

@ -0,0 +1,28 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: default
commonLabels:
app: traefik
resources:
- deployment.yaml
- service.yaml
- ingress.yaml
- pvc.yaml
- rbac.yaml
#
# Configs
#
configMapGenerator:
- name: configs
files:
- configs/traefik.toml
- config/traefik-forward-auth.ini
#
# Secrets
#
secretGenerator:
- name: secrets
env: secrets/traefik-forward-auth.env

View File

@ -0,0 +1,17 @@
# Source: traefik/templates/acme-pvc.yaml
#
# PVC
#
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: traefik-acme
labels:
app: traefik
spec:
accessModes:
- "ReadWriteOnce"
resources:
requests:
storage: "1Gi"
storageClassName: "local-traefik-acme"

View File

@ -0,0 +1,52 @@
#
# RBAC
# Source: traefik/templates/rbac.yaml
#
kind: ServiceAccount
apiVersion: v1
metadata:
name: traefik
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: traefik
rules:
- apiGroups:
- ""
resources:
- pods
- services
- endpoints
- secrets
verbs:
- get
- list
- watch
- apiGroups:
- extensions
resources:
- ingresses
verbs:
- get
- list
- watch
- apiGroups:
- extensions
resources:
- ingresses/status
verbs:
- update
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: traefik
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: traefik
subjects:
- kind: ServiceAccount
name: traefik
namespace: kube-system

View File

@ -0,0 +1,3 @@
google-client-id=client-id
google-client-secret=client-secret
cookie-secret=something-random

View File

@ -0,0 +1,36 @@
#
# Auth Service
#
apiVersion: v1
kind: Service
metadata:
name: traefik-forward-auth
labels:
app: traefik
spec:
type: ClusterIP
selector:
app: traefik
ports:
- name: auth-http
port: 4181
targetPort: 4181
---
#
# Dash Service
#
apiVersion: v1
kind: Service
metadata:
name: traefik-dashboard
labels:
app: traefik
spec:
type: ClusterIP
selector:
app: traefik
ports:
- name: dashboard-http
port: 8080
targetPort: 8080

View File

@ -0,0 +1,19 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: whoami
labels:
app: whoami
spec:
replicas: 1
selector:
matchLabels:
app: whoami
template:
metadata:
labels:
app: whoami
spec:
containers:
- image: containous/whoami
name: whoami

View File

@ -0,0 +1,16 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: whoami
labels:
app: whoami
annotations:
kubernetes.io/ingress.class: traefik
spec:
rules:
- host: whoami.example.com
http:
paths:
- backend:
serviceName: whoami
servicePort: http

View File

@ -0,0 +1,7 @@
commonLabels:
app: whoami
resources:
- deployment.yaml
- service.yaml
- ingress.yaml

View File

@ -0,0 +1,14 @@
apiVersion: v1
kind: Service
metadata:
name: whoami
labels:
app: whoami
spec:
type: ClusterIP
ports:
- name: http
port: 80
selector:
app: whoami

View File

@ -0,0 +1,43 @@
# Kubernetes - Simple Separate Pod Example
This is a simple example of how to deploy traefik-forward-auth in it's own pod with minimal configuration. This example is a good starting point for those who already have traefik deployed (e.g. using helm).
This example uses annotations to apply authentication to selected ingresses (see `k8s-app.yml`). This means ingresses will not be protected by default, only those with these annotations will require forward authentication. For example:
```
#
# Ingress
#
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: whoami
labels:
app: whoami
annotations:
kubernetes.io/ingress.class: traefik
ingress.kubernetes.io/auth-type: forward
ingress.kubernetes.io/auth-url: http://traefik-forward-auth:4181
ingress.kubernetes.io/auth-response-headers: X-Forwarded-User
spec:
rules:
- host: whoami.example.com
http:
paths:
- backend:
serviceName: whoami
servicePort: http
```
Example deployment:
```
# Deploy traefik-forward-auth
kubectl apply -f k8s-traefik-forward-auth.yml
# Deploy example whoami app
kubectl apply -f k8s-app.yml
```
Please see the advanced examples for more details.

View File

@ -0,0 +1,62 @@
#
# Example Application Deployment
#
apiVersion: apps/v1
kind: Deployment
metadata:
name: whoami
labels:
app: whoami
spec:
replicas: 1
selector:
matchLabels:
app: whoami
template:
metadata:
labels:
app: whoami
spec:
containers:
- name: whoami
image: emilevauge/whoami
---
#
# Service
#
apiVersion: v1
kind: Service
metadata:
name: whoami
labels:
app: whoami
spec:
ports:
- name: http
port: 80
selector:
app: whoami
---
#
# Ingress
#
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: whoami
labels:
app: whoami
annotations:
kubernetes.io/ingress.class: traefik
ingress.kubernetes.io/auth-type: forward
ingress.kubernetes.io/auth-url: http://traefik-forward-auth:4181
ingress.kubernetes.io/auth-response-headers: X-Forwarded-User
spec:
rules:
- host: whoami.example.com
http:
paths:
- backend:
serviceName: whoami
servicePort: http

View File

@ -0,0 +1,87 @@
#
# Traefik Forward Auth Deployment
#
apiVersion: apps/v1
kind: Deployment
metadata:
name: traefik-forward-auth
labels:
app: traefik-forward-auth
spec:
replicas: 1
selector:
matchLabels:
app: traefik-forward-auth
strategy:
type: Recreate
template:
metadata:
labels:
app: traefik-forward-auth
spec:
terminationGracePeriodSeconds: 60
containers:
- image: thomseddon/traefik-forward-auth:2
name: traefik-forward-auth
ports:
- containerPort: 4181
protocol: TCP
env:
- name: DOMAIN
value: "example.com"
- name: PROVIDERS_GOOGLE_CLIENT_ID
valueFrom:
secretKeyRef:
name: secrets
key: traefik-forward-auth-google-client-id
- name: PROVIDERS_GOOGLE_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: secrets
key: traefik-forward-auth-google-client-secret
- name: COOKIE_SECRET
valueFrom:
secretKeyRef:
name: secrets
key: traefik-forward-auth-cookie-secret
---
#
# Auth Service
#
apiVersion: v1
kind: Service
metadata:
name: traefik-forward-auth
labels:
app: traefik-forward-auth
spec:
type: ClusterIP
selector:
app: traefik-forward-auth
ports:
- name: auth-http
port: 4181
targetPort: 4181
---
#
# Secrets
#
# Kubernetes requires secret values to be converted to base64 when defined
# explicitly like this. (use `echo -n 'secret-value' | base64`)
#
# These are here for completeness, in reality you may define these elsewhere,
# for example using kustomize (shown in advanced examples)
#
apiVersion: v1
kind: Secret
metadata:
name: traefik-forward-auth-secrets
labels:
app: traefik-forward-auth
type: Opaque
data:
traefik-forward-auth-google-client-id: base64-client-id
traefik-forward-auth-google-client-secret: base64-client-secret
traefik-forward-auth-cookie-secret: base64-something-random