J'avais plusieurs applications web sans authentification sur une instance Traefik avec une simple BasicAuth. Cette dernière est suffisante dans une majorité des cas, mais le fait que les OS ne gèrent pas correctement les gestionnaires de mot de passe type 1Password m'ennuyait.
Je me suis dit que Traefik devait bien avoir un moyen de mettre en place un système plus globale et j'ai donc trouvé ce tutoriel, que j'ai suivi, sans le côté Swarm puisque je suis en Docker classique. Je partage donc ici ma réinterprétation du tutoriel.
Middleware
Je ne reviens pas sur mon installation de Traefik, mais pour le contexte, sachez que toutes mes applications sont connectées à Traefik par le réseau traefik_default
et que je configure Traefik par les labels Docker.
Voici ma config docker-compose :
# docker-compose.yml
version: '3'
services:
dex:
image: dexidp/dex
volumes:
- /etc/localtime:/etc/localtime:ro
- ./dex/:/data/
networks:
- traefik_default
command: ['dex', 'serve', '/data/config.yml']
labels:
- traefik.enable=true
- traefik.http.routers.dex.rule=Host(`dex.example.com`)
- traefik.http.services.dex.loadbalancer.server.port=5556
- traefik.docker.network=traefik_default
traefik-forward-auth:
# Attention, il existe une image différente si vous êtes sur un système ARM.
# Ajoutez "-arm" à la fin de la ligne suivante si vous êtes dans ce cas.
image: thomseddon/traefik-forward-auth:2.2.0
env_file: ./traefik-forward-auth/.env
volumes:
- ./traefik-forward-auth/config.ini:/config.ini:ro
networks:
- traefik_default
labels:
- traefik.enable=true
- traefik.docker.network=traefik_default
- traefik.http.services.auth.loadbalancer.server.port=4181
- traefik.http.routers.auth.rule=Host(`auth.example.com`)
# Configuration SSL spécifique pour bénéficier du wildcard, nécessaire pour le cookie d'authentification
- traefik.http.routers.auth.tls=true
- traefik.http.routers.auth.tls.certresolver=letsencrypt
- traefik.http.routers.auth.tls.domains[0].main=example.com
- traefik.http.routers.auth.tls.domains[0].sans=*.example.com
- traefik.http.routers.auth.service=auth@docker
# Configuration du middleware
- traefik.http.middlewares.forward-auth.forwardauth.address=http://traefik-forward-auth:4181
- traefik.http.middlewares.forward-auth.forwardauth.trustForwardHeader=true
- traefik.http.middlewares.forward-auth.forwardauth.authResponseHeaders=X-Forwarded-User
- traefik.http.routers.auth.middlewares=forward-auth
networks:
traefik_default:
external: true
Ma configuration de Dex :
# dex/config.yml
issuer: https://dex.example.com
storage:
type: sqlite3
config:
file: /data/dex.db
web:
http: 0.0.0.0:5556
oauth2:
skipApprovalScreen: true
staticClients:
- id: auth-example
redirectURIs:
- 'https://auth.example.com/_oauth'
name: 'example.com'
secret: 6P6D9UqCGORQI5Gz3vo7
enablePasswordDB: true
staticPasswords:
# Configurez vos utilisateurs ici
- email: 'admin@example.com'
hash: 'bcrypted password' # Changez ça
username: 'admin'
userID: 'c0ea1e12-8e5a-48c7-968e-87a30a093c03'
Pour générer le mot de passe bcrypt, avec Ruby : ruby -e 'require "bcrypt"; puts BCrypt::Password.create("password")'
.
La configuration de base Traefik Forward Auth :
# traefik-forward-auth/.env
DEFAULT_PROVIDER=oidc
# This is the staticClients.id value in config.yml above
PROVIDERS_OIDC_CLIENT_ID=auth-example
# This is the staticClients.secret value in config.yml above
PROVIDERS_OIDC_CLIENT_SECRET=6P6D9UqCGORQI5Gz3vo7
# This is the issuer value in config.yml above, and it has to be reachable via a browser
PROVIDERS_OIDC_ISSUER_URL=https://dex.example.com
# Make this up. It's not configured anywhere else
SECRET=IgDpvuikOnZOey8X7HNE
# This should match the value of the traefik hosts labels in Traefik Forward Auth
AUTH_HOST=auth.example.com
COOKIE_DOMAIN=example.com
LOG_LEVEL=info
Ajouter l'authentification sur vos services
Il ne reste plus qu'à ajouter le middleware sur les containers à sécuriser. Par exemple pour mon instance d'Hyperion, les labels dans mon docker-compose seront les suivants :
# [...]
labels:
- traefik.enable=true
- traefik.http.routers.hyperion.rule=Host(`hyperion.example.com`)
- traefik.http.routers.hyperion.middlewares=forward-auth
- traefik.http.services.hyperion.loadbalancer.server.port=8090
- traefik.docker.network=traefik_default
La ligne importante étant traefik.http.routers.hyperion.middlewares=forward-auth
qui ajoute le middleware à Traefik.
J'ai quelques services non configurés via Docker (par exemple, le dashboard Traefik) et pour cela j'ajoute le middleware dans la configuration dynamique de Traefik. Par exemple pour le dashboard Traefik :
[http.routers]
[http.routers.dashboard]
middlewares = ["forward-auth@docker"]
service = "api@internal"
rule = "Host(`traefik.example.com`)"
Votre certificat vers auth.example.com reste autosigné
Si c'est votre cas, c'est probablement parce que vous utilisez la méthode TLS Challenge pour générer votre certificat plutôt que DNS Challenge dans la configuration de Traefik. Allez voir de ce côté-là.