Перейти к основному содержимому
Перейти к основному содержимому

Аутентификация с помощью JWT

ClickHouse Cloud only

ClickHouse может аутентифицировать пользователей с помощью JSON Web Tokens (JWT). В отличие от других внешних аутентификаторов, таких как LDAP или Kerberos, аутентификация с помощью JWT не проверяет подлинность уже существующих пользователей. Вместо этого она динамически создаёт эфемерных пользователей на основе утверждений, встроенных в каждый токен. Эти пользователи существуют только в памяти, получают права доступа на основе утверждений токена и автоматически удаляются после истечения срока действия токена.

Это принципиально отличает аутентификацию с помощью JWT от методов на основе пароля или сертификата: оператора CREATE USER ... IDENTIFIED WITH jwt не существует, и попытка выполнить его приводит к исключению. Пользователи JWT полностью управляются жизненным циклом токена.

Обзор

Процесс аутентификации работает следующим образом:

  1. Клиент передаёт подписанный JWT через один из поддерживаемых транспортных механизмов (HTTP-заголовок Authorization: Bearer, собственный протокол TCP или поле gRPC jwt).
  2. ClickHouse проверяет подпись токена.
  3. Проверяются обязательные утверждения (exp, iat, iss, sub, aud).
  4. В памяти создаётся эфемерный пользователь с правами доступа, сформированными на основе утверждений токена clickhouse:grants и clickhouse:roles и ограниченными заданной верхней границей разрешений.
  5. Когда срок действия токена истекает, фоновая задача сборки мусора удаляет пользователя.

Утверждения токена

Обязательные утверждения

Каждый JWT, передаваемый в ClickHouse, должен содержать следующие утверждения:

ClaimОписание
algАлгоритм подписи (утверждение заголовка). Поддерживаемые значения: HS256, RS256, ES256.
expВремя истечения срока действия. Устанавливает valid_until для эфемерного пользователя.
iatВремя выпуска. Используется для предотвращения повторного использования более старых токенов для одного и того же идентификатора.
issИздатель. Сопоставляется с ожидаемым издателем провайдера.
subСубъект. Становится частью сгенерированного имени пользователя.
audАудитория. Сопоставляется с ожидаемой аудиторией провайдера.

Утверждение заголовка kid (ID ключа) также обязательно, если используется разрешение ключей на основе JWKS.

Режим JWKS поддерживает только ключи RSA

Хотя провайдеры со статическими ключами принимают любой из алгоритмов HS256, RS256 или ES256, провайдеры на основе JWKS принимают только JWK, у которых kty равно RSA (то есть токены, подписанные с помощью RS256). Токены, подписанные ключами HMAC (HS256) или EC (ES256), нельзя проверить через конечную точку JWKS, и они будут отклонены.

Другие распознаваемые утверждения

УтверждениеОписание
nbfВремя, раньше которого токен недействителен. Это утверждение необязательно, но если оно присутствует, токены отклоняются до наступления этого времени.
jtiЗарезервировано. Допускается в токенах, но в настоящее время не проверяется и не используется.

Необязательные утверждения

УтверждениеИмя по умолчаниюОписание
Привилегииclickhouse:grantsJSON-массив фрагментов SQL GRANT, например ["SELECT ON db.*", "INSERT ON db.table1"]. Каждый элемент разбирается как тело оператора GRANT.
Ролиclickhouse:rolesJSON-массив имён ролей, которые нужно назначить, например ["analyst", "reader"].
Стандартные имена утверждений можно сопоставить с пользовательскими, если ваш провайдер идентификации использует другую схему именования.

Пример заголовка токена и его полезной нагрузки

{
  "alg": "RS256",
  "kid": "my-key-id"
}
{
  "iss": "https://idp.example.com",
  "sub": "jane.doe",
  "aud": "my-clickhouse-cluster",
  "exp": 1719504000,
  "iat": 1719500400,
  "clickhouse:grants": ["SELECT ON analytics.*", "INSERT ON analytics.events"],
  "clickhouse:roles": ["analyst"]
}

