# 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`