Вход через Zentro для приложений без SSO (шлюз)
This content is not available in your language yet.
Инструкция для администратора Zentro и того, кто обслуживает приложение.
Если приложение не умеет подключаться к SSO напрямую (нет OIDC/SAML — только свои логины и пароли), вход через Zentro всё равно можно поставить перед ним: шлюз-прокси пускает к приложению только тех, кто вошёл в Zentro и у кого есть нужная роль. Так закрывают старые веб-приложения, веб-интерфейсы оборудования (роутеры, NAS, принтеры, СХД), внутренние админки.
Приложение умеет OIDC — подключайте его напрямую (Подключение приложения), шлюз не нужен.
В примере ниже все данные выдуманы: подставьте свои.
Как это устроено
Заголовок раздела «Как это устроено»Браузер → https://stock.example.com → шлюз (oauth2-proxy) ├─ нет входа → Zentro: логин + второй фактор → обратно на шлюз ├─ нет права → 403, к приложению не пускает └─ всё в порядке → http://10.20.0.15:8080 (приложение «Склад-Учёт»)Шлюз — обычное приложение Zentro (OAuth-клиент). Решение «пускать или нет» он принимает по
правам из id_token: права приходят в пространстве, заданном у клиента.
Чего шлюз не даёт:
- Приложение не узнаёт, кто вошёл. Свой вход у него остаётся: после Zentro оно спросит свой пароль. Если приложение умеет доверять заголовку с именем пользователя — шлюз может его передавать (ниже, «Если приложение доверяет заголовку»), но таких немного.
- Защищает только то, что идёт через шлюз. Прямой доступ к приложению в обход шлюза нужно закрыть сетью — иначе вход через Zentro ничего не защищает (шаг 5).
Пример, на котором показано
Заголовок раздела «Пример, на котором показано»| Что | Значение в примере |
|---|---|
| Приложение | «Склад-Учёт», веб-интерфейс http://10.20.0.15:8080, свои учётки, SSO не умеет |
| Адрес шлюза | https://stock.example.com |
| Zentro (Identity) | https://id.example.com — это PUBLIC_BASE_URL, он же issuer |
| Пространство прав | STOCK |
| Кто входит | сотрудник ivanov |
Прежде чем начать
Заголовок раздела «Прежде чем начать»- Нужна роль
IDENTITY_ADMIN(роли и OAuth-клиенты) и второй фактор — панель попросит подтвердить себя. - Машина для шлюза с Docker, из которой видно приложение (
10.20.0.15:8080) и Zentro (id.example.com). Шлюз сам ходит в Zentro за токеном — одного браузера мало. - Имя и TLS-сертификат для адреса шлюза. Без
httpsне работают защищённые cookie шлюза.
Шаг 1. Роль
Заголовок раздела «Шаг 1. Роль»Роли → Создать роль:
| Поле | Значение |
|---|---|
| Название | STOCK_USER |
| Права | STOCK:APP:ACCESS |
Пользователи → ivanov → Назначить роль → STOCK_USER. Дать доступ ещё кому-то — назначить ту же
роль; забрать — снять. Подробнее о ролях — Роли и права.
Шаг 2. Приложение (OAuth-клиент) для шлюза
Заголовок раздела «Шаг 2. Приложение (OAuth-клиент) для шлюза»OAuth-клиенты → Зарегистрировать клиента → «Люди — вход в приложение через Zentro»:
| Поле | Значение |
|---|---|
| Название | Склад-Учёт — его видно пользователю |
| Redirect URI | https://stock.example.com/oauth2/callback — точно, без слэша в конце |
| Публичный клиент | нет — у шлюза есть сервер и секрет |
| Scopes | openid profile email |
| Пространство прав | STOCK — без него права в токен не придут и шлюз не пустит никого |
| Приложение организации | да — своё приложение, экран «Разрешить» не нужен |
После «Зарегистрировать» сохраните client_id и секрет — он показывается один раз.
Шаг 3. Запустить шлюз
Заголовок раздела «Шаг 3. Запустить шлюз»Шлюз — oauth2-proxy. Ключ для cookie шлюза:
python3 -c 'import os,base64;print(base64.urlsafe_b64encode(os.urandom(32)).decode())'.env (секреты — только здесь, не в compose и не в git):
CLIENT_SECRET=секрет из шага 2COOKIE_SECRET=результат команды вышеdocker-compose.yml:
services: stock-gate: image: quay.io/oauth2-proxy/oauth2-proxy:latest # в проде — зафиксируйте версию restart: unless-stopped ports: ["4180:4180"] environment: OAUTH2_PROXY_CLIENT_SECRET: "${CLIENT_SECRET}" OAUTH2_PROXY_COOKIE_SECRET: "${COOKIE_SECRET}" command: - --http-address=0.0.0.0:4180 - --provider=oidc - --oidc-issuer-url=https://id.example.com # = PUBLIC_BASE_URL Identity - --client-id=cid_xxxxxxxx # из шага 2 - --redirect-url=https://stock.example.com/oauth2/callback - --code-challenge-method=S256 # PKCE в Zentro обязателен - --scope=openid profile email - --oidc-groups-claim=permissions # права пользователя из id_token - --allowed-group=STOCK:APP:ACCESS # без этого права — 403 - --email-domain=* - --upstream=http://10.20.0.15:8080/ - --pass-host-header=false - --skip-provider-button=true - --cookie-secure=true - --cookie-refresh=5m # снятая роль перестаёт действовать ≤ 5 мин - --cookie-expire=8h # дольше — снова вход в Zentrodocker compose up -d && docker compose logs -f stock-gate| Параметр | Зачем |
|---|---|
--allowed-group |
Какое право нужно для входа. Можно повторить несколько раз — достаточно любого |
--cookie-refresh |
Как часто шлюз обновляет токен и перечитывает права. Меньше — быстрее отзыв, чаще запросы к Zentro |
--cookie-expire |
Сколько живёт вход в шлюз без повторного входа в Zentro |
Шаг 4. Адрес и TLS
Заголовок раздела «Шаг 4. Адрес и TLS»Шлюз слушает :4180 без TLS — поставьте перед ним ваш nginx/Caddy/балансировщик с сертификатом на
stock.example.com. Если ничего нет, проще всего Caddy — сертификат он получит сам:
stock.example.com { reverse_proxy localhost:4180}Проверка: открыть https://stock.example.com в режиме инкогнито → экран входа Zentro → логин и
второй фактор → открывается «Склад-Учёт» (со своим экраном входа, если он у него есть).
Шаг 5. Закрыть обход шлюза
Заголовок раздела «Шаг 5. Закрыть обход шлюза»Делайте после успешной проверки на шаге 4 — иначе можно отрезать доступ и себе.
- Сеть: к
10.20.0.15:8080разрешить подключения только с машины шлюза (межсетевой экран на сервере приложения, на коммутаторе или в настройках оборудования). Сначала — правило «разрешить со шлюза», потом «запретить остальным». - Доступ снаружи: выключить публикацию приложения в интернет мимо шлюза — проброс портов, облачный/удалённый доступ производителя, старые DNS-имена.
- Другие входы: SSH, Telnet, API приложения — закрыть так же или оставить осознанно.
- Аварийный путь: решите заранее, как попасть в приложение, если шлюз или Zentro недоступны (консоль, отдельный хост администратора). Запишите его.
Шаг 6. Учётки самого приложения
Заголовок раздела «Шаг 6. Учётки самого приложения»Приложение по-прежнему спрашивает свой пароль. Рекомендуем:
- Именные учётки в приложении (
ivanov, а не общаяadmin) — тогда его собственный журнал показывает, кто что делал. - Встроенного администратора — длинный пароль в хранилище паролей, только для аварий.
- Не подставлять пароль приложения на шлюзе. Это требует своего кода и держит пароль администратора приложения на шлюзе — проще и безопаснее два рубежа: Zentro (кто ты, второй фактор, есть ли роль) и вход приложения.
Если приложение доверяет заголовку
Заголовок раздела «Если приложение доверяет заголовку»Некоторые приложения умеют брать пользователя из заголовка от прокси (обычно X-Forwarded-User,
X-Forwarded-Email или Remote-User — смотрите документацию приложения). Тогда добавьте шлюзу:
- --pass-user-headers=trueи обязательно выполните шаг 5: если приложение доступно в обход шлюза, такой заголовок подделает кто угодно.
Выход из шлюза — https://stock.example.com/oauth2/sign_out. Он завершает вход в шлюз, но не в
Zentro: следующий заход пройдёт без пароля, пока жива сессия Zentro. Выйти отовсюду — в кабинете
Zentro (Личный кабинет, «Сессии»).
Чек-лист
Заголовок раздела «Чек-лист»- Вход в инкогнито: Zentro (логин + второй фактор) → приложение.
- Пользователь без роли получает 403 от шлюза.
- Сняли роль — доступ пропал не позже чем через
--cookie-refresh. - Прямой заход на
http://10.20.0.15:8080с другой машины не открывается. - Аварийный путь записан.
Частые ошибки
Заголовок раздела «Частые ошибки»| Что видно | Причина | Что сделать |
|---|---|---|
Ошибка про redirect_uri на экране Zentro |
--redirect-url не совпал с Redirect URI клиента |
Сверить посимвольно: https, хост, путь /oauth2/callback, слэш |
| 403 от шлюза у того, кому доступ нужен | Нет роли, у клиента не задано пространство прав или право в --allowed-group написано иначе |
Роль — Пользователи; пространство — OAuth-клиенты → Изменить; сверить право |
Шлюз пишет про email (email not verified, пустой email) |
У пользователя нет почты или она не подтверждена | Добавить --insecure-oidc-allow-unverified-email=true; при пустой почте — ещё --user-id-claim=sub |
| Шлюз не стартует: ошибка discovery / issuer | Шлюз не видит Zentro или --oidc-issuer-url не равен PUBLIC_BASE_URL |
curl https://id.example.com/.well-known/openid-configuration с машины шлюза; сверить issuer |
invalid_grant после входа |
PKCE не включён или код просрочен | Проверить --code-challenge-method=S256; повторить вход |
| Бесконечный круг входа | Нет https перед шлюзом — браузер не сохраняет защищённую cookie |
Шаг 4 |
Приложение открывается кривым, ссылки ведут на 10.20.0.15 |
Приложение строит адреса из своего имени хоста | Попробовать --pass-host-header=true; иначе настроить в приложении внешний адрес |
| Роль сняли, а доступ остался | Действует до следующего обновления шлюза | Подождать --cookie-refresh; срочно — перезапустить шлюз со сменой COOKIE_SECRET (выйдут все) |