APIキー認証を使用してリモートクラスターを追加する

APIキー認証により、ローカルクラスターはリモートクラスターと認証を行うことができます。これは、クロスクラスターAPIキーを介して行われます。APIキーはリモートクラスターの管理者によって作成される必要があります。ローカルクラスターは、リモートクラスターへの各リクエストでこのAPIキーを提供するように構成されています。リモートクラスターはAPIキーを検証し、その権限に基づいてアクセスを許可します。

ローカルクラスターからのすべてのクロスクラスターリクエストは、APIキーの権限に制約されます。これは、リクエストに関連付けられたローカルユーザーに関係なく適用されます。たとえば、APIキーがリモートクラスターのmy-indexへの読み取りアクセスのみを許可している場合、ローカルクラスターのスーパーユーザーであってもこの制約に制限されます。このメカニズムにより、リモートクラスターの管理者は、誰がどのデータにアクセスできるかを完全に制御できます。リモートクラスターの管理者は、APIキーに明示的に割り当てられたものを超えるアクセスが不可能であることを確信できます。

ローカルクラスター側では、すべてのローカルユーザーがAPIキーによって許可されたすべてのデータにアクセスする必要はありません。ローカルクラスターの管理者は、ローカルユーザーに対して追加の権限制約をさらに構成できるため、各ユーザーは必要なリモートデータにのみアクセスできます。個々のローカルユーザーに対してAPIキーによって許可される権限をさらに減らすことは可能ですが、APIキーによって許可されるものを超えて権限を増やすことは不可能です。

このモデルでは、クロスクラスター操作は、クラスター間の通信のために専用サーバーポート(リモートクラスターインターフェース)を使用します。リモートクラスターは、ローカルクラスターが接続できるようにこのポートを有効にする必要があります。このポートに対してトランスポート層セキュリティ(TLS)を構成してセキュリティを最大化します(リモートクラスターとの信頼を確立するで説明されています)。

ローカルクラスターは、リモートクラスターインターフェースでリモートクラスターを信頼する必要があります。これは、ローカルクラスターがリモートクラスターインターフェースで使用されるサーバー証明書に署名する証明書機関(CA)を信頼することを意味します。接続を確立する際、クロスクラスター通信に参加するローカルクラスターのすべてのノードは、TLS信頼構成に基づいて、他方のノードからの証明書を検証します。

APIキー認証を使用してリモートクラスターを追加するには:

問題が発生した場合は、トラブルシューティングを参照してください。

前提条件

  • Elasticsearchのセキュリティ機能は、両方のクラスターのすべてのノードで有効にする必要があります。セキュリティはデフォルトで有効です。無効になっている場合は、xpack.security.enabledtrueに設定します。 一般的なセキュリティ設定を参照してください。
  • ローカルクラスターとリモートクラスターのノードは、バージョン8.10以上である必要があります。
  • ローカルクラスターとリモートクラスターは、適切なライセンスを持っている必要があります。詳細については、https://www.elastic.co/subscriptionsを参照してください。

リモートクラスターとの信頼を確立する

リモートクラスターがElasticsearchサービスのデプロイメントの一部である場合、デフォルトで有効な証明書があります。したがって、これらの手順における証明書に関連するステップをスキップできます。

リモートクラスターで

  • 1. リモートクラスターのすべてのノードでリモートクラスターサーバーを有効にします。elasticsearch.ymlで:
    • 1.1. remote_cluster_server.enabledtrueに設定します。
    • 1.2. リモートクラスターサーバートラフィックのバインドおよび公開アドレスを構成します。たとえば、remote_cluster.hostを使用します。アドレスを構成しないと、リモートクラスターのトラフィックがローカルインターフェースにバインドされ、他のマシンで実行されているリモートクラスターに接続できなくなります。
    • 1.3. オプションで、remote_cluster.portを使用してリモートサーバーポートを構成します(デフォルトは9443です)。
  • 2. 次に、証明書機関(CA)とサーバー証明書/キーのペアを生成します。リモートクラスターのノードの1つで、Elasticsearchがインストールされているディレクトリから:
    • 2.1. すでにCAを持っていない場合はCAを作成します:
      1. ./bin/elasticsearch-certutil ca --pem --out=cross-cluster-ca.zip --pass CA_PASSWORD
      CA_PASSWORDをCAに使用したいパスワードに置き換えます。プロダクション環境にデプロイしない場合は、--passオプションとその引数を削除できます。
    • 2.2. 生成されたcross-cluster-ca.zipファイルを解凍します。この圧縮ファイルには次の内容が含まれています:

