Spec-Zone.ru › Elasticsearch 8
›Руководство по Elasticsearch [8.17] ›Защита Elastic Stack ›Аутентификация пользователей

Аутентификация JWT

Elasticsearch можно настроить для доверия JSON Web Tokens (JWT), выпущенных внешней службой, в качестве токенов-носителей для аутентификации.

При использовании области JWT для аутентификации с Elasticsearch различают клиента, подключающегося к Elasticsearch, и пользователя, от имени которого должен выполняться запрос. JWT аутентифицирует пользователя, а отдельные учетные данные аутентифицируют клиента.

Область JWT поддерживает два типа токенов, id_token (по умолчанию) и access_token. Они разработаны для работы в следующих двух сценариях соответственно:

  1. id_token — Приложение аутентифицирует и идентифицирует пользователя с помощью процесса аутентификации, например, OpenID Connect (OIDC), а затем получает доступ к Elasticsearch от имени аутентифицированного пользователя, используя JSON Web Token (JWT), соответствующий спецификации ID Token OIDC.
  2. access_token — Приложение получает доступ к Elasticsearch, используя собственную идентичность, закодированную как JWT, например, приложение аутентифицирует себя на центральной платформе идентификации с помощью OAuth2 Client Credentials Flow и затем использует полученный JWT-токен доступа для подключения к Elasticsearch.

Одна область JWT может работать только с одним типом токенов. Для обработки обоих типов токенов необходимо настроить как минимум две области JWT. Вы должны тщательно выбрать тип токена в зависимости от сценария использования, так как это влияет на то, как выполняются проверки.

Область JWT проверяет входящий JWT на основе настроенного типа токена. JSON Web Tokens (JWT) обоих типов должны содержать следующие 5 элементов информации. Хотя ID Token, основанные на спецификации OIDC, имеют строгие правила для того, какие утверждения должны предоставлять эту информацию, токены доступа позволяют настраивать некоторые утверждения.

Утверждения

Информация

ID Token

Токен доступа

Издатель

iss

iss

Субъект

sub

По умолчанию sub, но может переключаться на другое утверждение, если sub отсутствует

Аудитории

aud

По умолчанию aud, но может переключаться на другое утверждение, если aud отсутствует

Время выдачи

iat

iat

Время истечения срока действия

exp

exp

Кроме того, Elasticsearch также проверяет утверждения nbf и auth_time для ID Token, если эти утверждения присутствуют. Но эти утверждения игнорируются для токенов доступа.

В целом, тип токена доступа имеет более гибкие правила проверки и подходит для более универсальных JWT, включая самоподписанные.

ID Tokens из рабочих процессов OIDC

Аутентификация JWT в Elasticsearch основана на рабочих процессах пользователей OIDC, где различные токены могут быть выпущены поставщиком OIDC (OP), включая ID Tokens. ID Tokens от поставщика OIDC — это хорошо определенные JSON Web Tokens (JWT) и всегда должны быть совместимы с областью JWT типа токена id_token. Утверждение субъекта ID токена представляет конечного пользователя. Это означает, что ID токены обычно имеют множество разрешенных субъектов. Поэтому область JWT типа токена id_token не требует проверки allowed_subjects (или allowed_subject_patterns).

Поскольку JWT получаются за пределами Elasticsearch, вы можете определить пользовательский рабочий процесс вместо использования рабочего процесса OIDC. Однако формат JWT должен по-прежнему быть JSON Web Signature (JWS). JWS заголовок и JWS подпись проверяются с помощью правил проверки токенов ID OIDC.

Elasticsearch поддерживает отдельную область OpenID Connect. Она предпочтительна для любого сценария, где Elasticsearch может действовать как OIDC RP. Область OIDC — единственный поддерживаемый способ включить аутентификацию OIDC в Kibana.

Пользователи, аутентифицированные с помощью области JWT, могут по желанию имитировать другого пользователя с помощью функции run_as. См. также применение привилегии run_as к пользователям области JWT.

Токены доступа

Распространенный метод получения токенов доступа — использование OAuth2 Client Credentials Flow. Типичное использование этого потока — приложение получает собственные учетные данные. Это сценарий, для которого предназначен тип токена access_token. Вероятно, это приложение также получает ID токены для своих конечных пользователей. Чтобы предотвратить использование ID токенов конечных пользователей для аутентификации с областью JWT, настроенной для приложения, мы требуем проверку allowed_subjects или allowed_subject_patterns, когда область JWT имеет тип токена access_token.

