JWT 認証

Elasticsearch は、外部サービスから発行された JSON Web Tokens (JWT) を認証のためのベアラートークンとして信頼するように構成できます。

JWT レルムを使用して Elasticsearch に認証する場合、Elasticsearch に接続している クライアント と、リクエストが実行されるべき ユーザー の区別がなされます。JWT はユーザーを認証し、別の資格情報がクライアントを認証します。

JWT レルムは、id_token (デフォルト) と access_token の 2 つのトークンタイプをサポートしています。これらは、それぞれ次の 2 つのシナリオで機能するように設計されています:

  • 1. id_token - アプリケーションが認証フローを使用してユーザーを認証および識別し、例えば OpenID Connect (OIDC) を使用して、認証されたユーザーの代わりに OIDC ID トークン仕様に準拠した JSON Web Token (JWT) を使用して Elasticsearch にアクセスします。
  • 2. access_token - アプリケーションが独自のアイデンティティを持ち、JWT としてエンコードされている場合、例えばアプリケーションが OAuth2 クライアント資格情報フローを使用して中央アイデンティティプラットフォームに自らを認証し、その後、得られた JWT ベースのアクセストークンを使用して Elasticsearch に接続します。

単一の JWT レルムは、単一のトークンタイプでのみ機能します。両方のトークンタイプを処理するには、少なくとも 2 つの JWT レルムを構成する必要があります。使用ケースに基づいてトークンタイプを慎重に選択する必要があります。これは、検証がどのように行われるかに影響を与えます。

JWT レルムは、構成されたトークンタイプに基づいて受信した JWT を検証します。両方のタイプの JSON Web Tokens (JWT) は、次の 5 つの情報を含む必要があります。OIDC 仕様に基づく ID トークンは、これらの情報を提供するために必要なクレームに厳格なルールがありますが、アクセストークンは一部のクレームを構成可能にします。

クレーム
情報 ID トークン アクセストークン
発行者 iss iss
主題 sub デフォルトは sub ですが、sub が存在しない場合は別のクレームにフォールバックできます
対象 aud デフォルトは aud ですが、aud が存在しない場合は別のクレームにフォールバックできます
発行時間 iat iat
有効期限 exp exp

さらに、Elasticsearch は、これらのクレームが存在する場合、ID トークンの nbf および auth_time クレームも検証します。ただし、これらのクレームはアクセストークンには無視されます。

全体として、アクセストークンタイプは検証ルールが緩和されており、自己署名のものを含むより一般的な JWT に適しています。

OIDC ワークフローからの ID トークン

Elasticsearch における JWT 認証は、OIDC ユーザーワークフローから派生しており、異なるトークンが OIDC プロバイダー (OP) によって発行されることがあります。OIDC プロバイダーからの ID トークンは、明確に定義された JSON Web Tokens (JWT) であり、常に id_token トークンタイプの JWT レルムと互換性があるべきです。ID トークンの主題クレームはエンドユーザーを表します。これは、ID トークンが一般的に多くの許可された主題を持つことを意味します。したがって、id_token トークンタイプの JWT レルムは、allowed_subjects (または allowed_subject_patterns) 検証を義務付けません。

JWT は Elasticsearch の外部で取得されるため、OIDC ワークフローを使用する代わりにカスタムワークフローを定義できます。ただし、JWT 形式は依然として JSON Web Signature (JWS) でなければなりません。JWS ヘッダーと JWS 署名は、OIDC ID トークン検証ルールを使用して検証されます。

Elasticsearch は、別の OpenID Connect レルム をサポートしています。これは、Elasticsearch が OIDC RP として機能できる任意のユースケースに推奨されます。OIDC レルムは、Kibana で OIDC 認証を有効にする唯一のサポートされた方法です。

JWT レルムで認証されたユーザーは、オプションで run_as 機能を使用して別のユーザーを偽装できます。詳細は JWT レルムユーザーに run_as 特権を適用する を参照してください。

