вход переехал на доверенный заголовок Authelia вместо собственного OIDC
- пришедшего называет заголовок Remote-User от прокси, и верят ему только с адреса из перечня trusted_proxies; своего входа у сервиса не осталось — ни корня /auth, ни кук, ни срока сессии, ни секрета клиента в конфиге и в базе - учётная запись заводится первым обращением: EnsureUser в пакете хранилища, шаг схемы 202608220001 с колонкой provider_login и снятыми правилами users - cmd/oidcstub заменён на cmd/devtools с подкомандой proxy; заодно закрыт унаследованный DL3066 — пользователь образа назван числом
This commit is contained in:
+17
-14
@@ -57,16 +57,17 @@ force_shutdown_timeout = <N> # ждать остановки ворке
|
||||
|
||||
Секретные поля оставляем пустыми — значение приходит из выкладки (см. «Секреты»).
|
||||
|
||||
*Расхождение:* адреса провайдера в секции `[auth]` образца заполнены примерами
|
||||
вида `https://auth.example.com/...`, а не оставлены пустыми: пустой адрес не
|
||||
говорит, какой формы значение здесь ждут. Пустым оставлен только
|
||||
`client_secret` — он и есть секрет.
|
||||
*Расхождение:* перечень доверенных адресов в секции `[auth]` образца заполнен
|
||||
примером — подсетью docker, — а не оставлен пустым: пустое значение не говорит,
|
||||
какой формы значение здесь ждут, а сервис с пустым перечнем не поднимается вовсе.
|
||||
Секретов в этой секции больше нет: они ушли 2026-08-22 вместе с собственным
|
||||
входом.
|
||||
|
||||
Там же, комментарием под секцией, стоит **второй набор значений `[auth]` — под
|
||||
подставной провайдер `cmd/oidcstub`**. Они — не живая форма, и это намеренно:
|
||||
образец описывает боевую выкладку, а локальный вход — способ до неё дойти, и два
|
||||
рабочих набора в одном файле читались бы как выбор без указания, какой из них
|
||||
чей.
|
||||
Там же, комментарием под секцией, стоит **второе значение перечня — петлевой
|
||||
адрес, под подставной прокси `cmd/devtools proxy`**. Оно стоит закомментированным, и это
|
||||
намеренно: образец описывает боевую выкладку, а локальный вход — способ до неё
|
||||
дойти, и два рабочих значения в одном файле читались бы как выбор без указания,
|
||||
какое из них чьё.
|
||||
|
||||
## Поля по дискриминатору `type`
|
||||
|
||||
@@ -95,7 +96,8 @@ Ansible из `pet-project-server`). Приложение просто читае
|
||||
|
||||
- Секретные поля transcriber: `yandex.speech_kit_api_key`,
|
||||
`yandex.object_storage_access_key_id`,
|
||||
`yandex.object_storage_secret_access_key`, `auth.client_secret`.
|
||||
`yandex.object_storage_secret_access_key`. Секрет клиента OIDC отсюда ушёл
|
||||
2026-08-22 вместе с собственным входом.
|
||||
- Отрендеренный `config.toml` (с секретами) **не коммитится**; права `0600`,
|
||||
владелец — пользователь процесса (`1000:1000`).
|
||||
- В `config.example.toml` секретные поля — пустые строки.
|
||||
@@ -137,10 +139,11 @@ TOML. Пустые ключи Yandex ловятся в конструкторе
|
||||
|
||||
Секция `[auth]` — первая, у которой проверка своя и стоит на старте:
|
||||
`AuthConfig.Validate()` зовётся из `cmd/transcriber` сразу после загрузки и роняет
|
||||
процесс с перечнем незаполненных ключей. Причина в цене умолчания: поднявшись с
|
||||
молча выключенным входом, сервис остался бы открытым наружу, а узнать об этом
|
||||
было бы неоткуда. Сообщение называет **имена ключей**, а не значения — значение
|
||||
`client_secret` в журнал попасть не должно.
|
||||
процесс с именем незаполненного ключа. Причина в цене умолчания: поднявшись с
|
||||
пустым перечнем доверенных адресов, сервис не узнавал бы никого, а узнать об
|
||||
этом было бы неоткуда — все адреса приложения просто отвечали бы отказом.
|
||||
Сообщение называет **имя ключа**; правило «значения в отказ не идут» остаётся в
|
||||
силе для прочих секций, где секреты есть.
|
||||
|
||||
## Структура в коде
|
||||
|
||||
|
||||
@@ -31,10 +31,13 @@ OpenSpec.
|
||||
{"time":"2026-08-10T11:23:45.123456Z","level":"INFO","msg":"record accepted","capability":"intake","record_id":"…","source":"api","duration_seconds":137}
|
||||
```
|
||||
|
||||
*Расхождение:* текстовый обработчик ставят **оба** пакета `cmd/` —
|
||||
`slog.NewTextHandler(os.Stdout, …)` и в `transcriber`, и в `oidcstub`. У второго
|
||||
это выбор, а не долг: его вывод читает человек в терминале, и разбирать его
|
||||
отбором никто не станет.
|
||||
*Расхождение:* текстовый обработчик ставит `cmd/transcriber` —
|
||||
`slog.NewTextHandler(os.Stdout, …)`.
|
||||
|
||||
*Изъятие:* оснастка разработчика `cmd/devtools` печатает не через `slog`, а
|
||||
stdlib-логом в поток ошибок. Это выбор, а не долг: её вывод читает человек в
|
||||
терминале, в сбор он не едет, а текст подсказки по командам `slog`-ом
|
||||
выглядел бы хуже, чем есть.
|
||||
|
||||
## Сообщение
|
||||
|
||||
@@ -103,6 +106,7 @@ OpenSpec.
|
||||
| Когда добавляем | Поля |
|
||||
| --- | --- |
|
||||
| на входящий HTTP-запрос | `transport` (`http`), `http.method`, `http.route`, `http.status_code`, `duration_ms` |
|
||||
| на узнавание пришедшего | `http.peer_addr` — адрес того, кто открыл соединение; плюс `account_id` на заведении учётной записи. **Значения заголовка в строке нет**: им довольно назваться, чтобы стать этим человеком, а с недоверенного адреса его пишет аноним |
|
||||
| на задачу | `capability` (значения — по именам заведённых capability в `openspec/specs/`), `record_id`, `file_id`, `source` |
|
||||
| на запись об ошибке | `error` |
|
||||
| на вызов внешнего сервиса | `ext.service`, `ext.operation`, `ext.status_code`, `duration_ms`, `retry` |
|
||||
|
||||
@@ -75,8 +75,10 @@
|
||||
- **Адреса обычные, а не после решётки** (`createWebHistory`). Отсюда требование
|
||||
к серверу: неизвестный путь **вне корней сервиса** отдаёт `index.html`, а не
|
||||
`404`; путь внутри корня в приложение не проваливается никогда. Корней
|
||||
сегодня четыре — `/api/` у хранилища, `/app/` у приложения, `/auth/` у входа,
|
||||
`/_/` у панели, — плюс `/health` и `/metrics` отдельными адресами. Приложение
|
||||
сегодня три — `/api/` у хранилища, `/app/` у приложения, `/_/` у панели, —
|
||||
плюс `/health` и `/metrics` отдельными адресами. Корень `/auth/` снят
|
||||
2026-08-22 вместе с собственным входом, и пути под ним стали обычными путями
|
||||
вне корней. Приложение
|
||||
уехало из общего `/api/` решением владельца 2026-08-15: пространство
|
||||
принадлежит хранилищу, и обновление библиотеки вправе занять там имя рядом с
|
||||
нашим. Перечень корней сервису не описывают, а из него **порождают**
|
||||
@@ -104,9 +106,11 @@
|
||||
- **Обёртка — единственное место, где читается код ответа.** Она же превращает
|
||||
ошибку контракта в доменную ошибку приложения; экран получает готовый текст, а
|
||||
не `Response`.
|
||||
- **Сессия живёт кукой `transcriber_session`**, и приложение её не читает: кука
|
||||
`HttpOnly`, браузер шлёт её сам, а вошедшего экран узнаёт по ответу API. Норма
|
||||
— [access](../../openspec/specs/access/spec.md).
|
||||
- **Сессии у сервиса нет вовсе**, и приложение не хранит ничего: кто пришёл,
|
||||
называет заголовок обратного прокси, а приложение узнаёт его ответом API.
|
||||
Кук сервис не ставит — это свойство сторожится проверкой. Норма —
|
||||
[access](../../openspec/specs/access/spec.md), решение —
|
||||
[ADR-2026-08-22-login-by-trusted-header](../adr/ADR-2026-08-22-login-by-trusted-header.md).
|
||||
|
||||
## Показ ошибок и состояний
|
||||
|
||||
|
||||
Reference in New Issue
Block a user