Один коміт, а не десяток тематичних, свідомо: теми переплетені в
спільних файлах (store.go, docker-compose.yml, deploy/README.md), і
розділити їх можна було б лише індексуванням шматків. Коміти, які не
збираються, гірші за один великий — тим паче що це рівно той стан, який
перевірявся разом.
ЩО ПРАЦЮЄ НА СТЕНДІ Й ПЕРЕВІРЕНО ТАМ
0058 подієві алерти: syslog, ncm, compliance спрацьовують у мить
події; правило з нереалізованим джерелом більше не зберігається
мовчки
0059 snmp.walk і прототипи шаблонів — таблиці з динамічним індексом
описуються шаблоном, а не Go
0060 відкат конфігу: план як різниця, маскування паролів із підписом
плану, обов'язковий контрольний збір, verifying при обриві
0061 кнопки Telegram: довге опитування, авторизація не з callback_data
0062 аудит і архів хостів; тест на AST, що падає на ключі без назви
0063 RLS: три ролі, окремий пул для фонових тактів
0064 строки зберігання даних і сторінка сховища
0065 приймач SNMP-трапів; перевірено справжніми пакетами по дроту,
переклад v1→v2 за RFC 3584 дає правильний OID
0066 ескалації сповіщень
0067 алерт про вичерпання диска
0068 поля заливки конфігу переїхали в каталог профілів
Плюс: 137 тестів вебу з нуля (їх не було взагалі), одинадцять справжніх
вад, знайдених ними й виправлених, і виправлення двох інтеграційних
тестів grpcapi, які мовчки пропускались півтора року.
ЩО ЩЕ НЕ ЗАПУСКАЛОСЬ
netpulse установник: одна команда замість 18 змінних і
593 рядків інструкції
RLS з першого запуску нова інсталяція під політиками одразу;
RLS-EXISTING-INSTALL.md лишається тільки для
старих інсталяцій
.forgejo + CI раннер не зареєстрований
Ці три перевірені компіляцією й міркуванням, але не виконанням.
ГОЛОВНИЙ ВИСНОВОК ДВОХ СЕСІЙ
Зелена перевірка доводить рівно те, що вона перевіряє. Тест ізоляції RLS
був правильний і зелений — і пропустив зламаний вхід, бо перевіряв «чи
не видно чужого», коли зламалось «чи видно своє». Інтеграційні тести
grpcapi були зелені, бо не виконувались. Схема, довідник і протокол
описували те, чого в коді не існувало, і виглядало це як готове.
Тому в кожному завданні цих сесій стояла вимога назвати НЕПОКРИТЕ, а
чотири задачі закінчились не можливістю, а відмовою: правило з
нереалізованим джерелом не зберігається, профіль без команд заливки
каже про це замість мовчазної кнопки, міграція RLS валить сама себе на
таблиці без політики, тест словника аудиту падає на ключі без назви.
Подробиці — HISTORY.md, розділи за 26 і 27 серпня.
125 lines
9.1 KiB
SQL
125 lines
9.1 KiB
SQL
-- =====================================================================
|
||
-- NetPulse :: 0058_event_alerts.sql
|
||
-- Тригери на події перестають бути обіцянкою, якої ніхто не виконує.
|
||
--
|
||
-- Движок правил рахував рівно три джерела: metric, icmp, interface.
|
||
-- Для syslog, trap, ncm, agent, compliance і link він свідомо повертав
|
||
-- порожньо — і на цьому все закінчувалось. Але форма дозволяла завести
|
||
-- таке правило без жодного слова застереження: людина писала тригер
|
||
-- «конфіг змінився», бачила його в переліку зеленим, з написом
|
||
-- «увімкнено» й нулем активних алертів, — і роками читала цей нуль як
|
||
-- «змін не було».
|
||
--
|
||
-- Це гірше за відсутність функції. Відсутньої функції шукають обхідний
|
||
-- шлях; функція, яка виглядає працюючою, обхідного шляху не шукає ніхто.
|
||
--
|
||
-- Різниця між подієвим і метричним алертом принципова, і саме через неї
|
||
-- потрібні нові стовпці. Метричний алерт живе доти, доки виконується
|
||
-- умова: движок щотіку перераховує її й закриває алерт різницею множин.
|
||
-- У подієвого умови немає взагалі. Рядок журналу стався один раз;
|
||
-- «перестати ставатись» він не може. Тому такий алерт не має способу
|
||
-- зникнути сам — його або закриває людина, або він доживає до
|
||
-- визначеного строку й гасне як прострочений.
|
||
-- =====================================================================
|
||
|
||
-- ---------------------------------------------------------------------
|
||
-- Правила: строк життя й частота
|
||
-- ---------------------------------------------------------------------
|
||
|
||
ALTER TABLE alr.rules
|
||
ADD COLUMN auto_close_seconds int NOT NULL DEFAULT 0,
|
||
ADD COLUMN min_interval_seconds int NOT NULL DEFAULT 60;
|
||
|
||
COMMENT ON COLUMN alr.rules.auto_close_seconds IS
|
||
'Через скільки секунд тиші подієвий алерт гасне сам; 0 — тільки руками';
|
||
|
||
COMMENT ON COLUMN alr.rules.min_interval_seconds IS
|
||
'Не частіше одного звернення до алерту за стільки секунд — захист від потоку журналу';
|
||
|
||
-- 0 означає «закриє людина». Для наявних подієвих правил це поганий
|
||
-- умовчальний вибір: вони писались тоді, коли не працювали взагалі, і
|
||
-- перший же ввімкнений тригер «конфіг змінився» дав би дошку, з якої
|
||
-- нічого не зникає, поки її не розбере руками черговий. Дошка, яку
|
||
-- треба розбирати руками, перестає бути дошкою через тиждень.
|
||
--
|
||
-- Доба — це «встиг побачити на наступній зміні». Менше — ризик, що
|
||
-- нічну подію ніхто не побачить; більше — накопичення, яке нікому не
|
||
-- потрібне: сама подія нікуди не дінеться, вона лежить у журналі
|
||
-- алертів і в історії.
|
||
UPDATE alr.rules
|
||
SET auto_close_seconds = 86400
|
||
WHERE source IN ('syslog', 'ncm', 'compliance');
|
||
|
||
-- ---------------------------------------------------------------------
|
||
-- Алерти: лічильник подій і позначка «ще не розіслано»
|
||
-- ---------------------------------------------------------------------
|
||
|
||
ALTER TABLE alr.alerts
|
||
ADD COLUMN event_count int NOT NULL DEFAULT 1,
|
||
ADD COLUMN notify_pending boolean NOT NULL DEFAULT false;
|
||
|
||
-- Один алерт на пару «правило + хост», скільки б подій під нього не
|
||
-- підпало. Без цього потік syslog зі швидкістю сотні рядків на секунду
|
||
-- дав би сотню алертів на секунду — тобто рівно те, від чого моніторинг
|
||
-- має рятувати.
|
||
--
|
||
-- Але злиття не має ховати масштаб: «порт мигнув один раз» і «порт
|
||
-- мигнув 4000 разів за годину» — різні аварії з однаковим текстом.
|
||
-- Лічильник і є та єдина відмінність, яку видно на екрані.
|
||
COMMENT ON COLUMN alr.alerts.event_count IS
|
||
'Скільки подій злилося в цей алерт — потік у журналі має бути видно числом';
|
||
|
||
-- Подія приходить не туди, де живуть канали доставки.
|
||
--
|
||
-- Syslog і конфіги приймає netpulse-server (gRPC для зондів), а ключі
|
||
-- шифрування каналів, маршрути й тихі години читає netpulse-api, де
|
||
-- крутиться движок. Розсилати з обох процесів означало б дублювати
|
||
-- повідомлення й розводити дві копії однієї логіки маршрутизації.
|
||
--
|
||
-- Тому подієвий шлях лише піднімає алерт і ставить цю позначку, а
|
||
-- розсилає його той самий движок, що й метричні, — під тим самим
|
||
-- advisory-блокуванням, тобто рівно в одному екземплярі.
|
||
COMMENT ON COLUMN alr.alerts.notify_pending IS
|
||
'Алерт піднято подієвим шляхом і ще не розісланий; знімає движок після доставки';
|
||
|
||
-- Вибірка «що розіслати» має бути дешевою: движок робить її кожен тік,
|
||
-- а непорожньою вона буває рідко.
|
||
CREATE INDEX alerts_notify_pending_idx ON alr.alerts (tenant_id)
|
||
WHERE notify_pending;
|
||
|
||
-- Пошук прострочених: за правилом і часом останньої події.
|
||
CREATE INDEX alerts_event_age_idx ON alr.alerts (rule_id, last_seen_at)
|
||
WHERE state IN ('firing', 'acknowledged', 'suppressed');
|
||
|
||
-- ---------------------------------------------------------------------
|
||
-- Джерела, яких не буде: краще вимкнене, ніж зелене
|
||
-- ---------------------------------------------------------------------
|
||
|
||
-- trap, link і agent лишаються нереалізованими, і API тепер відмовляє
|
||
-- у їх вмиканні з поясненням. Причини різні, спільне в них одне —
|
||
-- бракує не коду, а способу описати умову:
|
||
--
|
||
-- trap — трап приїжджає як OID і набір varbind-ів. Без словника MIB
|
||
-- «умова» звелася б до порівняння цифр із крапками, яких
|
||
-- людина не набере з голови. Це була б друга мовчазна
|
||
-- обіцянка замість першої.
|
||
-- link — лінк на мапі не має власних вимірів: він живий рівно
|
||
-- настільки, наскільки живі два його кінці. Правило про лінк
|
||
-- — це правило про пристрої, і воно вже є.
|
||
-- agent — «зонд не на звʼязку» — це стан, а не подія, і рахується він
|
||
-- опитуванням last_seen_at. Місце йому серед метричних правил,
|
||
-- а не тут.
|
||
--
|
||
-- Наявні правила з цими джерелами вимикаємо, а не видаляємо. Видалення
|
||
-- забрало б у людини і текст, і саму згадку про намір; вимкнене правило
|
||
-- лишається на екрані сірим — і це найкоротший спосіб сказати «воно не
|
||
-- працювало й не працює», не забравши при цьому нічого.
|
||
UPDATE alr.rules
|
||
SET enabled = false, updated_at = now()
|
||
WHERE source IN ('trap', 'link', 'agent') AND enabled;
|
||
|
||
-- Те саме для тригерів шаблонів. Вимкнений тригер не розгортається в
|
||
-- правило — звірка шаблонів прибере породжені ним рядки сама.
|
||
UPDATE tpl.triggers
|
||
SET enabled = false
|
||
WHERE source IN ('trap', 'link', 'agent') AND enabled;
|