authzcascade

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 13, 2026 License: AGPL-3.0 Imports: 4 Imported by: 0

Documentation

Overview

Package authzcascade — ДВЕРЬ РЕШЕНИЯ о доступе для собственных стражей iam.

───────────────────────────────────────────────────────────────────────────── ЧТО ЗДЕСЬ БЫЛО И ПОЧЕМУ ЭТОГО БОЛЬШЕ НЕТ

Пакет назывался каскадом потому, что каскад супер-доступа приходилось ДОСТРАИВАТЬ на пути запроса: внешний движок отношений знал только те кортежи, которые до него доехали очередью, поэтому отказ пересдавался ему второй раз — с «структурными фактами», прочитанными из закоммиченных строк iam и приложенными к вопросу как кортежи, действующие только на этот запрос.

Механизма нет. Решение принимает реляционная форма в собственной базе службы (`repo/kaname/pg/relverdict`): она поднимает цепь областей по своим таблицам тем же планом модели, из которого прежде компилировался ответ движка. Значит второй попытки нет не потому, что от неё отказались, а потому, что первая читает ровно те строки, которыми вторая её дополняла.

───────────────────────────────────────────────────────────────────────────── ЧТО ОСТАЛОСЬ И ПОЧЕМУ ИМЕННО ЗДЕСЬ

Client — одно значение, которое композиционный корень выдаёт КАЖДОМУ стражу.
         Оно и есть причина, по которой страж не может спросить «мимо»: другого
         значения в корне для него нет.

DerivableTypes — типы, чей структурный предок выводится из строки iam. Перечень
         остаётся владельцем вопроса «о каком типе цепь областей обязана
         высказаться», и его читает перепись источников звена
         (`internal/scopesourcecensus`). Выписанный рядом второй перечень не
         сдвинулся бы от нового типа и продолжал бы сторожить прежние.

Index

Constants

This section is empty.

Variables

View Source
var DerivableTypes = map[string]struct{}{
	"iam_access_binding":  {},
	"account":             {},
	"project":             {},
	"iam_user":            {},
	"iam_group":           {},
	"iam_role":            {},
	"iam_service_account": {},
}

DerivableTypes — типы объектов модели прав, чей структурный предок выводится из закоммиченной строки kaname: у такой строки предок лежит КОЛОНКОЙ, поэтому чтение однозначно.

Экспортирован ради переписи источников звена цепи областей: она обязана высказаться о каждом таком типе, включая тип с нулём объектов, и берёт перечень у владельца, а не выписывает свой.

View Source
var ErrFormNotWired = fmt.Errorf("authzcascade: дверь решения собрана без формы — спросить не у кого")

ErrFormNotWired — дверь собрана без формы.

Отдельная ошибка, а не «нет»: тип, у которого источник ответа не провязан, отвечал бы отказом на КАЖДЫЙ вопрос, и снаружи это неотличимо от честного отказа модели.

Functions

This section is empty.

Types

type Asker

type Asker interface {
	// Allowed — вердикт об объекте. Ошибка означает «ответа нет».
	Allowed(ctx context.Context, subject, objectType, objectID, relation string,
		condCtx map[string]any) (bool, error)
	// AllowedMany — вердикт о СТРАНИЦЕ объектов одного типа, одной читающей
	// транзакцией: все объекты страницы видят один снимок базы.
	AllowedMany(ctx context.Context, subject, objectType string, objectIDs []string,
		relation string, condCtx map[string]any) ([]bool, error)
	// SubjectsPage — кто держит отношение на объекте, страницей с курсором.
	SubjectsPage(ctx context.Context, objectType, objectID, relation, afterID string,
		limit int) (subjects []string, nextAfter string, err error)
	// Sources — кого называют основания права на объекте (разбор «почему»).
	Sources(ctx context.Context, objectType, objectID, relation string) ([]string, error)
	// DirectRelations — какие отношения субъект уже держит на объекте (текст отказа).
	DirectRelations(ctx context.Context, subject, objectType, objectID string,
		limit int) ([]string, error)
	// DirectRelationsMany — то же о СТРАНИЦЕ объектов одного типа, одним вопросом:
	// хвост текста отказа платится на каждом отказанном объекте, а страница
	// списка отказами и состоит.
	DirectRelationsMany(ctx context.Context, subject, objectType string, objectIDs []string,
		limit int) (map[string][]string, error)
}

