使用 API 密钥身份验证添加远程集群

编辑

使用 API 密钥身份验证添加远程集群编辑

API 密钥身份验证允许本地集群通过跨集群 API 密钥向远程集群进行身份验证。API 密钥需要由远程集群的管理员创建。本地集群配置为在每次向远程集群发出请求时提供此 API 密钥。远程集群会验证 API 密钥并根据 API 密钥的权限授予访问权限。

来自本地集群的所有跨集群请求都受 API 密钥权限的约束,而与与请求关联的本地用户无关。例如,如果 API 密钥仅允许对远程集群上的 my-index 进行读取访问,则即使来自本地集群的超级用户也会受到此约束的限制。此机制使远程集群的管理员可以完全控制谁可以使用跨集群搜索和/或跨集群复制访问哪些数据。远程集群的管理员可以确信,除了明确分配给 API 密钥的访问权限之外,任何访问都是不可能的。

在本地集群端,并非每个本地用户都需要访问 API 密钥允许的每条数据。本地集群的管理员可以进一步配置对本地用户的其他权限约束,以便每个用户只能访问必要的远程数据。请注意,只能进一步减少 API 密钥为各个本地用户允许的权限。不可能增加权限以超出 API 密钥允许的范围。

在此模型中,跨集群操作使用专用服务器端口(远程集群接口)进行集群之间的通信。远程集群必须启用此端口才能使本地集群连接。为此端口配置传输层安全性 (TLS) 以最大程度地提高安全性(如与远程集群建立信任中所述)。

本地集群必须信任远程集群接口上的远程集群。这意味着本地集群信任远程集群的证书颁发机构 (CA),该机构签署了远程集群接口使用的服务器证书。建立连接时,参与跨集群通信的所有来自本地集群的节点都会根据 TLS 信任配置验证来自另一侧节点的证书。

要使用 API 密钥身份验证添加远程集群

如果遇到任何问题,请参阅故障排除

先决条件编辑

  • 需要在两个集群的每个节点上启用 Elasticsearch 安全功能。默认情况下启用安全性。如果已禁用,请在 elasticsearch.yml 中将 xpack.security.enabled 设置为 true。请参阅常规安全设置
  • 本地集群和远程集群的节点必须为 8.10 或更高版本。
  • 本地集群和远程集群必须具有适当的许可证。有关更多信息,请参阅https://elastic.ac.cn/subscriptions

与远程集群建立信任编辑

如果远程集群是 Elasticsearch Service 部署的一部分,则默认情况下它具有有效的证书。因此,您可以跳过这些说明中与证书相关的步骤。

在远程集群上编辑

  1. 在远程集群的每个节点上启用远程集群服务器。在 elasticsearch.yml

    1. remote_cluster_server.enabled设置为 true
    2. 配置远程集群服务器流量的绑定和发布地址,例如使用remote_cluster.host。如果不配置地址,远程集群流量可能会绑定到本地接口,并且在其他机器上运行的远程集群将无法连接。
    3. (可选)使用remote_cluster.port配置远程服务器端口(默认为 9443)。
  2. 接下来,生成证书颁发机构 (CA) 和服务器证书/密钥对。在远程集群的其中一个节点上,从安装 Elasticsearch 的目录

    1. 创建 CA(如果您还没有 CA)

      ./bin/elasticsearch-certutil ca --pem --out=cross-cluster-ca.zip --pass CA_PASSWORD

      CA_PASSWORD 替换为您要用于 CA 的密码。如果您没有部署到生产环境,则可以删除 --pass 选项及其参数。

    2. 解压缩生成的 cross-cluster-ca.zip 文件。此压缩文件包含以下内容

      /ca
      |_ ca.crt
      |_ ca.key
    3. 为远程集群中的节点生成证书和私钥对

      ./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 地址指定多次。
    4. 如果远程集群有多个节点,您可以

      • 为所有节点创建一个通配符证书;
      • 或者,使用静默模式为每个节点手动或批量创建单独的证书。
  3. 在远程集群的每个节点上

    1. 将上一步中的 cross-cluster.p12 文件复制到 config 目录。如果您没有创建通配符证书,请确保复制了正确的节点特定 p12 文件。
    2. 将以下配置添加到 elasticsearch.yml

      xpack.security.remote_cluster_server.ssl.enabled: true
      xpack.security.remote_cluster_server.ssl.keystore.path: cross-cluster.p12
    3. 将 SSL 密钥库密码添加到 Elasticsearch 密钥库

      ./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. 将之前在远程集群上生成的 ca.crt 文件复制到 config 目录,并将文件重命名为 remote-cluster-ca.crt
    2. 将以下配置添加到 elasticsearch.yml

      xpack.security.remote_cluster_client.ssl.enabled: true
      xpack.security.remote_cluster_client.ssl.certificate_authorities: [ "remote-cluster-ca.crt" ]
    3. 将之前在远程集群上创建的跨集群 API 密钥添加到密钥库

      ./bin/elasticsearch-keystore add cluster.remote.ALIAS.credentials

      ALIAS 替换为您稍后将用于创建远程集群条目的相同名称。出现提示时,输入之前在远程集群上创建的编码后的跨集群 API 密钥。

  2. 重新启动本地集群以加载对密钥库和设置的更改。

