将远程集群从证书认证迁移到 API 密钥认证

编辑

将远程集群从证书认证迁移到 API 密钥认证

编辑

与基于 TLS 证书的安全模型相比,远程集群基于 API 密钥的安全模型为管理员提供了更细粒度的访问控制。因此,您可能需要将基于证书的安全模型迁移到基于 API 密钥的模型。

虽然可以通过定义新的远程集群连接(使用新的别名)来迁移,但这存在一些缺点。

  • 对于跨集群复制,无法更改现有任务的领导者集群别名。因此,对于新的远程集群,需要从头开始重新创建 follower 索引。
  • 对于跨集群搜索、转换和异常检测作业,允许更新远程集群别名。但是,如果作业是使用通配符创建的,例如 *:source_indexsuperuser,则添加新的远程集群会导致作业的工作量增加一倍,并可能由于重复而导致结果偏差。

由于这些原因,您可能更倾向于按照以下步骤就地迁移远程集群。

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

先决条件

编辑
  • 本地和远程集群的节点必须使用 8.10 或更高版本。
  • 本地和远程集群必须具有相应的许可证。有关更多信息,请参考 https://elastic.ac.cn/subscriptions

重新配置远程集群并生成跨集群 API 密钥

编辑

在远程集群上

  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. 使用所需的 远程索引权限远程集群权限 增强本地集群用户使用的任何角色,以进行跨集群复制和跨集群搜索。请参考 配置角色和用户。注意:

    • 您只需要为用于跨集群操作的现有角色分配额外的 remote_indicesremote_cluster 权限。您应该能够从远程集群上的原始角色复制这些权限,在这些角色中,它们是在基于认证的安全模型下定义的。
    • 本地集群上的角色不能超过跨集群 API 密钥授予的 access 权限。任何额外的本地权限都将被跨集群 API 密钥的权限所压制。
    • 如果跨集群复制或跨集群搜索任务已使用 superuser 角色配置,则无需更新。superuser 角色会自动更新以允许访问所有远程索引。
    • 使用命名角色的常规用户运行的任务会立即使用新的权限进行更新。任务在下一次运行时会加载新的定义。
    • 您需要重新启动使用 API 密钥运行的任务(在后面的步骤中完成)。
  2. 如果您已动态配置远程集群(通过集群设置 API)

    1. 检索当前远程集群配置,并将其存储在安全位置。如果您需要 回滚,您可能需要它。使用集群设置 API

      resp = client.cluster.get_settings(
          filter_path="persistent.cluster.remote",
      )
      print(resp)
      response = client.cluster.get_settings(
        filter_path: 'persistent.cluster.remote'
      )
      puts response
      const response = await client.cluster.getSettings({
        filter_path: "persistent.cluster.remote",
      });
      console.log(response);
      GET /_cluster/settings?filter_path=persistent.cluster.remote
    2. 通过将远程集群设置设置为 null 来删除现有的远程集群定义。
  3. 如果您已静态配置远程集群(通过 elasticsearch.yml),请复制 elasticsearch.yml 中的 cluster.remote 设置,并将它们存储在安全位置。如果您需要 回滚,您可能需要它们。
  4. 在本地集群的每个节点上

    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 密钥。

  5. 如果您已动态配置远程集群(通过集群设置 API)

    1. 重新启动本地集群以加载对密钥库和设置的更改。
    2. 重新添加远程集群。使用相同的远程集群别名,并将传输端口更改为远程集群端口。例如:

      resp = client.cluster.put_settings(
          persistent={
              "cluster": {
                  "remote": {
                      "my_remote": {
                          "mode": "proxy",
                          "proxy_address": "my.remote.cluster.com:9443"
                      }
                  }
              }
          },
      )
      print(resp)
      response = client.cluster.put_settings(
        body: {
          persistent: {
            cluster: {
              remote: {
                my_remote: {
                  mode: 'proxy',
                  proxy_address: 'my.remote.cluster.com:9443'
                }
              }
            }
          }
        }
      )
      puts response
      const response = await client.cluster.putSettings({
        persistent: {
          cluster: {
            remote: {
              my_remote: {
                mode: "proxy",
                proxy_address: "my.remote.cluster.com:9443",
              },
            },
          },
        },
      });
      console.log(response);
      PUT /_cluster/settings
      {
        "persistent" : {
          "cluster" : {
            "remote" : {
              "my_remote" : { 
                "mode": "proxy",
                "proxy_address": "my.remote.cluster.com:9443" 
              }
            }
          }
        }
      }

      远程集群别名。使用迁移前使用的相同别名。

      远程集群地址和远程集群端口(默认为 9443)。

  6. 如果您已静态配置远程集群(通过 elasticsearch.yml

    1. 更新本地集群每个节点上的 elasticsearch.yml 中的 cluster.remote 设置。将端口更改为远程集群端口(默认为 9443)。
    2. 重新启动本地集群以加载对密钥库和设置的更改。
  7. 使用 远程集群信息 API 验证本地集群是否已成功连接到远程集群。

    resp = client.cluster.remote_info()
    print(resp)
    response = client.cluster.remote_info
    puts response
    const response = await client.cluster.remoteInfo();
    console.log(response);
    GET /_remote/info

    API 响应应指示本地集群已连接到远程集群。

    {
      "my_remote": {
        "connected": true, 
        "mode": "proxy",
        "proxy_address": "my.remote.cluster.com:9443",
        "server_name": "",
        "num_proxy_sockets_connected": 0,
        "max_proxy_socket_connections": 18,
        "initial_connect_timeout": "30s",
        "skip_unavailable": false,
        "cluster_credentials": "::es_redacted::" 
      }
    }

    远程集群已连接。

    如果存在,则表示远程集群已使用 API 密钥认证连接。

恢复跨集群操作

编辑

恢复之前停止的任何持久性任务。任务应由与迁移前创建任务相同的用户或API密钥重新启动。确保此用户或API密钥的角色已更新为具有必需的remote_indicesremote_cluster权限。对于用户,任务在启动时会捕获调用方的凭据,并在该用户的安全上下文中运行。对于API密钥,重新启动任务会使用更新的API密钥更新任务。

禁用基于证书的身份验证和授权

编辑

只有在本地集群上迁移已成功证明的情况下,才执行此步骤。如果迁移不成功,请找出问题所在并尝试修复回滚

接下来,禁用基于证书的连接。可选地,您还可以撤销授权。

  1. 没有特定的设置可以启用或禁用基于证书的跨集群连接,因为它与集群内节点到节点的通信共享相同的传输协议。

    远程集群管理员阻止现有本地集群连接的一种方法是更改TLS信任。确切步骤因集群的配置方式而异。一个通用的解决方案是重新创建远程传输接口使用的CA和证书/密钥,以便任何现有的证书/密钥(本地或分布式)不再受信任。

    另一个解决方案是将IP过滤器应用于传输接口,阻止来自集群外部的流量。

  2. 可选地,删除远程集群上仅用于跨集群操作的任何角色。在基于API密钥的安全模型下不再使用这些角色。

回滚

编辑

如果需要回滚,请在本地集群上执行以下步骤

  1. 停止任何引用远程集群的持久性任务。
  2. 通过将远程集群设置设置为null来删除远程集群定义。
  3. 从迁移期间更新的任何角色中删除remote_indicesremote_cluster权限。
  4. 在每个节点上,从elasticsearch.yml中删除remote_cluster_client.ssl.*设置。
  5. 重新启动本地集群以应用对密钥库和elasticsearch.yml的更改。
  6. 在本地集群上应用原始远程集群设置。如果远程集群连接已静态配置(使用elasticsearch.yml文件),请重新启动集群。
  7. 使用远程集群信息API验证本地集群是否已连接到远程集群。响应应具有"connected": true并且不具有"cluster_credentials": "::es_redacted::"
  8. 重新启动之前停止的任何持久性任务。