magos/DATABASE_SCHEMA.md

23 KiB
Executable file
Raw Blame History

Magos - Схема базы данных


Обзор

Magos работает с PostgreSQL базой данных, которая содержит конфигурации WAF платформы. Программа использует несколько основных таблиц для получения информации о хостах, клиентах, приложениях и backend серверах.

Используемые таблицы

  1. instances_new - информация о хостах/серверах
  2. client_info - данные клиентов и контейнеров
  3. apps_settings - настройки приложений и кастомные директивы
  4. sp_info - кэш данных из API (origins, aliases)
  5. manual_info - ручные данные (альтернатива API)
  6. ips - IP адреса для WAF и antibot сетей

Подключение к БД

Параметры подключения

DB_USER=login
DB_PASSWORD=password
DB_NAME=waf_info
DB_PORT=5432
PRIMARY_DB_HOST=10.100.10.8
SECONDARY_DB_HOST=10.100.13.5

Failover логика

  1. Попытка подключения к Primary DB
  2. Если неудача → подключение к Secondary DB
  3. Если обе недоступны → программа останавливается

Функция: connectToDB()


Таблица: instances_new

Назначение

Хранит информацию о хостах/серверах в кластере WAF. Таблица instances (старая) переименована в instances_old и не используется — все запросы идут к instances_new.

Структура

Поле Тип Описание Пример
hostname TEXT Hostname сервера host01.example.com
instance TEXT Идентификатор инстанса waf-prod-01

Используемые запросы

Получение instances по hostname

SELECT instance
FROM instances_new
WHERE hostname = $1;

Функция: getInstancesByHostname(hostname string)

Один хост может принадлежать нескольким instances.

Проверка принадлежности хоста к инстансу

SELECT COUNT(*)
FROM instances_new
WHERE hostname = $1 AND instance = $2;

Функция: checkHostBelongsToInstance(hostname, instance string)


Таблица: client_info

Назначение

Хранит информацию о клиентах: количество контейнеров, Docker-образ, режим отладки и привязка к инстансу.

Структура

Поле Тип Описание Пример
id SERIAL Первичный ключ (автоинкремент) 1
client_title TEXT Идентификатор клиента CLIENT001
parent_client_title TEXT Родительский клиент (для grafana_gen) NULL
containers_count INTEGER Количество контейнеров (0 = drain всех) 3
ptaf_config TEXT Строка подключения к PTAF-серверу {...}
fluent_bit_port INTEGER Порт Fluent Bit 24224
waf_instance TEXT Instance для привязки к хосту waf-prod-01
docker_image TEXT Docker-образ (переопределяет глобальный) ptaf-core-nginx-agent:release-4.3.1...
docker_image_download TEXT URL для скачивания tar-архива образа https://...
debug BOOLEAN Режим отладки false
shm_size INTEGER Размер /dev/shm в GB 1
ptaf_fallback_code TEXT Код ответа ptaf_fallback: число или 'pass' 418
sp_antiddos BOOLEAN Использовать антиддос сети в set_real_ip true
real_ip_networks INET[] Кастомные сети для set_real_ip (если sp_antiddos=false) {10.0.0.0/8}
worker_processes INTEGER Количество worker процессов nginx 4
one_container BOOLEAN Все SID в один контейнер true
sid_block TEXT Блоки SID для разбивки: {sid1,sid2}{sid3} NULL

Используемые запросы

Получение клиентов по instance

SELECT
    containers_count,
    ptaf_config,
    client_title,
    fluent_bit_port,
    waf_instance,
    docker_image,
    docker_image_download,
    debug,
    shm_size,
    ptaf_fallback_code,
    sp_antiddos,
    real_ip_networks,
    worker_processes,
    one_container,
    sid_block
FROM client_info
WHERE waf_instance = $1;

Функция: getClientInfoByInstance(instance string)

Получение клиента по client_title

SELECT
    containers_count,
    ptaf_config,
    client_title,
    fluent_bit_port,
    waf_instance,
    docker_image,
    docker_image_download,
    debug,
    shm_size,
    ptaf_fallback_code,
    sp_antiddos,
    real_ip_networks,
    worker_processes,
    one_container,
    sid_block