注意: 如果您仅配置跨集群 API 密钥,则可以调用节点重新加载安全设置API,而不是重新启动集群。在 elasticsearch.yml 中配置 remote_cluster_client 设置仍然需要重新启动。

连接到远程集群编辑

您必须具有 manage 集群权限才能连接远程集群。

本地集群使用远程集群接口与远程集群建立通信。本地集群中的协调节点与远程集群中的特定节点建立长期 TCP 连接。Elasticsearch 要求这些连接保持打开状态,即使连接长时间处于空闲状态也是如此。

要从 Kibana 中的堆栈管理添加远程集群

  1. 从侧边导航中选择远程集群
  2. 输入远程集群的名称(*集群别名*)。
  3. 指定 Elasticsearch 端点 URL,或远程集群的 IP 地址或主机名,后跟远程集群端口(默认为 9443)。例如,cluster.es.eastus2.staging.azure.foundit.no:9443192.168.1.1:9443

或者,使用 集群更新设置 API 添加远程集群。您还可以使用此 API 为本地集群中的每个节点动态配置远程集群。要在本地集群中的各个节点上配置远程集群,请在每个节点的 elasticsearch.yml 中定义静态设置。

以下请求添加了一个别名为 cluster_one 的远程集群。此集群别名是表示到远程集群的连接的唯一标识符,用于区分本地索引和远程索引。

PUT /_cluster/settings
{
  "persistent" : {
    "cluster" : {
      "remote" : {
        "cluster_one" : {    
          "seeds" : [
            "127.0.0.1:9443" 
          ]
        }
      }
    }
  }
}

此远程集群的集群别名为 cluster_one

指定远程集群中种子节点的主机名和远程集群端口。

您可以使用 远程集群信息 API 验证本地集群是否已成功连接到远程集群

resp = client.cluster.remote_info()
print(resp)
response = client.cluster.remote_info
puts response
GET /_remote/info

API 响应表明本地集群已连接到集群别名为 cluster_one 的远程集群

{
  "cluster_one" : {
    "seeds" : [
      "127.0.0.1:9443"
    ],
    "connected" : true,
    "num_nodes_connected" : 1,  
    "max_connections_per_cluster" : 3,
    "initial_connect_timeout" : "30s",
    "skip_unavailable" : false, 
    "cluster_credentials": "::es_redacted::", 
    "mode" : "sniff"
  }
}

本地集群连接到的远程集群中的节点数。

指示如果通过跨集群搜索进行搜索但没有可用节点,是否跳过远程集群。

如果存在,则表示远程集群已使用 API 密钥身份验证进行连接。

动态配置远程集群编辑

使用 集群更新设置 API 在集群中的每个节点上动态配置远程设置。以下请求添加了三个远程集群:cluster_onecluster_twocluster_three

seeds 参数指定远程集群中种子节点的主机名和 远程集群端口(默认值为 9443)。

mode 参数确定配置的连接模式,默认为 sniff。由于 cluster_one 未指定 mode,因此它使用默认值。cluster_twocluster_three 都明确使用了不同的模式。

PUT _cluster/settings
{
  "persistent": {
    "cluster": {
      "remote": {
        "cluster_one": {
          "seeds": [
            "127.0.0.1:9443"
          ]
        },
        "cluster_two": {
          "mode": "sniff",
          "seeds": [
            "127.0.0.1:9444"
          ],
          "transport.compress": true,
          "skip_unavailable": true
        },
        "cluster_three": {
          "mode": "proxy",
          "proxy_address": "127.0.0.1:9445"
        }
      }
    }
  }
}

您可以在初始配置后动态更新远程集群的设置。以下请求更新 cluster_two 的压缩设置,以及 cluster_three 的压缩和 ping 计划设置。

当压缩或 ping 计划设置更改时,所有现有节点连接都必须关闭并重新打开,这可能会导致正在进行的请求失败。