Не каждый токен доступа имеет формат JSON Web Token (JWT). Чтобы быть совместимым с областью JWT, он должен, по крайней мере, использовать формат JWT и соответствовать соответствующим требованиям в таблице выше.

Настройка Elasticsearch для использования JWT-сферы

Для использования аутентификации JWT создайте сферу в файле elasticsearch.yml, чтобы настроить её в цепочке аутентификации Elasticsearch.

Сфера JWT имеет несколько обязательных настроек, а также необязательные, описанные в настройках сферы JWT.

Аутентификация клиента включена по умолчанию для сфер JWT. Выключение аутентификации клиента возможно, но крайне не рекомендуется.

  1. Добавьте вашу JWT-сферу в файл elasticsearch.yml. Следующий пример включает наиболее распространённые настройки, которые не подходят для всех случаев использования:

    xpack.security.authc.realms.jwt.jwt1:
      order: 3
      token_type: id_token
      client_authentication.type: shared_secret
      allowed_issuer: "https://issuer.example.com/jwt/"
      allowed_audiences: [ "8fb85eba-979c-496c-8ae2-a57fde3f12d0" ]
      allowed_signature_algorithms: [RS256,HS256]
      pkc_jwkset_path: jwt/jwkset.json
      claims.principal: sub
    order
    Указывает сферу order порядка 3, что указывает порядок проверки настроенной сферы при аутентификации пользователя. Сферы проверяются в порядке возрастания, где сфера с наименьшим значением порядка проверяется первой.
    token_type
    Указывает сфере обрабатывать и проверять входящие JWT как ID-токены (id_token).
    client_authentication.type
    Указывает тип аутентификации клиента как shared_secret, что означает, что клиент аутентифицируется с помощью заголовка HTTP-запроса, который должен соответствовать предварительно настроенному секретному значению. Клиент должен предоставлять этот общий секрет с каждым запросом в заголовке ES-Client-Authentication и с использованием схемы SharedSecret. Значение заголовка должно точно соответствовать (чувствительно к регистру) значению client_authentication.shared_secret сферы.
    allowed_issuer
    Устанавливает проверяемый идентификатор вашего издателя JWT. Это значение обычно является URL-адресом, UUID или некоторым другим значением строки, чувствительным к регистру.
    allowed_audiences
    Указывает список аудиторий JWT, которые сфера будет допускать. Эти значения обычно являются URL-адресами, UUID или другими значениями строк, чувствительными к регистру.
    allowed_signature_algorithms
    Указывает, что Elasticsearch должен использовать алгоритмы подписи RS256 или HS256 для проверки подписи JWT от издателя JWT.
    pkc_jwkset_path
    Имя файла или URL-адрес набора JSON Web Key (JWKS) с открытым ключом, который используется сферой JWT для проверки подписи токена. Значение считается именем файла, если оно не начинается с https. Имя файла разрешается относительно каталога конфигурации Elasticsearch. Если предоставлен URL-адрес, он должен начинаться с https:// (http:// не поддерживается). Elasticsearch автоматически кеширует набор JWK и будет пытаться обновить набор JWK при сбое проверки подписи, так как это может указывать на то, что поставщик JWT изменил ключи подписи.
    claims.principal
    Имя утверждения JWT, содержащее основное имя пользователя (имя пользователя).

    Ниже приведён пример фрагмента для настройки сферы JWT для обработки токенов доступа:

    xpack.security.authc.realms.jwt.jwt2:
      order: 4
      token_type: access_token
      client_authentication.type: shared_secret
      allowed_issuer: "https://issuer.example.com/jwt/"
      allowed_subjects: [ "123456-compute@admin.example.com" ]
      allowed_subject_patterns: [ "wild*@developer?.example.com", "/[a-z]+<1-10>\\@dev\\.example\\.com/"]
      allowed_audiences: [ "elasticsearch" ]
      required_claims:
        token_use: access
        version: ["1.0", "2.0"]
      allowed_signature_algorithms: [RS256,HS256]
      pkc_jwkset_path: "https://idp-42.example.com/.well-known/configuration"
      fallback_claims.sub: client_id
      fallback_claims.aud: scope
      claims.principal: sub
    token_type
    Указывает сфере обрабатывать и проверять входящие JWT как токены доступа (access_token).
    allowed_subjects
    Указывает список субъектов JWT, которые сфера будет допускать. Эти значения обычно являются URL-адресами, UUID или другими значениями строк, чувствительными к регистру.
    allowed_subject_patterns
    Аналогично allowed_subjects, но принимает список Lucene regexp и подстановочных знаков для разрешённых субъектов JWT. Подстановочные знаки используют специальные символы * и ? (которые экранированы с помощью \) для обозначения «любой строки» и «любого отдельного символа» соответственно, например «a?\**», соответствует «a1*» и «ab*whatever», но не «a», «abc» или «abc*» (в строках Java \ само должно быть экранировано с помощью другого \). Lucene regexp должны быть заключены в /, например «/https?://[^/]+/?/» соответствует любому URL-адресу http или https без компонента пути (соответствует «https://elastic.co/» но не «https://elastic.co/guide»).

    По крайней мере, одна из настроек allowed_subjects или allowed_subject_patterns должна быть указана (и не пуста) при token_type равном access_token.

    Если оба параметра allowed_subjects и allowed_subject_patterns указаны, утверждение sub входящего JWT принимается, если оно соответствует любому из двух списков.

    required_claims
    Указывает список пар ключ-значение для дополнительных проверок, которые должны быть выполнены для JWT. Значения являются строкой или массивом строк.
    fallback_claims.sub
    Имя утверждения JWT для извлечения информации о субъекте, если утверждение sub не существует. Эта настройка доступна только при token_type равном access_token. Кэширование применяется везде, где используется утверждение sub. В приведенном выше фрагменте это означает, что claims.principal также будет использовать client_id в качестве резервного варианта, если sub не существует.
    fallback_claims.aud
    Имя утверждения JWT для извлечения информации об аудитории, если утверждение aud не существует. Эта настройка доступна только при token_type равном access_token. Резервный вариант применяется везде, где используется утверждение aud.
  2. После определения настроек используйте инструмент elasticsearch-keystore для хранения значений защищённых настроек в хранилище ключей Elasticsearch.

    1. Сохраните значение shared_secret для client_authentication.type:

      bin/elasticsearch-keystore add xpack.security.authc.realms.jwt.jwt1.client_authentication.shared_secret
    2. Сохраните ключи HMAC для allowed_signature_algorithms, которые используют алгоритм HMAC SHA-256 HS256 в примере:

      bin/elasticsearch-keystore add-file xpack.security.authc.realms.jwt.jwt1.hmac_jwkset <path> 

      Путь к JWKS, который является ресурсом для набора кодированных JSON секретных ключей. Файл можно удалить после загрузки содержимого в хранилище ключей Elasticsearch.

      Использование JWKS предпочтительнее. Однако вы можете добавить ключ HMAC в формате строки, используя следующую команду. Этот формат совместим с ключами HMAC UTF-8, но поддерживает только один ключ без атрибутов. Вы можете использовать только один формат HMAC (либо hmac_jwkset, либо hmac_key) одновременно.

      bin/elasticsearch-keystore add xpack.security.authc.realms.jwt.jwt1.hmac_key