FROM client_info
WHERE client_title = $1;

Функция: getClientInfoByClientTitle(clientTitle string)

Миграции

-- Переименование PK (таблица была переименована из nodes в client_info)
ALTER TABLE client_info DROP CONSTRAINT nodes_pkey;
ALTER TABLE client_info ADD COLUMN id SERIAL PRIMARY KEY;

-- Добавление parent_client_title для grafana_gen
ALTER TABLE client_info
    ADD COLUMN IF NOT EXISTS parent_client_title TEXT DEFAULT NULL;

ALTER TABLE client_info
    ADD COLUMN IF NOT EXISTS docker_image TEXT DEFAULT NULL;

ALTER TABLE client_info
    ADD COLUMN IF NOT EXISTS docker_image_download TEXT DEFAULT NULL;

ALTER TABLE client_info
    ADD COLUMN IF NOT EXISTS debug BOOLEAN DEFAULT FALSE;

ALTER TABLE client_info
    ADD COLUMN IF NOT EXISTS shm_size INTEGER DEFAULT 1;

ALTER TABLE client_info
    ADD COLUMN IF NOT EXISTS ptaf_fallback_code TEXT DEFAULT '418';

ALTER TABLE client_info
    ADD COLUMN IF NOT EXISTS sp_antiddos BOOLEAN DEFAULT TRUE;

ALTER TABLE client_info
    ADD COLUMN IF NOT EXISTS real_ip_networks INET[] DEFAULT NULL;

ALTER TABLE client_info
    ADD COLUMN IF NOT EXISTS worker_processes INTEGER DEFAULT 4;

ALTER TABLE client_info
    ADD COLUMN IF NOT EXISTS one_container BOOLEAN DEFAULT TRUE;

ALTER TABLE client_info
    ADD COLUMN IF NOT EXISTS sid_block TEXT DEFAULT NULL;

Ключевые поля

containers_count

  • containers_count = 3 → создать ptaf_client_001, ptaf_client_002, ptaf_client_003
  • При увеличении → новые контейнеры добавляются, существующие не трогаются
  • При уменьшении → лишние контейнеры помечаются на graceful drain (90с)
  • containers_count = 0 → все контейнеры и Angie-конфиг помечаются на drain

docker_image / docker_image_download

Если заполнены — используются вместо глобальных настроек DOCKER_IMAGE и DOCKER_IMAGE_URL из magos.env. Позволяют иметь разные версии агента для разных клиентов.

debug

При true:

  • В docker-compose добавляются PTAF_DEBUG=True и ERROR_LOG_LEVEL=debug
  • В nginx.conf: PTAF_LOG_LEVEL=DEBUG, DEBUG=true, error_log stderr debug
  • В Angie server-блоки добавляется client_body_buffer_size 1m

shm_size

Размер разделяемой памяти /dev/shm для Docker-контейнера в гигабайтах. Результат в docker-compose: shm_size: '2gb'. Дефолт: 1.

ptaf_fallback_code

Код HTTP ответа который PTAF возвращает когда WAF-модуль недоступен. Записывается в блок http {} файла nginx.conf — применяется глобально для всех ресурсов контейнера.

UPDATE client_info SET ptaf_fallback_code = 'pass' WHERE client_title = 'CLIENT001';
UPDATE client_info SET ptaf_fallback_code = '503' WHERE client_title = 'CLIENT001';

worker_processes

Количество worker процессов nginx внутри контейнера. Изменение вызывает nginx -s reload без пересоздания контейнера. Дефолт: 4.

UPDATE client_info SET worker_processes = 8 WHERE client_title = 'CLIENT001';

one_container / sid_block

one_container = true (дефолт) — все SID клиента обслуживаются одним набором контейнеров. Стандартный режим.

one_container = false + заполненный sid_block — блочный режим. Каждый блок {} в sid_block создаёт отдельный набор контейнеров только со своими SID.

Формат sid_block: {sid1,sid2}{sid3}{sid4,sid5} — каждая пара фигурных скобок это один блок.

-- Три блока: первый с двумя SID, второй и третий с одним
UPDATE client_info
SET one_container = false,
    sid_block = '{10111,10231}{10112}{10113}'