テキスト

  1. /ca
  2. |_ ca.crt
  3. |_ ca.key
  • 2.3. リモートクラスターのノード用に証明書と秘密鍵のペアを生成します:
    1. ./bin/elasticsearch-certutil cert --out=cross-cluster.p12 --pass=CERT_PASSWORD --ca-cert=ca/ca.crt --ca-key=ca/ca.key --ca-pass=CA_PASSWORD --dns=example.com --ip=127.0.0.1
  • CA_PASSWORDを前のステップのCAパスワードに置き換えます。
    • CERT_PASSWORDを生成された秘密鍵に使用したいパスワードに置き換えます。
    • --dnsオプションを使用して、証明書の関連するDNS名を指定します。複数のDNSに対して複数回指定できます。
    • --ipオプションを使用して、証明書の関連するIPアドレスを指定します。複数のIPアドレスに対して複数回指定できます。
      • 2.4. リモートクラスターに複数のノードがある場合、次のいずれかを行うことができます:
    • すべてのノード用に単一のワイルドカード証明書を作成します。
    • または、手動またはサイレントモードで各ノード用に別々の証明書を作成します。
  • 3. リモートクラスターのすべてのノードで:
    • 3.1. 前のステップで生成されたcross-cluster.p12ファイルをconfigディレクトリにコピーします。ワイルドカード証明書を作成しなかった場合は、正しいノード固有のp12ファイルをコピーすることを確認してください。
    • 3.2. elasticsearch.ymlに次の構成を追加します:

YAML

  1. xpack.security.remote_cluster_server.ssl.enabled: true
  2. xpack.security.remote_cluster_server.ssl.keystore.path: cross-cluster.p12
  • 3.3. SSLキーストアパスワードをElasticsearchキーストアに追加します:
    1. ./bin/elasticsearch-keystore add xpack.security.remote_cluster_server.ssl.keystore.secure_password
    プロンプトが表示されたら、前のステップのCERT_PASSWORDを入力します。
  • 4. リモートクラスターを再起動します。
  • 5. リモートクラスターで、クロスクラスター検索またはクロスクラスター複製に使用するインデックスへのアクセスを提供するクロスクラスターAPIキーを生成します。 クロスクラスターAPIキーを作成する APIまたはKibanaを使用できます。
  • 6. エンコードされたキー(応答のencoded)を安全な場所にコピーします。後でリモートクラスターに接続するために必要です。

ローカルクラスターで

  • 1. ローカルクラスターのすべてのノードで:
    • 1.1. リモートクラスターで以前に生成されたca.crtファイルをconfigディレクトリにコピーし、ファイル名をremote-cluster-ca.crtに変更します。
    • 1.2. elasticsearch.ymlに次の構成を追加します:

YAML

  1. xpack.security.remote_cluster_client.ssl.enabled: true
  2. xpack.security.remote_cluster_client.ssl.certificate_authorities: [ "remote-cluster-ca.crt" ]
  • 1.3. リモートクラスターで以前に作成されたクロスクラスターAPIキーをキーストアに追加します:
    1. ./bin/elasticsearch-keystore add cluster.remote.ALIAS.credentials
    ALIASを後でリモートクラスターエントリを作成するために使用する同じ名前に置き換えます。プロンプトが表示されたら、リモートクラスターで以前に作成されたエンコードされたクロスクラスターAPIキーを入力します。
  • 2. キーストアと設定の変更を読み込むためにローカルクラスターを再起動します。

注意: クロスクラスターAPIキーのみを構成している場合は、クラスターを再起動する代わりにノードのセキュア設定を再読み込み APIを呼び出すことができます。remote_cluster_client設定をelasticsearch.ymlで構成するには、再起動が必要です。

リモートクラスターに接続する

リモートクラスターに接続するには、manageクラスター権限が必要です。