Кодирование и валидация JWT

JWT можно разделить на три части:

Заголовок
Предоставляет информацию о том, как валидировать токен.
Данные
Содержит данные о вызывающем пользователе или приложении.
Подпись
Данные, используемые для валидации токена.
Header: {"typ":"JWT","alg":"HS256"}
Claims: {"aud":"aud8","sub":"security_test_user","iss":"iss8","exp":4070908800,"iat":946684800}
Signature: UnnFmsoFKfNmKMsVoDQmKI_3-j95PCaKdgqqau3jPMY

Этот пример демонстрирует частичное декодирование JWT. Срок действия — с 2000 по 2099 год (включительно), как определено временем выдачи (iat) и временем истечения срока действия (exp). Обычно срок действия JWT короче 100 лет, например, 1-2 часа или 1-7 дней, а не вся человеческая жизнь.

Подпись в этом примере детерминированная, так как заголовок, данные и ключ HMAC фиксированы. JWT обычно имеют требование nonce, чтобы сделать подпись недетерминированной. Поддерживаемое кодирование JWT — JSON Web Signature (JWS), а валидация JWS Header и Signature выполняется по правилам валидации токенов OpenID Connect.

Данные заголовка

Данные заголовка указывают тип токена и алгоритм, используемый для его подписи.

alg
(Обязательно, Строка) Указывает алгоритм, используемый для подписи токена, например, HS256. Алгоритм должен быть в списке разрешенных алгоритмов для данного раздела.
typ
(Необязательно, Строка) Указывает тип токена, который должен быть JWT.

Данные полезной нагрузки

Токены содержат несколько данных, которые предоставляют информацию о пользователе, выпустившем токен, и о самом токене. В зависимости от типа токена, эта информация может быть представлена разными данными.

