Глава 30. PostgreSQL как часть модели безопасности
30.1. База данных как граница применения
База данных обычно рассматривается как место хранения.
В модели с RLS она становится ещё и местом принудительного применения ограничений.
Это не означает, что база данных становится владельцем всей модели авторизации.
Она получает дополнительную ответственность:
не вернуть физические строки, которые не должны быть доступны текущему запросу.
30.2. Авторизация и RLS — разные уровни
Полезно разделять:
Authorization
и:
Data enforcement
Авторизация отвечает:
Can(Subject, Action, Object)?
RLS отвечает:
Which rows can this SQL operation see or modify?
Поэтому архитектурно:
Relationship-based authorization
↓
Effective permission
↓
Object authorization
↓
PostgreSQL RLS
↓
Physical data
30.3. PostgreSQL не должен строить весь контекст
Если доступ зависит от длинной цепочки:
User
→ Group
→ Parent Group
→ Project
→ Role
→ Publication
→ Object
нет необходимости заставлять RLS каждый раз вычислять весь этот граф.
Это уже было сделано на этапе построения security projections.
База получает более компактное условие.
Так разделяются:
model construction
и:
data enforcement
30.4. Что именно проверяется в Guardian
Для объектной авторизации текущая схема использует:
object_scope
и:
effective_user_permission
Обычная ветка сопоставляет:
scope_type
scope_id
и проверяет:
permissionMask
&
publicationMask
&
requiredMask
Владелец проверяется отдельно через OWNER-scope.
Таким образом, PostgreSQL участвует в принятии решения, но получает уже материализованную модель.
30.5. Почему это не «Zanzibar внутри PostgreSQL»
Relationship-based подход и PostgreSQL RLS решают разные задачи.
Relationship-based authorization определяет, какие отношения и правила приводят к разрешению.
RLS ограничивает физические строки.
Поэтому архитектура может выглядеть так:
Relationship facts
↓
Security projections
↓
Authorization
↓
PostgreSQL RLS
Это не означает, что PostgreSQL является authorization engine целиком.
30.6. Контекст пользователя в базе
Чтобы RLS мог применять пользовательские ограничения, база должна знать контекст текущего запроса.
В Guardian используется:
current_company_id
current_user_id
Эти значения устанавливаются в рамках управляемого соединения.
Важно, что они не должны сохраняться как неконтролируемое состояние connection pool.
30.7. RlsDataSourceProxy
В текущей архитектуре приложение получает:
@Primary DataSource
↓
RlsDataSourceProxy
↓
physicalDataSource
Прокси не выполняет побочные SQL-операции просто при получении соединения.
RLS-контекст устанавливается лениво перед первым бизнес-SQL.
Это позволяет связать security context с тем же физическим соединением, на котором выполняется запрос.
30.8. Почему Flyway использует отдельный источник
Миграции базы данных — инфраструктурная операция.
Они не должны зависеть от пользовательского:
company_id
user_id
Поэтому:
Flyway
↓
physicalDataSource
а бизнес-приложение:
Hibernate / repositories
↓
RlsDataSourceProxy
Это два разных контекста доверия.
30.9. RLS как защита от ошибки приложения
Допустим, разработчик написал новый запрос:
SELECT *
FROM documents
и забыл добавить фильтр доступа.
Если единственной защитой была логика приложения, запрос может вернуть лишние данные.
При наличии корректного RLS запрос всё равно проходит через физическую границу:
SQL
↓
RLS policy
↓
allowed rows
Это не отменяет необходимость правильной авторизации.
Но создаёт дополнительный уровень защиты от ошибок конкретного пути доступа.
30.10. Почему RLS не должен быть универсальным
Не вся информация обязана защищаться одинаковым способом.
Для одних данных естественной границей являются строки.
Для других:
-
бизнес-операция;
-
состояние процесса;
-
отдельное поле;
-
внешний сервис;
-
документ;
-
результат вычисления.
Поэтому решение:
Всё защитим RLS
так же неправильно, как:
Ничего не будем защищать на уровне базы.
RLS должен соответствовать физической структуре данных и модели угроз.
30.11. Главный вывод
PostgreSQL может быть частью security architecture, не становясь всей моделью безопасности.
В рассматриваемой архитектуре его роль можно выразить так:
Source security facts
↓
Security projections
↓
Effective authorization
↓
Object authorization
↓
PostgreSQL RLS
↓
Physical data
Проекции строят производное состояние.
Авторизация принимает логическое решение.
RLS физически ограничивает данные.
Так три разных задачи остаются различимыми.