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

Глава 43. Отношения формируют контекст

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

Но сами по себе эти отношения ещё не дают ответа на вопрос о доступе.

Пусть известно:

User A
   ↓
member of
   ↓
Project P

Document D
   ↓
belongs to
   ↓
Project P

Мы уже знаем больше, чем в простой модели User → Role → Permission.

Но всё ещё не знаем, может ли User A выполнить над Document D конкретное действие.

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

Именно здесь появляется контекст.

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

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

43.1 Отношение связывает объекты, контекст связывает факты с решением

Само отношение отвечает на вопрос:

Кто с чем связан?

Например:

User A → member of → Project P

или:

Document D → belongs to → Project P

Но решение о доступе задаёт другой вопрос:

Can(User A, READ, Document D)?

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

User A
   ↓
member of
   ↓
Project P
   ↑
belongs to
   ↑
Document D

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

Но даже этот путь ещё не является разрешением.

Он становится частью контекста, который затем интерпретируется правилами.

Получается:

Relations
    ↓
Relevant relations
    ↓
Context
    ↓
Rules
    ↓
Effective permission

43.2 Контекст не равен одному отношению

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

Например:

User A → owner of → Document D

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

Но в более сложном случае может потребоваться несколько фактов:

User A → member of → Project P
Document D → belongs to → Project P
Document D → state = Released
Action = APPROVE

Здесь решение зависит уже от совокупности фактов.

Поэтому:

Context ≠ Relation

Отношение является элементом контекста.

Контекст — это совокупность релевантных отношений и других фактов, необходимых для применения правил.

43.3 В контекст попадают не все отношения объекта

У объекта может быть десятки отношений.

Но конкретному запросу может быть нужен только небольшой набор.

Допустим, документ имеет:

owner
project
publication
revision
change
audit
attachments

Для проверки:

READ

может быть достаточно:

project
publication
owner

Для:

APPROVE

могут потребоваться:

project
role
lifecycle state
delegation

Для:

UPDATE

может иметь значение ещё другой набор.

Следовательно, контекст нельзя строить как полный снимок объекта.

Он определяется вопросом, который система сейчас задаёт.

Context = f(Subject, Action, Object, relevant facts)

43.4 Контекст связывает несколько независимых отношений

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

Например:

User A
   ↓
member of
   ↓
Project P

и:

Document D
   ↓
belongs to
   ↓
Project P

и:

User A
   ↓
has role
   ↓
Reviewer

и:

Document D
   ↓
state
   ↓
Review

Ни один из этих фактов сам по себе не отвечает на вопрос:

Can(User A, APPROVE, Document D)?

Но вместе они могут сформировать необходимый контекст.

Например, правило может требовать:

User is Reviewer
AND
User participates in Document's Project
AND
Document is in Review state

Тогда контекст содержит несколько независимых измерений.

43.5 Отношения могут соединяться через промежуточные объекты

Контекст часто формируется не прямой связью:

User → Object

а через несколько объектов:

User
  ↓
Company
  ↓
Project
  ↓
Document

или:

User
  ↓
Group
  ↓
Project
  ↓
Document

Каждое звено является отдельным отношением.

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

Поэтому можно представить:

Subject
   ↓
Relation
   ↓
Intermediate object
   ↓
Relation
   ↓
Object

как часть контекста.

Это особенно важно в системах, где доступ определяется организационной структурой, проектами, делегированием или связями между объектами.

43.6 Путь отношений не становится правилом автоматически

Наличие пути ещё ничего не говорит о его допустимости.

Предположим:

User A
   ↓
member of
   ↓
Group G
   ↓
related to
   ↓
Project P
   ↓
contains
   ↓
Document D

Технически такой путь существует.

Но можно ли на его основании читать документ?

Это уже вопрос правил.

Одна система может считать такой путь достаточным.

Другая — потребовать ещё публикацию.

Третья — учитывать группу только для части объектов.

Четвёртая — вообще не использовать эту связь для авторизации.

Поэтому:

Path ≠ Access

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

43.7 Одни отношения дают основание, другие ограничивают его применение

Не все отношения выполняют одинаковую функцию.

Например:

User A → member of → Project P

может быть основанием доступа.

А:

Document D → state = Draft

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

В другом случае:

Document D → published to → Group G

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

А:

User A → delegated by → User B

может давать дополнительное основание.

Таким образом, контекст может содержать отношения разного назначения:

Основание
Область
Ограничение
Состояние
Делегирование
Связь объектов

Их нельзя смешивать только потому, что все они участвуют в одном решении.

43.8 Область становится частью контекста через отношение