Данные полезной нагрузки JWT

Следующие данные валидируются подмножеством правил OIDC токенов ID.

Elasticsearch не валидирует nonce данные, но пользовательский издатель JWT может добавить случайный nonce данные, чтобы ввести энтропию в подпись.

Можно ослабить валидацию любых данных, основанных на времени, установив allowed_clock_skew. Это значение устанавливает максимальное допустимое смещение часов до валидации JWT по отношению к времени аутентификации (auth_time), времени создания (iat), времени ожидания (nbf) и времени истечения срока действия (exp).

iss
(Обязательно, Строка) Указывает издателя, который создал токен ID. Значение должно точно совпадать с значением в настройке allowed_issuer.
sub
(Обязательно*, Строка) Указывает субъект, для которого создан токен ID. Если область JWT имеет тип id_token, эти данные обязательны. Область JWT типа id_token по умолчанию принимает всех субъектов. Область JWT типа access_token должна указать настройку allowed_subjects, и значение субъекта должно точно совпадать с любым из значений CSV в настройке allowed_subjects. Область JWT типа access_token может указать резервное значение, которое будет использоваться, если данные sub отсутствуют.
aud
(Обязательно*, Строка) Указывает аудиторию, на которую ориентирован токен ID, выраженную в виде CSV (запятая). Одно из значений должно точно совпадать с любым из значений CSV в настройке allowed_audiences. Если область JWT имеет тип id_token, эти данные обязательны. Область JWT типа access_token может указать резервное значение, которое будет использоваться, если данные aud отсутствуют.
exp
(Обязательно, целое число) Время истечения срока действия токена ID, выраженное в секундах UTC с момента эпохи.
iat
(Обязательно, целое число) Время выдачи токена ID, выраженное в секундах UTC с момента эпохи.
nbf
(Необязательно, целое число) Указывает время, до которого JWT не должен приниматься, выраженное в секундах UTC с момента эпохи. Данные необязательны. Если они существуют, область JWT типа id_token проверит их, в то время как область JWT типа access_token просто проигнорирует их.
auth_time
(Необязательно, целое число) Время, когда пользователь аутентифицировался у издателя JWT, выраженное в секундах UTC с момента эпохи. Данные необязательны. Если они существуют, область JWT типа id_token проверит их, в то время как область JWT типа access_token просто проигнорирует их.
Настройки Elasticsearch для потребления данных JWT

Elasticsearch использует данные JWT для следующих настроек.

principal
(Обязательно, Строка) Содержит имя пользователя (имя пользователя). Значение настраивается с помощью настройки раздела claims.principal. Можно настроить необязательное регулярное выражение с помощью настройки claim_patterns.principal для извлечения подстроки.
groups
(Необязательно, массив JSON) Содержит членство пользователя в группах. Значение настраивается с помощью настройки раздела claims.groups. Можно настроить необязательное регулярное выражение с помощью настройки claim_patterns.groups для извлечения значения подстроки.
name
(Необязательно, Строка) Содержит удобочитаемый идентификатор, который идентифицирует субъект токена. Значение настраивается с помощью настройки раздела claims.name. Можно настроить необязательное регулярное выражение с помощью настройки claim_patterns.name для извлечения значения подстроки.
mail
(Необязательно, Строка) Содержит адрес электронной почты, который нужно связать с пользователем. Значение настраивается с помощью настройки раздела claims.mail. Можно настроить необязательное регулярное выражение с помощью настройки claim_patterns.mail для извлечения значения подстроки.
dn
(Необязательно, Строка) Содержит полное доменное имя (DN) пользователя, которое однозначно идентифицирует пользователя или группу. Значение настраивается с помощью настройки раздела claims.dn. Можно настроить необязательное регулярное выражение с помощью настройки claim_patterns.dn для извлечения значения подстроки.

Авторизация в JWT домене

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

Вы не можете сопоставить роли в домене JWT, используя файл role_mapping.yml.

Авторизация с помощью API сопоставления ролей

Вы можете использовать API создания или обновления сопоставлений ролей, чтобы определить сопоставления ролей, которые определяют, какие роли должны быть назначены каждому пользователю на основе имени пользователя, групп или других метаданных.

