mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
225 lines
19 KiB
Markdown
225 lines
19 KiB
Markdown
---
|
||||
|
|
description: "Настройте единый вход SAML 2.0 для SnapOtter. Пошаговые руководства для Okta, Azure AD / Entra ID, Google Workspace и других поставщиков удостоверений SAML."
|
|||
|
|
i18n_source_hash: 33dfb8b02a22
|
|||
|
|
i18n_provenance: human
|
|||
|
|
i18n_output_hash: ddacfded782b
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
# SAML SSO {#saml-sso}
|
|||
|
|
|
|||
|
|
SnapOtter поддерживает SAML 2.0 для единого входа. Пользователи могут входить через внешнего поставщика удостоверений (Okta, Azure AD / Entra ID, Google Workspace или любой стандартный IdP SAML 2.0) вместо локальной аутентификации по имени пользователя и паролю.
|
|||
|
|
|
|||
|
|
::: tip Корпоративная функция
|
|||
|
|
SAML SSO требует лицензии **team** или **enterprise** с функцией `saml_sso`. Если `SAML_ENABLED=true` задан без действительной лицензии, маршруты SAML молча пропускаются и записывается предупреждение.
|
|||
|
|
:::
|
|||
|
|
|
|||
|
|
## Предварительные требования {#prerequisites}
|
|||
|
|
|
|||
|
|
- Работающий экземпляр SnapOtter, доступный по публичному URL
|
|||
|
|
- `EXTERNAL_URL` установлен в этот публичный URL (например, `https://photos.example.com`)
|
|||
|
|
- Лицензионный ключ team или enterprise с функцией `saml_sso`
|
|||
|
|
- Доступ администратора к вашему поставщику удостоверений SAML
|
|||
|
|
|
|||
|
|
## Быстрый старт {#quick-start}
|
|||
|
|
|
|||
|
|
Добавьте эти переменные окружения в ваш `docker-compose.yml`:
|
|||
|
|
|
|||
|
|
```yaml
|
|||
|
|
services:
|
|||
|
|
snapotter:
|
|||
|
|
image: snapotter/snapotter:latest
|
|||
|
|
environment:
|
|||
|
|
EXTERNAL_URL: "https://photos.example.com"
|
|||
|
|
SNAPOTTER_LICENSE_KEY: "your-license-key"
|
|||
|
|
SAML_ENABLED: "true"
|
|||
|
|
SAML_IDP_SSO_URL: "https://idp.example.com/sso/saml"
|
|||
|
|
SAML_IDP_CERTIFICATE: |
|
|||
|
|
MIICpDCCAYwCCQDU+pQ4pHgSpDANBgkqhkiG9w0BAQsFADAUMRIw
|
|||
|
|
...your IdP's signing certificate in PEM format...
|
|||
|
|
EAYHKoZIzj0CAQYFK4EEACIDYgAE
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Перезапустите контейнер. На странице входа появляется кнопка «Sign in with SAML» (или метка, заданная в `SAML_PROVIDER_NAME`).
|
|||
|
|
|
|||
|
|
## Справочник конфигурации {#configuration-reference}
|
|||
|
|
|
|||
|
|
| Переменная | По умолчанию | Описание |
|
|||
|
|
|---|---|---|
|
|||
|
|
| `SAML_ENABLED` | `false` | Включить вход через SAML. |
|
|||
|
|
| `SAML_IDP_SSO_URL` | | URL конечной точки SSO у IdP. **Обязательно**, когда SAML включён. |
|
|||
|
|
| `SAML_IDP_CERTIFICATE` | | Сертификат подписи X.509 у IdP в формате PEM (сам текст сертификата, а не путь к файлу). **Обязательно**, когда SAML включён. |
|
|||
|
|
| `EXTERNAL_URL` | | Публичный URL, по которому доступен SnapOtter. **Обязательно**, когда SAML включён. |
|
|||
|
|
| `SAML_ENTITY_ID` | `${EXTERNAL_URL}/api/auth/saml/metadata` | SP Entity ID / Audience URI, отправляемый IdP. |
|
|||
|
|
| `SAML_CALLBACK_URL` | `${EXTERNAL_URL}/api/auth/saml/callback` | URL Assertion Consumer Service (ACS). |
|
|||
|
|
| `SAML_AUTO_CREATE_USERS` | `true` | Автоматически создавать локальную учётную запись пользователя при первом входе через SAML. |
|
|||
|
|
| `SAML_AUTO_LINK_USERS` | `false` | Связать удостоверение SAML с существующим локальным пользователем, если адрес электронной почты совпадает. |
|
|||
|
|
| `SAML_DEFAULT_ROLE` | `user` | Роль, назначаемая автоматически создаваемым пользователям SAML. Одна из `admin`, `editor` или `user`. |
|
|||
|
|
| `SAML_PROVIDER_NAME` | | Отображаемая метка для кнопки входа SAML на фронтенде (например, «Okta», «Azure AD»). Если пусто, на кнопке написано «SAML». |
|
|||
|
|
| `SAML_USERNAME_ATTRIBUTE` | | Атрибут утверждения SAML, используемый как имя пользователя. Если пусто, используется локальная часть email, затем NameID. |
|
|||
|
|
| `SAML_EMAIL_ATTRIBUTE` | `email` | Атрибут утверждения SAML, используемый как адрес электронной почты пользователя. |
|
|||
|
|
|
|||
|
|
Сервер отказывается запускаться, если `SAML_ENABLED=true` и отсутствует любая из трёх обязательных переменных (`SAML_IDP_SSO_URL`, `SAML_IDP_CERTIFICATE`, `EXTERNAL_URL`).
|
|||
|
|
|
|||
|
|
::: details Замечания по безопасности
|
|||
|
|
И `wantAuthnResponseSigned`, и `wantAssertionsSigned` жёстко заданы как `true`. SnapOtter отклоняет неподписанные или неправильно подписанные ответы SAML. Утверждения от доверенного IdP считаются подтверждёнными по электронной почте.
|
|||
|
|
|
|||
|
|
Поддерживается только вход, инициированный SP. SnapOtter не поддерживает вход, инициированный IdP (незапрошенный), или единый выход (SLO). Выход из SnapOtter не выполняет выход пользователя из IdP.
|
|||
|
|
:::
|
|||
|
|
|
|||
|
|
## Метаданные и URL SP {#sp-metadata-and-urls}
|
|||
|
|
|
|||
|
|
Вашему IdP нужны три значения от SnapOtter:
|
|||
|
|
|
|||
|
|
| Поле | Значение |
|
|||
|
|
|---|---|
|
|||
|
|
| **ACS URL** (Assertion Consumer Service) | `${EXTERNAL_URL}/api/auth/saml/callback` |
|
|||
|
|
| **Entity ID** / **Audience URI** | `${EXTERNAL_URL}/api/auth/saml/metadata` |
|
|||
|
|
| **SP Metadata** (XML) | `GET ${EXTERNAL_URL}/api/auth/saml/metadata` |
|
|||
|
|
|
|||
|
|
Например, если `EXTERNAL_URL` равен `https://photos.example.com`:
|
|||
|
|
|
|||
|
|
- ACS URL: `https://photos.example.com/api/auth/saml/callback`
|
|||
|
|
- Entity ID: `https://photos.example.com/api/auth/saml/metadata`
|
|||
|
|
- Конечная точка метаданных: `https://photos.example.com/api/auth/saml/metadata` (возвращает XML)
|
|||
|
|
|
|||
|
|
Некоторые IdP могут импортировать URL метаданных SP напрямую, что автоматически заполняет ACS URL и Entity ID.
|
|||
|
|
|
|||
|
|
## Настройка провайдера {#provider-setup}
|
|||
|
|
|
|||
|
|
### Okta {#okta}
|
|||
|
|
|
|||
|
|
1. В административной консоли Okta перейдите в **Applications > Create App Integration**.
|
|||
|
|
2. Выберите **SAML 2.0** и нажмите **Next**.
|
|||
|
|
3. Задайте имя (например, «SnapOtter») и нажмите **Next**.
|
|||
|
|
4. Настройте параметры SAML:
|
|||
|
|
- **Single sign-on URL**: Ваш ACS URL (например, `https://photos.example.com/api/auth/saml/callback`)
|
|||
|
|
- **Audience URI (SP Entity ID)**: Ваш Entity ID (например, `https://photos.example.com/api/auth/saml/metadata`)
|
|||
|
|
- **Name ID format**: EmailAddress
|
|||
|
|
- **Application username**: Email
|
|||
|
|
5. В разделе **Attribute Statements** добавьте `email`, сопоставленный с `user.email`.
|
|||
|
|
6. Нажмите **Next**, затем **Finish**.
|
|||
|
|
7. Перейдите на вкладку **Sign On**, нажмите **View SAML setup instructions** и скопируйте:
|
|||
|
|
- **Identity Provider Single Sign-On URL** в `SAML_IDP_SSO_URL`
|
|||
|
|
- **X.509 Certificate** в `SAML_IDP_CERTIFICATE`
|
|||
|
|
|
|||
|
|
### Azure AD / Entra ID {#azure-ad-entra-id}
|
|||
|
|
|
|||
|
|
1. В портале Azure перейдите в **Microsoft Entra ID > Enterprise applications > New application**.
|
|||
|
|
2. Нажмите **Create your own application**, назовите его «SnapOtter» и выберите **Integrate any other application you don't find in the gallery**.
|
|||
|
|
3. Перейдите в **Single sign-on > SAML** и нажмите **Edit** в разделе **Basic SAML Configuration**:
|
|||
|
|
- **Identifier (Entity ID)**: Ваш Entity ID (например, `https://photos.example.com/api/auth/saml/metadata`)
|
|||
|
|
- **Reply URL (ACS URL)**: Ваш ACS URL (например, `https://photos.example.com/api/auth/saml/callback`)
|
|||
|
|
4. В разделе **SAML Certificates** скачайте **Certificate (Base64)**.
|
|||
|
|
5. В разделе **Set up SnapOtter** скопируйте **Login URL**.
|
|||
|
|
6. Задайте `SAML_IDP_SSO_URL` равным Login URL, а `SAML_IDP_CERTIFICATE` равным содержимому скачанного сертификата.
|
|||
|
|
7. Назначьте пользователей или группы приложению в разделе **Users and groups**.
|
|||
|
|
|
|||
|
|
### Google Workspace {#google-workspace}
|
|||
|
|
|
|||
|
|
1. В консоли администратора Google перейдите в **Apps > Web and mobile apps > Add app > Add custom SAML app**.
|
|||
|
|
2. Назовите приложение «SnapOtter» и нажмите **Continue**.
|
|||
|
|
3. На странице **Google Identity Provider details** скопируйте **SSO URL** и скачайте **Certificate**. Нажмите **Continue**.
|
|||
|
|
4. Настройте параметры поставщика услуг:
|
|||
|
|
- **ACS URL**: Ваш ACS URL (например, `https://photos.example.com/api/auth/saml/callback`)
|
|||
|
|
- **Entity ID**: Ваш Entity ID (например, `https://photos.example.com/api/auth/saml/metadata`)
|
|||
|
|
- **Name ID format**: EMAIL
|
|||
|
|
- **Name ID**: Basic Information > Primary email
|
|||
|
|
5. Нажмите **Continue**, затем **Finish**.
|
|||
|
|
6. Включите приложение (**ON**) для ваших организационных подразделений.
|
|||
|
|
7. Задайте `SAML_IDP_SSO_URL` равным SSO URL из шага 3, а `SAML_IDP_CERTIFICATE` равным содержимому скачанного сертификата.
|
|||
|
|
|
|||
|
|
### Универсальный IdP SAML 2.0 {#generic-saml-2-0-idp}
|
|||
|
|
|
|||
|
|
Для любого поставщика удостоверений, совместимого с SAML 2.0:
|
|||
|
|
|
|||
|
|
1. Создайте новое приложение SAML / поставщика услуг в вашем IdP.
|
|||
|
|
2. Задайте **ACS URL** равным `${EXTERNAL_URL}/api/auth/saml/callback`.
|
|||
|
|
3. Задайте **Entity ID** / **Audience** равным `${EXTERNAL_URL}/api/auth/saml/metadata`.
|
|||
|
|
4. Настройте IdP на отправку электронной почты пользователя в атрибуте с именем `email` (или задайте `SAML_EMAIL_ATTRIBUTE` в соответствии с именем атрибута вашего IdP).
|
|||
|
|
5. Скопируйте **IdP SSO URL** и **сертификат подписи** в `SAML_IDP_SSO_URL` и `SAML_IDP_CERTIFICATE`.
|
|||
|
|
|
|||
|
|
## Провижининг пользователей {#user-provisioning}
|
|||
|
|
|
|||
|
|
### Автоматическое создание {#auto-create}
|
|||
|
|
|
|||
|
|
Когда `SAML_AUTO_CREATE_USERS` равен `true` (по умолчанию), локальная учётная запись пользователя создаётся при первом входе кого-либо через SAML. Роль устанавливается в `SAML_DEFAULT_ROLE`.
|
|||
|
|
|
|||
|
|
Имя пользователя выводится в следующем порядке:
|
|||
|
|
|
|||
|
|
1. Значение атрибута утверждения, указанного в `SAML_USERNAME_ATTRIBUTE` (если задано и присутствует)
|
|||
|
|
2. Локальная часть адреса электронной почты (всё до `@`)
|
|||
|
|
3. SAML NameID
|
|||
|
|
|
|||
|
|
Если возникает конфликт имён пользователей, добавляется числовой суффикс (например, `jane` становится `jane_2`).
|
|||
|
|
|
|||
|
|
### Автоматическое связывание {#auto-link}
|
|||
|
|
|
|||
|
|
Когда `SAML_AUTO_LINK_USERS` равен `true`, SnapOtter связывает удостоверение SAML с существующей локальной учётной записью, если адреса электронной почты совпадают. Это полезно, когда у вас есть заранее созданные учётные записи пользователей и вы хотите, чтобы они начали использовать SSO без потери своих данных.
|
|||
|
|
|
|||
|
|
::: warning
|
|||
|
|
Включайте автоматическое связывание, только если вы доверяете своему IdP SAML в проверке адресов электронной почты. Непроверенный адрес электронной почты от неправильно настроенного IdP может позволить кому-либо захватить учётную запись другого пользователя.
|
|||
|
|
:::
|
|||
|
|
|
|||
|
|
### Сопоставление атрибутов {#attribute-mapping}
|
|||
|
|
|
|||
|
|
| Поле SnapOtter | Источник | Конфигурация |
|
|||
|
|
|---|---|---|
|
|||
|
|
| Email | Атрибут утверждения | `SAML_EMAIL_ATTRIBUTE` (по умолчанию: `email`) |
|
|||
|
|
| Username | Атрибут утверждения, email или NameID | `SAML_USERNAME_ATTRIBUTE` (см. порядок вывода выше) |
|
|||
|
|
| External ID | NameID | Всегда SAML NameID, не настраивается |
|
|||
|
|
|
|||
|
|
## Принудительное применение SSO {#sso-enforcement}
|
|||
|
|
|
|||
|
|
Если вы хотите обязать всех пользователей входить через SAML (или OIDC) и заблокировать локальный вход по паролю, включите принудительное применение SSO:
|
|||
|
|
|
|||
|
|
1. Убедитесь, что корпоративная функция `sso_enforcement` лицензирована (доступна в планах team и enterprise).
|
|||
|
|
2. В **Admin Settings > Security** включите **SSO Enforcement**.
|
|||
|
|
3. Задайте **break-glass username**: это единственная локальная учётная запись, которая всё ещё может входить с паролем для экстренного доступа, если IdP недоступен.
|
|||
|
|
|
|||
|
|
Когда принудительное применение SSO активно, любая попытка локального входа (кроме break-glass пользователя) возвращает ошибку 403 с сообщением «Local password login is disabled. Please use SSO.»
|
|||
|
|
|
|||
|
|
::: tip
|
|||
|
|
Всегда настраивайте break-glass username перед включением принудительного применения SSO. Без него вы можете быть заблокированы в SnapOtter, если ваш IdP выйдет из строя.
|
|||
|
|
:::
|
|||
|
|
|
|||
|
|
## Использование SAML вместе с OIDC {#using-saml-alongside-oidc}
|
|||
|
|
|
|||
|
|
SAML и OIDC можно включить одновременно. Когда оба активны, страница входа показывает отдельные кнопки для каждого провайдера (с метками из `SAML_PROVIDER_NAME` и `OIDC_PROVIDER_NAME`). Пользователи могут входить любым методом.
|
|||
|
|
|
|||
|
|
Оба провайдера независимо используют одни и те же настройки автоматического создания, автоматического связывания и принудительного применения SSO: у каждого есть собственные переменные `*_AUTO_CREATE_USERS`, `*_AUTO_LINK_USERS` и `*_DEFAULT_ROLE`.
|
|||
|
|
|
|||
|
|
## Устранение неполадок {#troubleshooting}
|
|||
|
|
|
|||
|
|
### Проверка утверждения не удалась {#assertion-validation-failed}
|
|||
|
|
|
|||
|
|
Подпись ответа SAML или подпись утверждения не удалось проверить. Проверьте:
|
|||
|
|
|
|||
|
|
- Сертификат в `SAML_IDP_CERTIFICATE` совпадает с текущим сертификатом подписи в вашем IdP (сертификаты ротируются, поэтому проверьте срок действия)
|
|||
|
|
- Сертификат в формате PEM (начинается с `-----BEGIN CERTIFICATE-----`)
|
|||
|
|
- Сертификат представляет собой полный текст, а не путь к файлу
|
|||
|
|
- ACS URL и Entity ID, настроенные в вашем IdP, точно совпадают со значениями SnapOtter (схема, хост, порт, путь)
|
|||
|
|
|
|||
|
|
### Отсутствующие атрибуты {#missing-attributes}
|
|||
|
|
|
|||
|
|
Если имена пользователей или адреса электронной почты пусты после входа, ваш IdP может не отправлять ожидаемые атрибуты. Проверьте:
|
|||
|
|
|
|||
|
|
- Ваш IdP настроен на передачу атрибута `email` (или того, что задано в `SAML_EMAIL_ATTRIBUTE`)
|
|||
|
|
- Если используется `SAML_USERNAME_ATTRIBUTE`, убедитесь, что этот атрибут включён в утверждение
|
|||
|
|
- Некоторые IdP требуют явной настройки сопоставления атрибутов перед передачей клеймов
|
|||
|
|
|
|||
|
|
### Расхождение часов {#clock-skew}
|
|||
|
|
|
|||
|
|
Утверждения SAML включают временные условия (`NotBefore`, `NotOnOrAfter`). Если часы вашего сервера и часы IdP не синхронизированы, проверка утверждения завершается неудачей. Запустите NTP на обеих машинах, чтобы синхронизировать часы.
|
|||
|
|
|
|||
|
|
### «SAML is enabled via env but saml_sso enterprise feature is not licensed» {#saml-is-enabled-via-env-but-saml-sso-enterprise-feature-is-not-licensed}
|
|||
|
|
|
|||
|
|
Это предупреждение появляется в логах сервера, когда `SAML_ENABLED=true`, но лицензия не включает функцию `saml_sso`. Проверьте ваш лицензионный ключ и план. Функция `saml_sso` доступна в планах team и enterprise.
|
|||
|
|
|
|||
|
|
### Вход перенаправляет обратно с ошибкой {#login-redirects-back-with-error}
|
|||
|
|
|
|||
|
|
Если нажатие кнопки входа SAML перенаправляет обратно на страницу входа с ошибкой, проверьте логи сервера для деталей. Частые причины:
|
|||
|
|
|
|||
|
|
- IdP SSO URL недоступен с сервера
|
|||
|
|
- IdP отклонил запрос аутентификации (проверьте журналы аудита IdP)
|
|||
|
|
- IdP вернул неподписанный ответ (SnapOtter требует, чтобы и ответ, и утверждение были подписаны)
|