アクセストークン

アクセストークンを取得する一般的な方法は、OAuth2 クライアント資格情報フローを使用することです。このフローの典型的な使用法は、アプリケーションが自分自身のために資格情報を取得することです。これは、access_token トークンタイプが設計されたユースケースです。このアプリケーションは、エンドユーザーのために ID トークンも取得する可能性があります。エンドユーザーの ID トークンがアプリケーション用に構成された JWT レルムで認証に使用されるのを防ぐために、JWT レルムがトークンタイプ access_token の場合、allowed_subjects または allowed_subject_patterns 検証を義務付けます。

すべてのアクセストークンが JSON Web Token (JWT) 形式であるわけではありません。JWT レルムと互換性があるためには、少なくとも JWT 形式を使用し、上記の表の関連要件を満たす必要があります。

Elasticsearch を JWT レルムを使用するように構成する

JWT 認証を使用するには、elasticsearch.yml ファイルにレルムを作成して、Elasticsearch 認証チェーン内で構成します。

JWT レルムには、いくつかの必須設定と、JWT レルム設定 に記載されているオプション設定があります。

クライアント認証は、JWT レルムに対してデフォルトで有効になっています。クライアント認証を無効にすることは可能ですが、強く推奨されません。

  • 1. あなたの JWT レルムを elasticsearch.yml ファイルに追加します。以下の例は、最も一般的な設定を含んでおり、すべてのユースケースに適しているわけではありません:

