Прокси и executor
Обычно rdc запускается на вашей машине с вашей конфигурацией и SSH-ключами и подключается к серверам напрямую. Модель с прокси разделяет это на две части: тонкий клиент, не хранящий никаких секретов, и executor, который хранит их и выполняет работу. И кнопка «Выполнить» в веб-консоли, и флаг --proxy в CLI являются тонкими клиентами, и оба говорят на одном и том же протоколе.
Намерение команды, а не сама команда
Тонкий клиент никогда не хранит SSH-ключ, адрес машины или расшифрованную конфигурацию. Когда ему нужно что-то выполнить, он отправляет только намерение команды: идентификатор команды (её путь в контракте CLI, например repo up) плюс параметры. Executor находит команду в том же контракте, сопоставляет её с соответствующей функцией на стороне сервера, определяет целевую машину из расшифрованной конфигурации и выполняет команду по собственному SSH-соединению. Вывод передаётся обратно клиенту потоком.
Executor представляет собой сам CLI, запущенный как сервер через rdc serve. Тот же самый бинарник, который оператор запускает на ноутбуке, становится тем, что выполняет команды от его имени. У него два варианта размещения:
--mode daemon: работает на хосте, который вы контролируете, подключён без браузера так же, как и любой CLI (см. Хранилище конфигурации), поэтому может сам вывести ключ конфигурации и не нуждается в предоставлении доступа для каждой сессии. Это строгий уровень: SSH никогда не покидает вашу сеть.--mode container: работает в контейнере, привязанном к организации и размещённом для вас. Стартует вообще без ключа и не может ничего делать, пока клиент не предоставит его для сессии. Это уровень удобства.
Предоставление CEK
Хранилище конфигурации устроено по принципу «без раскрытия данных»: сервер хранит только зашифрованные блобы, а ключ шифрования содержимого (CEK) существует в открытом виде только на клиенте, который его разблокировал. Поэтому executor’у в режиме контейнера ключ нужно предоставить, и это предоставление не должно раскрывать ключ серверу по пути.
Схема такая: разблокированный браузер открывает сессию с executor’ом, получает публичный ключ этой сессии и запечатывает CEK для неё через X25519. Запечатанный блоб проходит через сервер аккаунтов, но сервер не может его открыть, поэтому свойство «без раскрытия данных» сохраняется от начала до конца. Executor расшифровывает CEK только в оперативную память, с автоматическим истечением через 30 минут бездействия; на диск ничего не записывается никогда. Последующие запросы команд ссылаются на предоставленную сессию через заголовок X-Config-Session.
Одна деталь важна для аудита: одна и та же личность пользователя проходит через все три этапа (открытие сессии, предоставление ключа, выполнение команд). Сервер аккаунтов никогда не пересылает executor’у собственные учётные данные. Для каждого этапа он выпускает короткоживущий токен, привязанный к конкретному пользователю, и каждый раз заново проверяет членство этого пользователя. Executor проверяет тот токен, который ему предъявлен, прежде чем действовать. Предоставление доступа, сделанное одним пользователем, не может использоваться другим.
Часть конфигурации state (данные о состоянии, локальные для хоста) вообще никогда не передаётся в блобе конфигурации, поэтому и до executor’а по этому пути она тоже никогда не доходит.
Что может выполняться через прокси
Не любая команда имеет смысл удалённо. Каждая команда в контракте несёт флаг proxyCapable, и executor применяет его на стороне сервера, независимо от какой-либо настройки политики:
- Неинтерактивные команды уровня машины (развёртывание, резервное копирование, статус, логи и так далее) поддерживают прокси.
- Команды уровня конфигурации: нет, они редактируют конфигурацию, а на этом пути это задача браузера (веб-консоль направляет их в свой встроенный редактор конфигурации).
- Интерактивные команды (терминалы, сессии VS Code): нет, через этот канал нет TTY.
- Команды передачи на стороне клиента (
rdc repo sync): нет, они перемещают данные между файловой системой клиента и машиной, а у executor’а нет доступа к файлам клиента.
Веб-консоль читает тот же флаг, чтобы решить, получает ли команда кнопку «Выполнить» вообще, но executor отклоняет неподдерживаемые команды независимо от того, что отправляет клиент.
Mock-executor
В режиме разработки, когда реальный executor не настроен, сервер аккаунтов сам отвечает на запросы команд моковыми потоками и явно поддельными данными (имена ресурсов с префиксом mock-). Это делает всю консоль пригодной для проверки (включая формы, потоковую передачу и отрисовку результатов) без машины и без разблокировки. Реальное выполнение требует реального executor’а.
Смотрите также
- Веб-консоль: браузерный клиент, построенный на этой модели
- Хранилище конфигурации: хранилище без раскрытия данных, которое защищает CEK