Files
obsidian-vault/personal/projects/balda/ssh-permissions-2026-10-19.md
T

11 KiB
Raw Blame History

SSH Manager — постоянные и разовые права

Проверено и развёрнуто: 2026-10-19 22:19 UTC+6 (Asia/Bishkek).

SSH Manager 0.4.0, implementation commit d2806ac150363712b8baa9c40dbd37f2946b8c13. Рабочее дерево чистое при сборке, vcs.modified=false. Активный binary SHA256 536d389a4261e186fce8dfabe4a3adfe605d190d84ef188cdf105c3e8ee079bd, inode работающего процесса совпадает с установленным файлом. HTTP MCP 127.0.0.1:17796/mcp отдаёт 13 инструментов.

Balda остаётся на чистом upstream 138cc4a71d6889de30fe90e368f27f129fd8d792, binary SHA256 31c448af84428f83491d5fb8317549466f814f51c453de11fc8f6c9bd0836672. Каталог/кэш MCP обновлён штатным перезапуском: 2026-10-19T16:15:26.785581969Z. Config/env/mounts, OAuth login, SSH inventory и ключи сохранены; health/login 200, Mattermost websocket подключён. Все 49 runtime sessions и metadata, 28 questions, 2 users/bindings и 24 archive sessions из остановленного snapshot сохранены. Workspace Manager не менялся.

Что исправлено

В разобранном треде штатный ключ уже работал, но bubblewrap закрывал сеть хоста, Docker socket и sudo. Модель попыталась использовать sandbox-доступ Mac как административный и запустить вложенный ssh kraken; он завершился DNS-ошибкой. Прав не поменялось. У менеджера тогда отсутствовало API изменения профиля. Сбой произошёл до обновления Balda на upstream.

Теперь изменения выполняются через SSH Manager существующим операторским bootstrap-доступом, без передачи его ключей агенту и без хардкода хоста. Менеджер не получил инструмент произвольного выполнения команд: он выдаёт разрешение и native SSH-команду, которую запускает клиент своим установленным ключом.

Права

  • network: сеть хоста вместо отдельного Linux network namespace; на Mac — IP networking через Seatbelt.
  • read_paths / write_paths: конкретные канонические пути. Manager control state, личные SSH credentials, системные корни и каталоги с socket-файлами не выдаются обычным файловым grant. Linux использует проверенные открытые FD для bind mounts.
  • docker: none, read или manage. Read разрешает просмотр/логи/инспекцию, но не изменения. Docker CLI работает с фиксированным локальным daemon endpoint и закрытым control HOME/config; socket не появляется в sandbox.
  • admin: прямой sudo с уже существующими noninteractive правами оператора. Sudoers не изменяется. Native timeout запускается с теми же привилегиями, чтобы остановить обычную root-команду.

docker=manage и произвольный sudo могут обойти файловые/сетевые ограничения; форма подтверждения сообщает об этом. Это отдельные явно разрешённые исключения. Завершение вызова не откатывает его побочные эффекты и не обещает отозвать намеренно оставленную привилегированную работу.

Постоянное изменение

  1. ssh_permissions возвращает профиль и revision.
  2. ssh_permissions_update: полный новый профиль плюс expected_revision.
  3. Native owner form показывает before/after; затем выполняются реальная приёмка изоляции, CAS только managed key line и SSH-проверка из настроенного клиента. Ключ и маршрут сохраняются.
  4. Ошибка активации/проверки восстанавливает и проверяет прежний профиль либо явно сообщает, что rollback не подтверждён.

Новые вызовы используют новый профиль. Старые запущенные процессы не завершаются; неиспользованные разовые допуски инвалидируются. Действующие production mac и kraken пока возвращают managed=false: их прежние принятые ограничения при deployment не заменялись. Первый переход на управляемый профиль — отдельное явное ssh_permissions_update с owner confirmation, выполняемое самой Balda через MCP; ручная настройка JSON/хоста не требуется.

