вход переехал на доверенный заголовок Authelia вместо собственного OIDC

- пришедшего называет заголовок Remote-User от прокси, и верят ему только с
  адреса из перечня trusted_proxies; своего входа у сервиса не осталось — ни
  корня /auth, ни кук, ни срока сессии, ни секрета клиента в конфиге и в базе
- учётная запись заводится первым обращением: EnsureUser в пакете хранилища,
  шаг схемы 202608220001 с колонкой provider_login и снятыми правилами users
- cmd/oidcstub заменён на cmd/devtools с подкомандой proxy; заодно закрыт
  унаследованный DL3066 — пользователь образа назван числом
This commit is contained in:
av
2026-08-22 20:24:22 +03:00
parent e4441f3c49
commit 7f33c957e5
63 changed files with 5257 additions and 2305 deletions
+25 -18
View File
@@ -36,15 +36,14 @@ Taskfile, образ — Docker, выкладка — Ansible из `pet-project-
Что нарушать нельзя.
- **Секрет не покидает конфиг.** Ключ SpeechKit, пара ключей Object
Storage и секрет клиента OIDC не попадают в git, в лог, в ответ пользователю и
- **Секрет не покидает конфиг.** Ключ SpeechKit и пара ключей Object
Storage не попадают в git, в лог, в ответ пользователю и
в колонку `error_text`. Нарушение необратимо: утёкший ключ отзывают и меняют
вручную во всех местах выкладки. **critical**
*Изъятие:* секрет клиента OIDC живёт ещё и в настройках коллекции
пользователей хранилища — туда его кладёт приведение настроек при каждом
подъёме, потому что применённый шаг схемы не переписывается и не пережил бы
ротации. Чтение файла базы равносильно чтению этого секрета; перечисленные
места запрета это не отменяет.
Изъятия у инварианта нет. Оно было — секрет клиента OIDC жил ещё и в
настройках коллекции пользователей хранилища,и снято 2026-08-22 вместе с
самим секретом: вход переехал на доверенный заголовок, обменивать код стало не
на что. Чтение файла базы больше не равносильно чтению секрета.
- **Содержимое записи остаётся приватным.** Текст расшифровки, имя файла
пользователя и его сообщение в лог не пишутся — только длина и
идентификаторы. Нарушение необратимо: строки уже уехали в журнал контейнера.
@@ -120,7 +119,7 @@ go vet ./...
gofmt -l .
golangci-lint run
go run ./cmd/transcriber -c config.toml # флаг -c или --config, по умолчанию config.toml
go run ./cmd/oidcstub # подставной провайдер OIDC для локального входа
go run ./cmd/devtools proxy # подставной прокси: ставит заголовок входа локально
task front # приложение: зависимости, Biome, юнит-тесты, сборка
task image # docker-образ; тег и раскладка — docs/architecture.md
task gate # весь набор проверок разом
@@ -211,9 +210,16 @@ Node на машину **не ставится**: шаг сборки прило
Красный шаг означает поломку — свою или чужую, но поломку, а не наследство.
Списывать отказ на долг больше нельзя: списывать не на что.
Два прежних долга закрыты и здесь названы, чтобы отказ на их месте читался как
Три прежних долга закрыты и здесь названы, чтобы отказ на их месте читался как
новый:
- `hadolint` давал `DL3066` на строке `USER transcriber` — «Non-numeric user-id
may not be resolvable by host system». Отказ пришёл с обновлением `hadolint`,
а не с правкой репозитория, и жил на `master` незамеченным. Закрыто решением
владельца 2026-08-22: пользователь называется числом — `USER 1000:1000`.
Владельца файлов в смонтированном каталоге это не двигает, потому что те же
числа уже стояли при заведении пользователя (`-u 1000`, `-g 1000`);
- `golangci-lint run` давал 4 замечания — два непроверенных `Close` и два
сравнения ошибок приведением типа. Закрыто задачей
`errors-as-instead-of-typecast` 2026-08-11; тогда же у `errcheck` включена
@@ -230,17 +236,18 @@ Node на машину **не ставится**: шаг сборки прило
выкладка с чистого листа наполнит его снова. Локальный каталог данных — свой,
его ронять и пересоздавать можно свободно.
- **Локальный запуск не ходит наружу.** Секции `[auth]` и `[yandex]`
проверяются на старте, но наружу при этом не обращаются, так что годятся
выдуманные непустые значения — адреса `[auth]` должны лишь разбираться как
ссылки. Расшифровка при выдуманных ключах не работает: её подменяют
проверяются на старте, но наружу при этом не обращаются. У `[auth]` остался
один ключ — перечень доверенных адресов, — и он проверяется на читаемость, а не
на достижимость. Расшифровка при выдуманных ключах не работает: её подменяют
`internal/adapter/recognizer/memory.go`. Подробности строками в
`config.example.toml`.
**Войти при выдуманных адресах нельзя** — они никуда не ведут, а сервис без
входа не отдаёт ничего. Вместо провайдера поднимается заглушка
`cmd/oidcstub` — она отвечает на `/authorize`, `/token` и `/userinfo`, а
проверок не делает никаких;
значения `[auth]` под неё стоят строками в `config.example.toml`. Ключи
боевого провайдера на машине разработчика при этом по-прежнему не нужны.
**На машине без прокси представиться нечем**: сервис узнаёт
пришедшего по заголовку, который на сервере ставит Caddy, а браузер заголовков
не ставит. На место контура встаёт подставной прокси —
`go run ./cmd/devtools proxy`: он слушает свой порт, ставит заголовок и
переправляет запрос сервису, а проверок не делает никаких. Приложение при этом
открывают **по адресу прокси**, а не по адресу сервиса. Ключей боевого
провайдера на машине разработчика не нужно вовсе — их больше нет и в конфиге.
- **Yandex Cloud за деньги.** Распознавание и хранение в Object Storage
оплачиваются по факту. Прогон на реальных ключах ради проверки кода запрещён —
подставляй `internal/adapter/recognizer/memory.go`.