Права и scopes¶
Справочник по авторизации: права (permissions) Control Plane, роли,
IAM audiences и scopes всех сервисов, правило пересечения прав со scope
токена и то, какие права и потолки выдаёт make bootstrap. Статья для
администратора tenant и инженера, который заводит агентов и сервисы.
Два слоя: identity и доменные права¶
flowchart LR
PAT[PAT / client credentials] -->|обмен в IAM| AT["access token<br/>aud = один сервис<br/>scope = потолок"]
AT --> RS[Resource service]
RS -->|binding issuer + principal| PERM[Локальные права сервиса]
PERM -->|∩ scope токена| EFF[Эффективные права запроса]
- IAM удостоверяет identity и выдаёт короткоживущий access token на один audience (один сервис) со scopes — потолком полномочий токена. Доменных прав в токене нет.
- Resource service (Control Plane, память, policy-service …) сам решает,
что principal может делать. В Control Plane права хранятся в
binding — строке
iam_principal_bindings, связывающей IAM principal с локальным principal. - Эффективные права запроса — пересечение прав binding и scope токена. Scope только сужает, никогда не расширяет.
Подробнее — Модель безопасности и Токены, audiences, scopes.
Права Control Plane¶
Права — плоские строки, перечисление Permission в
control_plane/domain/enums.py. Проверка «хотя бы одно из» (require).
Право admin покрывает любое другое.
| Право | Что разрешает (область API) |
|---|---|
principals.read |
Чтение principals, их ролей, capabilities, skills. |
principals.write |
Создание и изменение principals; IAM-bindings (/principals/{id}/iam-bindings, :revoke). Выдать права, которых нет у вызывающего, нельзя (permission_escalation). |
delegations.manage |
Делегирования «агент действует от имени человека»; список делегирований. |
sessions.open |
Открыть сессию харнесса (POST /sessions), продлевать свою сессию. |
sessions.manage |
Управлять чужими сессиями; список сессий. |
tasks.read |
Чтение задач, связей, комментариев, внешних ссылок; контекст задачи. |
tasks.write |
Создание и изменение задач, связей, комментариев; переходы статусов. |
tasks.claim |
Взять задачу (claim), запускать runs, писать checkpoints, actions, handoff, завершать run. |
claims.manage |
Управлять чужими claims и runs: освобождение, reclaim, отмена, run controls, отзыв child handle. |
events.read |
Журнал событий (GET /events, WebSocket-поток). |
workspaces.read |
Чтение workspaces и дерева. |
workspaces.manage |
Создание, перемещение, архивирование workspaces; типы workspace. |
org.read |
Чтение ролей, capabilities, skills каталога. |
org.manage |
Создание и изменение ролей, capabilities, skills; назначение их principals. |
artifacts.read |
Чтение артефактов. |
artifacts.write |
Регистрация артефактов. |
approvals.read |
Чтение approvals. |
approvals.manage |
Создание и отмена approvals. |
approvals.decide |
Решение по approval (approve/reject). Только для людей. |
observations.write |
Запись наблюдений и снимков знаний в память через ядро. |
projects.read |
Чтение project profiles и их конфигурации. |
projects.manage |
Создание и изменение project profiles, ревизий конфигурации. |
project_templates.read |
Чтение шаблонов проектов. |
project_templates.manage |
Создание и изменение шаблонов проектов. |
operations.read |
Операционные сведения (состояние доставки, курсоры потребителей). |
operations.manage |
Операционные действия: redrive адаптера, архивирование и очистка журнала, rebuild курсора. |
task_types.read |
Чтение типов задач и их жизненного цикла. Нужен демону исполнителя, чтобы брать типизированную работу. |
task_types.manage |
Создание версий типов задач. |
skills.invoke |
Попросить ядро вызвать skill. |
skills.execute |
Исполнять вызовы skills (право исполнителя-транспорта). |
processes.read |
Чтение определений процессов, экземпляров и их журналов (на workspace процесса, без него — на tenant). См. Процессы. |
processes.write |
Публикация версии процесса (на workspace процесса). |
processes.operate |
Явный старт экземпляра, :suspend, :resume, :cancel (на workspace экземпляра). |
packages.test |
Проверка и тесты пакета в песочнице ядра, replay процесса (/packages:test, :replay). |
packages.plan |
План и применение пакета (/packages:plan, /packages:apply); применение требует ещё права видов. |
calendars.write |
Публикация производственного календаря. |
goals.read |
Чтение целей (Goals). |
goals.write |
Создание и изменение целей. |
admin |
Все права. Только для людей и только под scope control-plane:admin. |
Только для людей
admin и approvals.decide нельзя выдать principal вида agent или
service: создание такого binding отвечает
422 permissions_not_allowed_for_kind. Решение по approval и полный
доступ остаются за человеком.
Пересечение со scope токена¶
Правило narrow_permissions в control_plane/infrastructure/auth/iam.py:
| Scope в токене | Какие права binding остаются |
|---|---|
control-plane:admin |
Все права binding без сужения (включая admin). |
control-plane:write |
Все права, кроме admin и кроме *.read (если нет control-plane:read). |
control-plane:read |
Только права, оканчивающиеся на .read. |
control-plane:read + control-plane:write |
Все права binding, кроме admin. |
| ни одного | Ни одного права. |
Пример: у оператора binding со всеми правами, но токен выпущен со scope
control-plane:read — запрос на создание задачи получит
403 permission_denied.
IAM principal bindings¶
Binding ищется по паре (issuer, IAM principal id). Следствия:
- Смена публичного адреса (
TAIMEN_PUBLIC_URL) меняет issuer IAM, и все bindings перестают находиться — вход закрывается. Bindings нужно переносить одновременно со сменой адреса. - Заводите binding до первого запроса principal. Отказ
binding_not_foundкэшируется как отзыв credential наCP_IAM_BINDING_STALE_AFTER_SECONDS(по умолчанию 120 с). Изменение binding через API Control Plane сбрасывает кэш этой identity в процессе, который обработал запрос; если binding появился в обход API (например, SQL-ом) или API работает в нескольких экземплярах, отказ держится до истечения этого окна либо до перезапускаcontrol-plane-api. - Статусы binding:
active,disabled,revoked. Отключённый binding даёт тот же401 invalid_credentials, что и отсутствующий. - Управление — API Control Plane:
POST /api/v1/bootstrapс полемiamBinding,GET/POST /api/v1/principals/{id}/iam-bindings,…/iam-bindings/{id}:revoke.
Одна IAM identity может быть связана только с одним tenant Control Plane
(409 iam_identity_bound_elsewhere).
Доменная авторизация через policy-service¶
При CP_AUTHZ_MODE=policy решение по запросу с IAM-субъектом принимает
policy-service по каталогу действий control-plane/authz/catalog.yaml
(имена действий совпадают с правами). В режиме shadow решает локальная
проверка, а PDP опрашивается параллельно и расхождения пишутся в журнал.
Legacy-ключи всегда проверяются локально. Недоступность PDP даёт
503 decision_unavailable — запрос не выполняется (fail closed). См.
Авторизация и права и
Policy Service.
Роли¶
В платформе три разных понятия «роль» — не путайте их.
| Где | Что это | Как управляется |
|---|---|---|
| Control Plane | Организационная роль (slug, name, опционально workspaceId). Используется в требованиях задач (requirements: role / capability / skill), в approvals (requiredRoleId) и в контекстных кортежах policy. Права не даёт. |
POST /api/v1/roles, POST /api/v1/principals/{id}/roles (право org.manage); роли из пакетов каталога ставит make bootstrap. |
| policy-service | Набор действий каталогов (key, kind: системная или пользовательская), назначаемый principal в scope tenant или workspace с окном действия. |
Admin API policy-service (policy:admin или bootstrap-токен). make bootstrap создаёт системную роль tenant-admin со всеми действиями зарегистрированных каталогов и назначает её оператору на tenant. |
| Keycloak (панель платформы) | Роли realm platform: org_admin, platform_admin, billing_admin, editor, member, viewer. Видимость модулей консоли. |
Admin API Keycloak. |
IAM audiences и scopes¶
Audience — идентификатор одного resource service. Токен выпускается ровно
на один audience; список audiences в aud сервисы отвергают. Допустимые
scopes audience задаёт реестр IAM (allowedScopes), make bootstrap
приводит их к списку ниже идемпотентно.
| Audience | Scopes | Смысл |
|---|---|---|
control-plane |
control-plane:read, control-plane:write, control-plane:admin |
Потолок доменных прав Control Plane (см. таблицу пересечения). |
memory-service |
memory:read |
Чтение namespaces токена. |
memory:write |
Запись в namespaces токена. | |
memory:pii |
Полный доступ к персональным данным; без него при CB_PII_PROTECTION=true выдача маскируется. |
|
memory:tenants |
Всё поддерево tenant:* независимо от tenant токена. Только service account ядра. |
|
memory:on-behalf |
Сервис читает память от имени principal с переданной видимостью (при CB_POLICY_ENABLED). |
|
memory:service |
Service scope ядра: реестр доменных пакетов видов, reconcile, виды namespace. Только service account ядра. | |
policy-service |
policy:check |
Проверки для собственного principal. |
policy:check-on-behalf |
Проверки за конечного principal (resource services). | |
policy:admin |
Роли и bindings tenant. | |
entitlement-service |
entitlement:check-on-behalf |
Проверка лицензии пользователя от имени resource service. |
iam-scim |
scim:write (настраивается IAM_SCIM_AUDIENCE, IAM_SCIM_SCOPE) |
SCIM-provisioning; только confidential service identity. |
Namespaces памяти, доступные IAM-токену без memory:tenants:
tenant:<tenant_id> и поддерево tenant:<tenant_id>:*, плюс namespaces из
claim memory_namespaces (каждый — ровно и с поддеревом). Токен без
scopes памяти валиден, но не покрывает ни одного namespace.
Как выбираются scopes при обмене¶
| Обмен | Правило |
|---|---|
PAT → access token (POST /api/v1/platform-access-tokens:exchange) |
Audience должен быть в списке audiences PAT и активен в tenant. Запрошенные scopes ⊆ (потолок PAT ∩ allowedScopes); пустой запрос — весь этот пересечённый потолок. Нарушение — 403 audience_not_allowed / 403 scope_not_allowed. |
Client credentials (POST /api/v1/tokens/exchange) |
Audience — в списке audiences service account. Запрошенные scopes ⊆ потолок service account и ⊆ allowedScopes. Выдаются ровно запрошенные. |
Федерация (POST /api/v1/tenants/{t}/federation:exchange) |
Только human principal. Scopes ⊆ allowedScopes; пустой запрос — все allowedScopes. |
Scope — всегда с префиксом audience
Короткие read/write не существуют: запрос scopes: ["read"]
получит 403 scope_not_allowed. Пишите control-plane:read.
Кому IAM выпускает PAT¶
PAT выпускается только principal вида human или agent; для
service_account — 422 principal_kind_not_allowed (сервисы используют
client credentials). Человеку нужен свежий authentication context (не
старше IAM_PAT_MAX_AUTHENTICATION_AGE_SECONDS, по умолчанию 300 с).
Потолок PAT (scopeCeiling) должен входить в allowedScopes его
audiences (422 invalid_scope_ceiling). Подробнее —
Credentials и PAT.
Что выдаёт make bootstrap¶
deploy/bootstrap.py заводит identity и права идемпотентно (состояние —
deploy/state/<env>.json).
Human-оператор¶
| Что | Значение |
|---|---|
| IAM principal | kind: human |
| Binding в Control Plane | Все права (ALL_PERMISSIONS), создаётся вместе с tenant в POST /api/v1/bootstrap |
| PAT | secrets/harness-pat, audience control-plane, потолок control-plane:read, control-plane:write, control-plane:admin, срок --pat-ttl (по умолчанию 180 дней) |
| policy-service | Роль tenant-admin на scope tenant (если поднят профиль policy) |
Агенты¶
Исполнителей bootstrap не заводит: агента описывает пакет каталога (вид
Agent), права связки берутся из identity.permissions описания, а principal
и PAT выпускает платформа — см. Декларативные агенты.
Агенту нельзя admin и approvals.decide.
task_types.read обязателен исполнителю
Без task_types.read демон исполнителя не берёт типизированную работу
(fail closed): иначе задачу, предназначенную скиллу, мог бы забрать
кодовый адаптер.
Service accounts¶
| Service account | Audiences | Потолок scopes | Права в Control Plane | Где секрет |
|---|---|---|---|---|
| Control Plane (ядро) | memory-service, entitlement-service, policy-service |
memory:read, memory:write, memory:tenants, memory:on-behalf, memory:service, entitlement:check-on-behalf, policy:check, policy:check-on-behalf |
— | secrets/control-plane-iam.env |
Memory Service (профиль policy) |
policy-service |
policy:check, policy:check-on-behalf |
— | secrets/memory-service-iam.env |
Policy Projection (профиль policy) |
control-plane |
control-plane:read |
events.read (principal вида service) |
secrets/policy-service-cp.env |
При изменении потолка service account ядра bootstrap выпускает новый
service account и отзывает прежний; после этого перезапустите
control-plane-api, control-plane-worker, context-adapter.
Типичные вопросы¶
Агент получает 403 permission_denied на POST /api/v1/tasks/{id}:claim.
Проверьте три вещи: в binding есть tasks.claim; токен обменян со scope
control-plane:write; при CP_AUTHZ_MODE=policy у principal есть роль с
действием tasks.claim в scope workspace задачи.
Человек видит задачи, но не может решить approval. Нужно право
approvals.decide и scope control-plane:write; при политике — ещё и то,
что решающий не является автором запроса.
Сервис памяти отвечает 403 токену ядра на регистрацию пакета. В токене
нет memory:service: проверьте CP_CONTEXT_IAM_SCOPES и потолок service
account ядра.