Yaml

  1. xpack.security.authc.realms.jwt.jwt1:
  2. order: 3
  3. token_type: id_token
  4. client_authentication.type: shared_secret
  5. allowed_issuer: "https://issuer.example.com/jwt/"
  6. allowed_audiences: [ "8fb85eba-979c-496c-8ae2-a57fde3f12d0" ]
  7. allowed_signature_algorithms: [RS256,HS256]
  8. pkc_jwkset_path: jwt/jwkset.json
  9. claims.principal: sub
    1. - `````order````` `````3````` を指定し、ユーザーを認証する際に構成されたレルムがチェックされる順序を示します。レルムは昇順で参照され、最も低い順序値を持つレルムが最初に参照されます。
    2. - `````token_type
    • レルムに、受信した JWT を ID トークン (id_token) として扱い、検証するよう指示します。
    • client_authentication.type
    • クライアント認証タイプを shared_secret として指定します。これは、クライアントが事前に構成された秘密値と一致する必要がある HTTP リクエストヘッダーを使用して認証されることを意味します。クライアントは、ES-Client-Authentication ヘッダーでこの共有秘密をすべてのリクエストに提供する必要があります。ヘッダー値は、レルムの client_authentication.shared_secret に対して大文字と小文字を区別して一致する必要があります。
    • allowed_issuer
    • JWT 発行者の検証可能な識別子を設定します。この値は通常、URL、UUID、または他の大文字と小文字を区別する文字列値です。
    • allowed_audiences
    • レルムが許可する JWT 対象のリストを指定します。これらの値は通常、URL、UUID、または他の大文字と小文字を区別する文字列値です。
    • allowed_signature_algorithms
    • Elasticsearch が JWT 発行者からの JWT の署名を検証するために RS256 または HS256 署名アルゴリズムを使用することを示します。
    • pkc_jwkset_path
    • JWT レルムがトークン署名を検証するために使用する公開鍵素材を持つ JSON Web Key Set (JWKS) のファイル名または URL。値は https で始まらない場合、ファイル名と見なされます。ファイル名は Elasticsearch 構成ディレクトリに対して相対的に解決されます。URL が提供される場合、https:// で始まる必要があります (http:// はサポートされていません)。Elasticsearch は JWK セットを自動的にキャッシュし、署名検証失敗時に JWK セットを更新しようとします。これは、JWT プロバイダーが署名キーを回転させたことを示す可能性があります。
    • claims.principal
    • ユーザーのプリンシパル (ユーザー名) を含む JWT クレームの名前。
      JWT レルムを構成してアクセストークンを処理するための例のスニペットは次のとおりです:

Yaml

  1. xpack.security.authc.realms.jwt.jwt2:
  2. order: 4
  3. token_type: access_token
  4. client_authentication.type: shared_secret
  5. allowed_issuer: "https://issuer.example.com/jwt/"
  6. allowed_subjects: [ "[email protected]" ]
  7. allowed_subject_patterns: [ "wild*@developer?.example.com", "/[a-z]+<1-10>\\@dev\\.example\\.com/"]
  8. allowed_audiences: [ "elasticsearch" ]
  9. required_claims:
  10. token_use: access
  11. version: ["1.0", "2.0"]
  12. allowed_signature_algorithms: [RS256,HS256]
  13. pkc_jwkset_path: "https://idp-42.example.com/.well-known/configuration"
  14. fallback_claims.sub: client_id
  15. fallback_claims.aud: scope
  16. claims.principal: sub
    1. - 受信した JWT をアクセストークン (`````access_token`````) として扱い、検証するようにレルムに指示します。
    2. - `````allowed_subjects
    • レルムが許可する JWT 主題のリストを指定します。これらの値は通常、URL、UUID、または他の大文字と小文字を区別する文字列値です。
    • allowed_subject_patterns
    • allowed_subjects に類似していますが、許可された JWT 主題のために Lucene regexp とワイルドカードのリストを受け入れます。ワイルドカードは、* および ? 特殊文字 (これらは \ によってエスケープされます) を使用して「任意の文字列」と「任意の単一文字」を意味します。例えば「a?*」は「a1」や「abwhatever」に一致しますが、「a」、「abc」、または「abc」には一致しません (Java 文字列では \ 自体が別の \ によってエスケープされる必要があります)。 Lucene regexp/ で囲む必要があります。例えば「/https?://[^/]+/?/」は、パスコンポーネントのない任意の http または https URL に一致します (「https://elastic.co/」には一致しますが、「https://elastic.co/guide」には一致しません)。
      allowed_subjects または allowed_subject_patterns の設定のいずれかを指定する必要があります (かつ非空である必要があります) token_typeaccess_token の場合。
      allowed_subjects および allowed_subject_patterns の両方の設定が指定されている場合、受信した JWT の sub クレームは、2 つのリストのいずれかに一致する場合に受け入れられます。
    • required_claims
    • JWT に対して追加の検証を実行するためのキー/値ペアのリストを指定します。値は文字列または文字列の配列です。
    • fallback_claims.sub
    • sub クレームが存在しない場合に主題情報を抽出するための JWT クレームの名前。この設定は token_typeaccess_token の場合にのみ利用可能です。フォールバックは sub クレームが使用されるすべての場所に適用されます。上記のスニペットでは、claims.principalclient_id が存在しない場合に sub にもフォールバックします。
    • fallback_claims.aud
    • aud クレームが存在しない場合に対象情報を抽出するための JWT クレームの名前。この設定は token_typeaccess_token の場合にのみ利用可能です。フォールバックは aud クレームが使用されるすべての場所に適用されます。
  • 2. 設定を定義した後、elasticsearch-keystore ツールを使用して、Elasticsearch キーストアに安全な設定の値を保存します。
    • 2.1. shared_secret の値を client_authentication.type に保存します:

Shell

  1. bin/elasticsearch-keystore add xpack.security.authc.realms.jwt.jwt1.client_authentication.shared_secret
  • 2.2. allowed_signature_algorithms の HMAC キーを保存します。これは、例の HS256 アルゴリズムを使用します:

Shell

  1. 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) を同時に 1 つだけ使用できます。

Shell

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

JWT エンコーディングと検証