resp = client.security.put_role_mapping(
    name="jwt1_users",
    refresh=True,
    roles=[
        "user"
    ],
    rules={
        "all": [
            {
                "field": {
                    "realm.name": "jwt1"
                }
            },
            {
                "field": {
                    "username": "principalname1"
                }
            },
            {
                "field": {
                    "dn": "CN=Principal Name 1,DC=example.com"
                }
            },
            {
                "field": {
                    "groups": "group1"
                }
            },
            {
                "field": {
                    "metadata.jwt_claim_other": "other1"
                }
            }
        ]
    },
    enabled=True,
)
print(resp)
const response = await client.security.putRoleMapping({
  name: "jwt1_users",
  refresh: "true",
  roles: ["user"],
  rules: {
    all: [
      {
        field: {
          "realm.name": "jwt1",
        },
      },
      {
        field: {
          username: "principalname1",
        },
      },
      {
        field: {
          dn: "CN=Principal Name 1,DC=example.com",
        },
      },
      {
        field: {
          groups: "group1",
        },
      },
      {
        field: {
          "metadata.jwt_claim_other": "other1",
        },
      },
    ],
  },
  enabled: true,
});
console.log(response);
PUT /_security/role_mapping/jwt1_users?refresh=true
{
  "roles" : [ "user" ],
  "rules" : { "all" : [
      { "field": { "realm.name": "jwt1" } },
      { "field": { "username": "principalname1" } },
      { "field": { "dn": "CN=Principal Name 1,DC=example.com" } },
      { "field": { "groups": "group1" } },
      { "field": { "metadata.jwt_claim_other": "other1" } }
  ] },
  "enabled": true
}

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

principal
(Обязательно, Строка) Утверждение принципала, которое используется в качестве имени пользователя пользователя Elasticsearch.
dn
(Необязательно, Строка) Отличительное имя (DN), используемое в качестве DN пользователя Elasticsearch.
groups
(Необязательно, Строка) Список значений, разделённых запятыми (CSV), используемый в качестве списка групп пользователя Elasticsearch.
metadata
(Необязательно, объект) Дополнительные метаданные о пользователе, такие как строки, целые числа, логические значения и коллекции, которые используются в качестве метаданных пользователя Elasticsearch. Эти значения представляют собой пары ключ-значение в формате metadata.jwt_claim_<key> = <value>.

Делегирование авторизации JWT в другой домен

Если вы делегируете авторизацию другим доменам из домена JWT, доступно только утверждение principal для поиска ролей. При делегировании назначения и поиска ролей в другой домен из домена JWT утверждения для dn, groups, mail, metadata и name не используются для значений пользователя Elasticsearch. Только утверждение JWT principal передаётся делегированным доменам авторизации. Домены, которым делегирована авторизация (а не домен JWT), несут ответственность за заполнение всех значений пользователя Elasticsearch.

Следующий пример демонстрирует, как определить делегированную авторизацию в файле elasticsearch.yml для нескольких других доменов из домена JWT. Домен JWT с именем jwt2 делегирует авторизацию нескольким доменам:

xpack.security.authc.realms.jwt.jwt2.authorization_realms: file1,native1,ldap1,ad1

Затем вы можете использовать API создания или обновления сопоставлений ролей для сопоставления ролей с доменной авторизацией. Следующий пример сопоставляет роли в домене native1 для принципала JWT principalname1.

resp = client.security.put_role_mapping(
    name="native1_users",
    refresh=True,
    roles=[
        "user"
    ],
    rules={
        "all": [
            {
                "field": {
                    "realm.name": "native1"
                }
            },
            {
                "field": {
                    "username": "principalname1"
                }
            }
        ]
    },
    enabled=True,
)
print(resp)
const response = await client.security.putRoleMapping({
  name: "native1_users",
  refresh: "true",
  roles: ["user"],
  rules: {
    all: [
      {
        field: {
          "realm.name": "native1",
        },
      },
      {
        field: {
          username: "principalname1",
        },
      },
    ],
  },
  enabled: true,
});
console.log(response);
PUT /_security/role_mapping/native1_users?refresh=true
{
  "roles" : [ "user" ],
  "rules" : { "all" : [
      { "field": { "realm.name": "native1" } },
      { "field": { "username": "principalname1" } }
  ] },
  "enabled": true
}

Если домен jwt2 успешно аутентифицирует клиента с JWT для принципала principalname1 и делегирует авторизацию одному из указанных доменов (например, native1), то этот домен может найти значения пользователя Elasticsearch. С этим определённым сопоставлением ролей домен также может найти правило сопоставления ролей, связанное с доменом native1.

Применение привилегии run_as к пользователям домена JWT