Поведение эфемерных пользователей

Пользователи JWT отличаются от обычных пользователей ClickHouse по нескольким важным аспектам.

Идентификация и именование

Каждому пользователю JWT назначается детерминированный UUID, вычисляемый на основе утверждений iss, sub и aud. Этот UUID стабильный и не меняется между входами в систему. Пользователь, который входит в систему несколько раз с разными токенами (но с тем же издателем, subject и аудиторией), всегда получает один и тот же UUID.

Однако имя пользователя непостоянно. Оно формируется следующим образом:

JWT::<issuer>::<audience>::<subject>::<claims_hash>

Фрагмент <claims_hash> меняется всякий раз, когда меняются утверждения clickhouse:roles или clickhouse:grants. Это означает, что токены с разными наборами ролей или привилегий приводят к созданию разных имён пользователей даже для одной и той же идентичности.

Права доступа

Эффективные права доступа определяются следующим образом:

effective_rights = permission_limit ∩ (token_grants ∪ token_roles)

Где permission_limit — это набор прав доступа эталонной роли или пользователя, заданный в качестве верхней границы. Права, запрошенные токеном сверх этого ограничения, отбрасываются без уведомления.

Актуальность токена

ClickHouse отслеживает утверждение iat (issued-at) у последнего успешно аутентифицированного токена для каждой стабильной идентичности. Если предъявляется токен со значением iat, равным сохранённому или более ранним, сервер повторно использует существующего эфемерного пользователя без повторной проверки утверждений. Это не позволяет старым токенам снизить права пользователя.

Время жизни и сборка мусора

Эфемерные пользователи создаются при первой аутентификации по токену и удаляются фоновой задачей сборки мусора после истечения valid_until (рассчитывается на основе exp). Интервал GC задается параметром gc_interval (по умолчанию: 5 минут).

Между запусками GC пользователи с истекшим сроком действия могут по-прежнему отображаться в system.users, но аутентифицироваться уже не могут.

Постоянные назначения прав доступа

Поскольку UUID не меняется, вы можете назначать JWT-пользователю профили настроек, квоты, политики доступа к строкам и политики маскирования столбцов с помощью SQL-команд. Эти назначения сохраняются в хранилище управления доступом (на диске или в ZooKeeper) и продолжают действовать после истечения срока действия токена и повторной аутентификации.

Указывайте пользователя по его текущему имени пользователя:

ALTER SETTINGS PROFILE my_profile ADD TO 'JWT::ClickHouse::my-service-id::jane.doe::<claims-hash>';
Примечание

Имя пользователя и UUID для данной идентичности можно найти в столбцах name и id таблицы system.users, пока пользователь активен.

Обратите внимание, что ALTER USER не работает напрямую с пользователями JWT, так как они доступны в режиме только для чтения. Чтобы назначить профили настроек, квоты или политики, используйте команды ALTER SETTINGS PROFILE, ALTER QUOTA или ALTER ROW POLICY, как показано выше.

Отличия от обычных пользователей

ВозможностьJWT-пользователиОбычные пользователи
СозданиеАвтоматически на основе утверждений токенаОператор CREATE USER
ХранениеТолько в памяти (временно)Диск, ZooKeeper или файл конфигурации
CREATE USER ... IDENTIFIED WITH jwtНе поддерживается (вызывает исключение)Поддерживаются все остальные типы аутентификации
ALTER USER / DROP USERНе поддерживаетсяПоддерживается
Резервное копирование и восстановлениеНе включеноВключено
Имя пользователяГенерируется автоматически, непостоянноеВыбирается администратором, фиксированное
UUIDДетерминированно на основе iss+sub+audСлучайный при создании
Срок существованияОграничен значением exp токенаДо явного удаления
Права доступаОпределяются утверждениями токена и ограничиваются верхней границей разрешенийЯвно выдаются через GRANT
Ограничения по хостамСетевая конфигурация на уровне провайдераПредложение HOST на уровне пользователя
Профили настроекМожно назначать по UUID (постоянно)Настраиваются напрямую
Квоты и политики доступа к строкамМожно назначать по UUID (постоянно)Настраиваются напрямую
Роли по умолчаниюНе настраиваютсяНастраиваются

