Учётные записи, токены и журнал безопасности
Описывает текущее поведение identity в Arkvory. Решение и альтернативы — ADR 0049; исходная модель — ADR 0011, ADR 0012; сервисные ключи — SERVICE_KEYS.
Виды учётных данных
Каждый запрос получает Principal с полем credential:
| Вид | Источник | Администрирование учётных записей | Управление PAT и паролем |
|---|---|---|---|
session | POST /api/v1/auth/login, 12 часов, dps_ | если учётная запись — администратор | да |
personal-token | PAT pat_, создаётся из сессии | никогда | нет |
service-key | управляемый ключ arkvory_ | нет (свои делегированные действия) | нет |
file-key | файл ключей ARKVORY_KEYS_FILE | при administrator: true (bootstrap-ключ) | нет |
GET /api/v1/auth/me возвращает credential, а для PAT — tokenScope. Консоль показывает смену пароля и раздел токенов только для session.
Персональные токены доступа
- Создание:
POST /api/v1/auth/tokens{ name, expiresAt?, scope? }только из сессии. Токен не может создать другой токен. - Срок: по умолчанию 90 дней, максимум 365 (RFC 3339, в будущем; до часа сверх максимума усекается как расхождение часов). Бессрочных PAT нет; старые записи без срока истекают через 365 дней после создания.
- Scope:
read-write(по умолчанию в API) получает grants учётной записи без флага администратора;readполучает только чтение, и любой изменяющий запрос отклоняется 403 ещё до маршрута. Консоль по умолчанию создаётreadна 90 дней. - Не более 50 действующих PAT на учётную запись. Список показывает действующие первыми (до 100 строк). Отзыв идемпотентен.
- Смена своего пароля и административный сброс пароля отзывают все сессии и все PAT учётной записи. Отключение учётной записи приостанавливает её PAT до включения.
- Администратор (сессия или bootstrap-ключ) видит и отзывает PAT пользователя:
GET /api/v1/users/{id}/tokens,DELETE /api/v1/users/{id}/tokens/{tokenId}; в SDK —administration.users.tokens(id)иadministration.users.revokeToken(id, tokenId).
Вход и регистрация
- Самостоятельная регистрация выключена, пока не задано
ARKVORY_ALLOW_REGISTRATION=true. Флаг виден вfeatures.selfRegistrationcapabilities и публично вGET /api/v1/auth/options; консоль показывает кнопку регистрации только приtrue. Регистрация прекращается на 900 учётных записях, оставшиеся 100 мест доступны администратору. - Ограничение по адресу клиента выполняется до проверки пароля: вход — 10 попыток с пополнением одной за 15 секунд, успешный вход не расходует попытку; регистрация — 3 на адрес и 20 на процесс с медленным пополнением. Ответ
429с кодомrate_limited, причинойlogin_attempts/registration_attempts,Retry-Afterи тем же числом вretryAfterSeconds. IPv6 считается по /64. - За reverse proxy задайте
ARKVORY_TRUSTED_PROXIES(IP или CIDR через запятую), иначе все клиенты будут считаться одним адресом прокси. - Жёсткой блокировки нет. Ошибки пароля накапливают долг учётной записи, который убывает на единицу за 6 секунд. Выше 20 единиц включается backoff от 1 секунды, удваивающийся до 2 минут; в это время даже верный пароль получает
429. Один адрес в пределах своего лимита не может вызвать backoff; успешный вход и административный сброс пароля обнуляют долг. - Анонимная проверка паролей (вход, регистрация) и аутентифицированная (смена своего пароля, создание/сброс администратором) используют разные ограниченные очереди, поэтому поток анонимных входов не блокирует администратора.
Журнал безопасности
GET /api/v1/security/audit?limit=1..100&after=<id> — только администратор, новые записи первыми; next передаётся в after. SDK: administration.security.audit({ after, limit }).
| Поле | Значение |
|---|---|
actor, credential | кто действовал; для анонимного входа null, после успешного входа — user:<id> |
action | auth.login, auth.register, auth.password.change, user.*, group.*, token.* |
target | user:<id>, group:<id> или имя, с которым пытались войти |
outcome, code | success, failure (invalid_password, unknown_account, …) или denied |
clientIp, details | адрес клиента и небольшие факты (scope, expiresAt, revokedTokens); без секретов |
Изменения записываются в той же транзакции, что и само изменение. Таблица append-only (UPDATE/DELETE запрещены триггером), хранение — 365 дней и не более 1 000 000 записей; запросы, отклонённые throttling, не журналируются. Для расследований в production экспортируйте журнал во внешнее хранилище событий.
Причины отказов (ADR 0051): неверное имя, пароль или выключенная учётная запись при входе — одинаково 401 invalid_credentials; неверный текущий пароль — current_password_invalid (backoff — 429 password_attempts); отказ учётных данных запроса — credential_missing, credential_invalid (неизвестный, отозванный, выключенная учётная запись), session_expired или token_expired. Срок определяется повторным поиском того же дайджеста без фильтра срока и сообщается только владельцу точного секрета.