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

Глава 41. Межсервисный и B2B-доступ

До сих пор мы в основном рассматривали доступ внутри одной системы.

Пользователь обращается к объекту.

Система знает его отношения, роли, области и ограничения.

Но в распределённой архитектуре возникает другой случай:

Service A
    ↓
Service B

Или:

Company A
    ↓
B2B relationship
    ↓
Company B

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

Запрос может исходить от:

  • другого сервиса;

  • организации;

  • интеграционного компонента;

  • технического клиента;

  • пользователя, действующего через сервис;

  • сервиса, выполняющего действие от имени пользователя.

Это добавляет ещё один слой отношений.

Но основной принцип не меняется:

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

41.1 Сервис тоже может быть субъектом

В простой архитектуре можно представить:

User
   ↓
API
   ↓
Database

В распределённой системе путь может быть:

User
   ↓
Service A
   ↓
Service B
   ↓
Database

При этом Service B должен понимать, от чьего имени выполняется операция.

Есть как минимум два разных субъекта:

Technical caller = Service A
Business subject = User U

Иногда они совпадают.

Иногда нет.

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

Тогда:

Subject = Service A

а не:

Subject = User U

Смешивать эти понятия опасно.

41.2 Аутентификация сервиса не является разрешением

Пусть Service A успешно аутентифицировался в Service B.

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

Service B knows:
"this request came from Service A"

Но из этого не следует:

Service A may read every object

Нужно отдельно определить:

Can(Service A, READ, Object O, Context)?

Получается та же последовательность:

Authentication
      ↓
Subject
      ↓
Authorization model
      ↓
Access decision

Техническая идентичность вызывающей стороны — только один из входов.

41.3 Сервис может действовать от имени пользователя

Более сложный случай:

User U
   ↓
Service A
   ↓
Service B

Service A передаёт запрос дальше.

Теперь Service B должен отличать:

"Service A is allowed to call me"

от:

"User U is allowed to access this object"

Это разные утверждения.

Например, Service A может иметь право вызывать API Service B для всех пользователей своего продукта.

Но конкретный пользователь может не иметь права читать конкретный объект.

Тогда:

Service A → CALL → Service B

не означает:

User U → READ → Object O

Второе решение требует собственной модели доступа.

41.4 Передача идентичности не должна превращаться в передачу всех прав

Если Service A передаёт Service B сведения о пользователе, это не означает, что Service B должен доверять всем утверждениям Service A без ограничений.

Например, запрос может содержать:

user_id
company_id
roles
permissions

Но возникает вопрос:

кто является источником истины для этих данных?

Если Service B принимает произвольное:

role = ADMIN

от другого сервиса, граница доверия фактически становится неограниченной.

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

Identity

и:

Authorization facts

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

41.5 У межсервисного доступа есть собственный контекст

Рассмотрим:

Service A
   ↓
Service B
   ↓
Object O

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

calling service
business subject
organization
requested action
object
delegation
purpose

Например:

Service A
acts for User U
in Company C
to READ Object O

Это уже полноценный контекст.

Если Service A вызывает Service B самостоятельно:

Service A
acts as itself
to UPDATE Object O

контекст будет другим.

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

"request came from Service A"

полным описанием доступа.

41.6 B2B добавляет отношения между организациями

В SaaS пользователь мог иметь доступ внутри одного tenant.

В B2B появляется связь:

Company A
   ↓
partner of
   ↓
Company B

Но само партнёрство не обязательно означает доступ ко всем данным.

Может существовать более точное отношение:

Company A
   ↓
supplier for
   ↓
Company B

или:

Company A
   ↓
service provider for
   ↓
Company B

или:

Company A
   ↓
participant in Project P
   ↓
Company B

Каждое отношение имеет собственную семантику.

Поэтому:

Company A is partner of Company B

не является готовым permission.

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

41.7 Межорганизационный доступ часто ограничен объектом

Пусть компании связаны:

Company A
   ↓
partner
   ↓
Company B