Asker — реляционная форма, отвечающая на вопрос о доступе своей базой.

Объявлен ПОРТОМ, а не конкретным типом, по двум причинам: дверь остаётся переходником и не тянет за собой pgx, а проба может подставить форму, которая НЕ ОТВЕЧАЕТ, — иначе исход «форма не ответила» непроверяем, а он тут главный.

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client — дверь решения поверх формы.

func Wrap

func Wrap(form Asker) *Client

Wrap собирает дверь.

nil-форма — законный вход только для пробы, которая о доступе не спрашивает вовсе: каждый вопрос к такой двери возвращает ОШИБКУ, а не «нет». Боевая посадка в этом состоянии находиться не должна, и это проверяет отказ в старте (`ownGateWiringComplaint`), а не надежда.

func (*Client) BatchCheckWithContext

func (c *Client) BatchCheckWithContext(
	ctx context.Context, subject, relation string, objects []string, condCtx map[string]any,
) ([]bool, error)

BatchCheckWithContext — clients.RelationQueries / authzfilter.BatchObjectChecker.

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

func (*Client) Check

func (c *Client) Check(ctx context.Context, subject, relation, object string) (bool, error)

Check — clients.RelationStore / authzguard.RelationChecker.

func (*Client) CheckWithContext

func (c *Client) CheckWithContext(
	ctx context.Context, subject, relation, object string, condCtx map[string]any,
) (bool, error)

CheckWithContext — clients.RelationQueries / authzguard.ContextRelationChecker / authzfilter.ObjectChecker.

func (*Client) CheckWithContextConsistent

func (c *Client) CheckWithContextConsistent(
	ctx context.Context, subject, relation, object string, condCtx map[string]any,
) (bool, error)

CheckWithContextConsistent — вопрос, которому нужен СВЕЖИЙ ответ.

У формы это тождество обычному вопросу, и это не упрощение: она читает ведущую базу службы, а «сильное чтение» существовало ровно затем, чтобы заставить чужое хранилище не отвечать со своей отстающей копии. Метод остаётся ИМЕНЕМ вопроса — вызывающий по-прежнему объявляет, что отставание ему недопустимо, — и перестаёт быть просьбой к чужому транспорту.

func (*Client) DirectRelations

func (c *Client) DirectRelations(
	ctx context.Context, subject, objectType, objectID string, limit int,
) ([]string, error)

DirectRelations — какие отношения субъект уже держит на объекте.

func (*Client) DirectRelationsMany

func (c *Client) DirectRelationsMany(
	ctx context.Context, subject, objectType string, objectIDs []string, limit int,
) (map[string][]string, error)

DirectRelationsMany — те же прямые отношения о СТРАНИЦЕ объектов одного типа.

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

func (*Client) FormReachable

func (c *Client) FormReachable() bool

FormReachable — есть ли у двери чем отвечать. Читает страж старта.

func (*Client) ListSubjects

func (c *Client) ListSubjects(
	ctx context.Context, objectType, objectID, relation string, pageSize int, pageToken string,
) ([]string, string, error)

ListSubjects — clients.RelationQueries: кто держит отношение на объекте.

Курсор проходит НАСКВОЗЬ: страница без продолжения оставляет остаток недостижимым при живых правах.

func (*Client) ListUsers

func (c *Client) ListUsers(
	ctx context.Context, objectType, objectID, relation string, userTypes []string,
) ([]string, bool, error)

ListUsers — access_binding.PrincipalLister: развёрнутый набор принципалов.

Второй результат — признак усечения У ИСТОЧНИКА. Форма его не производит: перечисление постранично и продолжаемо, поэтому неполного ответа, о котором нельзя спросить дальше, у неё не бывает. Признак остаётся в подписи, потому что его читает вызывающий, и всегда false — это ЧЕСТНОЕ значение, а не заглушка.

userTypes сужает по типу субъекта; пустой набор — «любой».

func (*Client) Sources

func (c *Client) Sources(ctx context.Context, objectType, objectID, relation string) ([]string, error)

Sources — кого называют основания права на объекте.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL