RBAC: пользователи, роли, политики строк и квоты
SQL-based RBAC (Role-Based Access Control) — стандарт управления доступом в ClickHouse начиная с версии 20.x. Больше не нужно редактировать XML-файлы и перезапускать сервер: CREATE USER, CREATE ROLE, GRANT, CREATE ROW POLICY, CREATE QUOTA — всё выполняется SQL-командами на лету.
Иерархия RBAC
CREATE USER: создание пользователя
-- Пользователь с паролем и ограничением по IP
CREATE USER analyst_user
IDENTIFIED BY 'secure_password_here'
HOST IP '10.0.0.0/8';
-- Пользователь с ограничением по hostname
CREATE USER etl_service
IDENTIFIED BY 'etl_password'
HOST NAME 'etl.internal.company.com';
-- Пользователь с дефолтной ролью
CREATE USER dashboard_user
IDENTIFIED BY 'dashboard_pw'
HOST ANY
DEFAULT ROLE dashboard_role;
Просмотр существующих пользователей:
SHOW USERS;
SELECT name, host_ip, host_names, default_roles_list
FROM system.users
FORMAT PrettyCompact;
CREATE ROLE: создание роли
-- Базовые роли
CREATE ROLE analyst_role;
CREATE ROLE etl_role;
CREATE ROLE admin_role;
-- Назначить роль пользователю
GRANT analyst_role TO analyst_user;
-- Назначить несколько ролей
GRANT analyst_role, dashboard_role TO analyst_user;
GRANT: назначение привилегий
Привилегии на уровне таблицы
-- Полный SELECT на таблицу
GRANT SELECT ON default.events TO analyst_role;
-- SELECT только по определённым колонкам (column-level security)
GRANT SELECT(id, event_name, event_time, country) ON default.events TO analyst_role;
-- INSERT-права для ETL
GRANT INSERT ON default.events TO etl_role;
-- DDL-права для администратора
GRANT CREATE TABLE, DROP TABLE ON default.* TO admin_role;
Привилегии на уровне базы данных
-- Все операции на базу
GRANT ALL ON default.* TO admin_role;
-- Только чтение всей базы
GRANT SELECT ON analytics.* TO analyst_role;
CREATE ROW POLICY: политика строк
Row policy позволяет ограничить, какие строки видит конкретная роль при SELECT.
-- Политика: tenant_a видит только свои данные
CREATE ROW POLICY tenant_a_policy ON default.shared_events
FOR SELECT USING tenant_id = 'tenant_a'
TO tenant_a_role;
Критическая особенность: После создания ROW POLICY для одной роли все остальные пользователи теряют доступ к таблице. ClickHouse применяет неявный DENY к пользователям без явной policy. Всегда создавайте явную allow-policy для администраторов и других ролей:
CREATE ROW POLICY allow_all ON default.shared_events
USING 1
TO admin_role, service_role;Полный паттерн multi-tenant изоляции
-- Шаг 1: Политика для tenant_a
CREATE ROW POLICY tenant_a_policy ON default.shared_events
FOR SELECT USING tenant_id = 'tenant_a'
TO tenant_a_role;
-- Шаг 2: Политика для tenant_b
CREATE ROW POLICY tenant_b_policy ON default.shared_events
FOR SELECT USING tenant_id = 'tenant_b'
TO tenant_b_role;
-- Шаг 3 (ОБЯЗАТЕЛЬНО): Allow-all для admin — иначе admin тоже потеряет доступ
CREATE ROW POLICY admin_allow_all ON default.shared_events
USING 1
TO admin_role;
Просмотр существующих политик:
SHOW ROW POLICIES;
SELECT name, table, condition
FROM system.row_policies
FORMAT PrettyCompact;
CREATE QUOTA: квоты потребления
Квоты ограничивают суммарное потребление ресурсов за временной интервал (в отличие от per-query SETTINGS).
-- Квота: не более 1000 запросов в час и 1 млрд строк в день
CREATE QUOTA tenant_a_quota
FOR INTERVAL 1 HOUR MAX queries = 1000, read_rows = 1000000000
TO tenant_a_role;
-- Многоинтервальная квота
CREATE QUOTA strict_quota
FOR INTERVAL 10 MINUTE MAX queries = 100
FOR INTERVAL 1 HOUR MAX queries = 500
FOR INTERVAL 1 DAY MAX result_rows = 10000000
TO analyst_role;
Мониторинг использования квот:
-- Текущее использование квоты
SELECT *
FROM system.quota_usage
FORMAT PrettyCompact;
Полный пример: multi-tenant изоляция
-- 1. Пользователи
CREATE USER tenant_a_user
IDENTIFIED BY 'secure_password'
HOST IP '10.0.0.0/8';
-- 2. Роль
CREATE ROLE tenant_a_role;
-- 3. Column-level привилегии (скрыть PII-колонку phone_number)
GRANT SELECT(id, event_name, event_time, country) ON default.shared_events TO tenant_a_role;
-- 4. Row-level изоляция
CREATE ROW POLICY tenant_a_isolation ON default.shared_events
FOR SELECT USING tenant_id = 'tenant_a'
TO tenant_a_role;
-- 5. Admin allow-all (ОБЯЗАТЕЛЬНО!)
CREATE ROW POLICY admin_allow_all ON default.shared_events
USING 1
TO admin_role;
-- 6. Квота
CREATE QUOTA tenant_a_quota
FOR INTERVAL 1 HOUR MAX queries = 1000, read_rows = 1000000000
TO tenant_a_role;
-- 7. Назначение
GRANT tenant_a_role TO tenant_a_user;
Ключевые выводы
- SQL-based RBAC (20.x+) не требует редактирования XML и перезапуска сервера.
CREATE USER/ROLEвыполняются немедленно. GRANT SELECT(col1, col2)обеспечивает column-level security: пользователь видит только указанные колонки. Используйте для защиты PII-данных.- ROW POLICY — критическая ловушка: создание policy для одной роли делает таблицу невидимой для ВСЕХ остальных пользователей. Всегда добавляйте явный
USING 1allow-policy для admin_role. CREATE QUOTA FOR INTERVAL— накопительный счётчик за период. Отличие отmax_rows_to_read: квота суммирует потребление между запросами, не ограничивает один запрос.- Порядок создания важен: сначала создайте admin allow-policy, затем restrictive policy для тенантов — это предотвращает случайную потерю доступа к данным.