Elasticsearch может получать роли для пользователя JWT через сопоставление ролей или делегированную авторизацию. Независимо от выбранного варианта, вы можете применить привилегию run_as к роли, чтобы пользователь мог отправлять аутентифицированные запросы для выполнения действий от имени другого пользователя. Чтобы отправить запросы от имени другого пользователя, включите заголовок es-security-runas-user в свои запросы. Запросы выполняются так, как если бы они были выпущены этим пользователем, и Elasticsearch использует их роли.

Например, предположим, что есть пользователь с именем пользователя user123_runas. Следующий запрос создаёт роль пользователя с именем jwt_role1, которая определяет пользователя run_as с именем пользователя user123_runas. Любой пользователь с ролью jwt_role1 может отправлять запросы от имени указанного пользователя run_as.

resp = client.security.put_role(
    name="jwt_role1",
    refresh=True,
    cluster=[
        "manage"
    ],
    indices=[
        {
            "names": [
                "*"
            ],
            "privileges": [
                "read"
            ]
        }
    ],
    run_as=[
        "user123_runas"
    ],
    metadata={
        "version": 1
    },
)
print(resp)
const response = await client.security.putRole({
  name: "jwt_role1",
  refresh: "true",
  cluster: ["manage"],
  indices: [
    {
      names: ["*"],
      privileges: ["read"],
    },
  ],
  run_as: ["user123_runas"],
  metadata: {
    version: 1,
  },
});
console.log(response);
POST /_security/role/jwt_role1?refresh=true
{
  "cluster": ["manage"],
  "indices": [ { "names": [ "*" ], "privileges": ["read"] } ],
  "run_as": [ "user123_runas" ],
  "metadata" : { "version" : 1 }
}

Затем вы можете сопоставить эту роль с пользователем в определённом домене. Следующий запрос сопоставляет роль jwt_role1 с пользователем с именем пользователя user2 в домене JWT jwt2. Это означает, что Elasticsearch будет использовать домен jwt2 для аутентификации пользователя с именем user2. Поскольку у user2 есть роль (роль jwt_role1), которая включает привилегию run_as, Elasticsearch получает сопоставления ролей для пользователя user123_runas и использует роли этого пользователя для отправки запросов.

resp = client.security.put_role_mapping(
    name="jwt_user1",
    refresh=True,
    roles=[
        "jwt_role1"
    ],
    rules={
        "all": [
            {
                "field": {
                    "realm.name": "jwt2"
                }
            },
            {
                "field": {
                    "username": "user2"
                }
            }
        ]
    },
    enabled=True,
    metadata={
        "version": 1
    },
)
print(resp)
const response = await client.security.putRoleMapping({
  name: "jwt_user1",
  refresh: "true",
  roles: ["jwt_role1"],
  rules: {
    all: [
      {
        field: {
          "realm.name": "jwt2",
        },
      },
      {
        field: {
          username: "user2",
        },
      },
    ],
  },
  enabled: true,
  metadata: {
    version: 1,
  },
});
console.log(response);
POST /_security/role_mapping/jwt_user1?refresh=true
{
  "roles": [ "jwt_role1"],
  "rules" : { "all" : [
      { "field": { "realm.name": "jwt2" } },
      { "field": { "username": "user2" } }
  ] },
  "enabled": true,
  "metadata" : { "version" : 1 }
}

После сопоставления ролей вы можете выполнить аутентифицированный вызов Elasticsearch с использованием JWT и включить заголовок ES-Client-Authentication:

curl -s -X GET -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOlsiZXMwMSIsImVzMDIiLCJlczAzIl0sInN1YiI6InVzZXIyIiwiaXNzIjoibXktaXNzdWVyIiwiZXhwIjo0MDcwOTA4ODAwLCJpYXQiOjk0NjY4NDgwMCwiZW1haWwiOiJ1c2VyMkBzb21ldGhpbmcuZXhhbXBsZS5jb20ifQ.UgO_9w--EoRyUKcWM5xh9SimTfMzl1aVu6ZBsRWhxQA" -H "ES-Client-Authentication: sharedsecret test-secret" https://localhost:9200/_security/_authenticate

В ответе содержится информация о пользователе, который отправил запрос (user2), включая роль jwt_role1, которую вы сопоставили с этим пользователем в домене JWT:

{"username":"user2","roles":["jwt_role1"],"full_name":null,"email":"user2@something.example.com",
"metadata":{"jwt_claim_email":"user2@something.example.com","jwt_claim_aud":["es01","es02","es03"],
"jwt_claim_sub":"user2","jwt_claim_iss":"my-issuer"},"enabled":true,"authentication_realm":
{"name":"jwt2","type":"jwt"},"lookup_realm":{"name":"jwt2","type":"jwt"},"authentication_type":"realm"}
%

