feat(clickhouse): модель доступа — пользователи, роли и секрет кластера #78

Closed
opened 2026-08-09 23:24:45 +03:00 by ddmitry · 0 comments
Owner

Цель

Реализовать модель доступа к ClickHouse, принятую в
ADR 0007:
четыре пользователя и три роли, объявленные файлами настройки, общий секрет
кластера вместо учётных данных по репликам, пароль у default и отказ от него
как от учётки приложений.

Резолюция развилки — #66. ADR — источник истины по решению и доводам; этот
тикет его не переоткрывает.

Сначала прочитать

  • docs/adr/0007-clickhouse-access.md — решение целиком, включая хвост
    «осталось проверить при исполнении»: там четыре вопроса, и они работа этого
    тикета.
  • AGENTS.md — цена сложности и учебная ценность; правило про доки тем же PR.
  • compose.yamlx-clickhouse-common, clickhouse-init, подключения
    Airflow и Superset.
  • infra/clickhouse/config.d/cluster.xml, infra/airflow/init.sh,
    infra/superset/import/databases/clickhouse.yaml.
  • docs/architecture/storage.md — слои и что в них лежит сегодня.
  • docs/architecture/testing.md — что утверждает каждая цель make и куда
    класть проверку.

Порядок работы

Порядок не косметика: он ставит непроверенные допущения в начало, пока правок
почти нет. Коммиты по шагам.

  1. Пользователи, роли и секрет — не переключая контуры. Появляются etl,
    bi, analyst и общий секрет кластера, но default пока беспарольный и
    все ходят им. Стенд остаётся зелёным без единой правки проверок. Здесь же
    закрываются четыре вопроса из хвоста ADR; ответы с датой вносятся в ADR
    этим же PR, хвост оттуда убирается.
  2. Переключение контуров. DDL применяется etl, Airflow ходит etl,
    Superset — bi, пробник перестаёт читать вторую ноду под default.
  3. Пароль у default. Правятся проверки здоровья обеих нод и скрипты,
    зовущие clickhouse-client изнутри контейнеров.
  4. Документация. Раздел README «Состав и доступ» — кто каким
    пользователем ходит, вместо нынешнего «у локального учебного кластера нет
    пароля». Две строки в мастер-спеку: отложенные меры защиты в раздел 10,
    оставшееся к проверке — в раздел 11, если что-то останется. Отдельного
    справочника по доступу не заводить: своего содержания сверх ADR и README у
    него сегодня нет, а дом ему понадобится на этапе 4, когда появятся dds,
    dm и словари и гранты размножатся. Сюда же комментарии, которые правка
    делает неверными: compose.yaml про общего беспарольного пользователя для
    Distributed и абзац в dags/test_clickhouse.py про то, почему вторая
    нода читается через remote(). В этом репозитории комментарии — продукт.

Если подстановка пароля из окружения для пользователя не работает — идти
запасным путём, названным в ADR: пароли прямым текстом в файле настройки, и
README говорит об этом вслух. Останавливаться и спрашивать не нужно.

Известные подводные камни

Снято на живом стенде 9 августа 2026 года, ClickHouse 26.3.17.56, холодным
ревью постановки. Это не требования, а сэкономленное время: всё
перечисленное всплывёт в работе само, но позже и дороже.

  • ON CLUSTER требует отдельного разрешения. В конфигурации образа
    включён on_cluster_queries_require_cluster_grant, и у нынешнего default
    соответствующее право есть. Весь DDL стенда и пробник идут ON CLUSTER
    значит etl_writer это не только права на слои.
  • Чтение системных таблиц — тоже. Включён
    select_from_system_db_requires_grant; исключения в образе — только
    tables, columns, databases и константные. При этом
    clickhouse-connect (драйвер и Superset, и пробника) при создании клиента
    читает system.settings. Без разрешения Airflow и Superset не откроют
    соединение вовсе, и отказ придёт на подключении, а не там, где стенд
    собирается его показывать.
  • Движки разрешений не требуют: table_engines_require_grant в образе
    выключен, Kafka и Distributed отдельных прав не попросят.
  • Секрет кластера не покрывает remote(). Функция собирает соединение на
    лету, а не по описанию кластера. Пробник читает вторую ноду именно ей.
  • Пароль Superset некуда положить. Подключение импортируется из YAML,
    лежащего в git, а секреты не коммитятся; superset import-directory
    паролей не принимает. Развилка того же сорта, что подстановка пароля из
    окружения: выбрать способ, назвать выбор в README и в описании PR.
  • Пробник живёт в базе default — создаёт там служебные таблицы, а
    слоем она не является. Решено: права etl распространяются и на неё.
    Служебные таблицы проверок живут там, и заводить ради них слой дороже, чем
    сказать вслух, что default — место для служебного.
  • Подключение Airflow заводится без пароля, поэтому переменная с паролем
    нужна и в окружении процессов Airflow, не только у нод.
  • Порт метрик ClickHouse аутентификации сегодня не спрашивает. После
    пароля у default стоит убедиться, что Prometheus по-прежнему снимает три
    цели: на это смотрит make smoke.