Ранее мы различили контекст и область действия.

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

Если существует:

User A
   ↓
Role R
   ↓
Project P

то Project P может быть областью действия отношения пользователя и роли.

Но это не означает, что:

Project P = Context

Контекст может одновременно включать:

User A
Role R
Project P
Document D
Publication
Document state
Requested action

Поэтому область — только одно из измерений контекста.

Она появляется внутри контекста потому, что определённое отношение действует в некоторой области.

43.9 Контекст зависит от субъекта

Рассмотрим один объект:

Document D

Для:

User A

контекст может содержать:

member of Project P
role Reviewer

Для:

User B

тот же объект может иметь другой контекст:

owner of Document D

Для:

User C

может существовать:

published to Group G

Объект один.

Но контексты различаются.

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

43.10 Контекст зависит от действия

Даже для одного субъекта и одного объекта контекст может различаться.

Например:

User A
Document D

Для READ релевантны:

project membership
publication
ownership

Для APPROVE могут добавиться:

reviewer role
lifecycle state
delegation

Для UPDATE может использоваться:

ownership
editor role
document state

То есть:

Context(User A, READ, D)

и:

Context(User A, APPROVE, D)

могут быть разными.

Это фундаментальное свойство модели.

43.11 Контекст зависит от объекта

Обратная ситуация также возможна.

Пусть один пользователь имеет:

Role = Reviewer

Для одного документа эта роль может быть релевантной.

Для другого — нет.

Например:

Document D1 → Project P1
Document D2 → Project P2

а пользователь является reviewer только в P1.

Тогда:

Context(User A, APPROVE, D1)

и:

Context(User A, APPROVE, D2)

будут различаться.

Следовательно, контекст определяется не только субъектом.

Он является результатом отношения:

Subject × Action × Object

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

43.12 Контекст может содержать отношения между субъектами

Иногда путь к объекту проходит не через область или проект, а через другого субъекта.

Например:

User A
   ↓
delegated by
   ↓
User B

и:

User B
   ↓
owner of
   ↓
Document D

Если модель допускает делегирование, эта цепочка может стать частью контекста.

Но снова не следует делать вывод:

User A can access D

только из наличия такой цепочки.

Нужно знать:

  • разрешено ли делегирование;

  • какие действия делегируются;

  • в какой области;

  • на какой срок;

  • можно ли передавать право дальше.

Контекст содержит отношения.

Правила определяют их значение.

43.13 Временные отношения тоже могут входить в контекст

Некоторые отношения действуют не постоянно.

Например:

User A
   ↓
delegated access
   ↓
Document D

может быть действителен:

с 1 сентября
по 15 сентября

Тогда время становится частью контекста.

В один момент:

Can(User A, READ, D) = true

а в другой:

Can(User A, READ, D) = false

при неизменных объекте и субъекте.

Это ещё раз показывает, почему контекст нельзя представить только как структуру:

User → Scope → Permission

В него могут входить дополнительные измерения.

43.14 Контекст может содержать состояние объекта

Состояние также может быть релевантным отношением или фактом.

Например:

Document D
state = Draft

может означать:

UPDATE allowed
APPROVE forbidden

После изменения:

Document D
state = Review

правила могут измениться.

При этом пользовательские отношения не изменились.

Изменился объектный факт.

Поэтому контекст строится не только из отношений между субъектами.

В него входят любые факты, которые правила используют для данного решения.

43.15 Один и тот же факт может участвовать в разных контекстах

Допустим:

User A → member of → Project P

Этот факт может использоваться при проверке:

READ Document
UPDATE Document
APPROVE Change

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

Для READ членство может быть достаточным основанием.

Для UPDATE может потребоваться дополнительная роль.

Для APPROVE — ещё и соответствующее состояние объекта.

Таким образом, факт не имеет одного заранее определённого значения для всех решений.

Его значение определяется правилами конкретного запроса.

43.16 Несколько отношений могут образовывать одно основание

Иногда основанием доступа является не отдельное отношение, а их комбинация.

Например:

User A → member of → Project P
User A → has role → Reviewer
Document D → belongs to → Project P
Document D → state = Review

Правило может выглядеть концептуально так:

member(Project)
AND
role(Reviewer)
AND
state(Review)

Здесь ни один факт не даёт право самостоятельно.

Право появляется из их совместного применения.

Это показывает, почему полезно отделять:

facts

от:

rules

Факты формируют контекст.

Правило определяет, как из этого контекста получить результат.

43.17 Контекст не должен превращаться в огромный снимок системы

Есть опасная архитектурная крайность.

