backlog: добавлены задачи про локальную сборку образов и права секретов
- Уход от Yandex Container Registry на роль `app_image`: homepage, transcriber, remembos собираются локально и едут через docker save/load. - Сужение прав секретов: `yc_oauth_token` открывает весь аккаунт ради одного `docker login` — вторая задача зависит от первой.
This commit is contained in:
@@ -36,6 +36,8 @@ _(sec-ревью)_ — три независимых security-ревью на м
|
|||||||
- [Уведомления о размере приложений и заполнении диска](disk-usage-alerts.md) — алерты на заполнение диска и аномальный рост data-томов; сервер ресурсно ограничен _(tududi)_
|
- [Уведомления о размере приложений и заполнении диска](disk-usage-alerts.md) — алерты на заполнение диска и аномальный рост data-томов; сервер ресурсно ограничен _(tududi)_
|
||||||
- [Handlers рестарта для оставшихся приложений](handlers-remaining-apps.md) — apprise/dashboard/transcriber/miniflux монтируют конфиг в контейнер, но рестарта нет вовсе; правка конфига не подхватывается
|
- [Handlers рестарта для оставшихся приложений](handlers-remaining-apps.md) — apprise/dashboard/transcriber/miniflux монтируют конфиг в контейнер, но рестарта нет вовсе; правка конфига не подхватывается
|
||||||
- [Composable-роль `backup`](ansible-backup-role.md) — бэкап — самый чистый шов для extraction (одинаков у всех, различается только список targets) _(ансибл-ревью)_
|
- [Composable-роль `backup`](ansible-backup-role.md) — бэкап — самый чистый шов для extraction (одинаков у всех, различается только список targets) _(ансибл-ревью)_
|
||||||
|
- [Локальная сборка образов вместо Yandex Container Registry](local-image-build.md) — homepage/transcriber/remembos тянут образы из cr.yandex, ради `docker login` в vault лежит OAuth-токен всего аккаунта; роль `app_image` уже обкатана в umbar
|
||||||
|
- [Вывести из оборота секреты с широкими правами](narrow-secret-scopes.md) — один `yc_oauth_token` открывает весь аккаунт Yandex Cloud; после инцидента 24 июля цена утечки одной переменной должна быть ограничена одним сервисом
|
||||||
|
|
||||||
## Низкий
|
## Низкий
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
# Локальная сборка образов вместо Yandex Container Registry
|
||||||
|
|
||||||
|
**Приоритет:** Средний
|
||||||
|
|
||||||
|
Три приложения деплоятся через Yandex Container Registry: homepage, transcriber,
|
||||||
|
remembos. Схема одинаковая — образ собирается локально и пушится в
|
||||||
|
`cr.yandex/...` (`playbook-homepage-registry.yml`,
|
||||||
|
`playbook-transcriber-registry.yml`), плейбук деплоя делает `docker_login` с
|
||||||
|
`yc_oauth_token`, compose тянет образ по registry-пути с зашитым в git тегом
|
||||||
|
(`transcriber:2fc5a56-1761210134`, `remembos:v0.2.0`, `homepage-nginx:latest`).
|
||||||
|
У remembos registry-плейбука нет вовсе — образ пушится руками.
|
||||||
|
|
||||||
|
Роль `app_image` (канон в `~/projects/private/ansible-roles`) делает то же самое
|
||||||
|
без registry: собирает образ на control-хосте командой самого приложения
|
||||||
|
(контракт — `task image`, получает `BUILD_ID` через окружение), везёт его на
|
||||||
|
сервер через `docker save`/`load` и отдаёт факт `app_image_tag` для compose.
|
||||||
|
Обкатана в umbar на jellybit и trackers.
|
||||||
|
|
||||||
|
Что станет иначе: из деплоя уходят внешний реестр и OAuth-токен, тег образа
|
||||||
|
перестаёт быть константой в git, а `inv pl -- homepage` становится полным
|
||||||
|
деплоем — сейчас сборка живёт в `task deploy` репозитория homepage, который сам
|
||||||
|
зовёт `ansible-playbook`.
|
||||||
|
|
||||||
|
Шаги:
|
||||||
|
|
||||||
|
- завендорить роль `app_image` — в `roles/` сейчас только `owner`, `eget`,
|
||||||
|
`secrets`; механика переноса — [shared-roles-sync](shared-roles-sync.md)
|
||||||
|
- homepage: завести в Taskfile таск `image` с тегом из `$BUILD_ID`, перевести
|
||||||
|
плейбук на роль, удалить `playbook-homepage-registry.yml` и registry-переменные
|
||||||
|
из `vars/homepage.yml`
|
||||||
|
- remembos: контракта сборки нет (есть Dockerfile, нет Taskfile) — завести таск
|
||||||
|
`image`, убрать зашитый тег из compose
|
||||||
|
- transcriber: исходников на этой машине нет — до начала решить, живой ли сервис
|
||||||
|
и откуда его собирать; иначе он останется единственным держателем registry и
|
||||||
|
токен из оборота не выйдет
|
||||||
|
- убрать `docker_login`-таски и registry-переменные из vault — дальше по
|
||||||
|
[narrow-secret-scopes](narrow-secret-scopes.md)
|
||||||
|
|
||||||
|
Готово, когда ни один плейбук не делает `docker_login`, `cr.yandex` не
|
||||||
|
встречается в репозитории, а все три приложения деплоятся одним
|
||||||
|
`inv pl -- <app>`.
|
||||||
|
|
||||||
|
Цена размена: дедупликации по слоям больше нет — каждый деплой везёт полный
|
||||||
|
образ, и для сборки нужен локальный docker с тулчейном. Для ручного нечастого
|
||||||
|
деплоя это осознанный выбор (так решено в самой роли), но у transcriber образ
|
||||||
|
может оказаться крупным — это стоит проверить до перевода.
|
||||||
|
|
||||||
|
Пересекается с [gitea-runner-on-demand](gitea-runner-on-demand.md): если сборки
|
||||||
|
уедут в CI, доставка образа на сервер снова становится отдельным вопросом.
|
||||||
|
|
||||||
|
Связано: playbook-homepage.yml, playbook-transcriber.yml, playbook-remembos.yml,
|
||||||
|
playbook-homepage-registry.yml, playbook-transcriber-registry.yml,
|
||||||
|
vars/homepage.yml, vars/transcriber.yml, vars/transcriber.images.yml,
|
||||||
|
files/{homepage,transcriber,remembos}/docker-compose.template.yml.
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
# Вывести из оборота секреты с широкими правами
|
||||||
|
|
||||||
|
**Приоритет:** Средний
|
||||||
|
|
||||||
|
`yc_oauth_token` в vault — OAuth-токен аккаунта Yandex Cloud: реестр, виртуалки,
|
||||||
|
биллинг. Нужен он ради одной операции — `docker login` в плейбуках homepage,
|
||||||
|
transcriber и remembos. Радиус прав несопоставим с задачей, и 24 июля он вместе
|
||||||
|
с ещё 52 переменными ушёл открытым текстом в транскрипт: цена одной такой утечки
|
||||||
|
— весь аккаунт, а не один сервис.
|
||||||
|
|
||||||
|
Принцип, к которому идём: секрет даёт доступ ровно к тому, ради чего заведён.
|
||||||
|
Всё, что шире, — либо заменяется на скоупированный доступ (сервисный аккаунт с
|
||||||
|
минимальными ролями вместо токена аккаунта, отдельный ключ на бакет вместо
|
||||||
|
общего), либо выводится из оборота совсем, либо риск принимается явно и
|
||||||
|
записывается.
|
||||||
|
|
||||||
|
Ядро задачи закрывается сборкой без реестра: после
|
||||||
|
[local-image-build](local-image-build.md) `yc_oauth_token` не нужен ни в одном
|
||||||
|
плейбуке и удаляется из vault. До неё эта задача не начинается — иначе деплой
|
||||||
|
трёх приложений просто ляжет.
|
||||||
|
|
||||||
|
Дальше — ревизия остального: пройти по `group_vars/all/secrets.yml` и проставить
|
||||||
|
каждой переменной радиус («один сервис» / «весь аккаунт у провайдера» / «все
|
||||||
|
бэкапы»). Кандидаты в широкие видны уже по назначению — ключи S3 для restic,
|
||||||
|
доступ к Postbox, — но разбирать их надо в этой задаче, а не заранее.
|
||||||
|
|
||||||
|
Готово, когда у каждой переменной vault записан радиус, а каждая широкая либо
|
||||||
|
заменена на скоупированную, либо помечена принятым риском с причиной.
|
||||||
|
|
||||||
|
Держать в уме: [gitea-runner-on-demand](gitea-runner-on-demand.md) заводит новый
|
||||||
|
доступ к API Yandex Cloud (старт и остановка ВМ). Если она поедет раньше — сразу
|
||||||
|
сервисный аккаунт с минимальными ролями, а не переиспользование OAuth-токена,
|
||||||
|
иначе задача вернётся тем же текстом.
|
||||||
|
|
||||||
|
Ротация уже утёкших значений — отдельный сюжет, он ведётся в
|
||||||
|
`SECRETS-ROTATION.md` (файл вне git). Здесь речь не о смене значения, а о
|
||||||
|
сокращении того, что это значение открывает.
|
||||||
|
|
||||||
|
Связано: group_vars/all/secrets.yml, playbook-homepage.yml,
|
||||||
|
playbook-transcriber.yml, playbook-remembos.yml,
|
||||||
|
[vault-password-storage](vault-password-storage.md),
|
||||||
|
[secrets-env-to-file](secrets-env-to-file.md).
|
||||||
Reference in New Issue
Block a user