ローカルクラスターは、リモートクラスターインターフェースを使用してリモートクラスターとの通信を確立します。ローカルクラスターのコーディネートノードは、リモートクラスターの特定のノードと長期接続のTCP接続を確立します。Elasticsearchは、接続が長時間アイドル状態であっても、これらの接続が開いたままであることを要求します。

Kibanaのスタック管理からリモートクラスターを追加するには:

  • 1. サイドナビゲーションからリモートクラスターを選択します。
  • 2. リモートクラスターの名前(クラスターエイリアス)を入力します。
  • 3. ElasticsearchエンドポイントURL、またはリモートクラスターのIPアドレスまたはホスト名の後にリモートクラスターのポート(デフォルトは9443)を指定します。たとえば、cluster.es.eastus2.staging.azure.foundit.no:9443または192.168.1.1:9443です。

または、クラスター設定を更新するAPIを使用してリモートクラスターを追加できます。このAPIを使用して、ローカルクラスターのすべてのノードに対してリモートクラスターを動的に構成することもできます。ローカルクラスターの個々のノードにリモートクラスターを構成するには、各ノードのelasticsearch.ymlに静的設定を定義します。

次のリクエストは、エイリアスcluster_oneを持つリモートクラスターを追加します。このクラスターエイリアスは、リモートクラスターへの接続を表す一意の識別子であり、ローカルインデックスとリモートインデックスを区別するために使用されます。

Python

  1. resp = client.cluster.put_settings(
  2. persistent={
  3. "cluster": {
  4. "remote": {
  5. "cluster_one": {
  6. "seeds": [
  7. "127.0.0.1:{remote-interface-default-port}"
  8. ]
  9. }
  10. }
  11. }
  12. },
  13. )
  14. print(resp)

Js

  1. const response = await client.cluster.putSettings({
  2. persistent: {
  3. cluster: {
  4. remote: {
  5. cluster_one: {
  6. seeds: ["127.0.0.1:{remote-interface-default-port}"],
  7. },
  8. },
  9. },
  10. },
  11. });
  12. console.log(response);

コンソール

  1. PUT /_cluster/settings
  2. {
  3. "persistent" : {
  4. "cluster" : {
  5. "remote" : {
  6. "cluster_one" : {
  7. "seeds" : [
  8. "127.0.0.1:9443"
  9. ]
  10. }
  11. }
  12. }
  13. }
  14. }
このリモートクラスターのクラスターエイリアスはcluster_oneです。
リモートクラスターのシードノードのホスト名とリモートクラスターのポートを指定します。

リモートクラスター情報APIを使用して、ローカルクラスターがリモートクラスターに正常に接続されていることを確認できます:

Python

  1. resp = client.cluster.remote_info()
  2. print(resp)

Ruby

  1. response = client.cluster.remote_info
  2. puts response

Js

  1. const response = await client.cluster.remoteInfo();
  2. console.log(response);

コンソール

  1. GET /_remote/info

APIの応答は、ローカルクラスターがクラスターエイリアスcluster_oneを持つリモートクラスターに接続されていることを示しています:

コンソール-結果

  1. {
  2. "cluster_one" : {
  3. "seeds" : [
  4. "127.0.0.1:9443"
  5. ],
  6. "connected" : true,
  7. "num_nodes_connected" : 1,
  8. "max_connections_per_cluster" : 3,
  9. "initial_connect_timeout" : "30s",
  10. "skip_unavailable" : true,
  11. "cluster_credentials": "::es_redacted::",
  12. "mode" : "sniff"
  13. }
  14. }
ローカルクラスターが接続されているリモートクラスターのノード数。
クロスクラスター検索を通じて検索された場合、ノードが利用できない場合はリモートクラスターをスキップするかどうかを示します。
存在する場合、リモートクラスターはAPIキー認証を使用して接続されていることを示します。

リモートクラスターを動的に構成する