JWT は 3 つの部分に解析できます:

  • ヘッダー
  • トークンを検証する方法に関する情報を提供します。
  • クレーム
  • 呼び出しユーザーまたはアプリケーションに関するデータを含みます。
  • 署名
  • トークンを検証するために使用されるデータです。

Js

  1. Header: {"typ":"JWT","alg":"HS256"}
  2. Claims: {"aud":"aud8","sub":"security_test_user","iss":"iss8","exp":4070908800,"iat":946684800}
  3. 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 ID トークン検証ルールを使用して検証されます。一部の検証は、JWT レルム設定 を通じてカスタマイズ可能です。

ヘッダー クレーム

ヘッダー クレームは、トークンタイプとトークンに署名するために使用されるアルゴリズムを示します。

  • alg
  • (必須、文字列) トークンに署名するために使用されたアルゴリズムを示します。例えば HS256 のように。アルゴリズムはレルムの許可リストに含まれている必要があります。
  • typ
  • (オプション、文字列) トークンタイプを示します。これは JWT でなければなりません。

ペイロード クレーム

トークンには、トークンを発行しているユーザーおよびトークン自体に関する情報を提供するいくつかのクレームが含まれています。トークンタイプに応じて、これらの情報は異なるクレームによって識別される場合があります。

JWT ペイロード クレーム

次のクレームは、OIDC ID トークンルールのサブセットによって検証されます。

Elasticsearch は nonce クレームを検証しませんが、カスタム JWT 発行者は署名にエントロピーを導入するためにランダムな nonce クレームを追加できます。

allowed_clock_skew を設定することで、時間ベースのクレームの検証を緩和できます。この値は、認証時間 (auth_time)、作成時間 (iat)、有効前 (nbf)、および有効期限 (exp) に関して JWT を検証する前に許可される最大のクロックずれを設定します。

  • iss
  • (必須、文字列) ID トークンを作成した発行者を示します。この値は allowed_issuer 設定の値と正確に大文字と小文字を区別して一致する必要があります。
  • sub
  • (必須*) ID トークンが作成される対象を示します。JWT レルムが id_token タイプの場合、このクレームは必須です。id_token タイプの JWT レルムはデフォルトですべての主題を受け入れます。アクセストークンタイプの JWT レルムは allowed_subjects 設定を指定する必要があり、主題値は許可された主題の設定の CSV 値のいずれかに正確に大文字と小文字を区別して一致する必要があります。アクセストークンタイプの JWT レルムは、sub クレームが存在しない場合に使用されるフォールバッククレームを指定できます。
  • aud
  • (必須*) ID トークンの対象であるオーディエンスを示します。カンマ区切りの値 (CSV) として表現されます。値の 1 つは、allowed_audiences 設定の CSV 値のいずれかに正確に大文字と小文字を区別して一致する必要があります。id_token タイプの JWT レルムはこのクレームを必須とします。access_token タイプの JWT レルムは、aud クレームが存在しない場合に使用されるフォールバッククレームを指定できます。
  • exp
  • (必須、整数) ID トークンの有効期限。エポックからの UTC 秒で表現されます。
  • iat
  • (必須、整数) ID トークンが発行された時間。エポックからの UTC 秒で表現されます。
  • nbf
  • (オプション、整数) JWT が受け入れられないべき時間を示します。エポックからの UTC 秒で表現されます。このクレームはオプションです。存在する場合、id_token タイプの JWT レルムはそれを検証し、access_token タイプの JWT レルムはそれを無視します。
  • auth_time
  • (オプション、整数) JWT 発行者に認証されたユーザーの時間。エポックからの UTC 秒で表現されます。このクレームはオプションです。存在する場合、id_token タイプの JWT レルムはそれを検証し、access_token タイプの JWT レルムはそれを無視します。

JWT クレームを消費するための Elasticsearch 設定

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 での認可

