将远程集群从证书身份验证迁移到 API 密钥身份验证

编辑

将远程集群从证书身份验证迁移到 API 密钥身份验证

编辑

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

虽然可以通过定义新的远程集群连接(使用新的别名)进行迁移,但这有几个缺点

  • 对于跨集群复制,无法更改现有任务的领导者集群别名。因此,对于新的远程集群,需要从头开始重新创建追随者索引。
  • 对于跨集群搜索,转换和异常检测作业允许更新远程集群别名。但是,如果作业是使用通配符创建的,例如 *: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_indices 或 *remote_cluster* 权限。
  4. 在每个节点上,从 elasticsearch.yml 中删除 remote_cluster_client.ssl.* 设置。
  5. 重新启动本地集群以将更改应用到密钥库和 elasticsearch.yml
  6. 在本地集群上,应用原始的远程集群设置。如果远程集群连接是静态配置的(使用 elasticsearch.yml 文件),则重新启动集群。
  7. 使用 远程集群信息 API 来验证本地集群是否已连接到远程集群。响应应具有 "connected": true 且不应具有 "cluster_credentials": "::es_redacted::"
  8. 重新启动您之前停止的任何持久任务。