使用自行生成的证书从nodejs连接到elasticsearch时“无法验证第一个证书”

mat*_*eus 1 ssl node.js express elasticsearch docker

当我使用 生成的证书时,如何连接到我的 elasticsearch 集群(TLS 安全)elasticsearch-certutil

根据 ES 文档,这段代码应该可以做到这一点:

const client = new Client({
  node: config.elastic.node,
  auth: {
    username: "elastic",
    password: config.elastic.password
  },
  tls: {
    ca: fs.readFileSync( "./share/es/certs/ca.crt" ),
    rejectUnauthorized: false
  }
})
Run Code Online (Sandbox Code Playgroud)

不幸的是,这给了我这个著名的错误:

ConnectionError: unable to verify the first certificate
Run Code Online (Sandbox Code Playgroud)

我已经通过 docker-compose 设置了 ES。总结一下,我做了以下事情:

  1. elasticsearch-certutil使用 using命令通过以下方式生成证书certbin/elasticsearch-certutil cert --silent --pem --in config/instances.yml -out /certs/bundle.zipinstances.yml包含我的所有节点以及 kibana。bundle.zip包含所有证书和密钥以及 CA 的证书。

  2. 配置我的节点,docker-compose.yml以便它们可以读取生成的证书。例如,

       ...
       - xpack.security.http.ssl.key=${ES_CERTS_DIR}/es01/es01.key
       - xpack.security.http.ssl.certificate_authorities=${ES_CERTS_DIR}/ca/ca.crt
       - xpack.security.http.ssl.certificate=${ES_CERTS_DIR}/es01/es01.crt
       - xpack.security.transport.ssl.certificate_authorities=${ES_CERTS_DIR}/ca/ca.crt
       - xpack.security.transport.ssl.certificate=${ES_CERTS_DIR}/es01/es01.crt
       - xpack.security.transport.ssl.key=${ES_CERTS_DIR}/es01/es01.key
       ...
    
    Run Code Online (Sandbox Code Playgroud)
  3. 使用此命令验证与curl的连接

    $ curl -X GET "https://elastic:$ES_PASSWORD@my-cluster-doomain.com:9201" -H "Content-type: application/json" --cacert $CACERT --key $KEY --cert $CERT
    
    Run Code Online (Sandbox Code Playgroud)

    其中$CACERT$KEY$CERT指向 CA 证书,即我要连接的节点的密钥和证书。这导致:

    {
      "name" : "es01",
      "cluster_name" : "es-docker-cluster",
      ...
      "tagline" : "You Know, for Search"
    }
    
    Run Code Online (Sandbox Code Playgroud)

    我想这很好。

但为什么我无法从我的expressjs应用程序连接到我的集群?我读到了一些关于创建证书链并让 ES 知道这一点的内容。但是,我这有必要吗?我的意思是,我可以通过连接curl并使用elasticdump. 当我通过浏览器访问集群时出现错误https://my-cluster-domain.com:9201。浏览器警告我,虽然证书有效,但连接不安全。

有任何想法吗?谢谢。

mat*_*eus 5

好吧,经过大量谷歌搜索后发现,将 CA 文件添加到 ES 客户端配置是不够的,如我上面的示例配置所示。

  ...
  tls: {
    ca: fs.readFileSync( "./share/es/certs/ca.crt" ),
    rejectUnauthorized: false  # don't do this in production
  }
Run Code Online (Sandbox Code Playgroud)

相反,在配置与 ES 的连接之前,必须向 Node 进程本身宣布 CA 证书。您可以按照本文这篇文章(解决方案 2a ​​,使用NODE_EXTRA_CA_CERTS 环境变量 )中的描述执行此操作。我现在像这样开始我的过程,结果如下:

$ NODE_EXTRA_CA_CERTS="./share/es/certs/ca.crt" NODE_ENV=prod ...
Run Code Online (Sandbox Code Playgroud)

最后一点,如果您拥有当前版本的 Elasticsearch 客户端,则不必rejectUnauthorized: false某些解决方法那样进行设置。

我的最终配置如下所示:

  const client = new Client({
    node: config.elastic.node,
    auth: {
      username: "elastic",
      password: config.elastic.password
    }
  })
Run Code Online (Sandbox Code Playgroud)