Это ещё не означает:

Company A → READ → all Company B data

В реальной системе доступ может быть ограничен:

Project P
Document D
Order O
API resource R

Например:

Company A
   ↓
supplier
   ↓
Company B
   ↓
Project P

и только данные проекта P доступны партнёру.

Контекст становится:

Company relationship
+
Project relationship
+
Object
+
Action

То есть B2B не устраняет объектную модель доступа.

Он добавляет к ней ещё один уровень отношений.

41.8 Делегирование соединяет пользователя, сервис и организацию

Рассмотрим цепочку:

User U
   ↓
Company A
   ↓
Service A
   ↓
Company B
   ↓
Object O

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

пользователь компании A через сервис A выполняет разрешённую операцию с объектом компании B.

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

Нужно определить, какие отношения являются допустимыми.

Например:

User U
   ↓
authorized to use
   ↓
Service A

и:

Service A
   ↓
authorized by
   ↓
Company B

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

Это хорошо показывает принцип из главы 14:

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

41.9 Не каждый сервис должен видеть весь security graph

В распределённой системе возникает соблазн передать каждому сервису всю информацию:

all users
all groups
all roles
all projects
all permissions
all relationships

Но это быстро превращается в отдельную проблему.

Каждому сервису нужен только тот набор security facts, который необходим для его собственных решений.

Например:

Service B

может знать:

User U
Company C
Project P
effective permission

и не знать всю организационную структуру платформы.

Это тот же принцип проекций:

Source security model
      ↓
Relevant projection
      ↓
Local authorization

Распределение модели не означает копирование всей модели в каждый сервис.

41.10 Локальная проверка особенно важна для физического доступа

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

Service A

проверил:

User U may READ Object O

и затем передал запрос Service B.

Service B всё равно должен обеспечить собственную границу данных, если он является владельцем этих данных.

Иначе получится:

Service A
   ↓
ALLOW
   ↓
Service B
   ↓
all rows

Так нельзя.

Сервис, владеющий данными, должен иметь собственную модель enforcement.

Поэтому в распределённой системе появляются как минимум две ответственности:

Service A
→ may initiate the operation

Service B
→ may expose these data

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

41.11 Межсервисная модель не должна превращаться в сетевую ACL

Можно пойти по простому пути:

Service A → allowed to call Service B

Это полезное правило, но оно отвечает только на один вопрос:

может ли Service A вызвать Service B?

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

какие данные Service A может получить?

Тем более оно не отвечает:

какие данные конкретный пользователь может получить через Service A?

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

Условно:

Network / service trust
        ↓
Service authorization
        ↓
Business subject
        ↓
Object authorization
        ↓
Data enforcement

Один уровень не заменяет другой.

41.12 Изменение B2B-отношения может изменить множество доступов

Пусть две организации больше не сотрудничают:

Company A
   ↓
partner
   ↓
Company B

отношение удаляется.

Объекты не меняются.

Пользователи не меняются.

Но множество допустимых действий может измениться сразу:

B2B relation revoked
       ↓
Security facts change
       ↓
Effective permissions change
       ↓
Access changes

Если отношения использовались в нескольких сервисах, изменение должно распространиться на соответствующие локальные security projections.

Это тот же принцип согласованности, который мы уже рассматривали внутри одной системы.

Только теперь область распространения проходит через границу сервисов.

41.13 Границы сервисов не отменяют необходимость единой семантики

Несколько сервисов могут иметь собственные базы:

Service A → DB A
Service B → DB B
Service C → DB C

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

Например, если:

"member of project"

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

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

semantic model

и:

local implementation

Каждый сервис может хранить свою проекцию.

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

41.14 Синхронизация модели — отдельная задача

Если security facts распространяются между сервисами, возникает вопрос:

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

Например:

Company A
   ↓
removed from Project P

а Service B ещё некоторое время содержит старое производное состояние.

Это переходное состояние.