Если вы хотите указать запрос как пользователя run_as, включите заголовок es-security-runas-user с именем пользователя, от имени которого вы хотите отправить запросы. Следующий запрос использует пользователя user123_runas:

curl -s -X GET -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOlsiZXMwMSIsImVzMDIiLCJlczAzIl0sInN1YiI6InVzZXIyIiwiaXNzIjoibXktaXNzdWVyIiwiZXhwIjo0MDcwOTA4ODAwLCJpYXQiOjk0NjY4NDgwMCwiZW1haWwiOiJ1c2VyMkBzb21ldGhpbmcuZXhhbXBsZS5jb20ifQ.UgO_9w--EoRyUKcWM5xh9SimTfMzl1aVu6ZBsRWhxQA" -H "ES-Client-Authentication: sharedsecret test-secret" -H "es-security-runas-user: user123_runas" https://localhost:9200/_security/_authenticate

В ответе вы увидите, что запрос отправил пользователь user123_runas, и Elasticsearch использовал роль jwt_role1:

{"username":"user123_runas","roles":["jwt_role1"],"full_name":null,"email":null,"metadata":{},
"enabled":true,"authentication_realm":{"name":"jwt2","type":"jwt"},"lookup_realm":{"name":"native",
"type":"native"},"authentication_type":"realm"}%

Перезагрузка PKC JWKS

Авторизация JWT поддерживает проверку подписи с использованием алгоритмов PKC (криптография с открытым ключом) или HMAC.

PKC наборы ключей JSON Web Token (JWKS) могут содержать публичные ключи RSA и EC. HMAC JWKS или HMAC UTF-8 JWK содержат секретные ключи. Издатели JWT обычно чаще обновляют PKC JWKS (например, ежедневно), потому что публичные ключи RSA и EC предназначены для более лёгкого распространения, чем секретные ключи, такие как HMAC.

Домены JWT загружают PKC JWKS и HMAC JWKS или HMAC UTF-8 JWK при запуске. Домены JWT также могут перезагружать содержимое PKC JWKS во время выполнения; перезагрузка инициируется ошибками проверки подписи.

Перезагрузка HMAC JWKS или HMAC UTF-8 JWK в настоящее время не поддерживается.

Ошибки загрузки, ошибки разбора и ошибки конфигурации препятствуют запуску (и перезапуску) узла. Однако ошибки и восстановления PKC во время выполнения обрабатываются без проблем.

Все другие проверки домена JWT проверяются до того, как ошибка подписи может инициировать перезагрузку PKC JWKS. Если несколько ошибок подписи JWT происходят одновременно на одном узле Elasticsearch, перезагрузки объединяются для уменьшения количества перезагрузок, отправляемых внешнему интерфейсу.

Отдельные запросы на перезагрузку не могут быть объединены, если ошибки подписи JWT инициируют:

  • Перезагрузки PKC JWKS на разных узлах Elasticsearch
  • Перезагрузки PKC JWKS на одном узле Elasticsearch в разное время

Сильно рекомендуется включение аутентификации клиента (client_authentication.type). Только доверенные клиентские приложения и пользователи JWT, относящиеся к определённому домену, могут инициировать попытки перезагрузки PKC. Кроме того, рекомендуется настройка следующих настроек безопасности JWT:

  • allowed_audiences
  • allowed_clock_skew
  • allowed_issuer
  • allowed_signature_algorithms

Авторизация в домене JWT с ключом HMAC UTF-8

Следующие настройки предназначены для JWT-эмитента, Elasticsearch и клиента Elasticsearch. Пример ключа HMAC в формате OIDC, совместимом с HMAC. Байты ключа — это кодировка UTF-8 символов Юникода.

Ключи HMAC UTF-8 должны быть длиннее ключей HMAC случайных байтов, чтобы обеспечить ту же силу ключа.

JWT-эмитент

Следующие значения предназначены для настраиваемого JWT-эмитента.

Issuer:     iss8
Audiences:  aud8
Algorithms: HS256
HMAC UTF-8: hmac-oidc-key-string-for-hs256-algorithm

Настройки домена JWT

Чтобы определить домен JWT, добавьте следующие настройки домена в elasticsearch.yml.

