Как это работает
Как это устроено
Три процесса на сервере с Maran, контракт между ними и правила, которые решают, что корневому демону вообще позволено делать.
На сервере с Maran работают ровно три процесса. Разделение между ними — главное проектное решение продукта, и большинство правил ниже следуют из него.
Три процесса
| Процесс | Работает от | Держит |
|---|---|---|
maran-api | непривилегированного системного пользователя | всю бизнес-логику и единственное подключение к базе |
maran-agent | root | ничего — он без состояния, без базы и без собственной конфигурации |
| PostgreSQL | собственного пользователя | данные панели, на unix-сокете, вообще без TCP-порта |
Панель никогда не трогает систему. Агент ничего не решает. В этом вся форма: процесс, который знает, что должно произойти, не имеет привилегий, а процесс с привилегиями знает только, как выполнить фиксированный список вещей.
Контракт между ними
Они говорят через unix-сокет, и передаётся именованная операция с типизированными и проверенными аргументами. Отсюда три свойства, и каждое — правило, а не привычка:
- Нет операции, которая запускает переданную вызывающей стороной программу. Ни ограниченной, ни из белого списка — никакой. Поэтому множество того, что можно заставить сделать корневой процесс, конечно, записано и поддаётся ревью.
- Нигде в обмене нет shell-строки. Домен не экранируется перед попаданием в конфигурационный файл; он проверяется как домен — буквы, цифры, дефисы и точки, — и в нём неоткуда взяться переводу строки, который завершит одну директиву и начнёт другую, выбранную вызывающим.
- Агент проверяет, кто спрашивает. Учётные данные пира на сокете читаются до рассмотрения операции, так что демон знает, какой процесс на другом конце, а не верит тому, что ему сказали.
Запись конфигурационного файла
Каждая привилегированная запись идёт в одном и том же порядке, и порядок — это и есть суть:
- отрендерить во временный файл;
fsync;- атомарно переименовать на место;
- дать проверить результат самой службе —
nginx -t, а не нашему регулярному выражению; - перезагрузить;
- откатить файл, если проверка или перезагрузка отказали.
Один плохой рендер не может уронить остальные сайты сервера, потому что о качестве рендера судит собственный парсер сервера.
Изоляция между аккаунтами
- Аккаунт — настоящий пользователь Linux, со своим домашним каталогом и правами файловой системы.
- Его PHP работает в собственном пуле php-fpm под собственным uid, и файловые операции идут от этого пользователя — никогда от root.
- Таблицы арендаторов ограничены аккаунтом на уровне базы, фильтрами запросов, которые автоматический тест проверяет, обходя всю модель.
- Запрос чужого ресурса отвечает 404, а не 403, поэтому ошибка никогда не подтверждает, что строка существует.
Чего сознательно нет
Ни брокера сообщений, ни сайдкара, ни второго демона. Фоновая работа идёт по надёжным очередям в PostgreSQL, и установка Maran не добавляет на сервер ничего, чего нет в таблице выше, — кроме одного исключения, которое оператор включает сам: службы FTPS.
Платные модули этого тоже не меняют: это модули на C#, которые управляют операциями, уже собранными в открытом агенте. Агент никогда не загружает внешний код — поэтому лицензия не может добавить новую привилегированную возможность.