Если контекст зависит от множества фактов, может возникнуть желание включить в него вообще всё:

User
all roles
all groups
all projects
all objects
all publications
all states
all delegations
...

Но это уже не контекст конкретного решения.

Это почти снимок всей системы.

Такой подход делает модель тяжёлой и плохо объяснимой.

Правильный вопрос другой:

Какие факты действительно нужны для применения правил к этому субъекту, действию и объекту?

Только они и должны становиться частью релевантного контекста.

43.18 Контекст может быть вычислен, но не обязан храниться как объект

Контекст — концептуальная модель.

Это не означает, что в базе обязательно должна существовать таблица:

context

Контекст может быть:

  • вычислен во время запроса;

  • собран из нескольких проекций;

  • частично материализован;

  • представлен набором производных фактов;

  • сформирован несколькими слоями системы.

Важно не физическое представление, а семантика.

Если система хранит:

effective_user_permission
object_scope
effective_user_group

это не означает, что одна из этих таблиц является «контекстом».

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

43.19 Проекции ускоряют работу с отношениями, но не меняют их смысл

Когда отношения становятся сложными, повторно проходить весь граф при каждом запросе дорого.

Поэтому можно заранее получить производные факты:

User A
   ↓
effective relation
   ↓
Project P

или:

User A
   ↓
effective permission
   ↓
Project P

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

Он остаётся результатом вычисления.

Источник истины:

source facts

а проекция:

derived representation

Это различие особенно важно для безопасности.

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

43.20 Изменение отношения означает изменение контекста

Предположим:

User A → member of → Project P

было истинно.

Затем отношение удалено.

Сам документ:

Document D

не изменился.

Но для пользователя изменился контекст:

Context(User A, READ, D)

Следовательно, измениться может и эффективное разрешение.

Это означает, что контекст не является статическим объектом.

Он является результатом текущего состояния релевантных отношений.

43.21 Отношения образуют граф, но решение не обязано обходить весь граф

В сложной системе можно представить все отношения как граф:

Subject
   │
   ├── Group
   │     └── Project
   │
   ├── Company
   │     └── Project
   │
   └── Delegation
         └── Subject

Объекты также связаны между собой:

Project
   ├── Document
   ├── Task
   └── Product

Но конкретный запрос использует только часть этого графа.

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

Она должна уметь определить:

какие связи релевантны этому решению

и подготовить их в форме, пригодной для проверки.

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

43.22 Контекст — это не ещё один уровень разрешений

Важно не создать новую путаницу.

Мы уже различаем:

Relation
Context
Permission
Decision

Они находятся на разных уровнях.

Relation:

User A → member of → Project P

Context:

User A
Project P
Document D
READ
relevant membership
relevant publication
relevant object state

Effective permission:

READ

Decision:

ALLOW

Нельзя заменить эту цепочку одной сущностью.

Если контекст начинает хранить готовые permissions, он перестаёт быть контекстом и превращается в ещё один слой разрешений.

43.23 Контекст является связующим слоем

Теперь можно увидеть роль контекста во всей модели.

С одной стороны находятся предметные факты:

Objects
Relationships
States
Areas
Publications
Roles
Delegations

С другой:

Rules
Effective permissions
Access decisions

Контекст соединяет их:

Source facts
      ↓
Relevant relationships and facts
      ↓
Context
      ↓
Rules
      ↓
Effective permission
      ↓
Decision

Он не создаёт отношения.

Не создаёт permissions.

Не заменяет правила.

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

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

Мы начали эту часть книги с объекта.

Объект определяет пространство возможных отношений.

Теперь следующий шаг становится очевидным:

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

Но сами отношения ещё не являются контекстом.

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

Получается цепочка:

Object
   ↓
Possible relationships
   ↓
Actual relationships
   ↓
Relevant facts
   ↓
Context
   ↓
Rules
   ↓
Effective permission
   ↓
Access decision

При этом:

Relation ≠ Permission
Context ≠ Permission
Context ≠ Scope
Effective permission ≠ Decision

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

Объект говорит, что существует.

Отношения говорят, как объекты связаны.

Контекст говорит, какие из этих связей имеют значение сейчас.

Правила говорят, как их интерпретировать.

Эффективное разрешение показывает, какое право получилось.

Решение отвечает на конкретный вопрос:

Can(Subject, Action, Object)?

Именно поэтому контекст нельзя добавить в архитектуру как ещё одно поле или ещё одну таблицу.

Он возникает из самой структуры отношений.

Контекст — это не контейнер для отношений. Это релевантная структура отношений и фактов, рассмотренная с точки зрения конкретного решения о доступе.

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