Критерии приёмки

  • На обеих нодах есть etl, bi, analyst с ролями etl_writer,
    bi_reader, analyst_reader; объявлены файлами настройки, SQL-хранилище
    доступа не используется.
  • Границы прав измерены разово, руками, от лица пользователя, а не по
    содержимому конфига: bi получает отказ на stg и ods, analyst
    читает stg, etl пишет во все слои. Результат — в описание PR;
    постоянной проверки из этого не делать.
  • Измерено и записано в ADR, чьи права применяются на втором шарде при
    распределённом запросе от bi. Если вывод ADR не подтвердился — довод в
    ADR исправлен, решение пересмотрено или подтверждено по остальным
    основаниям. Подсказка к замеру: колонки user и initial_user в
    system.query_log на второй ноде.
  • У default есть пароль; проверки здоровья обеих нод зелёные; ни одно
    приложение не подключается пользователем default. За default
    остаются проверки здоровья и скрипты, зовущие клиента внутри
    контейнеров, — это не исключение из правила, а его граница.
  • Airflow ходит etl, Superset — bi; пробник test_clickhouse читает
    вторую ноду не под default.
  • Повторный make up на существующих томах проходит и доступ не меняет;
    make clean && make up даёт тот же доступ. «Доступ» здесь — набор
    пользователей, ролей и прав. Владелец матвью приёма у двух стендов
    разойдётся, и это ожидаемо: см. раздел «Следствия» в ADR 0007.
  • В .env.example появились переменные ClickHouse; make config-test
    зелёный. В описании PR сказано, что владельцу нужно дописать те же
    переменные в свой .env, иначе make up встанет на :?.
  • Зелены make config-test, make lint, make smoke,
    make check-clickhouse, make check-services. Проверки, сверявшие
    логин default, обновлены под новых пользователей, а не ослаблены.
  • Четыре вопроса из хвоста ADR 0007 закрыты ответами с датой; хвост из
    документа убран.
  • Раздел README «Состав и доступ» говорит, кто каким пользователем ходит
    и где живут пароли; утверждение об отсутствии пароля убрано. В
    мастер-спеку внесены отложенные меры защиты.

Границы

  • Слои dds и dm этот тикет не создаёт. Права на них выдаются заранее, и
    до появления слоёв bi не видит ничего — так решено, это не дефект.
  • Отложены и сюда не входят: TLS и защищённые межсерверные соединения,
    настоящее хранилище секретов, внешние поставщики учётных записей, квоты и
    профили под пользователя, политики строк, аудит запросов.
  • Лабы на правах — время подготовки уроков, не этот тикет.
  • Новых целей make и новых проверок тикет не заводит. Если по ходу
    покажется, что проверка нужна, — назвать, чему на ней учится менти, и
    вынести вопросом, а не дописывать молча.

Команды проверки

make config-test
make lint
make up
make smoke
make check-clickhouse
make check-services
make up            # повторно, на существующих томах
make clean && make up

Проверки, живущие на стенде, должны утверждать поведение, а не текст вывода:
отказ в правах ловится попыткой прочитать, а не поиском строки в конфиге.