response = client.cluster.put_settings(
  body: {
    persistent: {
      cluster: {
        remote: {
          cluster_two: {
            'transport.compress' => false
          },
          cluster_three: {
            'transport.compress' => true,
            'transport.ping_schedule' => '60s'
          }
        }
      }
    }
  }
)
puts response
PUT _cluster/settings
{
  "persistent": {
    "cluster": {
      "remote": {
        "cluster_two": {
          "transport.compress": false
        },
        "cluster_three": {
          "transport.compress": true,
          "transport.ping_schedule": "60s"
        }
      }
    }
  }
}

您可以通过为每个远程集群设置传递 null 值来从集群设置中删除远程集群。以下请求从集群设置中删除 cluster_two,而保留 cluster_onecluster_three 不变

response = client.cluster.put_settings(
  body: {
    persistent: {
      cluster: {
        remote: {
          cluster_two: {
            mode: nil,
            seeds: nil,
            skip_unavailable: nil,
            'transport.compress' => nil
          }
        }
      }
    }
  }
)
puts response
PUT _cluster/settings
{
  "persistent": {
    "cluster": {
      "remote": {
        "cluster_two": {
          "mode": null,
          "seeds": null,
          "skip_unavailable": null,
          "transport.compress": null
        }
      }
    }
  }
}

静态配置远程集群编辑

如果您在 elasticsearch.yml 中指定设置,则只有具有这些设置的节点才能连接到远程集群并处理远程集群请求。

使用 集群更新设置 API 指定的远程集群设置优先于您在 elasticsearch.yml 中为各个节点指定的设置。

在以下示例中,cluster_onecluster_twocluster_three 是表示到每个集群的连接的任意集群别名。这些名称随后用于区分本地索引和远程索引。

cluster:
    remote:
        cluster_one:
            seeds: 127.0.0.1:9443
        cluster_two:
            mode: sniff
            seeds: 127.0.0.1:9444
            transport.compress: true      
            skip_unavailable: true        
        cluster_three:
            mode: proxy
            proxy_address: 127.0.0.1:9445 

已为对 cluster_two 的请求明确启用了压缩。

断开的远程集群对于 cluster_two 是可选的。

用于连接到 cluster_three 的代理端点的地址。

配置角色和用户编辑

要将远程集群用于跨集群复制或跨集群搜索,您需要在本地集群上创建具有 远程索引权限 的用户角色。

您可以通过从侧边导航中选择 安全 > 角色 来管理 Kibana 中 Stack Management 的用户和角色。您还可以使用 角色管理 API 动态添加、更新、删除和检索角色。

以下示例使用 创建或更新角色 API。您必须至少具有 manage_security 集群权限才能使用此 API。

本地集群用于连接远程集群的跨集群 API 密钥必须具有足够的权限,以涵盖各个用户所需的所有远程索引权限。

配置跨集群复制的权限编辑

假设远程集群连接的名称为 my_remote_cluster,则以下请求在本地集群上创建一个名为 remote-replication 的角色,该角色允许复制远程 leader-index 索引

POST /_security/role/remote-replication
{
  "cluster": [
    "manage_ccr"
  ],
  "remote_indices": [
    {
      "clusters": [ "my_remote_cluster" ],
      "names": [
        "leader-index"
      ],
      "privileges": [
        "cross_cluster_replication"
      ]
    }
  ]
}

创建本地 remote-replication 角色后,使用 创建或更新用户 API 在本地集群上创建用户并分配 remote-replication 角色。例如,以下请求将 remote-replication 角色分配给名为 cross-cluster-user 的用户

POST /_security/user/cross-cluster-user
{
  "password" : "l0ng-r4nd0m-p@ssw0rd",
  "roles" : [ "remote-replication" ]
}

请注意,您只需要在本地集群上创建此用户。

配置跨集群搜索的权限编辑

假设远程集群连接的名称为 my_remote_cluster,则以下请求在本地集群上创建一个 remote-search 角色,该角色允许搜索远程 target-index 索引

POST /_security/role/remote-search
{
  "remote_indices": [
    {
      "clusters": [ "my_remote_cluster" ],
      "names": [
        "target-index"
      ],
      "privileges": [
        "read",
        "read_cross_cluster",
        "view_index_metadata"
      ]
    }
  ]
}

创建 remote-search 角色后,使用 创建或更新用户 API 在本地集群上创建用户并分配 remote-search 角色。例如,以下请求将 remote-search 角色分配给名为 cross-search-user 的用户

POST /_security/user/cross-search-user
{
  "password" : "l0ng-r4nd0m-p@ssw0rd",
  "roles" : [ "remote-search" ]
}

请注意,您只需要在本地集群上创建此用户。