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

174 lines
6.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Traefik ForwardAuth: HTML-логин для внутренних сервисов
## 1. Контекст
Текущая схема использует BasicAuth — браузерный нативный диалог, не кастомизируемый.
ForwardAuth позволяет заменить его на HTML-страницу входа с сессиями.
**Что меняется:** вместо `Middleware basicAuth``Middleware 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
```
**Ключевые параметры:**
```yaml
# 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:**
```yaml
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:
```yaml
# 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 вручную:
```bash
kubectl create secret generic oauth2proxy-htpasswd \
--from-literal=htpasswd="$(htpasswd -nb admin 'pass')" \
-n traefik
```
4. Создать Secret с cookie_secret:
```bash
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`