Перейти к основному содержимому
Версия: 2.0.x

IDE, AI/MCP, RBAC, пользователи и direct SQL

Этот документ выполняется после Engine READY и успешного POST /engine/cluster:bootstrap-auth-rbac. К этому моменту CM уже создал runtime credentials и записал passwords в selena-ide-secrets и selena-ai-secrets.

В Helm командах ниже используйте customer-specific values files, созданные из docs-external/values-minimal/ и заполненные под стенд: {selena_ide_values}, {selena_ai_values}, {selena_cm_values}. Не устанавливайте production/test стенд напрямую с values-minimal.

1. Установить Selena IDE​

Перед установкой IDE проверьте:

  • Keycloak client selena-ide создан;
  • Keycloak client selena-ide-service создан;
  • selena-ide-secrets содержит IDE_SELENA_IMPERSONATOR_PASSWORD после Engine bootstrap;
  • PUBLIC_URL в IDE values совпадает с {ide_public_url};
  • {ide_public_url} добавлен в Keycloak redirect URIs.

Установка:

helm upgrade --install selena-ide \
charts/internal/selena-ide/chart \
-n {selena_namespace} \
-f {selena_ide_values} \
--wait --timeout 10m

Проверка:

kubectl -n {selena_namespace} rollout status deploy/selena-ide-web
kubectl -n {selena_namespace} get pods -l app.kubernetes.io/instance=selena-ide -o wide
curl -fsS {ide_public_url}/health

Browser check:

  1. Откройте {ide_public_url}.
  2. Войдите через Keycloak.
  3. Откройте SQL console.
  4. Выполните простой query, который разрешен ролями пользователя.

2. Установить Selena AI backend/frontend/MCP​

Перед установкой AI проверьте:

  • Keycloak client selena-ai создан;
  • selena-ai-secrets содержит MCP_SELENA_IMPERSONATOR_PASSWORD после Engine bootstrap;
  • AI_BACKEND_LLM_API_KEY является реальным provider key, не placeholder;
  • AI values содержат {ai_public_url}, {ide_public_url} и Keycloak URLs;
  • при components.mcp.replicaCount > 1 включена sticky session affinity для MCP Service.

Установка:

helm upgrade --install selena-ai \
charts/internal/selena-ai/chart \
-n {selena_namespace} \
-f {selena_ai_values} \
--wait --timeout 10m

Проверка:

kubectl -n {selena_namespace} rollout status deploy/selena-ai-backend
kubectl -n {selena_namespace} rollout status deploy/selena-ai-frontend
kubectl -n {selena_namespace} rollout status deploy/selena-ai-mcp
kubectl -n {selena_namespace} get deploy selena-ai-backend selena-ai-frontend selena-ai-mcp -o wide
curl -fsS {ai_public_url}/api/v1/health | jq

Ожидаемый health:

{
"status": "ok",
"components": {
"agent": "ok",
"mcp": "ok",
"storage": "ok"
}
}

Browser check:

  1. Откройте IDE.
  2. Войдите пользователем, у которого есть Selena data role.
  3. Откройте AI Agent из IDE.
  4. Попросите выполнить SELECT 1 AS ok.
  5. Убедитесь, что AI вызывает query tool и показывает результат 1.

3. Как работает синхронизация Keycloak groups -> Selena users/roles​

CM не читает LDAP/AD напрямую. Источник правды для пользователей и групп - Keycloak.

Текущая схема:

Keycloak group membership
-> CM scheduled membership refresh
-> CM membership snapshot в PostgreSQL
-> mapped external groups
-> Selena roles bound to external groups
-> native Selena SQL users and role grants

Расписание membership refresh включено по умолчанию в CM. В minimal values его не нужно задавать: меняйте эти свойства только если customer runbook требует другой SLA или другой lock window.

