Агент MongoDB — это сервис рядом с развёртыванием. Он поддерживает собственное управление доступом MongoDB в соответствии с подписанными политиками сервиса данных mongodb: одна роль на пользователя, содержащая ровно то, что ему дают политики. Затем MongoDB сам проверяет каждую команду, а агент не стоит на пути ни одного клиента. Дистрибутив поставляет его как исполняемый JAR agents/mongodb/grantforge-agent-mongodb-<version>.jar; нужна Java 17 или новее.
Интеграционные тесты Testcontainers в репозитории запускают агента и поставляемый JAR на наборах реплик MongoDB 6.0, 7.0, 8.0 и 9.0 и шардированном кластере 9.0 и читают журнал аудита Percona Server for MongoDB 7.0 и 8.0. Это не сертифицирует все остальные версии; агент отклоняет развёртывания старше 6.0. О сервисном плагине см. MongoDB.
Как это работает
- Одна роль на пользователя содержит то, что даёт GrantForge. Для каждого пользователя, которому политики что-то дают, агент поддерживает в
adminроль с его именем,grantforge_aliceдляalice, и выдаёт её каждому пользователю MongoDB с этим именем, напримерalice@adminиalice@sales.rolesInfoпоказывает, что GrantForge даётalice. Другие роли агент не меняет. - Изменение происходит за один шаг.
updateRoleзаменяет привилегии роли разом, так что у пользователя никогда не бывает одновременно старых и новых или ни тех, ни других. - Целые базы данных там, где ниже ничего не решается иначе. Тип доступа, который политика разрешает на всю базу данных и который ни одна политика не может отнять ниже, выдаётся на базу, так что коллекции, созданные позже, получают его сразу. Иначе он выдаётся по коллекциям, а новые охватываются при следующей синхронизации.
- Никогда больше, чем разрешают политики. Привилегия MongoDB на удаление базы данных — это привилегия на удаление каждой её коллекции. Агент выдаёт её только там, где политики дают и это; иначе не выдаёт и один раз записывает в журнал, какой пользователь чего не может и почему.
- Политики текущего момента. Каждая синхронизация планирует по политикам, действующим в этот момент, так что сроки действия начинаются и заканчиваются вовремя, и по пользователям, базам данных и коллекциям, которые есть в MongoDB, так что новые охватываются при следующей синхронизации.
- Роли MongoDB — это группы. Политика для группы применяется к пользователям с ролью MongoDB с таким именем, а также к группам, в которые их помещает GrantForge.
- Ручные изменения отменяются. При каждой синхронизации агент сравнивает свои роли с планами и исправляет привилегии, изменённые вручную, роли, которые заставили их наследовать, выдачу роли кому-то другому и роли, которые никому не нужны. Если ничего не изменилось, он ничего не отправляет.
- Роли вне GrantForge читаются на предмет того, что они дают. MongoDB суммирует то, что дают все роли пользователя, поэтому агент не может отнять то, что у пользователя есть через другую роль. MongoDB сообщает, что даёт каждая роль, включая встроенные и унаследованные, поэтому агент по одному разу предупреждает о роли вроде
readWrite@hr, дающей то, что запрещает политика, называя пользователя, доступ и политику. Он также предупреждает о пользователях, которые могут администрировать пользователей и так выдать себе что угодно, о пользователях сrootили любым действием на любом ресурсе и о сервере, который вообще не проверяет авторизацию. - Доступ берётся из журнала аудита или профилировщика. См. раздел «Сообщения о доступе» ниже. Каждое событие сообщает, решил ли GrantForge, то есть решают ли политики так же, как MongoDB, или команду разрешила внешняя роль. Об агрегации сообщается для каждой коллекции, которую читают её стадии
$lookup,$graphLookupи$unionWithи записывают$outи$merge. События называют команду и её пространство имён, но никогда её аргументы, которые могут содержать документы и пароли.
Развёртывание
-
Добавьте сервис данных
mongodbи настройте его политики. Откройте Права доступа к данным → Агенты, выберите сервис и выпустите токен агента. Он показывается только один раз; сохраните его в файл, который может читать только учётная запись агента. -
Создайте пользователя MongoDB для агента. Он создаёт и меняет роли и читает пользователей и роли с помощью
userAdminAnyDatabase; перечисляет коллекции с помощью роли, которая содержит только это; и читает параметры сервера и профилировщик с помощьюclusterMonitor.userAdminAnyDatabaseможет выдать себе что угодно, поэтому защищайте этого пользователя как администратора. Имя роли для перечисления не должно начинаться с префикса ролей агента.const admin = db.getSiblingDB("admin"); admin.createRole({ role: "agent_inventory", roles: [], privileges: [{ resource: { db: "", collection: "" }, actions: ["listCollections"] }] }); admin.createUser({ user: "grantforge", pwd: passwordPrompt(), roles: ["userAdminAnyDatabase", "clusterMonitor", "agent_inventory"] }); -
Чтобы сообщать о доступе, настройте один из источников из раздела «Сообщения о доступе» ниже.
-
Напишите файл параметров, заменив примерные адреса, пути и имена:
grantforge.server.url=https://grantforge.example.com grantforge.token.file=/etc/grantforge/mongodb-agent.token grantforge.instance=mongodb-agent-1 grantforge.cache.dir=/var/lib/grantforge/mongodb-agent grantforge.mongodb.uri=mongodb://db1.internal:27017,db2.internal:27017/?replicaSet=rs0 grantforge.mongodb.user=grantforge grantforge.mongodb.password.file=/etc/grantforge/mongodb-agent.passwordЭти пути находятся на машине агента, а каталог кэша должен быть доступен для записи. Файлы паролей читаются в UTF-8 с обрезкой пробелов.
-
Запустите агент, например как службу systemd:
java -jar agents/mongodb/grantforge-agent-mongodb-<version>.jar /etc/grantforge/mongodb-agent.propertiesЗамените
<version>версией дистрибутива. Параметры, переданные какjava -Dgrantforge.…=… -jar …, переопределяют файл. По SIGTERM агент корректно останавливается и отправляет или откладывает ожидающие события; MongoDB сохраняет то, что получил. -
Перенос существующих привилегий в политики: роли, выданные вне GrantForge, продолжают действовать рядом с ролями агента. Создайте соответствующие политики, затем отзовите эти роли. Предупреждения агента указывают на те, что дают запрещённое политикой.
| Параметр | Назначение |
|---|---|
grantforge.server.url, grantforge.token.file, grantforge.instance, grantforge.cache.dir |
Обязательно: сервер GrantForge, файл токена агента, имя этого агента и доступный для записи каталог для подписанного снимка, отложенных событий и позиции чтения журнала аудита |
grantforge.signing.key.file |
Необязательный файл, закрепляющий ключ подписи снимков; скопируйте открытый ключ X.509 Ed25519 в Base64 со страницы «Агенты». Если не задан, ключ берётся с сервера при первом обращении |
grantforge.mongodb.uri |
Обязательно: строка подключения без учётных данных |
grantforge.mongodb.auth.mechanism |
SCRAM-SHA-256 (по умолчанию), SCRAM-SHA-1, MONGODB-X509, PLAIN или GSSAPI |
grantforge.mongodb.user, grantforge.mongodb.password.file, grantforge.mongodb.auth.source |
Пользователь агента, при GSSAPI его принципал, при MONGODB-X509 необязателен; его пароль; для SCRAM — база данных, в которой он определён, по умолчанию admin |
grantforge.mongodb.tls.ca.file, grantforge.mongodb.tls.certificate.key.file, grantforge.mongodb.tls.certificate.key.password.file |
При tls=true в строке подключения: PEM-сертификаты ЦС для проверки серверов, пустое значение — то, чему доверяет Java; один PEM-файл с клиентским сертификатом и его ключом; пароль зашифрованного ключа |
grantforge.mongodb.kerberos.keytab, grantforge.mongodb.kerberos.service.name |
GSSAPI: keytab принципала, иначе используется пароль, и имя службы принципала серверов, по умолчанию mongodb. Область берётся из krb5.conf машины |
grantforge.mongodb.timeout.ms |
Сколько могут занимать поиск сервера, подключение и одна команда, по умолчанию 30000, в диапазоне 1..600000 миллисекунд |
grantforge.mongodb.role.prefix |
С чего начинаются имена ролей агента, по умолчанию grantforge_. Буквы, цифры и подчёркивания, заканчивается подчёркиванием, не более 32 символов. Любая роль в admin, имя которой начинается так, принадлежит агенту |
grantforge.mongodb.unmanaged.users |
Пользователи, которых агент не трогает, через запятую, например служебные учётные записи. Он никогда не трогает собственного пользователя и пользователей с root, __system или любым действием на любом ресурсе |
grantforge.mongodb.databases |
Базы данных, в которых агент выдаёт по коллекциям, через запятую, пусто — все. Остальные получают только то, что можно выдать целиком, чтобы база с очень большим числом коллекций не перечислялась при каждой синхронизации |
grantforge.mongodb.audit.files |
Файлы журнала аудита для чтения, через запятую. Пустое значение читает профилировщик |
grantforge.sync.interval.ms |
Как часто агент приводит MongoDB в соответствие, по умолчанию 10000, диапазон 1000..3600000 миллисекунд |
grantforge.audit.log |
По умолчанию true. false не читает и не сообщает о доступе |
grantforge.audit.log.delay.ms, grantforge.audit.log.interval.ms, grantforge.audit.log.batch |
На сколько отставать от текущего момента при чтении профилировщика (по умолчанию 2000), как часто читать доступ (по умолчанию 5000 миллисекунд) и наибольшее число записей, которое одно чтение берёт из файла или базы данных (по умолчанию 1000) |
grantforge.connect.timeout.ms, grantforge.read.timeout.ms |
Тайм-ауты подключения и чтения GrantForge, по умолчанию 5000 / 8000 миллисекунд |
grantforge.refresh.interval.ms |
Как часто агент запрашивает новые политики, по умолчанию 30000, не менее 1000 миллисекунд |
grantforge.audit.batch.size, grantforge.audit.queue.capacity, grantforge.audit.flush.interval.ms, grantforge.audit.spool.limit.bytes |
События доступа: размер пакета (по умолчанию 500), размер очереди (по умолчанию 10000), интервал отправки (по умолчанию 5000 миллисекунд) и предел отложенного на диске (по умолчанию 64 МиБ) |
grantforge.audit.fold.window.ms |
Сколько времени одинаковые разрешённые обращения сворачиваются в одно событие, по умолчанию 10000, до 3600000 миллисекунд; 0 — отправлять каждое |
Сообщения о доступе
| Источник | Где | Что сообщает | Как включить |
|---|---|---|---|
| Журнал аудита | MongoDB Enterprise и Percona Server for MongoDB | Что разрешено и что отклонено на каждом члене, файл которого может прочитать агент | Запустите mongod с --auditDestination file --auditFormat JSON --auditPath <path> и --setParameter auditAuthorizationSuccess=true и укажите файлы в grantforge.mongodb.audit.files |
| Профилировщик | Все редакции | Что выполнялось на члене, с которым общается агент, — первичном в наборе реплик; отказов нет | db.setProfilingLevel(2) в каждой базе данных, о которой нужно сообщать. Это нагружает сервер, поэтому агент никогда не включает его сам, а system.profile — небольшая ограниченная коллекция |
Журнал аудита читается из файлов, поэтому запускайте агента на узле или дайте ему каталог, в котором они собираются. Тесты читают журнал аудита Percona Server, имеющий формат MongoDB Enterprise. У mongos нет профилировщика, поэтому шардированный кластер сообщает о доступе только из журнала аудита.
| Команда | Событие доступа |
|---|---|
find, aggregate, count, distinct, listIndexes |
read для каждой прочитанной коллекции |
aggregate, начинающаяся с $changeStream |
change_stream |
insert, update, delete, findAndModify, bulkWrite |
insert, update или remove для каждой записанной коллекции; при запросе также bypass_validation |
createIndexes, dropIndexes |
create_index, drop_index |
collMod, validate, convertToCapped |
alter |
drop, create, dropDatabase |
drop, create, drop_database |
listDatabases; serverStatus, top, replSetGetStatus, connPoolStats, hostInfo, currentOp |
list_databases; monitor |
MongoDB отклоняет команду целиком, не говоря, какая из её коллекций стала причиной, поэтому об отказе сообщается для тех, которые запрещают политики, или для первой, если они не запрещают ни одной.
Пользователи, группы и роли
Политики называют пользователей MongoDB по имени пользователя. Имя, определённое в нескольких базах данных, — это один пользователь, и роль агента выдаётся всем им. Группы — это роли MongoDB пользователя и группы, в которые его помещает GrantForge. Роли — это роли, которые GrantForge даёт пользователю.
Решения и ограничения
- Без снимка агент ничего не меняет. Токен, привязанный к неиспользуемому сервису или к сервису не типа
mongodb, ничего не выдаёт: агент удаляет свои роли, а собственные роли MongoDB остаются. - Пока агент не работает, MongoDB сохраняет полученное последним, а изменения политик ждут. Изменение доходит до MongoDB в пределах интервалов обновления и синхронизации;
mongosприменяет его, когда истечёт его кэш пользователей, по умолчанию в течение 30 секунд (userCacheInvalidationIntervalSecs). - Привилегии MongoDB точно называют базы данных и коллекции, поэтому подстановочный знак в политике выдаётся для того, что существует. База данных существует, когда в ней есть коллекция: до этого
createна базу, названную в политике, выдавать не на что. - Пользователи, нигде не определённые в MongoDB, например те, кого авторизация LDAP сама сопоставляет с ролями, не видны, и агент не поддерживает для них ролей.
- Привилегия на всю базу данных охватывает её коллекции, но не коллекции
system., а собственные базы MongoDB остаются за MongoDB. - Переименование коллекций и прочие административные действия MongoDB не являются типами доступа: они остаются за ролями вне GrantForge.
- MongoDB не фильтрует строки и не маскирует поля по ролям; представление даёт ограниченное чтение.
