Аутентификация с помощью JWT
ClickHouse может аутентифицировать пользователей с помощью JSON Web Tokens (JWT). В отличие от других внешних аутентификаторов, таких как LDAP или Kerberos, аутентификация с помощью JWT не проверяет подлинность уже существующих пользователей. Вместо этого она динамически создаёт эфемерных пользователей на основе утверждений, встроенных в каждый токен. Эти пользователи существуют только в памяти, получают права доступа на основе утверждений токена и автоматически удаляются после истечения срока действия токена.
Это принципиально отличает аутентификацию с помощью JWT от методов на основе пароля или сертификата: оператора CREATE USER ... IDENTIFIED WITH jwt не существует, и попытка выполнить его приводит к исключению. Пользователи JWT полностью управляются жизненным циклом токена.
Обзор
Процесс аутентификации работает следующим образом:
- Клиент передаёт подписанный JWT через один из поддерживаемых транспортных механизмов (HTTP-заголовок
Authorization: Bearer, собственный протокол TCP или поле gRPCjwt). - ClickHouse проверяет подпись токена.
- Проверяются обязательные утверждения (
exp,iat,iss,sub,aud). - В памяти создаётся эфемерный пользователь с правами доступа, сформированными на основе утверждений токена
clickhouse:grantsиclickhouse:rolesи ограниченными заданной верхней границей разрешений. - Когда срок действия токена истекает, фоновая задача сборки мусора удаляет пользователя.
Утверждения токена
Обязательные утверждения
Каждый JWT, передаваемый в ClickHouse, должен содержать следующие утверждения:
| Claim | Описание |
|---|---|
alg | Алгоритм подписи (утверждение заголовка). Поддерживаемые значения: HS256, RS256, ES256. |
exp | Время истечения срока действия. Устанавливает valid_until для эфемерного пользователя. |
iat | Время выпуска. Используется для предотвращения повторного использования более старых токенов для одного и того же идентификатора. |
iss | Издатель. Сопоставляется с ожидаемым издателем провайдера. |
sub | Субъект. Становится частью сгенерированного имени пользователя. |
aud | Аудитория. Сопоставляется с ожидаемой аудиторией провайдера. |
Утверждение заголовка kid (ID ключа) также обязательно, если используется разрешение ключей на основе JWKS.
Хотя провайдеры со статическими ключами принимают любой из алгоритмов HS256, RS256 или ES256, провайдеры на основе JWKS принимают только JWK, у которых kty равно RSA (то есть токены, подписанные с помощью RS256). Токены, подписанные ключами HMAC (HS256) или EC (ES256), нельзя проверить через конечную точку JWKS, и они будут отклонены.
Другие распознаваемые утверждения
| Утверждение | Описание |
|---|---|
nbf | Время, раньше которого токен недействителен. Это утверждение необязательно, но если оно присутствует, токены отклоняются до наступления этого времени. |
jti | Зарезервировано. Допускается в токенах, но в настоящее время не проверяется и не используется. |
Необязательные утверждения
| Утверждение | Имя по умолчанию | Описание |
|---|---|---|
| Привилегии | clickhouse:grants | JSON-массив фрагментов SQL GRANT, например ["SELECT ON db.*", "INSERT ON db.table1"]. Каждый элемент разбирается как тело оператора GRANT. |
| Роли | clickhouse:roles | JSON-массив имён ролей, которые нужно назначить, например ["analyst", "reader"]. |
| Стандартные имена утверждений можно сопоставить с пользовательскими, если ваш провайдер идентификации использует другую схему именования. |
Пример заголовка токена и его полезной нагрузки
Поведение эфемерных пользователей
Пользователи JWT отличаются от обычных пользователей ClickHouse по нескольким важным аспектам.
Идентификация и именование
Каждому пользователю JWT назначается детерминированный UUID, вычисляемый на основе утверждений iss, sub и aud. Этот UUID стабильный и не меняется между входами в систему. Пользователь, который входит в систему несколько раз с разными токенами (но с тем же издателем, subject и аудиторией), всегда получает один и тот же UUID.
Однако имя пользователя непостоянно. Оно формируется следующим образом:
Фрагмент <claims_hash> меняется всякий раз, когда меняются утверждения clickhouse:roles или clickhouse:grants. Это означает, что токены с разными наборами ролей или привилегий приводят к созданию разных имён пользователей даже для одной и той же идентичности.
Права доступа
Эффективные права доступа определяются следующим образом:
Где permission_limit — это набор прав доступа эталонной роли или пользователя, заданный в качестве верхней границы. Права, запрошенные токеном сверх этого ограничения, отбрасываются без уведомления.
Актуальность токена
ClickHouse отслеживает утверждение iat (issued-at) у последнего успешно аутентифицированного токена для каждой стабильной идентичности. Если предъявляется токен со значением iat, равным сохранённому или более ранним, сервер повторно использует существующего эфемерного пользователя без повторной проверки утверждений. Это не позволяет старым токенам снизить права пользователя.
Время жизни и сборка мусора
Эфемерные пользователи создаются при первой аутентификации по токену и удаляются фоновой задачей сборки мусора после истечения valid_until (рассчитывается на основе exp). Интервал GC задается параметром gc_interval (по умолчанию: 5 минут).
Между запусками GC пользователи с истекшим сроком действия могут по-прежнему отображаться в system.users, но аутентифицироваться уже не могут.
Постоянные назначения прав доступа
Поскольку UUID не меняется, вы можете назначать JWT-пользователю профили настроек, квоты, политики доступа к строкам и политики маскирования столбцов с помощью SQL-команд. Эти назначения сохраняются в хранилище управления доступом (на диске или в ZooKeeper) и продолжают действовать после истечения срока действия токена и повторной аутентификации.
Указывайте пользователя по его текущему имени пользователя:
Имя пользователя и 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, чтобы пройти аутентификацию с помощью заранее полученного токена:
Флаг --jwt нельзя использовать вместе с --user. Если указан --jwt, имя пользователя берётся из токена.
HTTP-интерфейс
Передайте токен в заголовке Authorization как Bearer-токен:
Всегда передавайте JWT по HTTPS. Bearer-токен, отправленный по обычному HTTP, становится доступен любому, кто находится на пути передачи данных, и равносилен утечке учетных данных.
Вход по коду устройства OAuth2
clickhouse-client поддерживает интерактивный поток OAuth2 Device Code через флаг --login. Для конечных точек ClickHouse Cloud клиент автоматически выполняет обмен токенов для получения JWT, специфичного для ClickHouse. Токены прозрачно обновляются в течение сеанса. При получении нового токена клиент автоматически выполняет повторное подключение.
Встроенный аутентификатор 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. Они полностью управляются жизненным циклом токена.