ロールマッピングを定義するために create or update role mappings API を使用できます。これにより、ユーザーのユーザー名、グループ、またはその他のメタデータに基づいて、どのロールが各ユーザーに割り当てられるべきかを決定します。

Python

  1. resp = client.security.put_role_mapping(
  2. name="jwt1_users",
  3. refresh=True,
  4. roles=[
  5. "user"
  6. ],
  7. rules={
  8. "all": [
  9. {
  10. "field": {
  11. "realm.name": "jwt1"
  12. }
  13. },
  14. {
  15. "field": {
  16. "username": "principalname1"
  17. }
  18. },
  19. {
  20. "field": {
  21. "dn": "CN=Principal Name 1,DC=example.com"
  22. }
  23. },
  24. {
  25. "field": {
  26. "groups": "group1"
  27. }
  28. },
  29. {
  30. "field": {
  31. "metadata.jwt_claim_other": "other1"
  32. }
  33. }
  34. ]
  35. },
  36. enabled=True,
  37. )
  38. print(resp)

Js

  1. const response = await client.security.putRoleMapping({
  2. name: "jwt1_users",
  3. refresh: "true",
  4. roles: ["user"],
  5. rules: {
  6. all: [
  7. {
  8. field: {
  9. "realm.name": "jwt1",
  10. },
  11. },
  12. {
  13. field: {
  14. username: "principalname1",
  15. },
  16. },
  17. {
  18. field: {
  19. dn: "CN=Principal Name 1,DC=example.com",
  20. },
  21. },
  22. {
  23. field: {
  24. groups: "group1",
  25. },
  26. },
  27. {
  28. field: {
  29. "metadata.jwt_claim_other": "other1",
  30. },
  31. },
  32. ],
  33. },
  34. enabled: true,
  35. });
  36. console.log(response);

コンソール

  1. PUT /_security/role_mapping/jwt1_users?refresh=true
  2. {
  3. "roles" : [ "user" ],
  4. "rules" : { "all" : [
  5. { "field": { "realm.name": "jwt1" } },
  6. { "field": { "username": "principalname1" } },
  7. { "field": { "dn": "CN=Principal Name 1,DC=example.com" } },
  8. { "field": { "groups": "group1" } },
  9. { "field": { "metadata.jwt_claim_other": "other1" } }
  10. ] },
  11. "enabled": true
  12. }

この API を JWT レルムで使用する場合、ロールマッピングに利用可能なクレームは次のとおりです:

  • principal
  • (必須、文字列) Elasticsearch ユーザーのユーザー名として使用されるプリンシパルクレーム。
  • dn
  • (オプション、文字列) Elasticsearch ユーザーの DN として使用される識別名 (DN)。
  • groups
  • (オプション、文字列) Elasticsearch ユーザーのグループリストとして使用されるカンマ区切りの値 (CSV) リスト。
  • metadata
  • (オプション、オブジェクト) ユーザーに関する追加のメタデータ。文字列、整数、ブール値、コレクションなど、Elasticsearch ユーザーのメタデータとして使用されます。これらの値は metadata.jwt_claim_<key> = <value> の形式でキーと値のペアとしてフォーマットされます。

別のレルムへの JWT 認可の委任

JWT レルムから他のレルムに 認可を委任 する場合、ロールルックアップに利用可能なクレームは principal のみです。JWT レルムから別のレルムにロールの割り当てとルックアップを委任する場合、dngroupsmailmetadata、および name のクレームは Elasticsearch ユーザーの値に使用されません。JWT principal クレームのみが委任された認可レルムに渡されます。認可のために委任されたレルムは、JWT レルムではなく、すべての Elasticsearch ユーザーの値を設定する責任を負います。

以下の例は、JWT レルムから複数の他のレルムに委任認可を定義する方法を示しています。jwt2 という名前の JWT レルムが複数のレルムに認可を委任しています:

Yaml

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

