Files
SnapOtter/apps/docs/ru/guide/scim.md
T
SnapOtterandGitHub d10d0f544f fix: release QA hardening across processing, media, security, and CI gates (#649)
A release-readiness QA pass over the whole product. The commits split into
defects a user would hit and gates that were reporting green while measuring
nothing.

## Fixes that change behaviour

Rate limiting was bypassable on every install: TRUST_PROXY defaulted to true, so
request.ip came from a client-set header and a forged X-Forwarded-For got past
the login limiter. The default is now a private-network trust list.

A transient Postgres outage stranded in-flight jobs, leaving finished output on
disk with no row pointing at it. A reconciler now resolves those rows and adopts
the bytes rather than dropping the work.

A Redis connection that moved to a new address wedged every read-blocked
consumer, so completions stopped signalling while health still answered 200.
Socket timeouts plus subscriber pings recover it.

Installing more than one AI bundle left the shared venv multi-versioned and
silently broke three tools. The installer now reconciles distributions to one
version each.

Converting an image to JXL at quality 1 through 4 returned a 500, because
libjxl 0.7 rejects the distance those values compute. The quality is floored at
what the encoder honours. A missing ffmpeg was also reported to the user as a
corrupt upload; it now says the engine is unavailable.

RAW uploads reached an unpatched LibRaw on arm64, so it is built from source at
0.22.2, and the release scan was split so it can fail on an unfixed critical
instead of hiding it behind ignore-unfixed.

## Gates that could not fail

Two mutation lanes ran zero mutants because Stryker crawled the gitignored docs
build; coverage discarded its whole report on any failing test; the lint gate
skipped root tests, scripts, and two workspaces; and several generated matrices
counted a host missing ffmpeg as a passing tool. Each now measures what it
claims.

Full evidence and the outstanding release items are tracked locally and are not
part of this branch.
2026-07-27 15:37:30 +08:00

20 KiB
Raw Blame History

description, i18n_source_hash, i18n_provenance, i18n_output_hash, i18n_hash_version
description i18n_source_hash i18n_provenance i18n_output_hash i18n_hash_version
Настройка провижининга SCIM 2.0 для синхронизации пользователей и групп из вашего поставщика идентификации в SnapOtter. Охватывает Okta, Azure AD / Entra ID и пользовательские интеграции. 06ee702b386e human 9a5a2bfad94c 2

Провижининг SCIM

SnapOtter реализует SCIM 2.0 (System for Cross-domain Identity Management) для автоматического провижининга пользователей и групп. Ваш поставщик идентификации может создавать, обновлять, деактивировать и повторно активировать учётные записи пользователей, а также автоматически синхронизировать членство в группах.

::: tip Функция уровня Enterprise Провижининг SCIM требует лицензии enterprise с функцией scim. Он недоступен в плане team. Без этой функции все конечные точки SCIM (кроме discovery) возвращают 403. :::

Предварительные требования

  • Работающий экземпляр SnapOtter, доступный по публичному URL
  • Ключ лицензии enterprise с функцией scim
  • Встроенная учетная запись SnapOtter admin с полным действующим набором разрешений. Делегированная пользовательская роль или ключ API администратора, у которого отсутствуют какие-либо разрешения администратора, не могут создать или отозвать глобальный токен SCIM.
  • Административный доступ к настройкам провижининга вашего поставщика идентификации

Быстрый старт

  1. Сгенерируйте bearer-токен SCIM:
curl -X POST https://photos.example.com/api/v1/enterprise/scim/token \
  -H "Cookie: snapotter-session=YOUR_SESSION" \
  -H "Content-Type: application/json"

Ответ содержит токен. Сохраните его немедленно; повторно его получить нельзя.

{
  "token": "so_scim_v2_a1b2c3d4e5f6...",
  "message": "Save this token - it cannot be retrieved again"
}
  1. В вашем поставщике идентификации настройте провижининг SCIM со следующими параметрами:
    • Base URL: https://photos.example.com/api/v1/scim/v2
    • Authentication: Bearer-токен (вставьте токен из шага 1)

Аутентификация

Конечные точки SCIM используют выделенный Bearer-токен, отдельный от пользовательских сессий и ключей API.

Генерация токена

POST /api/v1/enterprise/scim/token генерирует новый токен SCIM. Поскольку токен может подготавливать и изменять пользователей в экземпляре, для этой конечной точки требуется встроенная роль admin с полным набором эффективных разрешений администратора. Удерживать users:manage в пользовательской роли недостаточно.

Токен возвращается в открытом виде ровно один раз. SnapOtter хранит только scrypt-хеш. Если вы потеряете токен, отзовите его и сгенерируйте новый.

Одновременно активен только один токен SCIM. Генерация нового токена заменяет предыдущий.

::: warning Перевыпуск токена после обновления Устаревшие неверсионные токены SCIM отклоняются. После обновления до версии, которая выдает токены so_scim_v2_..., создайте новый токен и обновите поставщика удостоверений, прежде чем возобновить подготовку. :::

Отзыв токена

DELETE /api/v1/enterprise/scim/token отзывает текущий токен SCIM. Он имеет те же полностью встроенные требования администратора, что и генерация токенов.

Ограничение частоты запросов

Конечные точки SCIM ограничены 1000 запросами в минуту на токен. Превышение этого лимита возвращает HTTP 429.

Поддерживаемые ресурсы

Ресурс SCIM Концепция SnapOtter Создание Чтение Обновление Удаление
User Учётная запись пользователя Да Да Да Мягкое удаление
Group Team Да Да Да Да

::: warning Группы SCIM сопоставляются с командами SnapOtter, а не с ролями. SCIM не может задать роль пользователя. Всем пользователям, созданным через SCIM, назначается роль user. Чтобы изменить роль пользователя, используйте админ-интерфейс SnapOtter. :::

Операции с пользователями

Создание пользователя

POST /api/v1/scim/v2/Users

Создаёт новую учётную запись пользователя с authProvider, установленным в scim, и ролью user. Пользователь назначается в команду Default. Если active равно false, роль вместо этого устанавливается в disabled.

Обязательные атрибуты: userName. Необязательные: externalId, emails, active (по умолчанию true).

Список и фильтрация пользователей

GET /api/v1/scim/v2/Users

Возвращает постраничный список пользователей. Поддерживает параметры запроса startIndex и count (максимум 200 результатов на страницу).

Фильтрация поддерживает только eq (равно) по следующим атрибутам:

  • userName eq "jane"
  • externalId eq "ext-12345"

Другие операторы фильтрации и атрибуты возвращают HTTP 400.

Получение пользователя

GET /api/v1/scim/v2/Users/:id

Возвращает одного пользователя по его идентификатору пользователя SnapOtter.

Замена пользователя

PUT /api/v1/scim/v2/Users/:id

Заменяет атрибуты пользователя. Поддерживает userName, externalId, emails и active. Изменения имени пользователя проверяются на конфликты (409, если новое имя пользователя уже занято другим пользователем).

Частичное обновление пользователя

PATCH /api/v1/scim/v2/Users/:id

Частичное обновление с использованием SCIM PatchOp. Поддерживаемые операции:

Операция Пути
replace active, userName, externalId, emails, emails[type eq "work"].value, name.formatted, displayName
add То же, что и replace
remove externalId, emails

Пути name.formatted и displayName принимаются для совместимости, но не имеют постоянного эффекта (SnapOtter не хранит отдельное отображаемое имя).

Операции replace без значения (где значение является объектом без path) также поддерживаются, с ключами userName, externalId, emails и active.

Деактивация пользователя (мягкое удаление)

DELETE /api/v1/scim/v2/Users/:id

SnapOtter не удаляет пользователей окончательно через SCIM. Вместо этого DELETE выполняет мягкую деактивацию:

  1. Роль пользователя меняется с текущего значения (например, editor) на disabled:editor, сохраняя исходную роль.
  2. Пароль пользователя очищается.
  3. Все активные сессии отзываются.
  4. Все ключи API отзываются.

Пользователь больше не может входить в систему или использовать какие-либо ключи API. Его данные (файлы, история) сохраняются.

Повторная активация пользователя

Чтобы повторно активировать ранее деактивированного пользователя, отправьте запрос PUT или PATCH с active: true. SnapOtter восстанавливает исходную роль, существовавшую до деактивации (например, disabled:editor снова становится editor). Если исходную роль определить не удаётся, она возвращается к user.

::: details Пример: деактивация и повторная активация через PATCH

// Deactivate
{
  "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
  "Operations": [
    { "op": "replace", "path": "active", "value": false }
  ]
}

// Reactivate
{
  "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
  "Operations": [
    { "op": "replace", "path": "active", "value": true }
  ]
}

:::

Операции с группами

Группы SCIM сопоставляются с командами SnapOtter. Создание группы создаёт команду. Членство в группе определяет, к какой команде принадлежит пользователь.

Создание группы

POST /api/v1/scim/v2/Groups

Обязательно: displayName. Необязательно: members (массив { value: userId }).

Список и фильтрация групп

GET /api/v1/scim/v2/Groups

Фильтрация поддерживает только displayName eq "...". Постраничный вывод с startIndex и count (максимум 200 результатов на страницу).

Получение группы

GET /api/v1/scim/v2/Groups/:id

Замена группы

PUT /api/v1/scim/v2/Groups/:id

Заменяет имя группы и полный список членства. Существующие члены, отсутствующие в новом списке, перемещаются в команду Default.

Частичное обновление группы

PATCH /api/v1/scim/v2/Groups/:id

Поддерживает следующие операции:

Операция Путь Эффект
add members Добавляет пользователей в команду
remove members[value eq "userId"] Перемещает пользователя в команду Default
replace displayName Переименовывает команду
replace members Заменяет всех членов (удалённые члены перемещаются в команду Default)

Удаление группы

DELETE /api/v1/scim/v2/Groups/:id

Удаляет команду. Все члены удалённой команды перемещаются в команду Default. Пользователи не деактивируются и не удаляются.

Настройка IdP

Okta

  1. В консоли администратора Okta откройте своё приложение SnapOtter (или создайте новое).
  2. Перейдите на вкладку Provisioning и нажмите Configure API Integration.
  3. Отметьте Enable API Integration и введите:
    • Base URL: https://photos.example.com/api/v1/scim/v2
    • API Token: bearer-токен SCIM, сгенерированный выше
  4. Нажмите Test API Credentials, затем Save.
  5. В разделе Provisioning > To App включите:
    • Create Users
    • Update User Attributes
    • Deactivate Users
  6. В разделе Push Groups настройте, какие группы Okta синхронизировать как команды SnapOtter.

Azure AD / Entra ID

  1. В портале Azure перейдите к вашему корпоративному приложению SnapOtter.
  2. Перейдите в Provisioning и установите Provisioning Mode в Automatic.
  3. В разделе Admin Credentials введите:
    • Tenant URL: https://photos.example.com/api/v1/scim/v2
    • Secret Token: bearer-токен SCIM, сгенерированный выше
  4. Нажмите Test Connection, затем Save.
  5. В разделе Mappings настройте сопоставления атрибутов пользователей и групп. Значения по умолчанию обычно работают, но убедитесь, что userName сопоставляется с userPrincipalName или mail по вашему усмотрению.
  6. Установите Provisioning Status в On и сохраните.

Azure выполняет провижининг пользователей и групп по фиксированному циклу синхронизации (обычно каждые 40 минут).

Конечные точки discovery

Эти три конечные точки доступны без аутентификации и описывают возможности сервера SCIM:

Конечная точка Описание
GET /api/v1/scim/v2/ServiceProviderConfig Возможности сервера и поддерживаемые функции
GET /api/v1/scim/v2/Schemas Определения схем User и Group
GET /api/v1/scim/v2/ResourceTypes Доступные типы ресурсов (User, Group)

ServiceProviderConfig объявляет следующие возможности:

Функция Поддерживается
Patch Да
Bulk Нет
Filter Да (максимум 200 результатов, только оператор eq)
Change password Нет
Sort Нет
ETag Нет

Ограничения

  • Фильтрация: Поддерживается только оператор eq. Сложные фильтры, операторы and/or, co (содержит) и sw (начинается с) не реализованы.
  • Массовые операции: Не поддерживаются.
  • Sort и ETag: Не поддерживаются.
  • Роли: SCIM не может назначать роли SnapOtter. Все провизионированные пользователи получают роль user.
  • MAX_USERS: Лимит переменной окружения MAX_USERS не применяется при создании пользователей через SCIM. Если вам нужно ограничить количество пользователей, управляйте назначениями в вашем IdP.
  • Один токен: Одновременно может быть активен только один токен SCIM. Если нескольким IdP нужен доступ к SCIM, они должны использовать общий токен.
  • Группы соответствуют командам: Группы SCIM соответствуют командам, а не ролям или группам разрешений.

Устранение неполадок

403 "SCIM provisioning requires an enterprise license with the scim feature"

Ваша лицензия не включает функцию scim или лицензия не настроена. SCIM требует лицензию плана enterprise. Убедитесь, что SNAPOTTER_LICENSE_KEY установлена и лицензия включает функцию scim.

401 "Bearer token required"

Запрос SCIM не содержал заголовка Authorization: Bearer <token>. Проверьте конфигурацию провижининга вашего IdP.

401 "Invalid token"

Токен имеет неверный формат, использует устаревший неверсионный формат или не соответствует сохраненному хешу. Создайте текущий токен so_scim_v2_... и обновите его в настройках подготовки IdP.

401 "SCIM not configured"

Токен SCIM ещё не был сгенерирован. Используйте конечную точку POST /api/v1/enterprise/scim/token для его создания.

409 "User already exists" / "userName already taken"

Пользователь с таким же именем пользователя уже существует. Это может произойти, когда IdP повторяет неудавшуюся операцию создания. Проверьте наличие дубликатов имён пользователей в панели администратора SnapOtter.

429 "SCIM rate limit exceeded"

IdP отправляет более 1000 запросов в минуту. Обычно это происходит во время большой первоначальной синхронизации. Большинство IdP автоматически повторяют запросы после сброса окна ограничения частоты. Если проблема сохраняется, проверьте интервал синхронизации провижининга вашего IdP.

Пользователи деповизионированы, но не удалены из интерфейса

DELETE в SCIM выполняет мягкую деактивацию. Деактивированные пользователи по-прежнему отображаются в списке пользователей администратора со статусом «отключён». Это сделано намеренно, чтобы их данные сохранялись. Их роль отображается как disabled:<original-role>.