Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Глава 24. Холодный старт

До этого момента мы предполагали, что модель безопасности уже построена.

Есть исходные факты.

Есть отношения.

Есть проекции безопасности.

Есть эффективные разрешения.

Есть механизм, который ограничивает физические данные.

Но в реальной системе существует состояние, когда всего этого ещё нет.

Система только запускается.

База данных содержит исходные данные, но производные представления безопасности пусты или ещё не актуальны.

Это состояние можно назвать холодным стартом.

И оно показывает важную особенность всей архитектуры:

Производная модель безопасности не может считаться существующей только потому, что существуют её исходные данные.

Между ними есть процесс построения.

24.1 Исходные факты могут существовать раньше проекций

Представим минимальную систему.

В ней уже существуют:

User A
Project P
Object O

и отношения:

A → member of P
P → related to O

Но таблицы или представления, используемые для быстрых проверок, ещё пусты:

effective_user_permission = ∅
object_scope = ∅

Получается противоречивая на первый взгляд ситуация.

Предметная модель говорит:

отношения существуют.

Производная модель безопасности говорит:

необходимых фактов пока нет.

Это не обязательно означает ошибку.

Проекция является производным представлением.

Если она строится из исходных фактов, то в момент её построения естественно существует переходное состояние:

Source facts
    │
    │ build
    ▼
Security projections

Проблема начинается тогда, когда система пытается обслужить запрос так, будто производная модель уже полностью готова.

24.2 Пустая проекция не означает отсутствие права

Это принципиальное различие.

Пусть:

effective_user_permission = ∅

Можно ли из этого заключить:

User has no permission

Не всегда.

Это может означать два совершенно разных состояния:

A. Для пользователя действительно нет разрешения.

B. Разрешение существует в исходной модели,
   но проекция ещё не построена.

На уровне одной таблицы оба состояния выглядят одинаково.

Но с точки зрения безопасности это совершенно разные ситуации.

Поэтому производные данные должны иметь определённую семантику состояния.

Нельзя молча интерпретировать:

projection is empty

как:

authorization is denied

если пустота может означать ещё и то, что вычисление не завершено.

Иначе система смешивает отсутствие права и отсутствие результата вычисления.

24.3 Почему нельзя просто разрешить доступ до построения проекций

Возникает естественное решение:

Если проекция ещё не готова, временно доверимся исходным данным.

Но это создаёт другую проблему.

Допустим, обычная проверка должна использовать:

effective_user_permission
        +
object_scope

А во время холодного старта система начинает обходить исходные отношения непосредственно из приложения.

Получается уже две реализации одной модели:

normal path
  → projections

cold-start path
  → direct model traversal

Если они реализованы независимо, со временем они могут начать давать разные результаты.

Тогда холодный старт перестаёт быть временным состоянием и превращается во второй движок авторизации.

Поэтому fallback должен быть очень осторожным.

В идеале система должна иметь понятное правило:

проекция готова → используется обычный путь

проекция не готова → система не делает
                     необоснованный вывод о разрешении

Безопасное поведение при неопределённости обычно должно быть определено явно.

Но конкретное решение — отказ, ограниченный bootstrap-доступ или специальный доверенный путь — является уже свойством конкретной архитектуры.

Универсального варианта здесь нет.

24.4 Создание объекта особенно чувствительно к холодному старту

Проблема проявляется не только после запуска всей системы.

Она возникает при создании каждого нового объекта.

Последовательность может выглядеть так:

CREATE Object
      │
      ▼
Object exists
      │
      ▼
Security facts created
      │
      ▼
Projection updated
      │
      ▼
Object becomes normally accessible

Но между этими шагами существует промежуток.

Если объект уже физически создан, а его security projection ещё не появилась, возникает вопрос:

кто должен иметь доступ к объекту прямо сейчас?

Это особенно важно для создателя.

Новая запись не должна случайно оказаться:

  • недоступной самому создателю;

  • доступной всем;

  • доступной только потому, что сработал общий fallback;

  • доступной через устаревшую проекцию.

Следовательно, создание объекта и создание его первоначальных security facts нельзя рассматривать как полностью независимые операции.

На архитектурном уровне нужно определить bootstrap-состояние доступа.

24.5 Bootstrap не должен менять смысл модели

При холодном старте или создании объекта иногда требуется временный механизм, позволяющий завершить построение модели.

Например:

create object
     ↓
create initial security state
     ↓
build projection
     ↓
normal authorization

Но здесь существует опасность.

Если bootstrap получает особые права, легко сделать так, что эти права случайно станут частью обычной модели.

Тогда появляется скрытое правило:

"кто создал объект, тот всегда имеет право"

даже если предметная модель такого правила не содержит.

Именно поэтому нужно различать:

bootstrap authority

и:

domain authorization

Первое необходимо для технического перехода между состояниями.

Второе определяет обычный доступ системы.

Они могут использовать одни и те же идентификаторы и даже физические механизмы, но семантически это разные вещи.