СвойствоРекомендуемое значениеЧто делает
CM_GROUP_FILE_REFRESH_ENABLED"true"Product default. Включает cron refresh из Keycloak.
CM_GROUP_FILE_REFRESH_INITIAL_DELAY10sЧерез сколько после старта CM выполнить первый refresh.
CM_GROUP_FILE_REFRESH_INTERVAL30sКак часто CM перечитывает Keycloak groups и users.
CM_GROUP_FILE_FULL_RECONCILE_INTERVALPT6HКак часто делать полный reconcile даже если snapshot hash не изменился.
CM_GROUP_FILE_REFRESH_LOCK_AT_MOST_FORPT5MDistributed lock через CM DB, чтобы две CM replicas не выполняли refresh одновременно.
CM_GROUP_FILE_REFRESH_LOCK_AT_LEAST_FORPT1SМинимальное время удержания lock, защищает от слишком частых повторов.

Что происходит каждые {refresh_interval}:

  1. Одна CM replica берет ShedLock cm-group-file-refresh.
  2. CM через Keycloak Admin API читает effective members только для groups, которые указаны в external group mappings.
  3. CM генерирует membership snapshot и сравнивает hash с последним applied snapshot.
  4. Если hash изменился, CM reconcile'ит только пользователей, membership которых изменился: добавляет missing roles, revoke'ит лишние roles, создает новых Selena users и удаляет stale Selena users/metadata.
  5. Если hash не изменился, CM не трогает Selena до следующего full reconcile.
  6. Раз в {full_reconcile_interval} CM делает полный safety reconcile всех пользователей из snapshot.

Практический SLA: при CM_GROUP_FILE_REFRESH_INTERVAL=30s изменение группы в Keycloak обычно доезжает до Selena за один refresh cycle плюс время Keycloak Admin API и Selena SQL DDL. Для production runbook закладывайте 1-2 минуты.

Защита от опасного пустого snapshot: если предыдущий applied snapshot имел members, а новый snapshot внезапно пустой, CM откажется reconcile'ить его, чтобы не снять роли массово из-за сбоя Keycloak/LDAP.

Если external group mappings еще не настроены, scheduled refresh безопасно пропускается и не применяет пустой snapshot. Доступ к данным появится только после явного mapping Keycloak groups в Selena external groups.

Проверить текущий snapshot:

curl -fsS {cm_url}/selena/membership-snapshot/status \
-H 'Authorization: Bearer {cm_admin_access_token}' \
| jq

curl -fsS {cm_url}/selena/membership-snapshot/groups \
-H 'Authorization: Bearer {cm_admin_access_token}' \
| jq

4. CM roles и protected API​

CM API roles выдаются через Keycloak group paths в group-role-mappings. Эти roles нужны только для доступа в личный кабинет/административный UI Selena Cluster Manager и к защищенным CM API. Они не дают пользователю прав на чтение или запись данных в Selena Engine. Доступ к данным настраивается отдельно через Selena roles/grants и external group mappings в следующем разделе.

Минимальная схема:

{
"cm": {
"security": {
"group-role-mappings": {
"[/cm/admins]": "cm_admin",
"[/cm/role-admins]": "cm_role_admin",
"[/cm/viewers]": "cm_viewer"
}
}
}
}

Проверить текущего пользователя:

curl -fsS {cm_url}/auth/me \
-H 'Authorization: Bearer {cm_admin_access_token}' \
| jq

Negative check для пользователя без CM roles:

curl -i -sS {cm_url}/engine/cluster/status?refresh=true \
-H 'Authorization: Bearer {no_cm_role_access_token}'

Ожидаемо: HTTP 403.

5. External group mappings​

External group mapping переводит Keycloak group path в короткое имя external group для Selena grants.

Эти mappings нужны для бизнесового доступа к данным в Selena Engine. Их может быть сколько угодно: заказчик сам решает, какие группы отражают его команды, департаменты, проекты и уровни доступа. Например, можно завести groups /data/analytics/readers, /data/analytics/writers, /data/developers, /data/finance/admins или любые другие paths, которые соответствуют принятой у заказчика модели доступа.

External group name справа - это короткое техническое имя, к которому потом привязываются Selena roles. Например, Keycloak group /data/analytics/readers можно mapped в external group analytics_readers, а затем дать этой external group Selena role с read-only privileges на нужные catalogs/databases/tables.

