Агент ClickHouse — сервис рядом с серверами. Он поддерживает собственное управление доступом ClickHouse в соответствии с подписанными политиками сервиса данных clickhouse: по одной роли на пользователя, в которой ровно то, что политики дают пользователю, и по одной политике строк на каждый фильтр строк. Затем ClickHouse сам проверяет каждый запрос по каждому из своих протоколов, а агент никогда не стоит между клиентами и сервером. Дистрибутив поставляет его исполняемым JAR-файлом agents/clickhouse/grantforge-agent-clickhouse-<version>.jar, которому нужна Java 17 или новее.
Интеграционные тесты Testcontainers в репозитории запускают агента, и JAR в том виде, в каком он поставляется, против ClickHouse 24.8, 25.3, 25.8, 26.3 и 26.8. Это не означает сертификацию всех остальных версий; серверы старше 24.8 агент отклоняет. Плагин сервиса описан в ClickHouse.
Как это работает
- Одна роль на пользователя содержит то, что даёт GrantForge. Для каждого пользователя, которому политики что-то дают, агент ведёт роль с его именем,
grantforge_aliceдляalice, и выдаёт её пользователю как роль по умолчанию.SHOW GRANTS FOR grantforge_aliceпоказывает всё, что GrantForge даётalice; агент не меняет других ролей и привилегий, которые выдал не он. - Целые базы данных, где ниже ничего не решается иначе. Тип доступа, который политика разрешает на всю базу данных, если ни одна политика не может отнять его у таблицы или столбца в ней, выдаётся на базу данных, так что таблицы, созданные позже, сразу его получают. Иначе он выдаётся по таблицам, а чтение и запись — по столбцам.
- Фильтры строк становятся политиками строк. Фильтр строк — разрешающая (permissive) политика строк роли пользователя на таблице. Новый или изменённый фильтр вступает в силу раньше привилегий, которые он сужает. Фильтр, который ClickHouse отклоняет, или фильтр, текст которого сделал бы политику строк применимой к другим, заменяется фильтром, который не показывает пользователю ни одной строки, и записывается в журнал.
- Политики текущего момента. Каждая синхронизация планирует по политикам в том виде, в каком они действуют в этот момент, поэтому сроки действия начинаются и заканчиваются вовремя, и по пользователям, базам данных, таблицам и столбцам, которые есть в ClickHouse, поэтому новые охватываются при следующей синхронизации.
- Роли ClickHouse — это группы. Политика для группы применяется к пользователям с ролью ClickHouse с таким именем, полученной напрямую или через другие роли, вместе с группами, в которые GrantForge включает пользователя.
- Изменения, сделанные вручную, отменяются. Агент помнит, что он выдал каждой роли и политике строк; расходящиеся восстанавливаются при следующей синхронизации. Если ничего не изменилось, агент ничего не отправляет.
- О привилегиях вне GrantForge сообщается. ClickHouse складывает привилегии, поэтому агент не может отнять то, что пользователь получил напрямую или через другую роль. Он один раз предупреждает о каждой такой привилегии, которая даёт то, что запрещает политика, называя пользователя, привилегию, роль, через которую она получена, и политику.
- Обращения берутся из журнала запросов. Агент читает
system.query_logи передаёт каждую инструкцию как одно событие на таблицу, базу данных или сервер, которых она коснулась, а отказ — как одно событие отказа для того, что называет ошибка ClickHouse. Каждое событие говорит, решил ли его GrantForge, то есть решают ли политики так же, как ClickHouse, или его разрешила привилегия вне GrantForge.
| Инструкция | Событие доступа |
|---|---|
SELECT, читающая часть INSERT … SELECT |
select на каждую прочитанную таблицу |
INSERT |
insert на таблицу, в которую идёт запись |
ALTER, ALTER UPDATE, ALTER DELETE, DELETE, UPDATE |
alter на таблицу |
DROP TABLE, TRUNCATE, OPTIMIZE |
drop, truncate, optimize на таблицу |
CREATE TABLE, CREATE VIEW, CREATE DICTIONARY |
create на базу данных |
DROP DATABASE |
drop_database на базу данных |
CREATE DATABASE, KILL QUERY, SYSTEM … |
create_database, kill_query, system на сервер |
Развёртывание
-
Добавьте сервис данных
clickhouseи настройте его политики. Откройте Права доступа к данным → Агенты, выберите сервис и выпустите токен агента. Он показывается только один раз; сохраните его в файл, доступный для чтения только учётной записи агента. -
Создайте пользователя ClickHouse для агента. Он выдаёт то, что дают политики, поэтому ему нужны эти привилегии с правом передачи и управление доступом, чтобы вести роли и политики строк:
CREATE USER grantforge IDENTIFIED BY '…'; GRANT SELECT, INSERT, ALTER, CREATE TABLE, CREATE VIEW, CREATE DICTIONARY, CREATE DATABASE, DROP TABLE, DROP VIEW, DROP DICTIONARY, DROP DATABASE, TRUNCATE, OPTIMIZE, KILL QUERY, SYSTEM ON *.* TO grantforge WITH GRANT OPTION; GRANT ACCESS MANAGEMENT ON *.* TO grantforge;Пользователи, для которых агент ведёт роли, должны храниться там, где их можно изменить, — в каталоге пользователей
local_directoryилиreplicated, куда их помещаетCREATE USER. Пользователи изusers.xmlи LDAP не затрагиваются и один раз записываются в журнал. Кластеру следует хранить пользователей, роли и политики строк в каталоге пользователейreplicated: тогда один агент обслуживает весь кластер. -
Напишите файл настроек, заменив адреса, пути и имена из примера:
grantforge.server.url=https://grantforge.example.com grantforge.token.file=/etc/grantforge/clickhouse-agent.token grantforge.instance=clickhouse-agent-1 grantforge.cache.dir=/var/lib/grantforge/clickhouse-agent grantforge.clickhouse.urls=https://clickhouse1.internal:8443,https://clickhouse2.internal:8443 grantforge.clickhouse.user=grantforge grantforge.clickhouse.password.file=/etc/grantforge/clickhouse-agent.password grantforge.clickhouse.tls.ca=/etc/grantforge/clickhouse-ca.pem grantforge.audit.query.log.cluster=mainЭти пути находятся на машине агента, а каталог кэша должен быть доступен для записи. Файлы паролей читаются в UTF-8, пробелы по краям отбрасываются.
-
Запустите агента, например как сервис systemd:
java -jar agents/clickhouse/grantforge-agent-clickhouse-<version>.jar /etc/grantforge/clickhouse-agent.propertiesЗамените
<version>версией дистрибутива. Параметры, заданные какjava -Dgrantforge.…=… -jar …, переопределяют файл. По SIGTERM агент корректно останавливается и отправляет или буферизует ожидающие события; ClickHouse сохраняет то, что получил. -
Перенесите существующие привилегии в политики: привилегии, выданные вне GrantForge, продолжают действовать наряду с ролями агента. Создайте соответствующие политики, затем отзовите эти привилегии; предупреждения агента называют те из них, что дают запрещённое политикой.
| Параметр | Назначение |
|---|---|
grantforge.server.url, grantforge.token.file, grantforge.instance, grantforge.cache.dir |
Обязательные: сервер GrantForge, файл токена агента, имя этого агента и каталог с правом записи для подписанного снимка, буферизованных событий и позиции чтения журнала запросов |
grantforge.signing.key.file |
Необязательный файл, закрепляющий ключ подписи снимков; скопируйте открытый ключ X.509 Ed25519 в кодировке Base64 со страницы «Агенты». Если он не задан, ключ берётся с сервера при первом обращении |
grantforge.clickhouse.urls, grantforge.clickhouse.user |
Обязательные: HTTP-интерфейсы серверов, по очереди, если какой-то недоступен, и пользователь ClickHouse агента |
grantforge.clickhouse.password.file |
Пароль пользователя; без него агент входит без пароля |
grantforge.clickhouse.tls.ca |
Сертификат CA в формате PEM для проверки серверов https://; пустое значение — доверять тому, чему доверяет Java |
grantforge.clickhouse.tls.cert, grantforge.clickhouse.tls.key |
Клиентский сертификат PEM и закрытый ключ, вместе, для входа по сертификату (IDENTIFIED WITH ssl_certificate) вместо пароля |
grantforge.clickhouse.timeout.ms |
Сколько может длиться запрос к ClickHouse, по умолчанию 30000, диапазон 1..600000 миллисекунд |
grantforge.clickhouse.role.prefix |
Начало имён ролей агента, по умолчанию grantforge_; буквы, цифры и подчёркивания, в конце подчёркивание. Агенту принадлежат все роли и политики строк, чьё имя так начинается |
grantforge.clickhouse.unmanaged.users |
Пользователи, которых агент не трогает, через запятую, например администраторы; своего пользователя он не трогает никогда |
grantforge.sync.interval.ms |
Как часто агент синхронизирует ClickHouse, по умолчанию 10000, диапазон 1000..3600000 миллисекунд |
grantforge.audit.query.log |
По умолчанию true; false — не читать журнал запросов и не передавать обращения |
grantforge.audit.query.log.cluster |
Кластер, журналы реплик которого читаются через clusterAllReplicas; пустое значение — читать сервер, к которому обращается агент |
grantforge.audit.query.log.delay.ms, grantforge.audit.query.log.interval.ms, grantforge.audit.query.log.batch |
Насколько позже текущего момента читается журнал, по умолчанию 10000 миллисекунд, поскольку ClickHouse пишет его каждые 7,5 секунды; как часто, по умолчанию 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 передаёт каждое |
Пользователи, группы и роли
Политики называют пользователей ClickHouse. Группы — это роли ClickHouse, которые есть у пользователя напрямую или через другие роли, вместе с группами, в которые GrantForge включает пользователя; роли — это роли, которые GrantForge выдаёт пользователю.
Решения и ограничения
- Без снимка агент ничего не меняет. Неиспользуемый сервис или токен, привязанный к сервису с типом не
clickhouse, ничего не выдаёт: агент удаляет свои роли и политики строк, и действуют собственные привилегии ClickHouse. - Пока агент не работает, ClickHouse сохраняет то, что получил последним; изменения политик ждут агента. Изменение доходит до ClickHouse в пределах интервала обновления и интервала синхронизации.
- Таблицы, созданные в базе данных, на которую агент выдаёт привилегии по таблицам, получают их при следующей синхронизации.
- Пользователь, для которого в ClickHouse нет ни одной политики строк, видит все строки таблицы, как по умолчанию разрешает параметр ClickHouse
users_without_row_policies_can_read_rows; если он выключен, пользователи без фильтра не видят ни одной строки отфильтрованных таблиц. Разрешающие политики строк, созданные вне GrantForge для того же пользователя, расширяют то, что показывает его фильтр. systemвыдаёт любые инструкцииSYSTEM, включаяSYSTEM SHUTDOWN.- Журнал запросов передаёт то, что записывает ClickHouse: инструкции пользователей с выключенным
log_queriesне передаются. При отказе ClickHouse может назвать таблицу, когда пользователю не хватает одного столбца; тогда событие называет таблицу. - В ClickHouse нет маскирования столбцов вне ClickHouse Cloud, поэтому политики не могут маскировать значения.