create or update role mappings API を使用して、認可レルムにロールをマッピングできます。以下の例は、native1 レルムの principalname1 JWT プリンシパルにロールをマッピングします。

Python

  1. resp = client.security.put_role_mapping(
  2. name="native1_users",
  3. refresh=True,
  4. roles=[
  5. "user"
  6. ],
  7. rules={
  8. "all": [
  9. {
  10. "field": {
  11. "realm.name": "native1"
  12. }
  13. },
  14. {
  15. "field": {
  16. "username": "principalname1"
  17. }
  18. }
  19. ]
  20. },
  21. enabled=True,
  22. )
  23. print(resp)

Js

  1. const response = await client.security.putRoleMapping({
  2. name: "native1_users",
  3. refresh: "true",
  4. roles: ["user"],
  5. rules: {
  6. all: [
  7. {
  8. field: {
  9. "realm.name": "native1",
  10. },
  11. },
  12. {
  13. field: {
  14. username: "principalname1",
  15. },
  16. },
  17. ],
  18. },
  19. enabled: true,
  20. });
  21. console.log(response);

コンソール

  1. PUT /_security/role_mapping/native1_users?refresh=true
  2. {
  3. "roles" : [ "user" ],
  4. "rules" : { "all" : [
  5. { "field": { "realm.name": "native1" } },
  6. { "field": { "username": "principalname1" } }
  7. ] },
  8. "enabled": true
  9. }

jwt2 がプリンシパル principalname1 の JWT でクライアントを正常に認証し、native1 のようなリストされたレルムに認可を委任した場合、そのレルムは Elasticsearch ユーザーの値をルックアップできます。この定義されたロールマッピングにより、レルムは native1 レルムにリンクされたこのロールマッピングルールをルックアップすることもできます。

JWT レルムユーザーに run_as 特権を適用する

Elasticsearch は、ロールマッピングまたは委任された認可を通じて JWT ユーザーのロールを取得できます。どのオプションを選択しても、ユーザーが「他のユーザーとして実行する」ために認証されたリクエストを送信できるように、run_as 特権 をロールに適用できます。別のユーザーとしてリクエストを送信するには、リクエストに es-security-runas-user ヘッダーを含めます。リクエストは、そのユーザーから発行されたかのように実行され、Elasticsearch はそのユーザーのロールを使用します。

例えば、ユーザー名が user123_runas のユーザーがいると仮定します。次のリクエストは、jwt_role1 という名前のユーザーロールを作成します。これは、run_as ユーザーを user123_runas ユーザー名で指定します。jwt_role1 ロールを持つ任意のユーザーは、指定された run_as ユーザーとしてリクエストを発行できます。

Python

  1. resp = client.security.put_role(
  2. name="jwt_role1",
  3. refresh=True,
  4. cluster=[
  5. "manage"
  6. ],
  7. indices=[
  8. {
  9. "names": [
  10. "*"
  11. ],
  12. "privileges": [
  13. "read"
  14. ]
  15. }
  16. ],
  17. run_as=[
  18. "user123_runas"
  19. ],
  20. metadata={
  21. "version": 1
  22. },
  23. )
  24. print(resp)

Js

  1. const response = await client.security.putRole({
  2. name: "jwt_role1",
  3. refresh: "true",
  4. cluster: ["manage"],
  5. indices: [
  6. {
  7. names: ["*"],
  8. privileges: ["read"],
  9. },
  10. ],
  11. run_as: ["user123_runas"],
  12. metadata: {
  13. version: 1,
  14. },
  15. });
  16. console.log(response);

コンソール

  1. POST /_security/role/jwt_role1?refresh=true
  2. {
  3. "cluster": ["manage"],
  4. "indices": [ { "names": [ "*" ], "privileges": ["read"] } ],
  5. "run_as": [ "user123_runas" ],
  6. "metadata" : { "version" : 1 }
  7. }