По умолчанию CM также включает fallback-strategy: FULL_PATH: каждая Keycloak group автоматически получает Selena-safe external group name по full path. Например /cm/admins становится cm_admins, а /local/selena-readers становится local_selena_readers. Explicit mappings ниже остаются override для случаев, где нужно сохранить legacy short names.

Пример:

{
"cm": {
"identity": {
"external-groups": {
"fallback-strategy": "FULL_PATH",
"mappings": {
"[/ldap/selena-readers]": "ldap_selena_readers",
"[/ldap/selena-writers]": "ldap_selena_writers",
"[/local/selena-readers]": "local_selena_readers",
"[/local/selena-writers]": "local_selena_writers"
}
}
}
}
}

Правила:

  • любая Keycloak group может получить Selena SQL role через derived external group;
  • используйте explicit mappings, если нужно переименовать derived external group;
  • external group names используйте lowercase letters, digits и underscores;
  • новая Keycloak group не дает доступа, пока ее derived external group не bound к Selena role.

После изменения mappings обновите CM:

helm upgrade --install selena-cm \
charts/internal/selena-cm/chart \
-n {selena_namespace} \
-f {selena_cm_values} \
--wait --timeout 10m

6. Создать Selena roles​

curl -fsS -X POST {cm_url}/selena/roles \
-H 'Authorization: Bearer {cm_admin_access_token}' \
-H 'Content-Type: application/json' \
-d '{"name":"selena_readonly"}' \
| jq

curl -fsS -X POST {cm_url}/selena/roles \
-H 'Authorization: Bearer {cm_admin_access_token}' \
-H 'Content-Type: application/json' \
-d '{"name":"selena_writer"}' \
| jq

Проверить:

curl -fsS {cm_url}/selena/roles \
-H 'Authorization: Bearer {cm_admin_access_token}' \
| jq

7. Выдать privileges roles​

Этот раздел содержит минимальный пример. Подробная матрица privileges, object types, scopes и типовых ошибок описана в Selena grants, roles и CM API.

USAGE на catalog:

curl -fsS -X POST {cm_url}/selena/roles/selena_readonly/grants \
-H 'Authorization: Bearer {cm_admin_access_token}' \
-H 'Content-Type: application/json' \
-d '{
"privileges": ["USAGE"],
"objectType": "CATALOG",
"objectQualifier": "default_catalog",
"scope": "OBJECT",
"withGrantOption": false
}' \
| jq

Read-only access на database:

curl -fsS -X POST {cm_url}/selena/roles/selena_readonly/grants \
-H 'Authorization: Bearer {cm_admin_access_token}' \
-H 'Content-Type: application/json' \
-d '{
"privileges": ["SELECT"],
"objectType": "TABLE",
"objectQualifier": "{database_name}",
"scope": "ALL_TABLES_IN_DATABASE",
"withGrantOption": false
}' \
| jq

Write access на table:

curl -fsS -X POST {cm_url}/selena/roles/selena_writer/grants \
-H 'Authorization: Bearer {cm_admin_access_token}' \
-H 'Content-Type: application/json' \
-d '{
"privileges": ["SELECT", "INSERT"],
"objectType": "TABLE",
"objectQualifier": "{database_name}.{table_name}",
"scope": "OBJECT",
"withGrantOption": false
}' \
| jq

Проверить grants:

curl -fsS {cm_url}/selena/roles/selena_readonly/grants \
-H 'Authorization: Bearer {cm_admin_access_token}' \
| jq

8. Привязать Selena roles к external groups​

curl -fsS -X POST {cm_url}/selena/external-groups/ldap_selena_readers/roles \
-H 'Authorization: Bearer {cm_admin_access_token}' \
-H 'Content-Type: application/json' \
-d '{"roleName":"selena_readonly"}' \
| jq

curl -fsS -X POST {cm_url}/selena/external-groups/local_selena_readers/roles \
-H 'Authorization: Bearer {cm_admin_access_token}' \
-H 'Content-Type: application/json' \
-d '{"roleName":"selena_readonly"}' \
| jq

