# Dex Demo Application

Демонстрационное приложение для аутентификации через DexAuthenticator в Kubernetes кластере с Deckhouse.

![preview](preview.png)

## Описание

Простое приложение, демонстрирующее интеграцию с DexAuthenticator:
- **Backend (Python/FastAPI)**: Валидирует JWT токены, получает данные пользователя из PostgreSQL
- **Frontend (React/Vite)**: Отображает информацию о пользователе и доступные ресурсы на основе ролей
- **PostgreSQL**: Хранит пользователей, роли и доступные ссылки
- **DexAuthenticator**: Обеспечивает аутентификацию через Dex

## Работа приложения

1. Пользователь открывает `https://python-navigator-demo.127.0.0.1.sslip.io`
2. Ingress перенаправляет на DexAuthenticator для аутентификации
3. Если не аутентифицирован происходит редирект на Dex (HTTP 302) для входа
4. Если не аутентифицирован в Dex происходит редирект на Blitz IdP (HTTP 302) для входа
5. После аутентификации в Blitz IdP → возврат в Dex
6. После успешной аутентификации Dex возвращает токен в DexAuthenticator
7. DexAuthenticator устанавливает заголовки (`X-Auth-Request-Email`,`X-Auth-Request-User`, `Authorization`) и cookie
8. После успешной аутентификации Frontend загружается
9. Frontend делает запрос к `/api/user-info`
10. DexAuthenticator устанавливает заголовки (`X-Auth-Request-Email`,`X-Auth-Request-User`, `Authorization`) и cookie
11. Backend:
   - Валидирует JWT токен из заголовка `Authorization`
   - Извлекает email/id пользователя
   - Получает данные из PostgreSQL
   - Возвращает информацию о пользователе и доступных ресурсах 
12. Frontend отображает информацию о пользователе и доступные ресурсы

![Диаграмма последовательности](sequenceDiagram.png)

## Архитектура

```
┌─────────────┐
│   Browser   │
└─────┬───────┘
      │
      ▼
┌─────────────────────────────────────┐
│  Ingress + DexAuthenticator         │
│  (аутентификация через Dex)         │
└─────┬───────────────────────────────┘
      │
      ├──────────► Frontend (React)
      │                 │
      │                 ▼
      └──────────► Backend (FastAPI)
                        │
                        ▼
                  PostgreSQL
```

## Предварительные требования

- Kubernetes кластер с Deckhouse
- Настроенный Dex по адресу `https://dex.127.0.0.1.sslip.io`
- Docker
- kubectl
- make

## Быстрый старт

### 1. Сборка Docker образов

```bash
# Собрать все образы
make build-all

# Или по отдельности:
make build-backend
make build-frontend
```

### 2. Развертывание в Kubernetes

```bash
make deploy
```

Приложение будет доступно по адресу: `https://python-navigator-demo.127.0.0.1.sslip.io`

#### Финальная архитектура в Kubernetes:

```mermaid
flowchart
    A["python-navigator-demo.127.0.0.1.sslip.io"] --> B["Единый Ingress + DexAuthenticator<br/>(аутентификация)"]
    
    B --> C["Frontend Service"]
    B --> D["DexAuthenticator Service"]
    B --> E["Backend Service"]
    
    C --> F["Frontend Pods"]
    D --> G["DexAuthenticator Pods"]
    E --> H["Backend Pods"]
    
    H --> I["PostgreSQL Service"]
    
    classDef ingress fill:#e1f5fe
    classDef service fill:#f3e5f5
    classDef pod fill:#e8f5e8
    classDef database fill:#fff3e0
    
    class A,B ingress
    class C,D,E service
    class F,G,H pod
    class I database
```

### 3. Удаление приложения

```bash
make undeploy

# Или полная очистка (включая Docker образы):
make clean
```

## Структура проекта

```
.
├── backend/              # Python бэкенд
│   ├── main.py          # FastAPI приложение
│   ├── requirements.txt # Python зависимости
│   └── Dockerfile       # Docker образ
├── frontend/            # React фронтенд
│   ├── src/
│   │   ├── App.jsx     # Главный компонент
│   │   └── App.css     # Стили
│   ├── nginx.conf      # Nginx конфигурация
│   └── Dockerfile      # Docker образ
├── db/                  # База данных
│   └── init.sql        # SQL скрипт инициализации
├── k8s/                # Kubernetes манифесты
│   ├── namespace.yaml
│   ├── postgres.yaml
│   ├── backend.yaml
│   ├── frontend.yaml
│   ├── dex-authenticator.yaml
│   └── ingress.yaml
├── Makefile            # Команды для сборки и развертывания
└── README.md           # Документация
```

## Компоненты

### Backend (FastAPI)