特定のレルムのユーザーにロールをマッピングできます。次のリクエストは、jwt_role1 レルムのユーザー名 user2jwt2 ロールをマッピングします。これは、Elasticsearch が jwt2 レルムを使用して user2 という名前のユーザーを認証することを意味します。user2jwt_role1 ロールを持っているため、run_as 特権を含む user123_runas ユーザーのロールマッピングを取得し、そのユーザーのロールを使用してリクエストを送信します。

Python

  1. resp = client.security.put_role_mapping(
  2. name="jwt_user1",
  3. refresh=True,
  4. roles=[
  5. "jwt_role1"
  6. ],
  7. rules={
  8. "all": [
  9. {
  10. "field": {
  11. "realm.name": "jwt2"
  12. }
  13. },
  14. {
  15. "field": {
  16. "username": "user2"
  17. }
  18. }
  19. ]
  20. },
  21. enabled=True,
  22. metadata={
  23. "version": 1
  24. },
  25. )
  26. print(resp)

Js

  1. const response = await client.security.putRoleMapping({
  2. name: "jwt_user1",
  3. refresh: "true",
  4. roles: ["jwt_role1"],
  5. rules: {
  6. all: [
  7. {
  8. field: {
  9. "realm.name": "jwt2",
  10. },
  11. },
  12. {
  13. field: {
  14. username: "user2",
  15. },
  16. },
  17. ],
  18. },
  19. enabled: true,
  20. metadata: {
  21. version: 1,
  22. },
  23. });
  24. console.log(response);

コンソール

  1. POST /_security/role_mapping/jwt_user1?refresh=true
  2. {
  3. "roles": [ "jwt_role1"],
  4. "rules" : { "all" : [
  5. { "field": { "realm.name": "jwt2" } },
  6. { "field": { "username": "user2" } }
  7. ] },
  8. "enabled": true,
  9. "metadata" : { "version" : 1 }
  10. }

ロールをマッピングした後、JWT を使用して Elasticsearch に 認証された呼び出し を行い、ES-Client-Authentication ヘッダーを含めます:

  1. 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 レルムでこのユーザーにマッピングされた jwt_role1 ロールが含まれます:

  1. {"username":"user2","roles":["jwt_role1"],"full_name":null,"email":"[email protected]",
  2. "metadata":{"jwt_claim_email":"[email protected]","jwt_claim_aud":["es01","es02","es03"],
  3. "jwt_claim_sub":"user2","jwt_claim_iss":"my-issuer"},"enabled":true,"authentication_realm":
  4. {"name":"jwt2","type":"jwt"},"lookup_realm":{"name":"jwt2","type":"jwt"},"authentication_type":"realm"}
  5. %