24.6 Холодный старт требует определённого состояния готовности

Если безопасность зависит от производных данных, система должна понимать не только что построено, но и насколько модель готова.

Минимально существуют состояния:

SOURCE READY
      │
      ▼
PROJECTION BUILDING
      │
      ▼
PROJECTION READY

Но в распределённой системе этого может быть недостаточно.

Например, одна проекция уже обновлена:

а другая ещё нет:

или объектная проекция уже содержит новый объект, но не содержит новую публикацию.

Тогда система находится в частично построенном состоянии.

Это означает, что готовность должна рассматриваться не только для отдельных записей, но и для согласованного набора security facts, необходимого конкретной операции.

Для одного запроса может быть достаточно одной проекции.

Для другого потребуется несколько:

effective_user_group
       +
effective_user_permission
       +
object_scope

Следовательно, понятие «проекция готова» всегда имеет контекст.

Нужно понимать:

готова ли модель настолько, чтобы безопасно принять конкретное решение?

24.7 Холодный старт должен быть восстанавливаемым

Проекции — производные данные.

Значит, в правильно построенной архитектуре их можно уничтожить и построить заново из исходных фактов.

Это очень сильное свойство.

Оно означает:

Source facts
     │
     ▼
Rebuild
     │
     ▼
Security projections

Если после полного пересчёта получается другая модель безопасности, значит:

  • часть исходных фактов потеряна;

  • правила изменились;

  • вычисление неполно;

  • или производная модель содержит скрытую информацию, которой нет в источнике.

Последний вариант особенно опасен.

Проекция не должна становиться единственным местом, где существует критически важное знание о доступе.

Поэтому холодный старт является одновременно и механизмом запуска, и способом проверки архитектуры.

Если систему можно восстановить из исходных фактов, значит производный слой действительно остаётся производным.

24.8 Холодный старт в Guardian

В Guardian эта проблема проявляется непосредственно в момент создания объектов и построения security projections.

Сначала существуют исходные данные объекта и связанные с ним security facts.

Затем projection layer должен получить производное состояние:

source facts
     │
     ▼
effective_user_group
effective_user_permission
object_scope
     │
     ▼
object authorization
     │
     ▼
RLS

Для нового объекта особенно важен переход от состояния создания к обычному состоянию авторизации.

Создатель должен иметь определённую моделью возможность завершить этот переход, после чего объект должен участвовать в обычном механизме проверки.

При этом bootstrap-состояние не должно превращаться в универсальное право доступа.

В Guardian это также объясняет, почему первоначальная безопасность объекта и последующее обычное разрешение — связанные, но не идентичные этапы.

После построения проекций система возвращается к нормальному пути:

security facts
      ↓
projections
      ↓
effective permission
      ↓
object authorization
      ↓
RLS

Таким образом, холодный старт не является отдельной моделью доступа.

Это переходное состояние той же модели.

24.9 Что происходит при полном восстановлении

Теперь можно рассмотреть более жёсткий сценарий.

Предположим, все производные security projections потеряны.

Исходные факты остались.

Система должна иметь возможность выполнить:

DROP / CLEAR derived state
          ↓
rebuild from source facts
          ↓
validate
          ↓
enable normal access

Важна не конкретная последовательность SQL-операций.

Важен принцип:

производная модель безопасности должна быть восстанавливаемой без ручного восстановления каждого разрешения.

Это влияет на требования к архитектуре с самого начала.

Нужно знать:

  • какие факты являются источниками;

  • какие проекции из них строятся;

  • какие зависимости существуют между проекциями;

  • как определить завершённость пересчёта;

  • как проверить результат;

  • что происходит с запросами во время восстановления.

Таким образом, восстановление перестаёт быть аварийной процедурой, придуманной после сбоя.

Оно становится нормальным свойством модели.

24.10 Главный вывод

Холодный старт показывает фундаментальное свойство проекционной модели безопасности.

Исходные факты и производные факты не появляются одновременно.

Между ними существует переход:

Source
  ↓
Build
  ↓
Projection
  ↓
Authorization

Поэтому система должна различать как минимум три состояния:

есть факт
есть производный результат
есть подтверждённая готовность модели

Особенно важно не путать:

нет разрешения

с:

разрешение ещё не вычислено

И не превращать bootstrap-механизм во второй источник авторизации.

Холодный старт также даёт критерий качества архитектуры:

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

На этом заканчивается часть о физическом обеспечении доступа к данным.

Мы прошли путь от объекта и отношений до фактической строки:

Object
  ↓
Facts
  ↓
Context
  ↓
Access grounds
  ↓
Effective permission
  ↓
Authorization
  ↓
Data enforcement
  ↓
Physical data

Но до сих пор мы рассматривали отдельные элементы этой цепочки.

Следующая часть соберёт их в один процесс.

Мы посмотрим, что именно происходит с одним запросом — от момента его поступления до получения или изменения конкретных данных.