RBAC и авторизация

Корпоративный справочник по текущей реализации аутентификации, авторизации и machine-access runtime в CodeGraph.

Область действия и источник истины

Документ описывает реализацию, которая сейчас находится в src/.

Канонические code surfaces:

Область Источник
Permission enum и role mapping src/api/auth/tokens/permissions.py
Request auth context и FastAPI auth dependencies src/api/auth/providers/middleware.py
JWT creation, validation и blacklist src/api/auth/tokens/jwt_handler.py
User API-key helpers src/api/auth/tokens/api_keys.py
Machine credential catalog и authorization src/api/auth/machine/machine_access.py
Machine audit, project scope и optional mTLS binding src/api/auth/machine/machine_runtime.py
API-key/service-account middleware src/api/middleware/scope_enforcement.py
Path validation middleware src/api/middleware/path_validation.py
Local, OAuth, LDAP, API-key, service-account routes src/api/routers/auth_suite/*
User, API-key, tenant, project-access и service-account models src/api/database/models_*.py

Compatibility imports намеренно сохранены через src/api/auth/__init__.py: package path дополняется каталогами machine, providers и tokens. В новых ссылках лучше указывать физические пути из таблицы выше.

Runtime-модель

CodeGraph использует три связанных слоя авторизации:

Слой Что контролирует Основная реализация
User RBAC Ролевые разрешения human users для route dependencies и application logic Permission, Role, ROLE_PERMISSIONS, has_permission()
Machine scopes Доступ API keys и service accounts к API/MCP routes MachinePrincipal, API_ROUTE_SCOPE_MAP, MCP_ROUTE_SCOPE_MAP, authorize_machine_request()
Tenant/project scope Group membership и selected project access в multi-tenant инсталляциях GroupRole, ProjectScopeMode, UserGroupAccess, UserProjectAccess, project repositories

Методы аутентификации создают user identity или machine principal. Затем авторизация проверяет role permissions, raw scopes, interface allowlists, tenant/project restrictions и security middleware.

Пользовательские роли и разрешения

Роли

Роли пользователя определены в двух enum для разных границ:

Enum Источник Назначение
Role src/api/auth/tokens/permissions.py Permission checks в auth dependencies
UserRole src/api/database/models_base.py Persisted user role в application DB

Оба enum сейчас используют одинаковые значения:

Роль Value Смысл
VIEWER viewer Read-only product access
ANALYST analyst Viewer плюс query/scenario execution, session writes, API-key creation, базовая работа с digital-employee tasks
REVIEWER reviewer Analyst плюс review integrations и higher-risk digital-employee operations
ADMIN admin Platform admin role

src/api/dependencies.py::require_role() трактует роли как иерархию: viewer < analyst < reviewer < admin.

Поведение permission checks

Permission сейчас содержит 31 значение, включая admin:all.

Важные runtime-детали:

  • ROLE_PERMISSIONS[Role.ADMIN] хранит только {Permission.ADMIN_ALL}.
  • get_role_permissions(Role.ADMIN) возвращает этот raw set; он не разворачивает его во все permissions.
  • has_permission(Role.ADMIN, ...) возвращает True для любого запрошенного permission.
  • Explicit scopes также дают доступ, если строка scope совпадает с Permission.value.
  • Scope admin:all дает все permission checks в has_permission() и обходит machine scope checks.

Каталог permissions

Permission Enum name Viewer Analyst Reviewer Admin
scenarios:read SCENARIOS_READ x x x x
scenarios:execute SCENARIOS_EXECUTE x x x
query:execute QUERY_EXECUTE x x x
query:validate QUERY_VALIDATE x x x
review:execute REVIEW_EXECUTE x x
review:github REVIEW_GITHUB x x
review:gitlab REVIEW_GITLAB x x
sessions:read SESSIONS_READ x x x x
sessions:write SESSIONS_WRITE x x x
sessions:delete SESSIONS_DELETE x x x
history:read HISTORY_READ x x x x
history:export HISTORY_EXPORT x x x
users:read USERS_READ x
users:write USERS_WRITE x
users:delete USERS_DELETE x
api_keys:read API_KEYS_READ x x x
api_keys:write API_KEYS_WRITE x x x
api_keys:delete API_KEYS_DELETE x
stats:read STATS_READ x x x x
metrics:read METRICS_READ x
digital_employees:read DIGITAL_EMPLOYEES_READ x x x
digital_employees:task:write DIGITAL_EMPLOYEES_TASK_WRITE x x x
digital_employees:task:high_risk DIGITAL_EMPLOYEES_HIGH_RISK_TASK x x
digital_employees:handoff:write DIGITAL_EMPLOYEES_HANDOFF_WRITE x x
digital_employees:approval:write DIGITAL_EMPLOYEES_APPROVAL_WRITE x x
digital_employees:audit:write DIGITAL_EMPLOYEES_AUDIT_WRITE x x
digital_employees:external_publish:write DIGITAL_EMPLOYEES_EXTERNAL_PUBLISH x x
digital_employees:lifecycle:write DIGITAL_EMPLOYEES_LIFECYCLE_WRITE x
digital_employees:control_tower:repair DIGITAL_EMPLOYEES_CONTROL_TOWER_REPAIR x
digital_employees:admin DIGITAL_EMPLOYEES_ADMIN x
admin:all ADMIN_ALL x

ROLE_PERMISSIONS сейчас не включает USERS_*, API_KEYS_DELETE, METRICS_READ, admin-only digital-employee permissions и ADMIN_ALL для не-admin ролей. На практике они доступны через Role.ADMIN или explicit scope admin:all.

Permission helpers

Для role/scope checks используйте src.api.auth.permissions:

from src.api.auth.permissions import (
    Permission,
    Role,
    get_default_scopes_for_api_key,
    get_role_permissions,
    has_all_permissions,
    has_any_permission,
    has_permission,
    validate_scopes,
)

Ключевое поведение:

  • get_default_scopes_for_api_key() возвращает scenarios:read, scenarios:execute, query:execute, sessions:read, sessions:write, history:read.
  • validate_scopes() фильтрует неизвестные строки по Permission enum.
  • has_permission() сначала учитывает role grants, затем explicit scope strings.

FastAPI Auth Context

AuthContext определен в src/api/auth/providers/middleware.py.

Поля:

Поле Смысл
user_id Human user id, если есть
subject_id Канонический subject id: user id или service-account id
subject_type user или service_account
username Display name или username
role Optional Role для user RBAC
scopes Raw permission/scope strings
auth_method jwt, api_key, service_account_api_key, iam, local_plugin или none
group_id Optional tenant/group scope
project_id Optional project scope для service accounts
service_account_id Service-account id при machine auth
credential_id API key или service-account credential id
allowed_interfaces Interfaces, разрешенные для authenticated subject

Основной dependency flow:

  1. Повторно использовать request.state.machine_principal, если ScopeEnforcementMiddleware уже проверил API key.
  2. Проверить X-YC-IAM-Token, если IAM включен.
  3. Проверить JWT bearer token и отклонить blacklisted JWT ids.
  4. Проверить X-API-Key как machine credential.
  5. Вернуть unauthenticated context, если валидных credentials нет.

Route code должен использовать эти dependencies:

from src.api.auth.middleware import (
    get_auth_context,
    get_current_user,
    get_optional_user,
    require_admin,
    require_analyst,
    require_any_permission,
    require_auth,
    require_auth_or_localhost,
    require_permission,
    require_reviewer,
    require_role,
)

require_auth_or_localhost() разрешает local plugin traffic только при security.local_dev_unauthenticated_surfaces_enabled=true и loopback-запросе. Mutating local-plugin requests должны содержать X-Actor-Agent-Id и X-Task-Id; generic agent ids вроде codex или codex-headless отклоняются.

src/api/dependencies.py также содержит database-backed dependencies, которые возвращают ORM User. Auth-suite routes используют их для account administration и API-key CRUD.

Методы аутентификации

Local username/password

Routes монтируются под /api/v1/auth:

Route Назначение
POST /register Создать local user и вернуть tokens
POST /login Login alias для token issuance
POST /token Основной username/password token endpoint
POST /refresh Rotate refresh token и выдать новые tokens
DELETE /logout Добавить текущий bearer token в blacklist
POST /oauth/token RFC 6749-compatible password и refresh-token grants

Local passwords хешируются через bcrypt. Новые self-registered users получают роль analyst.

JWT Bearer Tokens

JWT code находится в src/api/auth/tokens/jwt_handler.py.

Поля TokenPayload:

Поле Смысл
sub Subject user id
jti JWT id
exp Expiration
iat Issued-at time
type access или refresh
scopes Raw permission scope strings
role Optional user role string
group_id Optional group scope

Defaults:

  • Access token TTL: 30 минут, если expires_delta не передан.
  • Refresh token TTL: 7 дней.
  • Signing settings берутся из src/api/config.py (API_JWT_ALGORITHM, JWT secret resolution).

Revocation:

  • blacklist_token() сохраняет SHA-256 fingerprint от JTI в memory и в таблицу token_blacklist.
  • is_token_blacklisted() проверяет memory first, затем database.
  • load_blacklist_cache() загружает неистекшие blacklist rows при startup.
  • _blacklist_sync_task() периодически обновляет in-memory cache.

User API keys

User API keys создаются через /api/v1/me/api-keys и передаются как X-API-Key.

Формат:

rag_<8 hex chars>_<48 hex chars>

Детали реализации:

  • generate_api_key() возвращает (full_key, prefix, key_hash).
  • Prefix начинается с rag_.
  • Secret генерируется через secrets.token_hex(24).
  • Stored hash: SHA-256.
  • verify_api_key() использует secrets.compare_digest().
  • ApiKey.group_id может ограничить ключ одним tenant group.
  • User API keys аутентифицируются как MachinePrincipal(subject_type="user", auth_method="api_key").
  • User API keys по умолчанию разрешают interfaces api и mcp.
  • ApiKeyInfo — response model без секрета.
  • ApiKeyWithSecret расширяет ApiKeyInfo и возвращается только при создании ключа.

API-key CRUD:

Route Назначение
POST /api/v1/me/api-keys Создать key для текущего пользователя
GET /api/v1/me/api-keys Список keys текущего пользователя без secrets
DELETE /api/v1/me/api-keys/{key_id} Revoke owned key

Create request по умолчанию использует ["scenarios:read", "query:execute"]; lower-level helper get_default_scopes_for_api_key() возвращает более широкий legacy default list. Route behavior является авторитетным runtime behavior.

Service accounts

Service accounts используют тот же транспорт X-API-Key, но другой credential prefix:

svc_<8 hex chars>_<48 hex chars>

Service-account records хранятся в service_accounts; credentials хранятся в service_account_credentials.

Реализованные controls:

  • Admin-only service-account management.
  • Policy templates: ci, portal, bot, agent.
  • Explicit scopes и allowed_interfaces.
  • Optional group_id или project_id restriction.
  • Account expiry и credential expiry.
  • Credential rotation без немедленного revoke старого credential.
  • Active credential quota через security.service_account_max_active_credentials.
  • Revoke и deactivate flows.
  • Machine contract header: X-CodeGraph-Machine-Contract, сейчас 2026-03-v1.
  • Optional proxy-terminated mTLS binding для configured interfaces.
  • Unified machine audit events через AuditAction.MACHINE_ACCESS.

Admin routes:

Route Назначение
GET /api/v1/admin/identity/service-accounts/action-catalog Вернуть route scopes, machine contract, policy templates и security limits
POST /api/v1/admin/identity/service-accounts Создать service account и initial credential
GET /api/v1/admin/identity/service-accounts Список service accounts
GET /api/v1/admin/identity/service-accounts/{service_account_id} Inspect service account и credential metadata
POST /api/v1/admin/identity/service-accounts/{service_account_id}/rotate Выдать новый credential
POST /api/v1/admin/identity/service-accounts/{service_account_id}/credentials/{credential_id}/revoke Revoke один credential
POST /api/v1/admin/identity/service-accounts/{service_account_id}/deactivate Disable account и revoke credentials

Policy templates:

Template Scopes Interfaces
ci query:execute, scenarios:read, mcp:access api, mcp
portal stats:read, history:read api
bot query:execute, scenarios:read, mcp:access api, mcp
agent query:execute, scenarios:execute, review:execute, mcp:access, digital_employees:read, digital_employees:task:write api, mcp

OAuth2/OIDC

OAuth code находится в src/api/auth/providers/oauth.py; routes находятся в auth_external_routes.py.

Поддерживаемые provider implementations:

Provider Notes
github GitHub OAuth
gitlab GitLab OAuth, configurable server URL
google Google OIDC
keycloak Keycloak OIDC, configurable server and realm
sourcecraft SourceCraft provider на базе Yandex ID
gitverse GitVerse provider

Routes:

Route Назначение
GET /api/v1/auth/oauth/providers Список configured providers и generated authorize URLs
GET /api/v1/auth/oauth/{provider} Start OAuth flow
GET /api/v1/auth/oauth/{provider}/callback Exchange code, create/find user, issue JWTs

Configured OAuth users получают JWTs с persisted database role.

LDAP/Active Directory

LDAP code находится в src/api/auth/providers/ldap_auth.py; route integration есть в auth_external_routes.py.

Routes:

Route Назначение
POST /api/v1/auth/ldap Authenticate against LDAP/AD и issue JWTs
GET /api/v1/auth/ldap/status Report LDAP availability и connection status

Runtime caveat: LDAPAuthenticator.map_groups_to_role() читает config.group_role_mapping. Убедитесь, что deployed LDAPConfig предоставляет этот attribute, иначе все LDAP-created users откатятся к роли analyst.

Yandex Cloud IAM

IAM validation находится в src/api/auth/providers/iam.py и инициализируется из API settings, когда IAM включен.

Request header:

X-YC-IAM-Token: <token>

Когда token валиден, get_auth_context() возвращает:

  • role=Role.ANALYST
  • scopes=["scenarios:read", "query:execute", "review:execute"]
  • auth_method="iam"

Validation results кешируются на configured IAM token cache TTL.

Machine scope enforcement

ScopeEnforcementMiddleware добавляется в src/api/main.py, когда security.api_key_scope_enforcement=true. Он проверяет requests с X-API-Key до выполнения router.

Процесс:

  1. Validate key как user API key или service-account credential.
  2. Сохранить MachinePrincipal в request.state.machine_principal.
  3. Resolve requested project scope из X-Project-Id.
  4. Validate optional machine contract header.
  5. Validate optional mTLS binding для service accounts.
  6. Выполнить authorize_machine_request().
  7. Записать machine audit event.
  8. Вернуть 403 insufficient_scope при denial.

Выдержка из API route scope map:

Prefix Required scope
/scenarios scenarios:read
/query query:execute
/review review:execute
/sessions sessions:read
/history history:read
/stats stats:read
/metrics metrics:read
/security, /import, /documentation, /edit, /optimize, /standards, /composition, /changelog, /acp, /chat scenarios:execute
/gocpg, /context, /patterns query:execute
/deps scenarios:read
/dashboard stats:read
/digital-employees digital_employees:read
/groups, /projects admin:all
/webhooks, /health, /auth, /demo, /ws public для middleware scope purposes

MCP route scope map:

Prefix Required scope
/mcp mcp:access
/sse mcp:access
/messages mcp:access

Только для MCP scope mcp:access может быть удовлетворен aliases: query:execute, scenarios:read, scenarios:execute, review:execute, stats:read, history:read и admin:all.

Explicit endpoint scope checks:

from src.api.auth.tokens.scope_enforcement import require_scope

@router.get("/example")
async def example(auth=Depends(require_scope("query:execute"))):
    ...

require_scope() проверяет raw AuthContext.scopes; admin:all обходит эту проверку.

Tenant и project access

Tenant/project authorization отделена от глобальных user roles.

Enums и tables:

Surface Values или назначение
GroupRole viewer, editor, admin
ProjectScopeMode all, selected
project_groups Tenant/group records
user_group_access User membership и tenant role
user_project_access Selected project allowlist при membership mode selected
api_keys.group_id Optional tenant restriction для user API keys
service_accounts.group_id / project_id Optional tenant/project restriction для service accounts

Admin access-management routes:

Route Назначение
GET /api/v1/admin/identity/users/{user_id}/access Прочитать unified system role плюс tenant/project assignments
PUT /api/v1/admin/identity/users/{user_id}/access Replace system role и tenant/project assignments

Guardrails:

  • Platform admin не может deactivate свой собственный account.
  • Last active platform admin не может быть deactivated или downgraded.
  • Last tenant admin не может быть removed или downgraded без другого tenant admin.
  • selected project scope должен включать хотя бы один project, и все selected projects должны принадлежать assigned tenant.
  • all project scope не может включать explicit project ids.

Project resolution и tenant-sensitive runtime paths должны использовать ProjectContext и resolved project scope, а не user-provided database paths.

Path Validation Middleware

PathValidationMiddleware проверяет поля db_path и source_path в JSON bodies для POST, PUT и PATCH.

Правила:

  • Empty strings и NUL bytes отклоняются.
  • Relative paths отклоняются, если path_validation_deny_relative=true.
  • Path components .. отклоняются.
  • Paths resolve-ятся через os.path.realpath().
  • Resolved path должен находиться под allowed base directory.

Allowed directories строятся из:

  • security.path_validation_allowed_base_dirs
  • parent directories зарегистрированных project db_path
  • зарегистрированных project source_path directories

Config fields определены в SecurityConfig:

Field Default
path_validation_enabled true
path_validation_deny_symlinks true
path_validation_deny_relative true
path_validation_allowed_base_dirs ["data/projects/"]

Webhook authentication

Webhook verification находится в src/api/auth/machine/webhook_auth.py. Основная функция проверки — verify_webhook_signature().

Поддерживаемые platforms:

Platform Signature/token header Timestamp header
sourcecraft X-SourceCraft-Signature X-SourceCraft-Timestamp
gitverse X-GitVerse-Signature; fallbacks включают X-Gitea-Signature, X-Gogs-Signature, X-Hub-Signature-256, X-Hub-Signature X-GitVerse-Timestamp
github X-Hub-Signature-256 X-Hub-Timestamp
gitlab X-Gitlab-Token none

sourcecraft, gitverse и github используют HMAC signature validation. gitlab использует constant-time token comparison. Replay protection использует configured security.webhook_max_age_seconds, когда у platform есть timestamp header.

Audit и SIEM-relevant events

Audit actions определены в src/api/logging/audit_logger.py.

Authorization-related actions:

Category Actions
Auth auth.login.success, auth.login.failure, auth.logout, auth.token.refresh, auth.token.revoked
OAuth and LDAP oauth.login.*, ldap.login.*
API keys api_key.created, api_key.revoked, api_key.deleted, api_key.used
Service accounts service_account.created, service_account.rotated, service_account.credential_revoked, service_account.disabled
Machine access machine.access
User and tenant admin user.created, user.updated, user.role.changed, user.tenant.*, user.project.scope.changed
Security security.permission.denied, security.rate_limit.exceeded, security.token.invalid, security.path_violation, security.idor_attempt, security.webhook.replay_rejected, security.mcp.auth_failure

Machine audit records содержат subject type/id, interface, operation, resource, result, credential id, optional service-account id, optional contract version, project id и group id.

Configuration reference

Selected current config fields:

Field Назначение
security.api_key_scope_enforcement Включает machine API-key scope middleware
security.local_dev_unauthenticated_surfaces_enabled Включает guarded loopback local-plugin auth bypass
security.webhook_max_age_seconds Replay window для timestamped webhook signatures
security.auth_rate_limit_* Login/register/refresh/LDAP rate-limit settings
security.service_account_token_ttl_days Default service-account account и credential TTL
security.service_account_default_interfaces Default interfaces для service accounts
security.service_account_max_active_credentials Rotation quota
security.service_account_rotation_overlap_seconds Intended overlap window для rotations
security.service_account_rotation_warning_days Warning window для credential age/expiry
security.service_account_revoke_sla_seconds Revocation SLA reference
security.service_account_mtls_enabled Включает service-account mTLS binding checks
security.service_account_mtls_required_interfaces Interfaces, требующие mTLS при включенной проверке
security.service_account_mtls_subject_header Proxy header для certificate subject
security.service_account_mtls_fingerprint_header Proxy header для certificate fingerprint
security.service_account_mtls_bindings Allowed fingerprints by service-account id

Операционные рекомендации

Для администраторов:

  1. Используйте admin только для platform administration.
  2. Для повседневной сегрегации предпочитайте tenant GroupRole и selected project access.
  3. Используйте service accounts для CI, bots, portals, MCP clients и long-lived machine access.
  4. Берите policy templates как baseline и добавляйте только нужные caller scopes.
  5. Rotate service-account credentials до revoke старых credentials.
  6. Оставляйте JWT blacklist cache loading включенным при application startup.
  7. Держите path validation и API-key scope enforcement включенными в shared environments.

Для разработчиков:

  1. Используйте require_permission() или require_role() для human user route checks.
  2. Используйте require_scope() только когда raw scope strings являются intended contract.
  3. Добавляйте новые machine routes в API_ROUTE_SCOPE_MAP или MCP_ROUTE_SCOPE_MAP.
  4. Сохраняйте REST/MCP parity через shared services, а не дублирование auth logic.
  5. Никогда не авторизуйте tenant-sensitive operations от user-provided db_path.
  6. Для mutating local-plugin routes требуйте named actor и task evidence.
  7. Не логируйте bearer tokens, API keys, service-account secrets, raw webhook secrets или raw prompts.

Связанные документы

Версия: 3.0 | Май 2026