リクエストを run_as ユーザーとして指定したい場合は、es-security-runas-user ヘッダーにリクエストを送信したいユーザーの名前を含めます。次のリクエストは user123_runas ユーザーを使用します:

  1. 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 ロールを使用しました:

  1. {"username":"user123_runas","roles":["jwt_role1"],"full_name":null,"email":null,"metadata":{},
  2. "enabled":true,"authentication_realm":{"name":"jwt2","type":"jwt"},"lookup_realm":{"name":"native",
  3. "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 の再ロードをトリガーする前にチェックされます。単一の Elasticsearch ノードで同時に複数の JWT 認証署名失敗が発生した場合、再ロードは外部に送信される再ロードを減らすために結合されます。

JWT 署名の失敗がトリガーされた場合、別々の再ロード要求は結合できません:

  • 異なる Elasticsearch ノードでの PKC JWKS の再ロード
  • 同じ Elasticsearch ノードで異なる時間に PKC JWKS の再ロード

クライアント認証を有効にすること (client_authentication.type) は強く推奨されます。信頼されたクライアントアプリケーションとレルム固有の JWT ユーザーのみが PKC 再ロードの試行をトリガーできます。さらに、次の JWT セキュリティ設定 を構成することを推奨します:

  • allowed_audiences
  • allowed_clock_skew
  • allowed_issuer
  • allowed_signature_algorithms

HMAC UTF-8 キーで JWT レルムに認可する

次の設定は、JWT 発行者、Elasticsearch、および Elasticsearch のクライアントに関するものです。例の HMAC キーは、HMAC と互換性のある OIDC 形式です。キーのバイトは、UNICODE 文字の UTF-8 エンコーディングです。

HMAC UTF-8 キーは、同じキー強度を達成するために HMAC ランダムバイトキーよりも長くする必要があります。

JWT 発行者

次の値は、特注の JWT 発行者に関するものです。

Js

  1. Issuer: iss8
  2. Audiences: aud8
  3. Algorithms: HS256
  4. HMAC UTF-8: hmac-oidc-key-string-for-hs256-algorithm

JWT レルム設定

JWT レルムを定義するには、次のレルム設定を elasticsearch.yml に追加します。

Yaml

  1. xpack.security.authc.realms.jwt.jwt8.order: 8
  2. xpack.security.authc.realms.jwt.jwt8.allowed_issuer: iss8
  3. xpack.security.authc.realms.jwt.jwt8.allowed_audiences: [aud8]
  4. xpack.security.authc.realms.jwt.jwt8.allowed_signature_algorithms: [HS256]
  5. xpack.security.authc.realms.jwt.jwt8.claims.principal: sub
  6. xpack.security.authc.realms.jwt.jwt8.client_authentication.type: shared_secret
Elastic Cloud では、レルムの順序は 2 から始まります。01 は、Elastic Cloud のレルムチェーンで予約されています。

JWT レルムのセキュア設定

レルム設定を定義した後、elasticsearch-keystore ツールを使用して、Elasticsearch キーストアに次のセキュア設定を追加します。Elastic Cloud では、デプロイメントの セキュリティ の下で Elasticsearch キーストアの設定を定義します。

Yaml

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

JWT レルムのロールマッピングルール

次のリクエストは、ユーザー principalname1 のために jwt8 レルムで Elasticsearch のロールマッピングを作成します:

Python

  1. resp = client.security.put_role_mapping(
  2. name="jwt8_users",
  3. refresh=True,
  4. roles=[
  5. "user"
  6. ],
  7. rules={
  8. "all": [
  9. {
  10. "field": {
  11. "realm.name": "jwt8"
  12. }
  13. },
  14. {
  15. "field": {
  16. "username": "principalname1"
  17. }
  18. }
  19. ]
  20. },
  21. enabled=True,
  22. )
  23. print(resp)

Js

  1. const response = await client.security.putRoleMapping({
  2. name: "jwt8_users",
  3. refresh: "true",
  4. roles: ["user"],
  5. rules: {
  6. all: [
  7. {
  8. field: {
  9. "realm.name": "jwt8",
  10. },
  11. },
  12. {
  13. field: {
  14. username: "principalname1",
  15. },
  16. },
  17. ],
  18. },
  19. enabled: true,
  20. });
  21. console.log(response);

コンソール

  1. PUT /_security/role_mapping/jwt8_users?refresh=true
  2. {
  3. "roles" : [ "user" ],
  4. "rules" : { "all" : [
  5. { "field": { "realm.name": "jwt8" } },
  6. { "field": { "username": "principalname1" } }
  7. ] },
  8. "enabled": true
  9. }

リクエストヘッダー

次のヘッダー設定は、Elasticsearch クライアントに関するものです。

Js

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

このヘッダーを使用して、curlリクエストでElasticsearchに認証された呼び出しを行うことができます。ベアラートークンとクライアント認証トークンは、-Hオプションを使用して別々のヘッダーとして指定する必要があります:

  1. 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、そのroles、ユーザーに関するメタデータ、およびJWTレルム自体の詳細が含まれます。

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