Агент OpenSearch — это сервис рядом с кластером. Он поддерживает собственный контроль доступа плагина безопасности в соответствии с подписанными политиками сервиса данных opensearch: одна роль на пользователя, которая содержит ровно то, что ему дают политики, сопоставлена только с этим пользователем и включает безопасность на уровне полей, маскированные поля и безопасность на уровне документов. Затем OpenSearch сам проверяет каждый запрос, а агент никогда не стоит между клиентами и кластером. Дистрибутив поставляет его как исполняемый JAR agents/opensearch/grantforge-agent-opensearch-<version>.jar, которому нужна Java 17 или новее.
Интеграционные тесты Testcontainers в репозитории запускают агент и поставляемый JAR на OpenSearch 2.19, 3.3, 3.6 и 3.9 с плагином безопасности. Это не означает сертификацию всех остальных версий; агент отклоняет кластеры старше 2.19 и кластеры без плагина безопасности. О сервисном плагине см. OpenSearch.
Как это работает
- Одна роль на пользователя содержит то, что даёт GrantForge. Для каждого пользователя, которому политики что-то дают, агент ведёт роль с его именем,
grantforge_aliceдляalice, сопоставленную только с ним. Её описание помечает её как роль агента, и агент не считает своей ни одну роль без такой пометки, поэтому не меняет другие роли и сопоставления. - Шаблоны индексов остаются шаблонами. Шаблон индекса из политики, например
logs-*, выдаётся как шаблон там, где все политики решают одинаково по всему шаблону: любая политика любого вида, чьи индексы пересекаются с шаблоном, покрывает его целиком. Агент определяет это точно, с помощью конечных автоматов шаблонов. Индексы, созданные позже, например завтрашние журналы, становятся доступны сразу, в том числе когда их создаёт первый записанный документ. Где политика решает иначе внутри шаблона, например запрещаетlogs-secretвнутриlogs-*, агент выдаёт по имени каждый индекс и поток данных кластера, а новые — при следующей синхронизации. - Безопасность на уровне полей — только где ниже решается иначе. Индекс, который пользователь может читать целиком и где ни одна политика не может отнять поле, читается без безопасности на уровне полей, поэтому добавленные позже поля читаются сразу. Иначе пользователь читает поля, которые разрешает политика, из тех, что есть в его документах, и тех, что названы в политиках; мультиполя вроде
name.keywordследуют за своим полем. - Маски и фильтры строк — механизмы самого плагина безопасности. Маска становится маскированным полем записи, а фильтр строк — её запросом безопасности на уровне документов. API validate OpenSearch проверяет каждый запрос до выдачи; запрос, который OpenSearch не выполнил бы, не показывает пользователю ни одного документа и записывается в журнал. Маска, которую плагин безопасности не знает, вместо этого скрывает поле.
- Одна запись на набор прав. Индексы и шаблоны с одинаковыми правами делят одну запись; записи никогда не пересекаются, так как плагин безопасности объединяет безопасность на уровне полей и документов пересекающихся записей.
- Составные операции кластера приходят вместе с чтением и записью. Чтение приносит
cluster_composite_ops_roдля multi-search, multi-get и прокрутки, запись —cluster_composite_opsдля bulk. - Изменения — это один патч. Агент записывает роли и сопоставления как JSON-патчи, которые плагин безопасности применяет сразу во всём кластере: роли — до сопоставлений, которые на них ссылаются, сопоставления — до удаления ролей, на которые они ссылаются. Патч, который плагин безопасности отклоняет, применяется по одному изменению, так что ошибочная роль отказывает в одиночку.
- Политики текущего момента. Каждая синхронизация строит план по политикам в том виде, в каком они действуют в этот момент, поэтому сроки действия начинаются и заканчиваются вовремя.
- Роли бэкенда — это группы. Политика для группы действует для внутренних пользователей с ролью бэкенда с таким именем, а также для групп, в которые GrantForge помещает пользователей.
- Ручные изменения отменяются. При каждой синхронизации агент сравнивает свои роли и сопоставления с тем, что хранит плагин безопасности; отличия записываются заново. Если ничего не изменилось, агент ничего не отправляет.
- Роли вне GrantForge сообщаются. OpenSearch выдаёт то, что даёт любая из ролей пользователя, поэтому агент не может отнять то, что даёт другая роль, сопоставленная с пользователем. Он однократно предупреждает о каждой такой роли, которая даёт то, что запрещает политика, называя роль, пользователя, доступ, индекс и политику, а также о пользователях, сопоставленных с
all_access, которых не ограничивает ни одна роль. - Обращения берутся из журнала аудита. Агент читает журнал аудита плагина безопасности из индексов, куда тот его пишет,
security-auditlog-*: отклонённое — какMISSING_PRIVILEGES, разрешённое — какGRANTED_PRIVILEGES, если конфигурация аудита их записывает. Каждое событие называет пользователя, тип доступа, каждый затронутый индекс или поток данных либо кластер и сообщает, решил ли это GrantForge или разрешила роль вне GrantForge.
| Действие | Событие доступа |
|---|---|
indices:data/read/*: поиск, получение, подсчёт |
read на каждом индексе или потоке данных |
indices:data/write/index, update, bulk |
index |
indices:data/write/delete |
delete |
indices:admin/create, auto_create, data_stream/create |
create_index |
indices:admin/aliases*, indices:monitor/* |
manage_aliases, monitor |
Прочие indices:admin/* |
manage |
cluster:monitor/*, cluster:admin/snapshot/* и repository/* |
cluster_monitor, manage_snapshots на кластере |
| Шаблоны индексов и компонентов, конвейеры приёма | manage_templates, manage_pipelines на кластере |
Развёртывание
-
Добавьте сервис данных
opensearchи настройте его политики. Откройте Права доступа к данным → Агенты, выберите сервис и выпустите токен агента. Он показывается только один раз; сохраните его в файл, который может читать только учётная запись агента. -
Дайте агенту пользователя, который может менять конфигурацию плагина безопасности: пользователя, сопоставленного с
all_access, если его перечисляетplugins.security.restapi.roles_enabled, или административный сертификат, указанный вplugins.security.authcz.admin_dn. Тесты запускают агент от имениadminдемонстрационной конфигурации и с её административным сертификатом. -
Чтобы сообщать об обращениях, храните журнал аудита в кластере (
plugins.security.audit.type: internal_opensearch). Для того, что OpenSearch разрешил, также уберитеGRANTED_PRIVILEGESиз отключённых категорий конфигурации аудита; отказы записываются по умолчанию. -
Напишите файл настроек, заменив примеры адресов, путей и имён:
grantforge.server.url=https://grantforge.example.com grantforge.token.file=/etc/grantforge/opensearch-agent.token grantforge.instance=opensearch-agent-1 grantforge.cache.dir=/var/lib/grantforge/opensearch-agent grantforge.opensearch.hosts=https://opensearch1.internal:9200,https://opensearch2.internal:9200 grantforge.opensearch.user=grantforge grantforge.opensearch.password.file=/etc/grantforge/opensearch-agent.password grantforge.opensearch.tls.ca=/etc/grantforge/opensearch-ca.pemЭти пути находятся на машине агента, а каталог кеша должен быть доступен для записи. Файлы паролей читаются в UTF-8 с обрезкой пробелов.
-
Запустите агент, например как сервис systemd:
java -jar agents/opensearch/grantforge-agent-opensearch-<version>.jar /etc/grantforge/opensearch-agent.propertiesЗамените
<version>версией дистрибутива. Параметры, переданные какjava -Dgrantforge.…=… -jar …, переопределяют файл. По SIGTERM агент корректно останавливается и отправляет или откладывает ожидающие события; OpenSearch сохраняет то, что получил. -
Перенесите существующие роли в политики: роли, сопоставленные с пользователями вне GrantForge, продолжают действовать наряду с ролями агента. Создайте соответствующие политики, затем удалите эти сопоставления; предупреждения агента называют роли, которые дают то, что запрещает политика.
| Параметр | Назначение |
|---|---|
grantforge.server.url, grantforge.token.file, grantforge.instance, grantforge.cache.dir |
Обязательно: сервер GrantForge, файл токена агента, имя этого агента и доступный для записи каталог для подписанного снимка, отложенных событий и позиции чтения журнала аудита |
grantforge.signing.key.file |
Необязательный файл, закрепляющий ключ подписи снимков; скопируйте открытый ключ X.509 Ed25519 в Base64 со страницы «Агенты». Если не задан, ключ берётся с сервера при первом обращении |
grantforge.opensearch.hosts |
Обязательно: узлы в виде URL, по очереди, если один недоступен; без схемы узел считается https, порт по умолчанию 9200 |
grantforge.opensearch.user, grantforge.opensearch.password.file |
Пользователь агента и файл его пароля |
grantforge.opensearch.tls.cert, grantforge.opensearch.tls.key |
Вместо этого: клиентский PEM-сертификат и его закрытый ключ, вместе, для входа по сертификату; grantforge.opensearch.tls.key.passphrase.file содержит парольную фразу зашифрованного ключа |
grantforge.opensearch.ssl.verification.mode |
full (по умолчанию) проверяет сертификаты и имена узлов, certificate — только сертификаты, none — ничего |
grantforge.opensearch.tls.ca |
PEM-сертификаты CA, которыми проверяются узлы; пусто — доверие тому, чему доверяет Java |
grantforge.opensearch.timeout.ms |
Сколько могут занимать подключение и запрос, по умолчанию 30000, диапазон 1..600000 миллисекунд |
grantforge.opensearch.role.prefix |
Начало имён ролей агента, по умолчанию grantforge_; строчные буквы, цифры, дефисы и подчёркивания, оканчивается подчёркиванием, не более 32 символов. Агенту принадлежат помеченные им роли, имена которых начинаются с него |
grantforge.opensearch.unmanaged.users |
Пользователи, которых агент не трогает, через запятую, например сервисные учётные записи; своего пользователя и пользователей, сопоставленных с all_access, он не трогает никогда |
grantforge.sync.interval.ms |
Как часто агент приводит OpenSearch в соответствие, по умолчанию 10000, диапазон 1000..3600000 миллисекунд |
grantforge.audit.log |
По умолчанию true; false — журнал аудита не читается, обращения не сообщаются |
grantforge.audit.log.index, grantforge.audit.log.interval.ms, grantforge.audit.log.max.documents |
Индексы журнала аудита, по умолчанию security-auditlog-*; как часто он читается, по умолчанию 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 — отправлять каждое |
Пользователи, группы и роли
Политики называют пользователей OpenSearch так, как их знает плагин безопасности. Агент ведёт роли для внутренних пользователей, для пользователей, названных в политиках, которые могут входить через каталог, например LDAP или SAML, и для пользователей, для которых он уже вёл роли; зарезервированных и скрытых пользователей плагина безопасности, например kibanaserver, он не трогает. Группы — это роли бэкенда внутреннего пользователя вместе с группами, в которые GrantForge помещает пользователя; роли бэкенда, которые каталог выдаёт при входе, агенту неизвестны, поэтому задайте таким пользователям группы в GrantForge. Роли — это роли, которые GrantForge даёт пользователю.
Решения и ограничения
- Без снимка агент ничего не меняет. Неиспользуемый сервис или токен, привязанный к сервису с типом не
opensearch, ничего не выдают: агент удаляет свои роли и сопоставления, и действуют собственные роли плагина безопасности. - Пока агент не работает, OpenSearch сохраняет то, что получил последним; изменения политик ждут агента. Изменение доходит до OpenSearch в пределах интервала обновления и интервала синхронизации.
- Индексы, выданные по имени, а не через шаблон, получают права при следующей синхронизации.
- Псевдонимы ведут к индексам за ними: поиск по псевдониму требует прав на каждый входящий в него индекс, поэтому политики называют индексы и потоки данных, а не псевдонимы.
- Фильтр строк может проверять только поля, которые пользователь может читать, а маска применяется к значениям полей text и keyword.
- Индексы, имена которых начинаются с точки, доступны только через шаблоны политик, начинающиеся с точки.
- Арендаторов (tenants) плагина безопасности для OpenSearch Dashboards агент не ведёт.