Разовый вызов

ssh_call_request принимает хост, точный argv и только временные overrides профиля. Например: command ["docker","ps","-a"], permissions {"docker":"read"}.

Одно owner confirmation связывает хост, argv, эффективные права и сроки. Затем Balda запускает возвращённый ssh_command своим установленным ключом. Сервер атомарно потребляет id до запуска, включая ошибочные вызовы; повтор/гонка второго подключения не дают второго запуска. Argv исполняется буквально, stdin закрыт. Start TTL 1–900 секунд (default 300), runtime 1–600 секунд (default 60). Часы — общесистемные на целевом хосте, включая macOS system Python.

ssh_call_status читает серверную квитанцию; issued не означает выполнение, consumed без result не означает, что процесс ещё работает. Успех — finished и exit_code 0 после реального SSH. ssh_call_cancel подтверждённо отменяет неиспользованный допуск, но не останавливает запущенную команду. Изменение профиля и revoke не воскрешают старые разрешения при повторной регистрации.

Постоянный профиль при разовом вызове не меняется. Штатная политика Balda для запуска локальной SSH-команды остаётся отдельным уровнем; SSH grant не выключает её. Старые диалоги с кэшированной MCP schema обновляются обычной новой сессией / /reset; история автоматически не сбрасывалась.

Проверено

  • Go race и vet, diff --check — pass.
  • Native macOS + MCP + временный sshd: 22 проверки, включая отказы, stale revision, rollback после сбоя SSH-проверки, буквальный argv, закрытый stdin, race двух соединений, consumption после ошибки, TTL/timeout/cancel, постоянные file/network права и отзыв/re-authorize.
  • Linux strict bubblewrap в Colima: 10 проверок, в том числе Docker read/manage отдельно, отказ управления при read, sudo от обычного пользователя с получением host root и остановка root-команды по тайм-ауту. Kernel/AppArmor/proc protection не ослаблялись. Временный Docker volume удалён.
  • Прежний native lifecycle произвольных хостов/ProxyJump/pin/restart/revoke/remove: 14 проверок.
  • Реальная модель в работающей Balda: session 01a154e9-5b6a-7a32-ae5b-d5efcdc03ca6. Постоянный update → one-call → проверка серверной квитанции → восстановление профиля. Ровно 3 native owner forms для этих 3 изменений, без generic MCP approval. Harness выполнил pinned native SSH из реального контейнера UID 1000 установленным временным fixture-ключом; успех подтверждён, повтор запрещён, исходная сеть восстановлена.
  • После deployment свежий Codex ACP вызвал новый ssh_permissions на production Mac/Kraken: session 01a154f0-1bb2-7932-aa2d-cf2907fc4ed0, 0 подтверждений. Это read-only проверка установленного API, без миграции профилей.
  • После перезапуска Balda прежние production-ключи к Mac и Kraken ещё раз проверены native SSH из настоящего UID 1000 Balda; оба вернули случайный marker.

Тесты используют случайные aliases/порты, временные ключи и отдельные private пути. Тестовые сообщения в Mattermost не отправлялись. Никакие bootstrap keys/passwords не передавались модели или в agent volume.

Evidence: /Users/admin/.local/share/balda-workspace/candidate/ssh-permissions-20261019. Backup менеджера: /Users/admin/.local/share/balda-workspace/backups/ssh-permissions-20261019T161039Z. Согласованный state backup Balda: /Users/admin/.local/share/balda-workspace/backups/ssh-permissions-balda-20261019T161515Z. Backup изменённых заметок: /Users/admin/.local/share/balda-workspace/backups/obsidian-ssh-permissions-20261019T221941+0600.

Исходники и contract: /Users/admin/Developer/ssh-manager/README.md, docs/permissions-2026-10-19.md. Текущий setup: personal/projects/balda/setup. План: personal/plans/balda-remote-agent.