curl -fsS -X POST {cm_url}/selena/external-groups/ldap_selena_writers/roles \
-H 'Authorization: Bearer {cm_admin_access_token}' \
-H 'Content-Type: application/json' \
-d '{"roleName":"selena_writer"}' \
| jq

curl -fsS -X POST {cm_url}/selena/external-groups/local_selena_writers/roles \
-H 'Authorization: Bearer {cm_admin_access_token}' \
-H 'Content-Type: application/json' \
-d '{"roleName":"selena_writer"}' \
| jq

Проверить external group:

curl -fsS {cm_url}/selena/external-groups/ldap_selena_readers/roles \
-H 'Authorization: Bearer {cm_admin_access_token}' \
| jq

После следующего membership refresh CM материализует роли на users.

9. Direct SQL CLI secret​

Web password Keycloak/LDAP не используется для direct SQL. Это отдельная граница безопасности: Keycloak/LDAP password нужен для web login и identity policies, а MySQL/JDBC clients используют CM-generated CLI secret. Так основной identity password не попадает в database tools, может оставаться под SSO/MFA/password-policy контролем, а direct SQL secret можно независимо сбросить при утечке или увольнении пользователя.

Пользователь логинится в CM и сбрасывает CLI secret:

curl -fsS -X POST {cm_url}/auth/login \
-H 'Content-Type: application/json' \
-d '{"username":"{username}","password":"{web_password}"}' \
| jq

Скопируйте .accessToken из ответа. Дальше это {user_access_token}.

curl -fsS -X POST {cm_url}/me/cli-secret:reset \
-H 'Authorization: Bearer {user_access_token}' \
| jq

Скопируйте .cliSecret из ответа. Дальше это {cli_secret}. Secret больше нельзя прочитать; если он потерян, выполните reset снова.

Подключение:

mysql --protocol=TCP \
-h {selena_fe_mysql_host} \
-P 9030 \
-u {username} \
-p{cli_secret} \
-e "SELECT CURRENT_USER(); SHOW GRANTS;"

DBeaver и IntelliJ IDEA Database Tools используют обычный MySQL driver:

ПолеЗначение
Host{selena_fe_mysql_host}
Port9030
User{username}
Password{cli_secret}

MySQL clear-password plugin не нужен, потому что Selena Engine не настроен как LDAP client.

10. Проверка изменения membership​

Проверка добавления пользователя в group:

  1. Добавьте {username} в Keycloak group, mapped на external group.
  2. Подождите один refresh interval, обычно 30s.
  3. Проверьте snapshot:
curl -fsS {cm_url}/selena/membership-snapshot/groups/{external_group}/members \
-H 'Authorization: Bearer {cm_admin_access_token}' \
| jq
  1. Проверьте роли пользователя:
curl -fsS {cm_url}/me/direct-sql \
-H 'Authorization: Bearer {user_access_token}' \
| jq
  1. Проверьте direct SQL:
mysql --protocol=TCP \
-h {selena_fe_mysql_host} \
-P 9030 \
-u {username} \
-p{cli_secret} \
-e "SHOW GRANTS;"

Проверка удаления пользователя из group:

  1. Удалите {username} из Keycloak group.
  2. Подождите один refresh interval.
  3. Убедитесь, что user исчез из members external group.
  4. Убедитесь, что роль удалена из /me/direct-sql и SHOW GRANTS.

Проверка новой group:

  1. Создайте Keycloak group.
  2. Добавьте пользователя в Keycloak group.
  3. Дождитесь refresh, чтобы CM показал derived external group.
  4. Создайте или выберите Selena role.
  5. Привяжите role к derived external group через CM UI или API.
  6. Дождитесь materialization и проверьте role.

Проверка удаления group:

  1. Уберите пользователей из Keycloak group или удалите group.
  2. Дождитесь refresh.
  3. Проверьте, что CM revoked roles, выданные через эту external group.
  4. Только после этого удаляйте mapping из CM values.