WHERE client_title = 'CLIENT001';

Именование контейнеров в блочном режиме:

  • Блок 1 → {clientTitle}_block1_AZ3_hn01_a001
  • Блок 2 → {clientTitle}_block2_AZ3_hn01_a001

containers_count применяется к каждому блоку — если containers_count=2 и 3 блока → 6 контейнеров суммарно.

SID не указанные ни в одном блоке не обрабатываются.

sp_antiddos = true (дефолт) — в Angie используются антиддос сети из таблицы ips для set_real_ip_from.

sp_antiddos = false + непустой real_ip_networks — вместо антиддос сетей используются кастомные сети из real_ip_networks. WAF сети из ips при этом всегда присутствуют.

UPDATE client_info
SET sp_antiddos = false,
    real_ip_networks = '{10.0.0.0/8, 192.168.1.0/24}'
WHERE client_title = 'CLIENT001';

Таблица: apps_settings

Назначение

Основная таблица с настройками приложений и кастомными директивами Nginx/Angie.

Структура

Поле Тип Описание Значение по умолчанию
l7resourceid INTEGER ID ресурса Первичный ключ
client_title TEXT Клиент (FK)
waf_enabled BOOLEAN WAF включен true
waf_vendor TEXT Вендор: 'ptaf' или 'sw'
mode TEXT auto/manual/disabled auto
sni INTEGER SNI режим (0=keepalive on, 1=keepalive off) 0
ssl_enabled BOOLEAN SSL на HTTPS портах true
custom_input_http_ports INTEGER[] HTTP порты для прослушивания {80}
custom_input_https_ports INTEGER[] HTTPS порты для прослушивания {443}
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/SW) NULL
server_angie_custom TEXT Кастомный server блок (Angie) NULL
server_nginx_custom TEXT Кастомный server блок (Nginx/SW) NULL
server_directives_angie_custom TEXT Кастомные server директивы (Angie) NULL
server_directives_nginx_custom TEXT Кастомные server директивы (Nginx/SW) NULL
location_angie_custom TEXT Кастомные location блоки (Angie) NULL
location_nginx_custom TEXT Кастомные location блоки (Nginx/SW) NULL
custom_angie_ssl TEXT Замена SSL директив (Angie) NULL
custom_sw_nginx_ssl TEXT Замена SSL директив (SW) NULL
max_fails INTEGER Попыток до пометки сервера недоступным 5
fail_timeout INTEGER Время восстановления сервера (сек) 15
balancing_method TEXT Метод балансировки upstream NULL
proxy_next_upstream_codes TEXT HTTP-коды для proxy_next_upstream '500,502,503,504'

Используемые запросы

Получение настроек по client_title

SELECT
    l7resourceid,
    waf_enabled,
    waf_vendor,
    mode,
    custom_input_http_ports,
    custom_input_https_ports,
    custom_output_http_ports,
    custom_output_https_ports,
    upstream_angie_custom,
    upstream_nginx_custom,
    server_nginx_custom,
    server_angie_custom,
    location_angie_custom,
    location_nginx_custom,
    server_directives_angie_custom,
    server_directives_nginx_custom,
    custom_angie_ssl,
    custom_sw_nginx_ssl,
    client_title,
    sni,
    ssl_enabled,
    max_fails,
    fail_timeout,
    balancing_method,
    proxy_next_upstream_codes
FROM apps_settings
WHERE client_title = $1
ORDER BY l7resourceid ASC;

Функция: getAppsSettingsByClientTitle(clientTitle string)

Миграции

ALTER TABLE apps_settings
    ADD COLUMN IF NOT EXISTS custom_sw_nginx_ssl TEXT DEFAULT NULL;

ALTER TABLE apps_settings
    ADD COLUMN IF NOT EXISTS balancing_method TEXT DEFAULT NULL;

ALTER TABLE apps_settings
    ADD COLUMN IF NOT EXISTS proxy_next_upstream_codes TEXT DEFAULT '500,502,503,504';

Кастомные поля (подробно)

balancing_method

Метод балансировки upstream. Записывается без точки с запятой. Вставляется первой строкой в upstream-блок.