**Эндпоинты:**
- `GET /api/health` - Проверка здоровья сервиса
- `GET /api/user-info` - Получение информации о пользователе

**Функциональность:**
- Валидация JWT токенов от Dex (проверка подписи, issuer, exp)
- Извлечение email пользователя из токена или заголовков
- Получение данных пользователя из PostgreSQL (организация, полное имя)
- Получение ролей пользователя
- Получение доступных ссылок на основе ролей

### Frontend (React + Vite)

**Функциональность:**
- Отображение информации о пользователе
- Список ролей
- Доступные ресурсы на основе ролей пользователя
- Никакой логики аутентификации (вся аутентификация на стороне DexAuthenticator)

### База данных (PostgreSQL)

**Схема:**
- `organizations` - Организации
- `users` - Пользователи
- `roles` - Роли
- `user_roles` - Связь пользователей и ролей
- `links` - Доступные ссылки
- `role_links` - Связь ролей и ссылок

### Тестовые данные

По умолчанию в БД загружаются следующие тестовые пользователи:

1. **admin@example.com** (Иван Администраторов)
   - Роли: admin, developer
   - Организация: Acme Corporation
   - Доступ: ко всем ресурсам

2. **developer@example.com** (Мария Разработчикова)
   - Роли: developer, user
   - Организация: Tech Innovators Inc
   - Доступ: технические ресурсы (CI/CD, Git, Docs, Wiki)

3. **user@example.com** (Петр Пользователев)
   - Роли: user
   - Организация: Global Solutions Ltd
   - Доступ: только база знаний

4. **manager@example.com** (Анна Менеджерова)
   - Роли: manager, user
   - Организация: Acme Corporation
   - Доступ: управленческие ресурсы (Проекты, Отчеты, Wiki)

**Важно:** Убедитесь, что эти email совпадают с пользователями в вашем Dex, или измените данные в `db/init.sql`

## Конфигурация

### Backend переменные окружения

- `DB_HOST` - Хост PostgreSQL (по умолчанию: `postgres`)
- `DB_PORT` - Порт PostgreSQL (по умолчанию: `5432`)
- `DB_NAME` - Имя БД (по умолчанию: `dexdemo`)
- `DB_USER` - Пользователь БД (по умолчанию: `dexdemo`)
- `DB_PASSWORD` - Пароль БД
- `DEX_ISSUER` - URL Dex issuer (по умолчанию: `https://dex.127.0.0.1.sslip.io/`)

### DexAuthenticator

Настройки в `k8s/dex-authenticator.yaml`:
- `applicationDomain` - Домен приложения
- `sendAuthorizationHeader` - Отправка заголовка Authorization с JWT
- `keepUsersLoggedInFor` - Время сессии (24h)


## Разработка

### Локальная разработка backend

```bash
cd backend
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt
export DB_HOST=localhost
export DEX_ISSUER=https://dex.127.0.0.1.sslip.io/

python main.py
```
Для удобной локальной разработки без настройки OIDC/Dex есть режим разработки.
```bash
export INSECURE_DEV_MODE=true
export INSECURE_DEV_EMAIL=developer@example.com
```
#### Что происходит в режиме разработки

- **Отключается проверка JWT токенов** - не требуется настройка Dex или OIDC
- **Используется фиксированный email** - задается через переменную `INSECURE_DEV_EMAIL`
- **Логирование** - в консоли будет выводиться сообщение о том, какой email используется

**Никогда не используйте INSECURE_DEV_MODE=true в продакшене!** Это отключает всю аутентификацию.

### Локальная разработка frontend

```bash
cd frontend
npm install
npm run dev
```

Frontend будет доступен на `http://localhost:5173` с проксированием API на `http://localhost:8000`


### Ошибка "User not found in database"

Убедитесь, что email пользователя из Dex совпадает с email в таблице `users` в PostgreSQL.

### JWT валидация не работает

Проверьте:
1. Доступность Dex JWKS endpoint: `https://dex.127.0.0.1.sslip.io/keys`
2. Переменную окружения `DEX_ISSUER` в backend
3. Логи backend для деталей ошибки

## Дополнительная настройка

### Изменение тестовых пользователей

Отредактируйте `db/init.sql` или `k8s/postgres.yaml` (ConfigMap `postgres-init`), затем:

```bash
kubectl delete pod -n navigator-demo -l app=postgres
```

### Использование собственного домена

Измените `applicationDomain` в `k8s/dex-authenticator.yaml` и `host` в `k8s/ingress.yaml`

### Production deployment

Для production окружения:
1. Используйте secrets для паролей БД
3. Включите TLS сертификаты
4. Настройте resource limits
5. Добавьте HorizontalPodAutoscaler
6. Используйте внешний PostgreSQL
