Documentation
¶
Overview ¶
Package accesssnapshot снимает множество объектов, доступных субъекту, и сравнивает два таких снимка.
Инструмент существует ради одного утверждения перехода IAM-ID-1: права переносятся, НЕ РАСШИРЯЯСЬ. Пока оно не закреплено, перенос доказан только косвенно.
Почему страница + пообъектная проверка, а НЕ перечисление разрешённого ¶
Соблазн — спросить у движка прав «перечисли всё, что доступно». Так делать нельзя, и причина не в стиле: перечисление разрешённых объектов имеет ЖЁСТКИЙ серверный предел, не имеет продолжения, и предел этот ОБЩИЙ НА ТИП, а не по-арендаторный (`security.md` §«Фильтрация — страница → проверка страницы»). Сравнение двух УСЕЧЁННЫХ множеств сойдётся «элемент в элемент», не доказав ничего, — и выглядеть это будет как успех.
Поэтому: страница курсором ИЗ СВОЕЙ БАЗЫ → пообъектная проверка партиями ≤100 → следующая страница. Своя база предела не имеет и перечисляет ровно то, что в ней лежит.
Бюджет времени принадлежит ЗАПРОСУ, а не партии ¶
Партии исполняются параллельно под ОДНИМ сроком вызывающего. Последовательные партии превращают срок в сумму сроков: на странице контрактного размера снимок не укладывался бы в бюджет и давал бы отказ на ПОЛОЖИТЕЛЬНОМ пути. Сужать страницу ради бюджета запрещено — размер страницы часть контракта.
Почему снимок несёт ЧИСЛО ОСМОТРЕННОГО ¶
Пустое множество равно пустому. Снимок, не собравшийся ни по какой причине (курсор не отдал строк, движок отказал, грант пуст), сравнивается с таким же пустым — и объявляет перенос доказанным. Поэтому снимок несёт `Examined`, а `Compare` ОТКАЗЫВАЕТСЯ сравнивать, когда осмотрено ноль: «ноль находок» обязано быть отличимо от «ноль прочитанного».
Index ¶
Constants ¶
const BatchSize = 100
BatchSize — сколько объектов уходит в одну партию проверок. Потолок партии — 100 (`security.md` §AuthN/AuthZ).
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Checker ¶
type Checker interface {
Check(ctx context.Context, subject, relation, object string) (bool, error)
}
Checker — то, чем задаётся вопрос о доступе. Реализуется продовым клиентом движка прав: инструмент обязан спрашивать ТУ ЖЕ сторону, что и продукт, иначе он утверждает про свою копию правил.
type Diff ¶
type Diff struct {
// Lost — было доступно, стало недоступно. Потеря есть дефект переноса.
Lost []string
// Gained — не было доступно, стало доступно. Приобретение есть РАСШИРЕНИЕ
// доступа, и оно опаснее потери: потеря шумит, расширение молчит.
Gained []string
}
Diff — что потеряно и что приобретено между двумя снимками.
func Compare ¶
Compare сверяет два снимка ПО СОСТАВУ и отказывается сравнивать пустоту.
Отказ — не придирка: снимок, не собравшийся ни по какой причине, сравнивается с таким же пустым и объявляет перенос доказанным. Это то же «ноль находок неотличимо от ноль прочитанного», только про права, — и цена ошибки здесь выше, потому что её не видно.
type PageFunc ¶
PageFunc отдаёт следующую страницу идентификаторов объектов ИЗ СВОЕЙ БАЗЫ, курсором после afterID. Пустой срез означает «страниц больше нет».
type Snapshot ¶
type Snapshot struct {
// Allowed — идентификаторы объектов, на которые движок ответил разрешением.
Allowed map[string]struct{}
// Examined — сколько объектов вообще прошло через проверку. Ноль означает,
// что снимок не собрался, а НЕ что доступа нет.
Examined int
}
Snapshot — что субъекту доступно и СКОЛЬКО объектов для этого осмотрено.
func Take ¶
func Take( ctx context.Context, ch Checker, page PageFunc, subject, relation, objectType string, ) (Snapshot, error)
Take снимает множество доступных субъекту объектов одного типа.
relation — глагол, который спрашивают (например "v_get"); objectType — префикс объекта в модели прав (например "project"). Идентификаторы приходят из page.