-- Включить least_conn
UPDATE apps_settings SET balancing_method = 'least_conn' WHERE l7resourceid = 12345;

-- Вернуть round-robin (дефолт)
UPDATE apps_settings SET balancing_method = NULL WHERE l7resourceid = 12345;

Допустимые значения: least_conn, ip_hash, random, random two least_conn

proxy_next_upstream_codes

Коды HTTP ответов при которых Angie/nginx переключается на следующий upstream-сервер. Записывается через запятую без префикса http_.

-- Убрать 500 из retry (бэкенд вернул 500, не нужно делать retry)
UPDATE apps_settings
SET proxy_next_upstream_codes = '502,503,504'
WHERE l7resourceid = 12345;

-- Вернуть дефолт
UPDATE apps_settings
SET proxy_next_upstream_codes = NULL
WHERE l7resourceid = 12345;

Итоговая строка в конфиге:

proxy_next_upstream error timeout invalid_header http_502 http_503 http_504;

upstream_angie_custom / upstream_nginx_custom

Режим: REPLACE (полная замена keepalive директив)

-- Кастомный keepalive
UPDATE apps_settings
SET upstream_angie_custom = 'keepalive 200;
keepalive_timeout 90s;'
WHERE l7resourceid = 12345;

server_directives_angie_custom / server_directives_nginx_custom

Режим: REPLACE (замена блока дефолтных таймаутов/буферов)

Важно: при использовании кастома нужно указать ВСЕ нужные директивы, включая proxy_set_header X-Request-ID.

server_angie_custom / server_nginx_custom

Поддерживает формат SERVER_BLOCK для создания дополнительных server-блоков:

[SERVER_BLOCK:443:report.example.com:www.report.example.com]
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
[/SERVER_BLOCK]

Синтаксис: [SERVER_BLOCK:{порт}:{server_name}:{alias1}:{alias2}...]

custom_angie_ssl / custom_sw_nginx_ssl

Полная замена SSL директив. При NULL используются дефолтные:

ssl_certificate ssl/cert.pem;
ssl_certificate_key ssl/key.pem;
ssl_protocols TLSv1.2 TLSv1.3;

Таблица: sp_info (кэш)

Назначение

Кэширует данные из ServicePipe API. TTL: 10 минут.

Структура

Поле Тип Описание
sid INTEGER l7resourceid
domain_name TEXT Основной домен
aliases JSON Массив алиасов
origins JSON Массив origin серверов
updated_at TIMESTAMP Время последнего обновления

Таблица: manual_info

Назначение

Ручное управление данными ресурсов (альтернатива API). Используется при mode = 'manual'.

Структура

Поле Тип Описание
sid INTEGER l7resourceid
domain_name TEXT Основной домен
aliases JSON Массив алиасов
origins JSON Массив origin серверов

Данные не имеют TTL и всегда актуальны.


Таблица: ips

Структура

Поле Тип Описание
id INTEGER Всегда = 1
antibot_networks TEXT[] CIDR сети antibot
waf_networks TEXT[] CIDR сети WAF (исключаются из origins)

Связи между таблицами

instances_new
    ↓ (hostname → instance)
client_info (waf_instance)
    ↓ (client_title)
apps_settings (client_title)
    ↓ (l7resourceid через API/manual_info)
Origins, Aliases

Примеры типичных операций

Добавить нового PTAF-клиента

INSERT INTO client_info (client_title, containers_count, waf_instance)
VALUES ('NewClient', 2, 'PTAFd_01');

INSERT INTO apps_settings (l7resourceid, client_title, waf_vendor, waf_enabled, mode)
VALUES (99999, 'NewClient', 'ptaf', true, 'auto');

Добавить нового SW-клиента

INSERT INTO client_info (client_title, containers_count, waf_instance)
VALUES ('NewSWClient', 0, 'SWd_01');

INSERT INTO apps_settings (l7resourceid, client_title, waf_vendor, waf_enabled, mode)
VALUES (99998, 'NewSWClient', 'sw', true, 'auto');

Изменить количество контейнеров

-- Увеличить до 5
UPDATE client_info SET containers_count = 5 WHERE client_title = 'CLIENT001';

