k8s/research/traefik-forwardauth.md
2026-07-15 11:14:21 +03:00

6.6 KiB
Raw Blame History

Traefik ForwardAuth: HTML-логин для внутренних сервисов

1. Контекст

Текущая схема использует BasicAuth — браузерный нативный диалог, не кастомизируемый. ForwardAuth позволяет заменить его на HTML-страницу входа с сессиями.

Что меняется: вместо Middleware basicAuthMiddleware forwardAuth + отдельный auth-pod.


2. Как работает ForwardAuth

Клиент → Traefik :10002 → ForwardAuth Middleware
                                │
                                ▼
                         auth-сервис /auth
                                │
                    ┌───────────┴───────────┐
                    │ 200 OK                │ 401 → redirect на /login
                    │ (сессия валидна)      │ (HTML-страница логина)
                    ▼                       ▼
             longhorn-frontend        форма → POST /login
                                            │
                                      проверка пароля
                                            │
                                      Set-Cookie session
                                            │
                                      redirect обратно

Traefik делает subrequest на authResponseHeaders — если auth-сервис вернул 200, пропускает запрос дальше. Если 401/302 — возвращает клиенту ответ auth-сервиса (redirect на страницу логина).


3. Варианты реализации

3.1. oauth2-proxy (рекомендуется)

Что это: легковесный reverse-proxy с поддержкой htpasswd, GitHub, Google, OIDC. Для внутреннего использования подходит режим --htpasswd-file без внешнего провайдера.

Плюсы:

  • Один pod, ~50MB RAM
  • Htpasswd-файл через Kubernetes Secret — никаких внешних зависимостей
  • HTML-форма из коробки, можно переопределить шаблоны
  • Cookie-сессии, configurable TTL

Минусы:

  • Один экземпляр oauth2-proxy на весь Traefik (или по одному на сервис)
  • Нет 2FA

Схема деплоя:

roles/oauth2-proxy/
  tasks/main.yml    — Kubernetes Deployment + Service
  tasks/secret.yml  — инструкция по созданию htpasswd Secret вручную
  tasks/middleware.yml — ForwardAuth Middleware CRD

inventory/prod/group_vars/oauth2proxy.yml — cookie_secret, upstream, htpasswd ref

Ключевые параметры:

# Helm values / env vars
--provider=htpasswd
--htpasswd-file=/etc/oauth2-proxy/htpasswd
--cookie-secret=<32-byte-random>     # генерируется вручную
--cookie-secure=false                # HTTP, без TLS
--email-domain=*
--upstream=static://200              # ForwardAuth: upstream не используется

Middleware CRD:

apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
  name: forwardauth-oauth2proxy
  namespace: traefik
spec:
  forwardAuth:
    address: http://oauth2-proxy.traefik.svc:4180/oauth2/auth
    trustForwardHeader: true
    authResponseHeaders:
      - X-Auth-Request-User
      - X-Auth-Request-Email

3.2. Authelia

Что это: полноценный self-hosted identity provider. HTML-логин, 2FA (TOTP, WebAuthn), LDAP, правила доступа по пользователям/группам.

Плюсы:

  • Красивая HTML-форма с брендингом
  • 2FA из коробки
  • Гранулярный контроль: разные пользователи для разных сервисов

Минусы:

  • Требует Redis (сессии) + хранилище пользователей (файл или LDAP)
  • ~150MB RAM минимум
  • Сложнее в настройке (YAML-конфиг, несколько секретов)

Оправдано если: нужен 2FA или несколько пользователей с разными правами.


3.3. thomseddon/traefik-forward-auth

Что это: минималистичный ForwardAuth-сервис только для Google/OIDC OAuth. Для htpasswd не подходит — требует внешний провайдер.


4. Рекомендация

Для текущего стека (внутренняя сеть, один оператор, нет SSO) — oauth2-proxy с htpasswd.

Критерий oauth2-proxy Authelia
RAM ~50MB ~150MB
Внешние зависимости нет Redis
2FA нет да
Сложность настройки низкая средняя
HTML-логин да (кастомизируемый) да (красивый)

5. Интеграция с текущим port_map

Схема остаётся прежней — меняется только тип Middleware:

# inventory/prod/group_vars/traefik.yml
traefik_port_map:
  - name: longhorn-ui
    port: 10002
    backend:
      namespace: longhorn-system
      service: longhorn-frontend
      port: 80
      scheme: http
    auth:
      type: forwardauth                      # вместо basicauth
      middleware: forwardauth-oauth2proxy    # имя Middleware

При type: forwardauth шаблон ingressroute.yml.j2 подставляет ForwardAuth Middleware вместо BasicAuth. При type: basicauth — как сейчас.


6. Порядок развёртывания (если решим внедрить)

  1. Добавить роль oauth2-proxy в roles/
  2. Добавить playbooks/setup_oauth2proxy.yml
  3. Создать Secret с htpasswd вручную:
    kubectl create secret generic oauth2proxy-htpasswd \
      --from-literal=htpasswd="$(htpasswd -nb admin 'pass')" \
      -n traefik
    
  4. Создать Secret с cookie_secret:
    kubectl create secret generic oauth2proxy-cookie \
      --from-literal=cookie-secret="$(openssl rand -base64 32)" \
      -n traefik
    
  5. Заменить basicAuth Middleware на forwardAuth в IngressRoute для нужных сервисов
  6. Удалить старые BasicAuth Middleware и Secret traefik-auth-longhorn