クラスター設定を更新するAPIを使用して、クラスター内のすべてのノードでリモート設定を動的に構成します。次のリクエストは、cluster_onecluster_twocluster_threeの3つのリモートクラスターを追加します。

  1. `````mode`````パラメータは、構成された接続モードを決定し、デフォルトは[`````sniff`````](7781101e63c937c9.md#sniff-mode)です。`````cluster_one`````が`````mode`````を指定しないため、デフォルトが使用されます。`````cluster_two`````と`````cluster_three`````は明示的に異なるモードを使用します。
  2. #### Python
  3. ``````python
  4. resp = client.cluster.put_settings(
  5. persistent={
  6. "cluster": {
  7. "remote": {
  8. "cluster_one": {
  9. "seeds": [
  10. "127.0.0.1:{remote-interface-default-port}"
  11. ]
  12. },
  13. "cluster_two": {
  14. "mode": "sniff",
  15. "seeds": [
  16. "127.0.0.1:{remote-interface-default-port-plus1}"
  17. ],
  18. "transport.compress": True,
  19. "skip_unavailable": True
  20. },
  21. "cluster_three": {
  22. "mode": "proxy",
  23. "proxy_address": "127.0.0.1:{remote-interface-default-port-plus2}"
  24. }
  25. }
  26. }
  27. },
  28. )
  29. print(resp)
  30. `

Js

  1. const response = await client.cluster.putSettings({
  2. persistent: {
  3. cluster: {
  4. remote: {
  5. cluster_one: {
  6. seeds: ["127.0.0.1:{remote-interface-default-port}"],
  7. },
  8. cluster_two: {
  9. mode: "sniff",
  10. seeds: ["127.0.0.1:{remote-interface-default-port-plus1}"],
  11. "transport.compress": true,
  12. skip_unavailable: true,
  13. },
  14. cluster_three: {
  15. mode: "proxy",
  16. proxy_address: "127.0.0.1:{remote-interface-default-port-plus2}",
  17. },
  18. },
  19. },
  20. },
  21. });
  22. console.log(response);

コンソール

  1. PUT _cluster/settings
  2. {
  3. "persistent": {
  4. "cluster": {
  5. "remote": {
  6. "cluster_one": {
  7. "seeds": [
  8. "127.0.0.1:9443"
  9. ]
  10. },
  11. "cluster_two": {
  12. "mode": "sniff",
  13. "seeds": [
  14. "127.0.0.1:9444"
  15. ],
  16. "transport.compress": true,
  17. "skip_unavailable": true
  18. },
  19. "cluster_three": {
  20. "mode": "proxy",
  21. "proxy_address": "127.0.0.1:9445"
  22. }
  23. }
  24. }
  25. }
  26. }

初期構成後、リモートクラスターの設定を動的に更新できます。次のリクエストは、cluster_twoの圧縮設定とcluster_threeの圧縮およびpingスケジュール設定を更新します。

圧縮またはpingスケジュール設定が変更されると、すべての既存のノード接続は閉じて再オープンする必要があり、これにより進行中のリクエストが失敗する可能性があります。

Python

  1. resp = client.cluster.put_settings(
  2. persistent={
  3. "cluster": {
  4. "remote": {
  5. "cluster_two": {
  6. "transport.compress": False
  7. },
  8. "cluster_three": {
  9. "transport.compress": True,
  10. "transport.ping_schedule": "60s"
  11. }
  12. }
  13. }
  14. },
  15. )
  16. print(resp)

Ruby

  1. response = client.cluster.put_settings(
  2. body: {
  3. persistent: {
  4. cluster: {
  5. remote: {
  6. cluster_two: {
  7. 'transport.compress' => false
  8. },
  9. cluster_three: {
  10. 'transport.compress' => true,
  11. 'transport.ping_schedule' => '60s'
  12. }
  13. }
  14. }
  15. }
  16. }
  17. )
  18. puts response

Js

  1. const response = await client.cluster.putSettings({
  2. persistent: {
  3. cluster: {
  4. remote: {
  5. cluster_two: {
  6. "transport.compress": false,
  7. },
  8. cluster_three: {
  9. "transport.compress": true,
  10. "transport.ping_schedule": "60s",
  11. },
  12. },
  13. },
  14. },
  15. });
  16. console.log(response);

コンソール

  1. PUT _cluster/settings
  2. {
  3. "persistent": {
  4. "cluster": {
  5. "remote": {
  6. "cluster_two": {
  7. "transport.compress": false
  8. },
  9. "cluster_three": {
  10. "transport.compress": true,
  11. "transport.ping_schedule": "60s"
  12. }
  13. }
  14. }
  15. }
  16. }

クラスター設定からリモートクラスターを削除するには、各リモートクラスター設定にnullの値を渡します。次のリクエストは、cluster_twoをクラスター設定から削除し、cluster_onecluster_threeをそのままにします:

Python

  1. resp = client.cluster.put_settings(
  2. persistent={
  3. "cluster": {
  4. "remote": {
  5. "cluster_two": {
  6. "mode": None,
  7. "seeds": None,
  8. "skip_unavailable": None,
  9. "transport.compress": None
  10. }
  11. }
  12. }
  13. },
  14. )
  15. print(resp)

Ruby

  1. response = client.cluster.put_settings(
  2. body: {
  3. persistent: {
  4. cluster: {
  5. remote: {
  6. cluster_two: {
  7. mode: nil,
  8. seeds: nil,
  9. skip_unavailable: nil,
  10. 'transport.compress' => nil
  11. }
  12. }
  13. }
  14. }
  15. }
  16. )
  17. puts response

Js

  1. const response = await client.cluster.putSettings({
  2. persistent: {
  3. cluster: {
  4. remote: {
  5. cluster_two: {
  6. mode: null,
  7. seeds: null,
  8. skip_unavailable: null,
  9. "transport.compress": null,
  10. },
  11. },
  12. },
  13. },
  14. });
  15. console.log(response);

コンソール

  1. PUT _cluster/settings
  2. {
  3. "persistent": {
  4. "cluster": {
  5. "remote": {
  6. "cluster_two": {
  7. "mode": null,
  8. "seeds": null,
  9. "skip_unavailable": null,
  10. "transport.compress": null
  11. }
  12. }
  13. }
  14. }
  15. }

リモートクラスターを静的に構成する

  1. [クラスター設定を更新するAPI](/read/elasticsearch-8-15/a43f4ba05b0b929e.md)を使用して指定されたリモートクラスター設定は、個々のノードの`````elasticsearch.yml`````で指定された設定よりも優先されます。
  2. 次の例では、`````cluster_one``````````cluster_two``````````cluster_three`````は、各クラスターへの接続を表す任意のクラスターエイリアスです。これらの名前は、その後、ローカルインデックスとリモートインデックスを区別するために使用されます。
  3. #### YAML
  4. ``````yaml
  5. cluster:
  6. remote:
  7. cluster_one:
  8. seeds: 127.0.0.1:9443
  9. cluster_two:
  10. mode: sniff
  11. seeds: 127.0.0.1:9444
  12. transport.compress: true
  13. skip_unavailable: true
  14. cluster_three:
  15. mode: proxy
  16. proxy_address: 127.0.0.1:9445
  17. `
cluster_twoへのリクエストの圧縮が明示的に有効になっています。
切断されたリモートクラスターはcluster_twoに対してオプションです。
cluster_threeに接続するために使用されるプロキシエンドポイントのアドレス。

ロールとユーザーを構成する

クロスクラスター複製またはクロスクラスター検索にリモートクラスターを使用するには、ローカルクラスターでリモートインデックス権限を持つユーザーロールを作成する必要があります。

Kibanaのスタック管理から、サイドナビゲーションのセキュリティ > ロールを選択して、ユーザーとロールを管理できます。また、ロール管理APIを使用して、ロールを動的に追加、更新、削除、取得できます。

次の例では、ロールの作成または更新 APIを使用します。このAPIを使用するには、少なくともmanage_securityクラスター権限が必要です。

ローカルクラスターがリモートクラスターに接続するために使用するクロスクラスターAPIキーは、個々のユーザーが必要とするすべてのリモートインデックス権限をカバーするのに十分な権限を持っている必要があります。

クロスクラスター複製のための権限を構成する

リモートクラスターがmy_remote_clusterという名前で接続されていると仮定すると、次のリクエストは、ローカルクラスターにremote-replicationというロールを作成し、リモートleader-indexインデックスを複製することを許可します:

Python

  1. resp = client.security.put_role(
  2. name="remote-replication",
  3. cluster=[
  4. "manage_ccr"
  5. ],
  6. remote_indices=[
  7. {
  8. "clusters": [
  9. "my_remote_cluster"
  10. ],
  11. "names": [
  12. "leader-index"
  13. ],
  14. "privileges": [
  15. "cross_cluster_replication"
  16. ]
  17. }
  18. ],
  19. )
  20. print(resp)

Js

  1. const response = await client.security.putRole({
  2. name: "remote-replication",
  3. cluster: ["manage_ccr"],
  4. remote_indices: [
  5. {
  6. clusters: ["my_remote_cluster"],
  7. names: ["leader-index"],
  8. privileges: ["cross_cluster_replication"],
  9. },
  10. ],
  11. });
  12. console.log(response);

コンソール

  1. POST /_security/role/remote-replication
  2. {
  3. "cluster": [
  4. "manage_ccr"
  5. ],
  6. "remote_indices": [
  7. {
  8. "clusters": [ "my_remote_cluster" ],
  9. "names": [
  10. "leader-index"
  11. ],
  12. "privileges": [
  13. "cross_cluster_replication"
  14. ]
  15. }
  16. ]
  17. }

ローカルremote-replicationロールを作成した後、ユーザーの作成または更新 APIを使用して、ローカルクラスターにユーザーを作成し、remote-replicationロールを割り当てます。たとえば、次のリクエストは、remote-replicationロールをcross-cluster-userという名前のユーザーに割り当てます:

Python

  1. resp = client.security.put_user(
  2. username="cross-cluster-user",
  3. password="l0ng-r4nd0m-p@ssw0rd",
  4. roles=[
  5. "remote-replication"
  6. ],
  7. )
  8. print(resp)

Js

  1. const response = await client.security.putUser({
  2. username: "cross-cluster-user",
  3. password: "l0ng-r4nd0m-p@ssw0rd",
  4. roles: ["remote-replication"],
  5. });
  6. console.log(response);

コンソール

  1. POST /_security/user/cross-cluster-user
  2. {
  3. "password" : "l0ng-r4nd0m-p@ssw0rd",
  4. "roles" : [ "remote-replication" ]
  5. }

このユーザーはローカルクラスターにのみ作成する必要があることに注意してください。

クロスクラスター検索のための権限を構成する

リモートクラスターがmy_remote_clusterという名前で接続されていると仮定すると、次のリクエストは、ローカルクラスターにremote-searchロールを作成し、リモートtarget-indexインデックスを検索することを許可します:

Python

  1. resp = client.security.put_role(
  2. name="remote-search",
  3. remote_indices=[
  4. {
  5. "clusters": [
  6. "my_remote_cluster"
  7. ],
  8. "names": [
  9. "target-index"
  10. ],
  11. "privileges": [
  12. "read",
  13. "read_cross_cluster",
  14. "view_index_metadata"
  15. ]
  16. }
  17. ],
  18. )
  19. print(resp)

Js

  1. const response = await client.security.putRole({
  2. name: "remote-search",
  3. remote_indices: [
  4. {
  5. clusters: ["my_remote_cluster"],
  6. names: ["target-index"],
  7. privileges: ["read", "read_cross_cluster", "view_index_metadata"],
  8. },
  9. ],
  10. });
  11. console.log(response);

コンソール

  1. POST /_security/role/remote-search
  2. {
  3. "remote_indices": [
  4. {
  5. "clusters": [ "my_remote_cluster" ],
  6. "names": [
  7. "target-index"
  8. ],
  9. "privileges": [
  10. "read",
  11. "read_cross_cluster",
  12. "view_index_metadata"
  13. ]
  14. }
  15. ]
  16. }

remote-searchロールを作成した後、ユーザーの作成または更新 APIを使用して、ローカルクラスターにユーザーを作成し、remote-searchロールを割り当てます。たとえば、次のリクエストは、remote-searchロールをcross-search-userという名前のユーザーに割り当てます:

Python

  1. resp = client.security.put_user(
  2. username="cross-search-user",
  3. password="l0ng-r4nd0m-p@ssw0rd",
  4. roles=[
  5. "remote-search"
  6. ],
  7. )
  8. print(resp)

Js

  1. const response = await client.security.putUser({
  2. username: "cross-search-user",
  3. password: "l0ng-r4nd0m-p@ssw0rd",
  4. roles: ["remote-search"],
  5. });
  6. console.log(response);

コンソール

  1. POST /_security/user/cross-search-user
  2. {
  3. "password" : "l0ng-r4nd0m-p@ssw0rd",
  4. "roles" : [ "remote-search" ]
  5. }

このユーザーはローカルクラスターにのみ作成する必要があることに注意してください。