-- Отключить клиента (drain всех контейнеров)
UPDATE client_info SET containers_count = 0 WHERE client_title = 'CLIENT001';

Включить debug-режим

UPDATE client_info SET debug = true WHERE client_title = 'CLIENT001';

Задать индивидуальный Docker-образ

UPDATE client_info
SET
    docker_image = 'ptaf-core-nginx-agent:release-4.3.1.431839-debian-bullseye-nginx-1.28.0',
    docker_image_download = 'https://example.com/image.tar'
WHERE client_title = 'CLIENT001';

Настроить балансировку

UPDATE apps_settings SET balancing_method = 'least_conn' WHERE l7resourceid = 12345;

Убрать 500 из retry

UPDATE apps_settings
SET proxy_next_upstream_codes = '502,503,504'
WHERE l7resourceid = 12345;

Добавить кастомные SSL для SW

UPDATE apps_settings
SET custom_sw_nginx_ssl = 'ssl_certificate /etc/solidwall-nginx/ssl/custom.crt;
ssl_certificate_key /etc/solidwall-nginx/ssl/custom.key;
ssl_protocols TLSv1.2 TLSv1.3;'
WHERE l7resourceid = 12345;

Добавить SERVER_BLOCK с увеличенными таймаутами

UPDATE apps_settings
SET server_angie_custom = '[SERVER_BLOCK:443:report.example.com:www.report.example.com]
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
[/SERVER_BLOCK]'
WHERE l7resourceid = 12345;

Best Practices

NULL vs пустая строка

-- Правильно: NULL для дефолтов
UPDATE apps_settings SET upstream_angie_custom = NULL WHERE l7resourceid = 12345;

-- Неправильно: пустая строка может вызвать ошибки
UPDATE apps_settings SET upstream_angie_custom = '' WHERE l7resourceid = 12345;

Массивы портов

-- Правильно: PostgreSQL array
UPDATE apps_settings SET custom_input_https_ports = '{443, 8443}' WHERE l7resourceid = 12345;

-- Неправильно: строка
UPDATE apps_settings SET custom_input_https_ports = '443,8443' WHERE l7resourceid = 12345;

balancing_method — без точки с запятой

-- Правильно
UPDATE apps_settings SET balancing_method = 'least_conn' WHERE l7resourceid = 12345;

-- Неправильно
UPDATE apps_settings SET balancing_method = 'least_conn;' WHERE l7resourceid = 12345;

Мониторинг БД

-- Количество клиентов на каждом instance
SELECT waf_instance, COUNT(*) as clients_count
FROM client_info
GROUP BY waf_instance;

-- Клиенты с debug-режимом
SELECT client_title FROM client_info WHERE debug = true;

-- Клиенты с индивидуальным образом
SELECT client_title, docker_image FROM client_info WHERE docker_image IS NOT NULL;

-- Клиенты в блочном режиме
SELECT client_title, sid_block FROM client_info WHERE one_container = false;

-- Клиенты с нестандартным количеством worker процессов
SELECT client_title, worker_processes FROM client_info WHERE worker_processes != 4;

-- Клиенты без антиддоса
SELECT client_title, real_ip_networks FROM client_info WHERE sp_antiddos = false;

-- Клиенты с кастомным ptaf_fallback
SELECT client_title, ptaf_fallback_code FROM client_info WHERE ptaf_fallback_code != '418';

-- Ресурсы с кастомной балансировкой
SELECT client_title, l7resourceid, balancing_method
FROM apps_settings
WHERE balancing_method IS NOT NULL;

-- Ресурсы с кастомными upstream директивами
SELECT client_title, l7resourceid
FROM apps_settings
WHERE upstream_angie_custom IS NOT NULL
   OR upstream_nginx_custom IS NOT NULL;

Индексы (рекомендуемые)

CREATE INDEX idx_instances_new_hostname ON instances_new(hostname);
CREATE INDEX idx_client_info_waf_instance ON client_info(waf_instance);
CREATE INDEX idx_client_info_client_title ON client_info(client_title);
CREATE INDEX idx_apps_settings_client_title ON apps_settings(client_title);
CREATE INDEX idx_apps_settings_l7resourceid ON apps_settings(l7resourceid);