xpack.security.authc.realms.jwt.jwt8.order: 8 
xpack.security.authc.realms.jwt.jwt8.allowed_issuer: iss8
xpack.security.authc.realms.jwt.jwt8.allowed_audiences: [aud8]
xpack.security.authc.realms.jwt.jwt8.allowed_signature_algorithms: [HS256]
xpack.security.authc.realms.jwt.jwt8.claims.principal: sub
xpack.security.authc.realms.jwt.jwt8.client_authentication.type: shared_secret

В Elastic Cloud порядок доменов начинается с 2. 0 и 1 зарезервированы в цепочке доменов в Elastic Cloud.

Безопасные настройки домена JWT

После определения настроек домена используйте инструмент elasticsearch-keystore, чтобы добавить следующие безопасные настройки в хранилище ключей Elasticsearch. В Elastic Cloud вы определяете настройки для хранилища ключей Elasticsearch в разделе Безопасность своего развертывания.

xpack.security.authc.realms.jwt.jwt8.hmac_key: hmac-oidc-key-string-for-hs256-algorithm
xpack.security.authc.realms.jwt.jwt8.client_authentication.shared_secret: client-shared-secret-string

Правило сопоставления ролей домена JWT

Следующий запрос создает сопоставления ролей для Elasticsearch в домене jwt8 для пользователя principalname1:

resp = client.security.put_role_mapping(
    name="jwt8_users",
    refresh=True,
    roles=[
        "user"
    ],
    rules={
        "all": [
            {
                "field": {
                    "realm.name": "jwt8"
                }
            },
            {
                "field": {
                    "username": "principalname1"
                }
            }
        ]
    },
    enabled=True,
)
print(resp)
const response = await client.security.putRoleMapping({
  name: "jwt8_users",
  refresh: "true",
  roles: ["user"],
  rules: {
    all: [
      {
        field: {
          "realm.name": "jwt8",
        },
      },
      {
        field: {
          username: "principalname1",
        },
      },
    ],
  },
  enabled: true,
});
console.log(response);
PUT /_security/role_mapping/jwt8_users?refresh=true
{
  "roles" : [ "user" ],
  "rules" : { "all" : [
      { "field": { "realm.name": "jwt8" } },
      { "field": { "username": "principalname1" } }
  ] },
  "enabled": true
}

Заголовки запроса

Следующие настройки заголовков предназначены для клиента Elasticsearch.

Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJpc3M4IiwiYXVkIjoiYXVkOCIsInN1YiI6InNlY3VyaXR5X3Rlc3RfdXNlciIsImV4cCI6NDA3MDkwODgwMCwiaWF0Ijo5NDY2ODQ4MDB9.UnnFmsoFKfNmKMsVoDQmKI_3-j95PCaKdgqqau3jPMY
ES-Client-Authentication: SharedSecret client-shared-secret-string

Вы можете использовать этот заголовок в запросе curl, чтобы выполнить аутентифицированный вызов Elasticsearch. И токен пользователя, и токен авторизации клиента должны быть указаны как отдельные заголовки с опцией -H:

curl -s -X GET -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJpc3M4IiwiYXVkIjoiYXVkOCIsInN1YiI6InNlY3VyaXR5X3Rlc3RfdXNlciIsImV4cCI6NDA3MDkwODgwMCwiaWF0Ijo5NDY2ODQ4MDB9.UnnFmsoFKfNmKMsVoDQmKI_3-j95PCaKdgqqau3jPMY" -H "ES-Client-Authentication: SharedSecret client-shared-secret-string" https://localhost:9200/_security/_authenticate

Если вы использовали сопоставление ролей в домене JWT, ответ включает роль пользователя, их username, метаданные о пользователе и подробности о самом домене JWT.

{"username":"user2","roles":["jwt_role1"],"full_name":null,"email":"user2@something.example.com",
"metadata":{"jwt_claim_email":"user2@something.example.com","jwt_claim_aud":["es01","es02","es03"],
"jwt_claim_sub":"user2","jwt_claim_iss":"my-issuer"},"enabled":true,"authentication_realm":
{"name":"jwt2","type":"jwt"},"lookup_realm":{"name":"jwt2","type":"jwt"},"authentication_type":"realm"}

© 2023-2025 Elasticsearch
As of September 2024, Elasticsearch is available under a choice of three licenses: the Server Side Public License (SSPL), the Elastic License, or the AGPLv3 (OSI approved).
Elasticsearch and the Elasticsearch logo are trademarks of Elasticsearch B.V., registered in the U.S. and in other countries.
https://www.elastic.co/guide/en/elasticsearch/reference/8.17/jwt-auth-realm.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API