912 lines
24 KiB
Markdown
912 lines
24 KiB
Markdown
# Magos - Схема базы данных
|
||
|
||
---
|
||
|
||
## Обзор
|
||
|
||
Magos работает с PostgreSQL базой данных `waf_info`, которая содержит конфигурации WAF платформы. Программа использует 5 основных таблиц для получения информации о хостах, клиентах, приложениях и backend серверах.
|
||
|
||
### Используемые таблицы
|
||
|
||
1. **instances** - информация о хостах/серверах
|
||
2. **client_info** - данные клиентов и контейнеров
|
||
3. **apps_settings** - настройки приложений и кастомные директивы
|
||
4. **origins** - backend серверы (получаются через REST API)
|
||
5. **aliases** - дополнительные домены (получаются через REST API)
|
||
6. **ips** - IP адреса для WAF и antibot сетей
|
||
|
||
---
|
||
|
||
## Подключение к БД
|
||
|
||
### Параметры подключения
|
||
|
||
```bash
|
||
DB_USER=login
|
||
DB_PASSWORD=password
|
||
DB_NAME=waf_info
|
||
DB_PORT=5432
|
||
PRIMARY_DB_HOST=10.10.10.8
|
||
SECONDARY_DB_HOST=10.10.10.5
|
||
```
|
||
|
||
### Failover логика
|
||
|
||
1. Попытка подключения к Primary DB (10.10.10.8)
|
||
2. Если неудача → подключение к Secondary DB (10.10.10.5)
|
||
3. Если обе недоступны → программа останавливается
|
||
|
||
**Функция:** `connectToDB()`
|
||
|
||
---
|
||
|
||
## Таблица: instances
|
||
|
||
### Назначение
|
||
|
||
Хранит информацию о хостах/серверах в кластере PTAF.
|
||
|
||
### Структура
|
||
|
||
| Поле | Тип | Описание | Пример |
|
||
|------|-----|----------|--------|
|
||
| `hostname` | TEXT | Hostname сервера | `host01.example.com` |
|
||
| `instance` | TEXT | Идентификатор инстанса | `waf-prod-01` |
|
||
|
||
### Используемые запросы
|
||
|
||
#### 1. Получение instance по hostname
|
||
|
||
```sql
|
||
SELECT instance
|
||
FROM instances
|
||
WHERE hostname = $1;
|
||
```
|
||
|
||
**Функция:** `getInstanceByHostname(hostname string)`
|
||
|
||
**Использование:** При старте программы для определения какой это инстанс.
|
||
|
||
**Пример:**
|
||
```go
|
||
hostname := "host01.example.com"
|
||
instance, err := getInstanceByHostname(db, hostname)
|
||
// instance = "waf-prod-01"
|
||
```
|
||
|
||
---
|
||
|
||
#### 2. Проверка принадлежности хоста к инстансу
|
||
|
||
```sql
|
||
SELECT COUNT(*)
|
||
FROM instances
|
||
WHERE hostname = $1 AND instance = $2;
|
||
```
|
||
|
||
**Функция:** `checkHostBelongsToInstance(hostname, instance string)`
|
||
|
||
**Использование:** Валидация что хост принадлежит данному инстансу.
|
||
|
||
**Пример:**
|
||
```go
|
||
hostname := "host01.example.com"
|
||
instance := "waf-prod-01"
|
||
err := checkHostBelongsToInstance(db, hostname, instance)
|
||
// err == nil если хост принадлежит инстансу
|
||
```
|
||
|
||
---
|
||
|
||
### Примеры данных
|
||
|
||
```sql
|
||
INSERT INTO instances (hostname, instance) VALUES
|
||
('host01.example.com', 'waf-prod-01'),
|
||
('host02.example.com', 'waf-prod-01'),
|
||
('host03.example.com', 'waf-prod-02');
|
||
```
|
||
|
||
---
|
||
|
||
## Таблица: client_info
|
||
|
||
### Назначение
|
||
|
||
Хранит информацию о клиентах: количество контейнеров, привязка к инстансу.
|
||
|
||
### Структура
|
||
|
||
| Поле | Тип | Описание | Пример |
|
||
|------|-----|----------|--------|
|
||
| `client_title` | TEXT | Идентификатор клиента | `CLIENT001` |
|
||
| `containers_count` | INTEGER | Количество контейнеров | `3` |
|
||
| `ptaf_config` | TEXT | Конфигурация PTAF (JSON) | `{"key": "value"}` |
|
||
| `fluent_bit_port` | INTEGER | Порт Fluent Bit | `24224` |
|
||
| `waf_instance` | TEXT | Instance для apps_settings | `waf-prod-01` |
|
||
|
||
### Используемые запросы
|
||
|
||
#### 1. Получение клиентов по instance
|
||
|
||
```sql
|
||
SELECT
|
||
containers_count,
|
||
ptaf_config,
|
||
client_title,
|
||
fluent_bit_port,
|
||
waf_instance
|
||
FROM client_info
|
||
WHERE waf_instance = $1;
|
||
```
|
||
|
||
**Функция:** `getClientInfoByInstance(instance string)`
|
||
|
||
**Использование:** Получение всех клиентов для данного инстанса.
|
||
|
||
**Пример:**
|
||
```go
|
||
instance := "waf-prod-01"
|
||
clients, err := getClientInfoByInstance(db, instance)
|
||
// clients = [{ContainersCount: 3, ClientTitle: "CLIENT001", ...}, ...]
|
||
```
|
||
|
||
---
|
||
|
||
#### 2. Получение клиента по client_title
|
||
|
||
```sql
|
||
SELECT
|
||
containers_count,
|
||
ptaf_config,
|
||
client_title,
|
||
fluent_bit_port,
|
||
waf_instance
|
||
FROM client_info
|
||
WHERE client_title = $1;
|
||
```
|
||
|
||
**Функция:** `getClientInfoByClientTitle(clientTitle string)`
|
||
|
||
**Использование:** Получение информации о конкретном клиенте.
|
||
|
||
---
|
||
|
||
### Примеры данных
|
||
|
||
```sql
|
||
INSERT INTO client_info
|
||
(client_title, containers_count, ptaf_config, fluent_bit_port, waf_instance)
|
||
VALUES
|
||
('CLIENT001', 3, '{"version": "1.0"}', 24224, 'waf-prod-01'),
|
||
('CLIENT002', 5, '{"version": "1.0"}', 24225, 'waf-prod-01'),
|
||
('CLIENT003', 2, '{"version": "1.0"}', 24226, 'waf-prod-02');
|
||
```
|
||
|
||
---
|
||
|
||
### Ключевое поле: containers_count
|
||
|
||
**Назначение:** Определяет сколько Docker контейнеров нужно создать для клиента.
|
||
|
||
**Логика:**
|
||
- `containers_count = 3` → создать ptaf_client_001, ptaf_client_002, ptaf_client_003
|
||
- При увеличении → создаются новые контейнеры
|
||
- При уменьшении → лишние контейнеры помечаются на graceful shutdown (90s)
|
||
|
||
**Пример изменения:**
|
||
```sql
|
||
-- Увеличить до 5 контейнеров
|
||
UPDATE client_info
|
||
SET containers_count = 5
|
||
WHERE client_title = 'CLIENT001';
|
||
|
||
-- Manager автоматически создаст ptaf_client_004 и ptaf_client_005
|
||
```
|
||
|
||
---
|
||
|
||
## Таблица: apps_settings
|
||
|
||
### Назначение
|
||
|
||
Основная таблица с настройками приложений и кастомными директивами Nginx/Angie.
|
||
|
||
### Структура
|
||
|
||
| Поле | Тип | Описание | Значение по умолчанию |
|
||
|------|-----|----------|----------------------|
|
||
| `l7resourceid` | INTEGER | ID ресурса | Первичный ключ |
|
||
| `client_title` | TEXT | Клиент (FK) | `CLIENT001` |
|
||
| `waf_enabled` | BOOLEAN | WAF включен | `true` |
|
||
| `sni` | INTEGER | SNI режим (0=keepalive on, 1=keepalive off) | `0` |
|
||
| `custom_input_http_ports` | INTEGER[] | HTTP порты для прослушивания | `{80, 8080}` |
|
||
| `custom_input_https_ports` | INTEGER[] | HTTPS порты для прослушивания | `{443, 8443}` |
|
||
| `custom_output_http_ports` | INTEGER[] | HTTP порты к backend | `{80}` |
|
||
| `custom_output_https_ports` | INTEGER[] | HTTPS порты к backend | `{443}` |
|
||
| `upstream_angie_custom` | TEXT | Кастомные upstream директивы (Angie) | `NULL` |
|
||
| `upstream_nginx_custom` | TEXT | Кастомные upstream директивы (Nginx) | `NULL` |
|
||
| `server_angie_custom` | TEXT | Полная замена server блока (Angie) | `NULL` |
|
||
| `server_nginx_custom` | TEXT | Полная замена server блока (Nginx) | `NULL` |
|
||
| `server_directives_angie_custom` | TEXT | Кастомные server директивы (Angie) | `NULL` |
|
||
| `server_directives_nginx_custom` | TEXT | Кастомные server директивы (Nginx) | `NULL` |
|
||
| `location_angie_custom` | TEXT | Кастомные location блоки (Angie) | `NULL` |
|
||
| `location_nginx_custom` | TEXT | Кастомные location блоки (Nginx) | `NULL` |
|
||
|
||
---
|
||
|
||
### Используемые запросы
|
||
|
||
#### Получение настроек по client_title
|
||
|
||
```sql
|
||
SELECT
|
||
l7resourceid,
|
||
waf_enabled,
|
||
custom_input_http_ports,
|
||
custom_input_https_ports,
|
||
custom_output_http_ports,
|
||
custom_output_https_ports,
|
||
upstream_angie_custom,
|
||
server_nginx_custom,
|
||
server_angie_custom,
|
||
client_title,
|
||
upstream_nginx_custom,
|
||
location_angie_custom,
|
||
location_nginx_custom,
|
||
server_directives_angie_custom,
|
||
server_directives_nginx_custom,
|
||
sni
|
||
FROM apps_settings
|
||
WHERE client_title = $1
|
||
ORDER BY l7resourceid ASC;
|
||
```
|
||
|
||
**Функция:** `getAppsSettingsByClientTitle(clientTitle string)`
|
||
|
||
**Использование:** Получение всех настроек приложений для клиента.
|
||
|
||
---
|
||
|
||
### Примеры данных
|
||
|
||
```sql
|
||
INSERT INTO apps_settings
|
||
(l7resourceid, client_title, waf_enabled, sni,
|
||
custom_input_http_ports, custom_input_https_ports,
|
||
custom_output_http_ports, custom_output_https_ports)
|
||
VALUES
|
||
(12323, 'CLIENT001', true, 0, '{80}', '{443}', '{80}', '{443}'),
|
||
(12324, 'CLIENT001', true, 0, '{80,8080}', '{443,8443}', '{80}', '{443}'),
|
||
(15000, 'CLIENT002', true, 0, '{80}', '{443}', '{80}', '{443}');
|
||
```
|
||
|
||
---
|
||
|
||
### Кастомные поля (подробно)
|
||
|
||
#### upstream_angie_custom / upstream_nginx_custom
|
||
|
||
**Режим:** REPLACE (полная замена keepalive директив)
|
||
|
||
**NULL значение:**
|
||
```nginx
|
||
upstream backend {
|
||
server 127.0.0.1:21000;
|
||
|
||
# Default upstream directives
|
||
keepalive 60;
|
||
keepalive_timeout 70s;
|
||
}
|
||
```
|
||
|
||
**НЕ NULL значение:**
|
||
```nginx
|
||
upstream backend {
|
||
server 127.0.0.1:21000;
|
||
|
||
# Custom upstream directives (replace defaults)
|
||
keepalive 200;
|
||
keepalive_timeout 90s;
|
||
least_conn;
|
||
}
|
||
```
|
||
|
||
**Пример SQL:**
|
||
```sql
|
||
-- Изменить балансировку на least_conn
|
||
UPDATE apps_settings
|
||
SET upstream_angie_custom = 'keepalive 60;
|
||
keepalive_timeout 70s;
|
||
least_conn;'
|
||
WHERE l7resourceid = 12323;
|
||
|
||
-- Вернуть дефолты
|
||
UPDATE apps_settings
|
||
SET upstream_angie_custom = NULL
|
||
WHERE l7resourceid = 12323;
|
||
```
|
||
|
||
---
|
||
|
||
#### server_directives_angie_custom / server_directives_nginx_custom
|
||
|
||
**Режим:** REPLACE (замена else блока в server)
|
||
|
||
**NULL значение:**
|
||
```nginx
|
||
server {
|
||
listen 443 ssl;
|
||
|
||
# Default directives
|
||
keepalive_timeout 80s;
|
||
send_timeout 60s;
|
||
proxy_connect_timeout 60s;
|
||
proxy_read_timeout 120s;
|
||
proxy_send_timeout 120s;
|
||
|
||
large_client_header_buffers 4 128k;
|
||
proxy_buffers 4 32k;
|
||
proxy_buffer_size 16k;
|
||
proxy_busy_buffers_size 32k;
|
||
}
|
||
```
|
||
|
||
**НЕ NULL значение:**
|
||
```nginx
|
||
server {
|
||
listen 443 ssl;
|
||
|
||
# Custom directives (replace defaults)
|
||
keepalive_timeout 120s;
|
||
client_max_body_size 100m;
|
||
# Нужно указать ВСЕ директивы, включая буферы!
|
||
}
|
||
```
|
||
|
||
**Пример SQL:**
|
||
```sql
|
||
-- Увеличить таймауты
|
||
UPDATE apps_settings
|
||
SET server_directives_angie_custom = 'keepalive_timeout 120s;
|
||
send_timeout 90s;
|
||
proxy_connect_timeout 90s;
|
||
proxy_read_timeout 180s;
|
||
proxy_send_timeout 180s;
|
||
|
||
large_client_header_buffers 4 128k;
|
||
proxy_buffers 4 32k;
|
||
proxy_buffer_size 16k;'
|
||
WHERE l7resourceid = 12323;
|
||
```
|
||
|
||
---
|
||
|
||
#### server_angie_custom / server_nginx_custom
|
||
|
||
**Режим:** SERVER_BLOCK (полная замена всего server блока)
|
||
|
||
**NULL значение:** Используется стандартный шаблон server блока
|
||
|
||
**НЕ NULL значение:** Полная замена server блока
|
||
|
||
**Пример SQL:**
|
||
```sql
|
||
-- Создать полностью кастомный server блок
|
||
UPDATE apps_settings
|
||
SET server_angie_custom = 'server {
|
||
listen 9999;
|
||
server_name special.example.com;
|
||
|
||
location / {
|
||
return 200 "Custom response";
|
||
}
|
||
}'
|
||
WHERE l7resourceid = 12323;
|
||
```
|
||
|
||
---
|
||
|
||
#### location_angie_custom / location_nginx_custom
|
||
|
||
**Режим:** APPEND (добавление к дефолтному location)
|
||
|
||
**NULL значение:** Только стандартный `location / { proxy_pass }`
|
||
|
||
**НЕ NULL значение:** Добавляются дополнительные location блоки
|
||
|
||
**Пример SQL:**
|
||
```sql
|
||
-- Добавить location для API
|
||
UPDATE apps_settings
|
||
SET location_nginx_custom = 'location /api {
|
||
proxy_pass http://api.backend.com;
|
||
proxy_set_header X-API-Key secret;
|
||
}
|
||
|
||
location /static {
|
||
alias /var/www/static;
|
||
}'
|
||
WHERE l7resourceid = 12323;
|
||
```
|
||
|
||
---
|
||
|
||
#### sni (Server Name Indication)
|
||
|
||
**Значения:**
|
||
- `0` - Keepalive ВКЛЮЧЕН (дефолт)
|
||
- `1` - Keepalive ОТКЛЮЧЕН
|
||
|
||
**Когда sni = 1:**
|
||
- Директивы `keepalive` и `keepalive_timeout` НЕ добавляются в upstream
|
||
- Используется для SNI passthrough (прямая передача без терминации SSL)
|
||
|
||
**Пример SQL:**
|
||
```sql
|
||
-- Отключить keepalive для SNI passthrough
|
||
UPDATE apps_settings
|
||
SET sni = 1
|
||
WHERE l7resourceid = 12323;
|
||
```
|
||
|
||
---
|
||
|
||
#### custom_input_*_ports и custom_output_*_ports
|
||
|
||
**custom_input_http_ports / custom_input_https_ports:**
|
||
- Порты на которых Angie и Nginx контейнеры будут слушать
|
||
- Angie слушает на этих портах (80, 443, 8080, 8443)
|
||
- Nginx контейнеры слушают на этих же портах
|
||
|
||
**custom_output_http_ports / custom_output_https_ports:**
|
||
- Порты к которым Nginx контейнеры будут проксировать на backend
|
||
- Обычно {80} для HTTP и {443} для HTTPS
|
||
- Могут быть нестандартные порты (8080, 8443)
|
||
|
||
**Пример:**
|
||
```sql
|
||
-- Приложение слушает на портах 80, 8080 (HTTP) и 443, 8443 (HTTPS)
|
||
-- Backend работает на порту 443
|
||
UPDATE apps_settings
|
||
SET
|
||
custom_input_http_ports = '{80, 8080}',
|
||
custom_input_https_ports = '{443, 8443}',
|
||
custom_output_http_ports = '{80}',
|
||
custom_output_https_ports = '{443}'
|
||
WHERE l7resourceid = 12323;
|
||
```
|
||
|
||
**Результат:**
|
||
```nginx
|
||
# Angie
|
||
server {
|
||
listen 80; # custom_input_http_ports[0]
|
||
listen 8080; # custom_input_http_ports[1]
|
||
listen 443 ssl; # custom_input_https_ports[0]
|
||
listen 8443 ssl; # custom_input_https_ports[1]
|
||
}
|
||
|
||
# Nginx upstream
|
||
upstream backend {
|
||
server 185.22.65.148:443; # custom_output_https_ports[0]
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## Таблица: ips
|
||
|
||
### Назначение
|
||
|
||
Хранит IP адреса для WAF и antibot сетей (белые списки).
|
||
|
||
### Структура
|
||
|
||
| Поле | Тип | Описание |
|
||
|------|-----|----------|
|
||
| `antibot_networks` | TEXT[] | IP сети для antibot |
|
||
| `waf_networks` | TEXT[] | IP сети для WAF |
|
||
|
||
### Используемые запросы
|
||
|
||
```sql
|
||
SELECT antibot_networks, waf_networks
|
||
FROM ips;
|
||
```
|
||
|
||
**Функция:** `loadIPsFromDB()`
|
||
|
||
**Использование:** При старте программы для загрузки IP сетей.
|
||
|
||
**Пример данных:**
|
||
```sql
|
||
INSERT INTO ips (antibot_networks, waf_networks) VALUES
|
||
(
|
||
'{172.16.0.0/12, 10.0.0.0/8}',
|
||
'{172.16.0.0/12, 10.100.0.0/16}'
|
||
);
|
||
```
|
||
|
||
**Использование в конфигах:**
|
||
```nginx
|
||
server {
|
||
# Доверенные IP для получения реального IP клиента
|
||
set_real_ip_from 172.16.0.0/12;
|
||
set_real_ip_from 10.100.0.0/16;
|
||
real_ip_header X-Forwarded-For;
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## REST API (origins и aliases)
|
||
|
||
### Origins (Backend серверы)
|
||
|
||
**Не хранятся в БД**, получаются через REST API.
|
||
|
||
**Эндпоинт:** `/api/waf-proxy/get-apps-and-resourses`
|
||
|
||
**Функция:** `makeAPIRequest()`, `getResourceDataFromCache()`
|
||
|
||
**Пример ответа:**
|
||
```json
|
||
{
|
||
"data": {
|
||
"result": {
|
||
"items": [
|
||
{
|
||
"id": 1,
|
||
"ip": "185.22.65.148",
|
||
"weight": 100,
|
||
"mode": "active",
|
||
"comment": "Primary backend"
|
||
},
|
||
{
|
||
"id": 2,
|
||
"ip": "185.22.65.149",
|
||
"weight": 50,
|
||
"mode": "backup",
|
||
"comment": "Backup backend"
|
||
}
|
||
]
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
**Использование в конфигах:**
|
||
```nginx
|
||
upstream backend {
|
||
server 185.22.65.148:443 weight=100;
|
||
server 185.22.65.149:443 weight=50 backup;
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### Aliases (Дополнительные домены)
|
||
|
||
**Не хранятся в БД**, получаются через REST API.
|
||
|
||
**Эндпоинт:** `/api/waf-proxy/get-apps-and-resourses`
|
||
|
||
**Пример ответа:**
|
||
```json
|
||
{
|
||
"data": {
|
||
"result": {
|
||
"items": [
|
||
{
|
||
"id": 1,
|
||
"alias": "www.example.com"
|
||
},
|
||
{
|
||
"id": 2,
|
||
"alias": "app.example.com"
|
||
}
|
||
]
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
**Использование в конфигах:**
|
||
```nginx
|
||
server {
|
||
listen 443 ssl;
|
||
server_name example.com www.example.com app.example.com;
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## Связи между таблицами
|
||
|
||
```
|
||
instances
|
||
↓ (hostname → instance)
|
||
client_info (waf_instance)
|
||
↓ (client_title)
|
||
apps_settings (client_title)
|
||
↓ (l7resourceid через API)
|
||
Origins (от REST API)
|
||
Aliases (от REST API)
|
||
```
|
||
|
||
**Поток данных:**
|
||
|
||
1. Program запускается на хосте с hostname = `host01.example.com`
|
||
2. Запрос к `instances` → получаем `instance = "waf-prod-01"`
|
||
3. Запрос к `client_info` WHERE `waf_instance = "waf-prod-01"` → получаем клиентов
|
||
4. Для каждого клиента запрос к `apps_settings` WHERE `client_title = "CLIENT001"`
|
||
5. Для каждого ресурса API запрос → получаем origins и aliases
|
||
6. Генерируем конфиги на основе всех данных
|
||
|
||
---
|
||
|
||
## Примеры типичных запросов
|
||
|
||
### Получить все ресурсы клиента
|
||
|
||
```sql
|
||
SELECT
|
||
a.l7resourceid,
|
||
a.custom_input_https_ports,
|
||
a.upstream_angie_custom,
|
||
c.containers_count
|
||
FROM apps_settings a
|
||
JOIN client_info c ON a.client_title = c.client_title
|
||
WHERE a.client_title = 'CLIENT001'
|
||
ORDER BY a.l7resourceid;
|
||
```
|
||
|
||
---
|
||
|
||
### Изменить количество контейнеров
|
||
|
||
```sql
|
||
-- Увеличить до 5
|
||
UPDATE client_info
|
||
SET containers_count = 5
|
||
WHERE client_title = 'CLIENT001';
|
||
|
||
-- Проверка
|
||
SELECT client_title, containers_count
|
||
FROM client_info
|
||
WHERE client_title = 'CLIENT001';
|
||
```
|
||
|
||
---
|
||
|
||
### Добавить кастомную балансировку
|
||
|
||
```sql
|
||
UPDATE apps_settings
|
||
SET upstream_nginx_custom = 'keepalive 60;
|
||
keepalive_timeout 70s;
|
||
least_conn;'
|
||
WHERE l7resourceid = 12323;
|
||
|
||
-- Проверка
|
||
SELECT l7resourceid, upstream_nginx_custom
|
||
FROM apps_settings
|
||
WHERE l7resourceid = 12323;
|
||
```
|
||
|
||
---
|
||
|
||
### Включить SNI passthrough
|
||
|
||
```sql
|
||
UPDATE apps_settings
|
||
SET sni = 1
|
||
WHERE l7resourceid = 12323;
|
||
|
||
-- Проверка
|
||
SELECT l7resourceid, sni
|
||
FROM apps_settings
|
||
WHERE sni = 1;
|
||
```
|
||
|
||
---
|
||
|
||
### Добавить дополнительные порты
|
||
|
||
```sql
|
||
UPDATE apps_settings
|
||
SET
|
||
custom_input_https_ports = '{443, 8443, 9443}',
|
||
custom_output_https_ports = '{443, 8443, 9443}'
|
||
WHERE l7resourceid = 12323;
|
||
|
||
-- Проверка
|
||
SELECT l7resourceid, custom_input_https_ports, custom_output_https_ports
|
||
FROM apps_settings
|
||
WHERE l7resourceid = 12323;
|
||
```
|
||
|
||
---
|
||
|
||
## Индексы (рекомендуемые)
|
||
|
||
```sql
|
||
-- Для быстрого поиска по hostname
|
||
CREATE INDEX idx_instances_hostname ON instances(hostname);
|
||
|
||
-- Для быстрого поиска клиентов по instance
|
||
CREATE INDEX idx_client_info_waf_instance ON client_info(waf_instance);
|
||
CREATE INDEX idx_client_info_client_title ON client_info(client_title);
|
||
|
||
-- Для быстрого поиска настроек по client_title
|
||
CREATE INDEX idx_apps_settings_client_title ON apps_settings(client_title);
|
||
CREATE INDEX idx_apps_settings_l7resourceid ON apps_settings(l7resourceid);
|
||
```
|
||
|
||
---
|
||
|
||
## Миграции и изменения схемы
|
||
|
||
### Добавление нового кастомного поля
|
||
|
||
```sql
|
||
-- Добавить новое поле для header манипуляций
|
||
ALTER TABLE apps_settings
|
||
ADD COLUMN headers_custom TEXT DEFAULT NULL;
|
||
|
||
-- Обновить код для чтения этого поля
|
||
```
|
||
|
||
---
|
||
|
||
### Изменение типа поля
|
||
|
||
```sql
|
||
-- Изменить тип sni на boolean (если сейчас integer)
|
||
ALTER TABLE apps_settings
|
||
ALTER COLUMN sni TYPE BOOLEAN
|
||
USING (sni::integer = 0);
|
||
```
|
||
|
||
---
|
||
|
||
## Best Practices
|
||
|
||
### 1. NULL vs пустая строка
|
||
|
||
**Правильно:**
|
||
```sql
|
||
UPDATE apps_settings
|
||
SET upstream_angie_custom = NULL -- NULL для дефолтов
|
||
WHERE l7resourceid = 12323;
|
||
```
|
||
|
||
**Неправильно:**
|
||
```sql
|
||
UPDATE apps_settings
|
||
SET upstream_angie_custom = '' -- Пустая строка может вызвать ошибки
|
||
WHERE l7resourceid = 12323;
|
||
```
|
||
|
||
---
|
||
|
||
### 2. Массивы портов
|
||
|
||
**Правильно:**
|
||
```sql
|
||
UPDATE apps_settings
|
||
SET custom_input_https_ports = '{443, 8443}' -- PostgreSQL array
|
||
WHERE l7resourceid = 12323;
|
||
```
|
||
|
||
**Неправильно:**
|
||
```sql
|
||
UPDATE apps_settings
|
||
SET custom_input_https_ports = '443,8443' -- Строка, не массив
|
||
WHERE l7resourceid = 12323;
|
||
```
|
||
|
||
---
|
||
|
||
### 3. Многострочные кастомные директивы
|
||
|
||
**Правильно:**
|
||
```sql
|
||
UPDATE apps_settings
|
||
SET server_directives_angie_custom = 'keepalive_timeout 80s;
|
||
send_timeout 60s;
|
||
proxy_buffers 4 32k;'
|
||
WHERE l7resourceid = 12323;
|
||
```
|
||
|
||
**Также правильно (с экранированием):**
|
||
```sql
|
||
UPDATE apps_settings
|
||
SET server_directives_angie_custom = E'keepalive_timeout 80s;\nsend_timeout 60s;'
|
||
WHERE l7resourceid = 12323;
|
||
```
|
||
|
||
---
|
||
|
||
## Мониторинг БД
|
||
|
||
### Проверка соединения
|
||
|
||
```sql
|
||
-- Проверить активные соединения
|
||
SELECT
|
||
datname,
|
||
usename,
|
||
client_addr,
|
||
state,
|
||
query_start
|
||
FROM pg_stat_activity
|
||
WHERE datname = 'waf_info';
|
||
```
|
||
|
||
---
|
||
|
||
### Проверка данных
|
||
|
||
```sql
|
||
-- Количество клиентов на каждом instance
|
||
SELECT waf_instance, COUNT(*) as clients_count
|
||
FROM client_info
|
||
GROUP BY waf_instance;
|
||
|
||
-- Количество ресурсов на клиента
|
||
SELECT client_title, COUNT(*) as resources_count
|
||
FROM apps_settings
|
||
GROUP BY client_title;
|
||
|
||
-- Клиенты с кастомными upstream директивами
|
||
SELECT client_title, l7resourceid
|
||
FROM apps_settings
|
||
WHERE upstream_angie_custom IS NOT NULL
|
||
OR upstream_nginx_custom IS NOT NULL;
|
||
```
|
||
|
||
---
|
||
|
||
## Резервное копирование
|
||
|
||
```bash
|
||
# Дамп всей БД
|
||
pg_dump -h 10.100.10.8 -U install -d waf_info > waf_info_backup.sql
|
||
|
||
# Дамп только структуры
|
||
pg_dump -h 10.100.10.8 -U install -d waf_info --schema-only > schema.sql
|
||
|
||
# Дамп только данных
|
||
pg_dump -h 10.100.10.8 -U install -d waf_info --data-only > data.sql
|
||
|
||
# Восстановление
|
||
psql -h 10.100.10.8 -U install -d waf_info < waf_info_backup.sql
|
||
```
|
||
|
||
---
|
||
|
||
## Итого
|
||
|
||
### Основные таблицы
|
||
|
||
| Таблица | Записей (примерно) | Частота изменений |
|
||
|---------|-------------------|-------------------|
|
||
| instances | 10-50 | Редко (при добавлении хостов) |
|
||
| client_info | 50-500 | Редко (при добавлении клиентов) |
|
||
| apps_settings | 500-5000 | Часто (изменение настроек) |
|
||
| ips | 1 | Очень редко |
|
||
|
||
### Ключевые связи
|
||
|
||
- `instances.instance` → `client_info.waf_instance`
|
||
- `client_info.client_title` → `apps_settings.client_title`
|
||
- `apps_settings.l7resourceid` → REST API (origins, aliases)
|
||
|
||
### Кастомизация
|
||
|
||
Все кастомные поля в `apps_settings`:
|
||
- 8 полей для кастомных директив
|
||
- 4 режима: REPLACE (upstream, server_directives), SERVER_BLOCK, APPEND (location)
|
||
- NULL = дефолты, NOT NULL = кастом
|