Runbook: Visibility policy cache poisoning / неконсистентность
Severity (default): P1 (риск раскрытия / сокрытия данных). Owner: visibility / security team. Связанные алерты:
visibility_cache_miss_rate > 0.5за 5 мин (нарушение инвалидации).visibility_policy_compile_errors_total > 0.- Жалоба клиента / оператора: “видны данные, которых не должно быть” / “пропали данные, которых не должно быть”.
Симптом
- Клиент видит товары / цены, которые должна скрывать
deny-policy. - Клиент НЕ видит данные, которые должны быть видны (после изменения policy не подхватилось).
- Симулятор в admin UI и реальный ответ расходятся.
Диагностика
ВНИМАНИЕ: пока не подтвердим scope — действуем как при потенциальном инциденте безопасности. Не “просто перезагружаем кэш и забываем”.
# 1. Какие policies сейчас активны для затронутого subject?
kubectl -n tracium exec deploy/admin-api -- \
curl -X POST localhost:8080/v1/admin/visibility-policies/simulate \
-H 'X-Admin-Token: <token>' \
-d '{"subject":{"customer_id":"<CUSTOMER>","role":"<ROLE>"},"target_kind":"<KIND>","candidates":[<sample>]}'# 2. Состояние кэша по этому subject
kubectl -n tracium exec deploy/redis -- \
redis-cli GET "visibility:compiled:<SUBJECT_HASH>"
kubectl -n tracium exec deploy/redis -- \
redis-cli TTL "visibility:compiled:<SUBJECT_HASH>"-- 3. История изменений policies для этого subject
SELECT id, version, occurred_at, event_type, event_data->'subject' AS subject
FROM event_store
WHERE aggregate_type='data_visibility_policy'
AND occurred_at > now() - interval '24h'
ORDER BY occurred_at DESC;# 4. Ошибки компиляции
kubectl -n tracium logs deploy/visibility --since=1h | grep -E "compile|error"Возможные причины:
- A: Изменение policy не инвалидировало кэш (баг в инвалидации).
- B: Ошибка компиляции policy — fallback к
default allowсработал на ошибочной policy, поднимая риск утечки данных. - C: Race в multi-replica visibility (одна реплика с новой policy, другая со старой).
- D: Поломанная схема policies (после миграции).
- E: Намеренное вмешательство в БД мимо API (audit trail должен показать).
Смягчение
Шаг 0 — пауза (ВСЕГДА перед расследованием при подозрении на data leak)
# Глобально переключить fallback effect на deny — стоп раскрытия. ВЛИЯЕТ НА ВСЕХ КЛИЕНТОВ.
# Делать только если подтверждён leak и blast radius серьёзный.
kubectl -n tracium set env deploy/visibility VISIBILITY_DEFAULT_EFFECT=deny
kubectl -n tracium rollout restart deploy/visibilityПосле этого — клиенты массово увидят пустые ответы по неуказанным policies. Снимать только после fix.
A: Инвалидация кэша
# Сбросить кэш по конкретному subject
kubectl -n tracium exec deploy/redis -- \
redis-cli DEL "visibility:compiled:<SUBJECT_HASH>"
# Или сбросить всё (с осторожностью — поднимет latency пока идёт recompile)
kubectl -n tracium exec deploy/redis -- redis-cli --scan --pattern 'visibility:compiled:*' \
| xargs -n 100 kubectl -n tracium exec deploy/redis -- redis-cli DELB: Ошибка компиляции
Найти конкретную policy:
kubectl -n tracium logs deploy/visibility --since=2h | grep -E "compile" | tail -20Откатить policy:
kubectl -n tracium exec deploy/admin-api -- \
curl -X POST localhost:8080/v1/admin/visibility-policies/<POLICY_ID>/revert \
-d '{"to_version":<N>,"reason":"compile error in v<N+1>"}'C: Race
Принудительный перезапуск всех реплик visibility (последовательно):
kubectl -n tracium rollout restart deploy/visibilityE: Вмешательство
Эскалация в #security немедленно. Аудит:
SELECT * FROM event_store
WHERE aggregate_type='data_visibility_policy'
AND metadata->'actor'->>'type' NOT IN ('user','system')
ORDER BY occurred_at DESC LIMIT 50;Устранение root cause
- A: тест на инвалидацию (event-driven invalidation в consumer’е visibility).
- B: pre-publish dry-run компиляции policy в admin-api.
- C: версия snapshot в Redis-ключе (ключ кэша включает версию policy).
- D: тесты миграций схем.
- E: ограничение прямого DB access (через bastion + аудит).
Пост-инцидент
При подтверждённой утечке данных:
- Аудит, кто видел что:
policy_evaluation_audit+ ответы через correlation_id. - Уведомление затронутых клиентов (в зависимости от масштаба утечки).
- Запись инцидента в security log (отдельный регистр).
- Post-mortem.
Эскалация
- Любое подозрение на утечку данных →
#securityнемедленно. - 30 мин без mitigation → on-call lead.
Связано
- ADR-0012 (data visibility policy).
10-business/contexts/visibility.md30-services/visibility/README.md