Traefik Forward Auth

Traefik 的 Dashboard 默认是没有用户认证的,也就是说你需要自己通过其他方法来实现身份认证。最简单的方法就是用 Basic Auth 中间件,还有一种稍微复杂一点的方案,就是在 Dashboard 路由中使用 AccessToken 作为身份认证的凭证。
但是上述两种方式都不够灵活,在团队中,我们可能希望能动态增加身份认证,并且能够灵活的管理。
前提条件⌗
- Traefik: https://traefik.svc.dev
- Zitadel: https://zitadel.svc.dev
- OAuth2 Proxy: https://authentication.svc.dev
Zitadel 是开源的外部身份认证提供者,如果不了解 Zitadel 的可以去看我的这篇文章 开源身份认证和授权解决方案。
Traefik 配置⌗
services:
traefik:
image: traefik:latest
labels:
- traefik.tls.stores.default.defaultgeneratedcert.resolver=step-ca
- traefik.tls.stores.default.defaultgeneratedcert.domain.main=svc.dev
- traefik.tls.stores.default.defaultgeneratedcert.domain.sans=*.svc.dev
- traefik.enable=true
- traefik.docker.network=traefik
- traefik.http.routers.traefik-dashboard.tls=true
- traefik.http.routers.traefik-dashboard.tls.certresolver=step-ca
- traefik.http.routers.traefik-dashboard.rule=Host(`traefik.svc.dev`)
- traefik.http.routers.traefik-dashboard.entrypoints=http,https
- traefik.http.routers.traefik-dashboard.service=dashboard@internal
# 为 Traefik Dashboard 设置中间件
- traefik.http.routers.traefik-dashboard.middlewares=unauthentication@docker,authentication@docker
- traefik.http.routers.traefik-dashboard-api.tls=true
- traefik.http.routers.traefik-dashboard-api.tls.certresolver=step-ca
- traefik.http.routers.traefik-dashboard-api.rule=Host(`traefik.svc.dev`) && PathPrefix(`/api`)
- traefik.http.routers.traefik-dashboard-api.entrypoints=http,https
- traefik.http.routers.traefik-dashboard-api.service=api@internal
# 为 Traefik Dashboard 设置中间件
- traefik.http.routers.traefik-dashboard-api.middlewares=unauthentication@docker,authentication@docker
# 为 Traefik 设置 /oauth2 路由,转发到 OAuth2 proxy
- traefik.http.routers.traefik-oauth.tls=true
- traefik.http.routers.traefik-oauth.tls.certresolver=step-ca
- traefik.http.routers.traefik-oauth.rule=Host(`traefik.svc.dev`) && PathPrefix(`/oauth2`)
- traefik.http.routers.traefik-oauth.entrypoints=http,https
- traefik.http.routers.traefik-oauth.service=authentication
- traefik.http.routers.traefik-oauth.middlewares=unauthentication@docker
- traefik.http.middlewares.authentication.forwardauth.address=https://authentication.svc.dev/oauth2/auth
- traefik.http.middlewares.authentication.forwardauth.trustForwardHeader=true
- traefik.http.middlewares.authentication.forwardauth.authResponseHeaders=X-Auth-Request-User,X-Auth-Request-Preferred-Username,X-Auth-Request-Access-Token,X-Auth-Request-Groups,Authorization,Set-Cookie,Location
- traefik.http.middlewares.authentication.forwardauth.tls.insecureSkipVerify=true
- traefik.http.middlewares.unauthentication.errors.query=/oauth2/sign_in
- traefik.http.middlewares.unauthentication.errors.status=401-403
- traefik.http.middlewares.unauthentication.errors.service=authentication
restart: always
hostname: traefik
networks:
- traefik
command:
- --api=true
- --api.insecure=false
- --api.dashboard=true
- --log.level=ERROR
- --ping=true
- --providers.file=true
- --providers.file.watch=true
- --providers.file.directory=/etc/traefik/config
- --providers.file.debugloggeneratedtemplate=true
- --providers.docker=true
- --providers.docker.watch=true
- --providers.docker.network=traefik
- --providers.docker.useBindPortIP=false
- --providers.docker.endpoint=unix:///var/run/docker.sock
- --entrypoints.http.address=:80
- --entrypoints.http.http.redirections.entryPoint.to=https
- --entrypoints.http.http.redirections.entryPoint.scheme=https
- --entryPoints.http.http.redirections.entrypoint.permanent=true
- --entrypoints.https.address=:443
- --entryPoints.https.http3.advertisedport=443
- --entryPoints.https.http.tls.certResolver=step-ca
- --entryPoints.https.http.tls.domains[0].main=svc.dev
- --entryPoints.https.http.tls.domains[0].sans=*.svc.dev
- --serverstransport.insecureskipverify=true
volumes:
- ./certs/:/certs/:rw
- ./config/:/etc/traefik/config/:ro
- /var/run/docker.sock:/var/run/docker.sock
environment:
- TZ=Asia/Shanghai
container_name: traefik
networks:
traefik:
external: true
OAuth2 Proxy 配置⌗
services:
authentication:
image: quay.io/oauth2-proxy/oauth2-proxy:v7.7.1
labels:
- traefik.enable=true
- traefik.http.routers.authentication.tls=true
- traefik.http.routers.authentication.tls.certresolver=step-ca
- traefik.http.routers.authentication.rule=Host(`authentication.svc.dev`) && PathPrefix(`/oauth2/`)
- traefik.http.routers.authentication.service=authentication
- traefik.http.routers.authentication.entrypoints=http,https
- traefik.http.routers.authentication.middlewares=authentication-headers@docker
- traefik.http.services.authentication.loadbalancer.server.port=4180
- traefik.http.middlewares.authentication-headers.headers.sslHost=svc.dev
- traefik.http.middlewares.authentication-headers.headers.frameDeny=true
- traefik.http.middlewares.authentication-headers.headers.stsSeconds=315360000
- traefik.http.middlewares.authentication-headers.headers.stsPreload=true
- traefik.http.middlewares.authentication-headers.headers.sslRedirect=true
- traefik.http.middlewares.authentication-headers.headers.forceSTSHeader=true
- traefik.http.middlewares.authentication-headers.headers.browserXssFilter=true
- traefik.http.middlewares.authentication-headers.headers.contentTypeNosniff=true
- traefik.http.middlewares.authentication-headers.headers.stsIncludeSubdomains=true
volumes:
- ./templates:/templates
restart: no
hostname: authentication
networks:
- traefik
environment:
- OAUTH2_PROXY_PROVIDER=oidc
- OAUTH2_PROXY_PROVIDER_DISPLAY_NAME=ZITADEL
- OAUTH2_PROXY_PROVIDER_CA_FILES=/root_ca.crt
- OAUTH2_PROXY_HTTP_ADDRESS=0.0.0.0:4180
- OAUTH2_PROXY_EMAIL_DOMAINS=*
- OAUTH2_PROXY_OIDC_ISSUER_URL=https://zitadel.svc.dev
- OAUTH2_PROXY_CLIENT_ID=
- OAUTH2_PROXY_CLIENT_SECRET=
- OAUTH2_PROXY_COOKIE_NAME=authentication
- OAUTH2_PROXY_COOKIE_SECURE=true
- OAUTH2_PROXY_COOKIE_SECRET=
- OAUTH2_PROXY_COOKIE_DOMAINS=.svc.dev
- OAUTH2_PROXY_WHITELIST_DOMAINS=*.svc.dev
- OAUTH2_PROXY_REVERSE_PROXY=true
- OAUTH2_PROXY_PASS_ACCESS_TOKEN=true
- OAUTH2_PROXY_CUSTOM_TEMPLATES_DIR=/templates
- OAUTH2_PROXY_INSECURE_OIDC_ALLOW_UNVERIFIED_EMAIL=true
- OAUTH2_PROXY_UPSTREAMS=file:///dev/null
- OAUTH2_PROXY_UPSTREAM_TIMEOUT=30s
- OAUTH2_PROXY_SSL_INSECURE_SKIP_VERIFY=true
- OAUTH2_PROXY_SSL_UPSTREAM_INSECURE_SKIP_VERIFY=false
container_name: authentication
volumes:
step-ca:
name: step-ca
external: true
networks:
traefik:
external: true
Zitadel 配置⌗
通过上述的配置就可以实现为 Traefik Dashboard 设置用户认证了。
I hope this is helpful, Happy hacking…