## Цель Реализовать модель доступа к ClickHouse, принятую в [ADR 0007](https://git.dementev.space/ddmitry/clickstream-data-platform/src/branch/main/docs/adr/0007-clickhouse-access.md): четыре пользователя и три роли, объявленные файлами настройки, общий секрет кластера вместо учётных данных по репликам, пароль у `default` и отказ от него как от учётки приложений. Резолюция развилки — #66. ADR — источник истины по решению и доводам; этот тикет его не переоткрывает. ## Сначала прочитать - `docs/adr/0007-clickhouse-access.md` — решение целиком, включая хвост «осталось проверить при исполнении»: там четыре вопроса, и они работа этого тикета. - `AGENTS.md` — цена сложности и учебная ценность; правило про доки тем же PR. - `compose.yaml` — `x-clickhouse-common`, `clickhouse-init`, подключения Airflow и Superset. - `infra/clickhouse/config.d/cluster.xml`, `infra/airflow/init.sh`, `infra/superset/import/databases/clickhouse.yaml`. - `docs/architecture/storage.md` — слои и что в них лежит сегодня. - `docs/architecture/testing.md` — что утверждает каждая цель `make` и куда класть проверку. ## Порядок работы Порядок не косметика: он ставит непроверенные допущения в начало, пока правок почти нет. Коммиты по шагам. 1. **Пользователи, роли и секрет — не переключая контуры.** Появляются `etl`, `bi`, `analyst` и общий секрет кластера, но `default` пока беспарольный и все ходят им. Стенд остаётся зелёным без единой правки проверок. Здесь же закрываются четыре вопроса из хвоста ADR; ответы с датой вносятся в ADR этим же PR, хвост оттуда убирается. 2. **Переключение контуров.** DDL применяется `etl`, Airflow ходит `etl`, Superset — `bi`, пробник перестаёт читать вторую ноду под `default`. 3. **Пароль у `default`.** Правятся проверки здоровья обеих нод и скрипты, зовущие `clickhouse-client` изнутри контейнеров. 4. **Документация.** Раздел README «Состав и доступ» — кто каким пользователем ходит, вместо нынешнего «у локального учебного кластера нет пароля». Две строки в мастер-спеку: отложенные меры защиты в раздел 10, оставшееся к проверке — в раздел 11, если что-то останется. Отдельного справочника по доступу не заводить: своего содержания сверх ADR и README у него сегодня нет, а дом ему понадобится на этапе 4, когда появятся `dds`, `dm` и словари и гранты размножатся. Сюда же комментарии, которые правка делает неверными: `compose.yaml` про общего беспарольного пользователя для `Distributed` и абзац в `dags/test_clickhouse.py` про то, почему вторая нода читается через `remote()`. В этом репозитории комментарии — продукт. Если подстановка пароля из окружения для пользователя не работает — идти запасным путём, названным в ADR: пароли прямым текстом в файле настройки, и README говорит об этом вслух. Останавливаться и спрашивать не нужно. ## Известные подводные камни Снято на живом стенде 9 августа 2026 года, ClickHouse 26.3.17.56, холодным ревью постановки. Это не требования, а сэкономленное время: всё перечисленное всплывёт в работе само, но позже и дороже. - **`ON CLUSTER` требует отдельного разрешения.** В конфигурации образа включён `on_cluster_queries_require_cluster_grant`, и у нынешнего `default` соответствующее право есть. Весь DDL стенда и пробник идут `ON CLUSTER` — значит `etl_writer` это не только права на слои. - **Чтение системных таблиц — тоже.** Включён `select_from_system_db_requires_grant`; исключения в образе — только `tables`, `columns`, `databases` и константные. При этом `clickhouse-connect` (драйвер и Superset, и пробника) при создании клиента читает `system.settings`. Без разрешения Airflow и Superset не откроют соединение вовсе, и отказ придёт на подключении, а не там, где стенд собирается его показывать. - **Движки разрешений не требуют**: `table_engines_require_grant` в образе выключен, `Kafka` и `Distributed` отдельных прав не попросят. - **Секрет кластера не покрывает `remote()`.** Функция собирает соединение на лету, а не по описанию кластера. Пробник читает вторую ноду именно ей. - **Пароль Superset некуда положить.** Подключение импортируется из YAML, лежащего в git, а секреты не коммитятся; `superset import-directory` паролей не принимает. Развилка того же сорта, что подстановка пароля из окружения: выбрать способ, назвать выбор в README и в описании PR. - **Пробник живёт в базе `default`** — создаёт там служебные таблицы, а слоем она не является. Решено: права `etl` распространяются и на неё. Служебные таблицы проверок живут там, и заводить ради них слой дороже, чем сказать вслух, что `default` — место для служебного. - **Подключение Airflow заводится без пароля**, поэтому переменная с паролем нужна и в окружении процессов Airflow, не только у нод. - **Порт метрик ClickHouse** аутентификации сегодня не спрашивает. После пароля у `default` стоит убедиться, что Prometheus по-прежнему снимает три цели: на это смотрит `make smoke`. ## Критерии приёмки - [ ] На обеих нодах есть `etl`, `bi`, `analyst` с ролями `etl_writer`, `bi_reader`, `analyst_reader`; объявлены файлами настройки, SQL-хранилище доступа не используется. - [ ] Границы прав измерены разово, руками, от лица пользователя, а не по содержимому конфига: `bi` получает отказ на `stg` и `ods`, `analyst` читает `stg`, `etl` пишет во все слои. Результат — в описание PR; постоянной проверки из этого не делать. - [ ] Измерено и записано в ADR, чьи права применяются на втором шарде при распределённом запросе от `bi`. Если вывод ADR не подтвердился — довод в ADR исправлен, решение пересмотрено или подтверждено по остальным основаниям. Подсказка к замеру: колонки `user` и `initial_user` в `system.query_log` на второй ноде. - [ ] У `default` есть пароль; проверки здоровья обеих нод зелёные; ни одно приложение не подключается пользователем `default`. За `default` остаются проверки здоровья и скрипты, зовущие клиента внутри контейнеров, — это не исключение из правила, а его граница. - [ ] Airflow ходит `etl`, Superset — `bi`; пробник `test_clickhouse` читает вторую ноду не под `default`. - [ ] Повторный `make up` на существующих томах проходит и доступ не меняет; `make clean && make up` даёт тот же доступ. «Доступ» здесь — набор пользователей, ролей и прав. Владелец матвью приёма у двух стендов разойдётся, и это ожидаемо: см. раздел «Следствия» в ADR 0007. - [ ] В `.env.example` появились переменные ClickHouse; `make config-test` зелёный. В описании PR сказано, что владельцу нужно дописать те же переменные в свой `.env`, иначе `make up` встанет на `:?`. - [ ] Зелены `make config-test`, `make lint`, `make smoke`, `make check-clickhouse`, `make check-services`. Проверки, сверявшие логин `default`, обновлены под новых пользователей, а не ослаблены. - [ ] Четыре вопроса из хвоста ADR 0007 закрыты ответами с датой; хвост из документа убран. - [ ] Раздел README «Состав и доступ» говорит, кто каким пользователем ходит и где живут пароли; утверждение об отсутствии пароля убрано. В мастер-спеку внесены отложенные меры защиты. ## Границы - Слои `dds` и `dm` этот тикет не создаёт. Права на них выдаются заранее, и до появления слоёв `bi` не видит ничего — так решено, это не дефект. - Отложены и сюда не входят: TLS и защищённые межсерверные соединения, настоящее хранилище секретов, внешние поставщики учётных записей, квоты и профили под пользователя, политики строк, аудит запросов. - Лабы на правах — время подготовки уроков, не этот тикет. - Новых целей `make` и новых проверок тикет не заводит. Если по ходу покажется, что проверка нужна, — назвать, чему на ней учится менти, и вынести вопросом, а не дописывать молча. ## Команды проверки ``` make config-test make lint make up make smoke make check-clickhouse make check-services make up # повторно, на существующих томах make clean && make up ``` Проверки, живущие на стенде, должны утверждать поведение, а не текст вывода: отказ в правах ловится попыткой прочитать, а не поиском строки в конфиге.
ddmitry added the ready-for-agent label 2026-08-09 23:24:45 +03:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: ddmitry/clickstream-data-platform#78