Представления с SQL SECURITY DEFINER

Когда эфемерный JWT-пользователь создает представление с SQL SECURITY DEFINER, сервер автоматически создает постоянную теневую копию этого пользователя, чтобы использовать ее как пользователя-определителя представления. Этот теневой пользователь:

  • Имеет имя <original_jwt_username>:definer
  • Имеет NO_AUTHENTICATION (его нельзя использовать для входа)
  • Сохраняет те же права доступа, что и исходный JWT-пользователь на момент создания представления

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

Использование клиента

Передача токена напрямую

Используйте флаг --jwt с clickhouse-client, чтобы пройти аутентификацию с помощью заранее полученного токена:

clickhouse-client --host your-instance.clickhouse.cloud --secure --jwt '<your_jwt_token>'
Примечание

Флаг --jwt нельзя использовать вместе с --user. Если указан --jwt, имя пользователя берётся из токена.

HTTP-интерфейс

Передайте токен в заголовке Authorization как Bearer-токен:

curl -H 'Authorization: Bearer <your_jwt_token>' \
    'https://your-instance.clickhouse.cloud:8443/?query=SELECT+currentUser()'
Примечание

Всегда передавайте JWT по HTTPS. Bearer-токен, отправленный по обычному HTTP, становится доступен любому, кто находится на пути передачи данных, и равносилен утечке учетных данных.

Вход по коду устройства OAuth2

clickhouse-client поддерживает интерактивный поток OAuth2 Device Code через флаг --login. Для конечных точек ClickHouse Cloud клиент автоматически выполняет обмен токенов для получения JWT, специфичного для ClickHouse. Токены прозрачно обновляются в течение сеанса. При получении нового токена клиент автоматически выполняет повторное подключение.

clickhouse-client --host your-instance.clickhouse.cloud --login

Встроенный аутентификатор JWT в ClickHouse Cloud

Каждый сервис ClickHouse Cloud поставляется с преднастроенным аутентификатором JWT, который используется в SQL Console и в сценарии входа --login клиента clickhouse-client. Этот аутентификатор настроен следующим образом:

ПараметрЗначение
iss (издатель)ClickHouse
aud (аудитория)UUID сервиса (виден в URL консоли Cloud)
sub (субъект)Адрес электронной почты вашей учетной записи ClickHouse Cloud

Для встроенного аутентификатора верхняя граница разрешений задается ролью default_role и пользователем default. Это означает, что фактические права любого JWT-пользователя определяются пересечением с привилегиями этих двух сущностей, поэтому токен никогда не сможет повысить привилегии сверх того, что разрешено default_role и default.

Чтобы использовать этот аутентификатор, ничего настраивать не нужно. Он создается автоматически при создании сервиса.

Межсерверное взаимодействие

Когда запрос перенаправляется на другой сегмент или реплику, JWT-токен передаётся через межсерверный протокол. Удалённый узел самостоятельно повторно аутентифицирует токен, создавая собственного эфемерного пользователя.

Устранение неполадок

  • Права доступа не предоставлены: У указанной роли или пользователя может не быть необходимых привилегий. Убедитесь, что роли, указанные в clickhouse:roles, существуют и включают соответствующие привилегии.
  • Токен отклонён: Убедитесь, что iss, aud и алгоритм подписи в вашем токене соответствуют ожиданиям провайдера JWT. Если используется JWKS, убедитесь, что kid токена совпадает с ключом в наборе ключей провайдера.
  • Пользователь исчезает между запросами: Временные пользователи удаляются после истечения срока действия токена. Для длительных сеансов используйте клиент с поддержкой обновления токена (например, режим --login).
  • CREATE USER ... IDENTIFIED WITH jwt завершается ошибкой: Это ожидаемое поведение. Пользователей JWT нельзя создавать через DDL. Они полностью управляются жизненным циклом токена.