Après un article sur la mise en place de conteneur WordPress avec Docker, je me devais de réaliser la même chose mais cette fois avec un environnement Kubernetes !
Comme je ne suis pas ici pour faire un simple copier/coller d'une technologie à une autre, je vais en profiter pour expliquer quelques petites astuces de Traefik que je n'ai pas encore eu l'occasion d'évoquer sur le blog, notamment dans son utilisation avec Kubernetes !
Nous verrons, par exemple, comment appliquer des options TLS à toutes nos routes Ingress. Mais aussi l'application de Middleware !
Ce sera également l'occasion de revoir une installation de Traefik avec les CRD de Kubernetes et notamment la mise en place d'un filtrage IP pour l'accès à l'interface d'administration. Et oui, nous n'allons donc pas négliger la partie sécurité !
J'en profite également pour utiliser Kustomize
pour gérer mes configurations !
Pré-requis 🏗️
Comme à mon habitude, je vais réaliser l'intégralité de ce tutoriel avec un environnement K3S. Pour réaliser cette installation, rien de plus simple :
curl -sfL https://get.k3s.io | sh -s - --no-deploy=traefik
Nous allons réaliser l'installation de Traefik par la suite.
Quickstart 🚀
Voici comment procéder à cette mise en place en quelques minutes !
Récupérez les fichier sur le dépôt Git :
git clone https://github.com/lfache/awesome-traefik-kubernetes
Afin de personnaliser votre installation, voici les éléments à modifier pour Traefik dans le dossier traefik-kustomize-sample/production
:
Variable | Fichier à modifier | Example |
---|---|---|
email |
traefik-configmap.yaml | [email protected] |
storage |
traefik-volumeclaim.yaml | 20Gi |
Ensuite vous pouvez lancer Traefik :
kubectl apply -k ./traefik-kustomize-sample/production
Pour personnaliser votre installation de WordPress, voici les éléments à modifier dans le dossier wordpress/
:
Variable | Fichier à modifier | Example |
---|---|---|
database |
kustomization.yaml | YOUR_DATABASE |
user |
kustomization.yaml | YOUR_USER |
password |
kustomization.yaml | YOUR_PASSWORD |
Enfin vous pouvez lancer WordPress :
kubectl apply -k ./wordpress
Enjoy :
![](/content/images/2020/04/ssllabs-1.png)
![](/content/images/2020/04/wordpress-2.png)
![](/content/images/2020/04/securityheaders-1.png)
Quelques explications 🤔
Pour réaliser ces déploiements, j'utilise Kustomize
. J'ai réalisé une présentation de cet outil lors d'un précédent article que vous pouvez consulter ici :
![](/content/images/2020/04/amir-abbas-abdolali-_Tm4622z4Dg-unsplash.jpg)
J'utilise la version de Traefik 2.2, vous pouvez trouver plus de détails sur cette version sur le test de la version release candidate que j'avais pu effectuer il y a quelques semaines :
![](/content/images/2020/03/camille-brodard-f6Wpz1QPFZI-unsplash.jpg)
Pour rappel, au menu de cette version, je vais utiliser :
- Redirection dès la création de l'entrypoint HTTP vers le HTTPS,
Tout ceci est déclaré dans mon fichier ConfigMap
:
entryPoints:
web:
address: :80
http:
redirections:
entryPoint:
to: websecure
scheme: https
Enfin nous allons aborder une "petite" modification de la 2.2 qui prend tout son sens avec Kubernetes.
Cet ajout est presque passé inaperçu mais heureusement je suis là pour vous faire découvrir tout ça ! 😂
Les options LTS
Habituellement - et le plus simple - pour déclarer des options TLS dans un environnement Kubernetes, on applique les options à la création de la route Ingress :
Exemple :
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: traefik-tls
namespace: default
spec:
entryPoints:
- websecure
routes:
- kind: Rule
match: Host(``)
services:
- name: XXX
port: 80
tls:
certResolver: le
options:
name: mytlsoption
namespace: default
🚩 Cette façon de faire fonctionne, aucun soucis. Par contre je n'aime pas appliquer une option pour chacune de mes routes Ingress alors que je souhaite la voir appliquer à tout mes sites ! 🚩
Heureusement la documentation de la version 2.2 nous apporte une nouvelle piste :
entryPoints:
EntryPoint0:
address: foobar
http:
tls:
options: foobar
Tout comme les middlewares, on peut déclarer des options TLS par défaut ! Je vais donc déclarer un CRD avec mes options TLS :
apiVersion: traefik.containo.us/v1alpha1
kind: TLSOption
metadata:
name: mytlsoption
namespace: default
spec:
minVersion: VersionTLS12
sniStrict: true
Et m’empresser de déclarer cette ressource dans ma configuration statique, donc dans ma ressource ConfigMap
:
websecure:
address: :443
http:
tls:
options: default-mytlsoption
certResolver: myresolver
🚩 Attention de préfixer le nom de votre option avec votre namespace, j'utilise ici le namespace default ! 🚩
Cette option pourra également ravir ceux qui utilisent Traefik avec Docker Swarm et souhaitent utiliser le moins possible de fichier de configuration !
Headers et middlewares
Enfin vous pourrez noter que mon score sur securityheaders.com n'est que de A
! Pourquoi ?
Il était très simple d'obtenir un A+ pour une capture d'écran mais certaines CSP ne sont pas conseillées avec WordPress. J'ai donc préféré utiliser des headers réalistes et utilisables en production ( attention toutefois, à valider en fonction de vos modules ) et dégrader d'un cran mon score.
L'instruction qui dégrade ma note est la suivante : This policy contains 'unsafe-inline' which is dangerous in the style-src directive.
Enfin je déclare deux middlewares pour WordPress :
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: wp-headers
spec:
headers:
frameDeny: true
contentTypeNosniff: true
browserXssFilter: true
#HSTS
forceSTSHeader: true
stsIncludeSubdomains: true
stsSeconds: 31536000
# remove Server and X-Powered-By headers
customResponseHeaders:
Server: ''
X-Powered-By: ''
# add some sec headers
contentSecurityPolicy: "default-src 'self' data: ; script-src 'self' 'unsafe-inline' ; style-src 'self' 'unsafe-inline' fonts.googleapis.com https://code.jquery.com ; font-src 'self' fonts.gstatic.com data: ; img-src 'self' data: https://code.jquery.com"
referrerPolicy: "same-origin"
featurePolicy: "vibrate 'self'; geolocation 'self'; midi 'self'; notifications 'self'; push 'self'; microphone 'none'; camera 'none'; magnetometer 'none'; gyroscope 'none'; speaker 'none'; vibrate 'self'; fullscreen 'self'"
Celui-ci afin de manipuler les en-têtes de sécurité et de retirer certaines en-têtes renvoyées par WordPress ( Server et X-Powered-By ).
Enfin je déclare un middleware pour restreindre l'accès à l'administration :
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: wp-ipwhitelist
spec:
ipWhiteList:
sourceRange:
- X.X.X.X/32
Il ne reste plus qu'à appliquer ces middlewares à vos routes :
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: ingressroutetls
spec:
entryPoints:
- websecure
routes:
- match: Host(`wordpress.mydomain.com`)
kind: Rule
services:
- name: wordpress
port: 80
middlewares:
- name: wp-headers
- match: Host(`wordpress.mydomain.com`) && (Path(`/wp-admin`)|| Path(`/wp-login.php`))
kind: Rule
services:
- name: wordpress
port: 80
middlewares:
- name: wp-ipwhitelist
Nous avons donc pu installer WordPress dans un environnement Kubernetes à l'aide de Traefik ! Cet article est l'occasion d'affiner notre déploiement avec des options de sécurité que nous n'avions pas encore eu l'occasion de mettre en place.
Il nous a également permis de découvrir une nouvelle option de la version 2.2 qui va nous permettre d'activer des options TLS à toutes nos routes Ingress sans les rappeler de façon systématique !
En tout cas n'hésitez pas à m'apporter des remarques ou des commentaires sur Twitter ! C'est toujours un plaisir d'avoir des retours ! 😘