Для него нужна явная семантика.

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

  • допускается ли временная задержка;

  • какие операции должны быть заблокированы;

  • как обрабатывается отзыв;

  • как обнаруживается потеря изменения;

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

  • как восстанавливается локальная проекция.

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

41.15 Snapshot и изменения решают разные задачи

При передаче security model между сервисами можно использовать два типа информации.

Первый:

Snapshot

— текущее состояние модели.

Второй:

Change

— изменение этого состояния.

Snapshot позволяет восстановить состояние.

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

Поэтому надёжная архитектура обычно должна учитывать оба сценария:

Known snapshot
      +
Subsequent changes

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

Это не специфично для B2B.

Это общий принцип для любой производной security model.

41.16 Сервис не должен доверять удалённой авторизации без собственной границы данных

Предположим, Service A отвечает:

ALLOW

Service B не должен автоматически воспринимать это как:

return any data

Если Service B владеет данными, он должен проверить собственные ограничения.

В зависимости от архитектуры это может быть:

  • собственная authorization projection;

  • локальный policy check;

  • ограничение запроса;

  • database policy;

  • RLS;

  • комбинация этих механизмов.

Главное — сохраняется принцип:

Authorization
≠
Data enforcement

Даже если authorization распределена между сервисами.

41.17 Один сервис может быть одновременно субъектом и владельцем данных

Роли сервисов не всегда фиксированы.

Например:

Service A
   ↓
calls
   ↓
Service B

но:

Service B
   ↓
calls
   ↓
Service C

При этом Service B одновременно:

  • субъект для Service C;

  • владелец данных для собственного домена;

  • посредник для Service A.

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

Нельзя сказать:

"Service B is trusted"

и считать вопрос закрытым.

Нужно определить:

trusted for what?
within which boundary?
for which action?
on which objects?

41.18 Межсервисный доступ особенно хорошо показывает ограниченность простого RBAC

Можно назначить:

Service A → role = CLIENT

Но этого недостаточно, если Service A работает:

  • с несколькими организациями;

  • с несколькими проектами;

  • от имени разных пользователей;

  • с разными типами объектов;

  • с разными операциями.

Тогда возникает знакомая конструкция:

Subject
+
Action
+
Object
+
Relationships
+
Context

Просто субъектом теперь может быть сервис.

Или пользователь через сервис.

Или организация.

Или комбинация этих сущностей.

41.19 Что B2B и межсервисный доступ добавляют к общей модели

В корпоративной системе основными отношениями были:

User
→ Department
→ Project
→ Object

В PLM добавилась структура самих объектов.

В RAG — множество источников и производных данных.

В SaaS — tenant и изоляция организаций.

B2B и межсервисный доступ добавляют ещё одну границу:

Subject
   ↓
Organization
   ↓
Relationship between organizations
   ↓
Service
   ↓
Object

Но принцип остаётся тем же.

Каждое отношение является фактом.

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

Контекст объединяет релевантные факты.

Эффективное разрешение является результатом.

Физический слой обеспечивает enforcement.

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

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

Им может быть:

User
Service
Organization

или пользователь, действующий через сервис.

Но изменение субъекта не меняет саму архитектурную задачу.

По-прежнему нужно определить:

кто действует
какое действие выполняется
над каким объектом
в каком контексте

и:

какие отношения являются основанием доступа

А затем:

Source facts
      ↓
Context
      ↓
Effective permission
      ↓
Authorization
      ↓
Data enforcement

В распределённой системе появляется ещё одна важная граница: доверие между участниками не должно автоматически превращаться в право на все данные.

Аутентифицированный сервис — ещё не всесильный сервис.

Партнёрская организация — ещё не владелец всех данных другой организации.

Пользователь, переданный через доверенный сервис, — ещё не пользователь с неограниченными правами.

Каждая граница должна иметь собственную семантику.

Именно поэтому межсервисный и B2B-доступ не требуют другого принципа.

Они показывают, насколько далеко этот принцип может быть распространён:

Object
   ↓
Relationships
   ↓
Context
   ↓
Access

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

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

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