站长素材网上的Elasticsearch service已经开始为我们提供基于HTTPS协议访问的Elasticsearch集群了;Elastic Cloud的Elasticsearch服务则一直都是默认使用的HTTPS安全协议。而我们自建的Elasticsearch集群,从8.0版本开始,也默认地简化了安全功能,为用户自动配置:用户认证、基于角色的访问控制进行用户授权、使用 TLS 加密的节点到节点通信、使用 HTTPS 与 Elasticsearch API 进行加密通信。
为什么我们需要进行如此复杂的安全配置,并启用SSL/TLS对Elasticsearch的服务进行认证与通信加密?
因为这将帮助我们获得:
总的来说,将Elasticsearch集群配置为使用HTTPS和TLS可以提高数据的保护和安全性,对于任何要求数据保密性的场合,都是一个重要的安全措施。
虽然我们明白安全配置的重要性,但是要知其然,知其所以然却并不是一件简单的事情,特别是涉及到这些安全配置相关的各种CA证书、证书、公钥、秘钥、数字签名、证书指纹(finger print)登,要搞清楚他们之间的关系,通常会让我们头晕脑胀。
本文,我们将尝试为大家解析整个Elasticsearch配置加密通信的各种概念,以让我们清楚,如何才能够配置合适的安全配置来配合我们生产环境的安全需求。
HTTPS(Hypertext Transfer Protocol Secure)是一种安全的HTTP协议,通过使用SSL(Secure Sockets Layer)或TLS(Transport Layer Security)协议对数据进行加密和认证,以保护网络通信的安全性。
以下是HTTPS中的一些重要概念:
而在配置Elasticsearch集群的安全通信时,我们都会用到上面提到的这些元素,用于验证服务器和客户端的验证,以及通信的加密和完整。
我们在配置Elasticsearch集群的安全通信时,需要分别配置集群间节点的TLS通信,以及客户端与集群的HTTPS通信。
现在,假设我们有一个多节点的集群,有Kibana和Logstash需要和集群进行通信。因此,会有类似的角色需要去配置:
[root@node1 cert_blog]# vi ~/tmp/cert_blog/instance.yml
# add the instance information to yml file
instances:
- name: 'node1'
dns: [ 'node1.elastic.test.com' ]
- name: "node2"
dns: [ 'node2.elastic.test.com' ]
- name: 'my-kibana'
dns: [ 'kibana.local' ]
- name: 'logstash'
dns: [ 'logstash.local' ]
然后使用配套的elasticsearch-certutil
工具来生成对应的CA证书和服务器证书。
[root@node1 elasticsearch]# bin/elasticsearch-certutil cert --keep-ca-key --pem --in ~/tmp/cert_blog/instance.yml --out ~/tmp/cert_blog/certs.zip
解压certs.zip后,会有如下的文件目录与文件:
├── ca
│ ├── ca.crt
│ └── ca.key
├── ca.zip
├── certs2.zip
├── node1
│ ├── node1.crt
│ └── node1.key
├── node2
│ ├── node2.crt
│ └── node2.key
├── my-kibana
│ ├── my-kibana.crt
│ └── my-kibana.key
├── logstash
│ ├── logstash.crt
│ └── logstash.key
在这其中,ca.crt
就是Elasticsearch自签名的CA证书,而 es01.crt
、 es02.crt
、my-kibana.crt
、logstash.crt
等,都是用这个ca.crt
对应的ca.key
签发的服务器证书。
具体一点,ca.key
和ca.crt
是用于生成和签发服务器证书的CA(Certificate Authority,证书授权机构)的私钥和公钥。CA是用来签发服务器证书的可信任实体,用于验证证书持有者身份并对证书进行数字签名,以确保证书在传输过程中的完整性和真实性。
ca.key
是CA的私钥,用于对服务器证书进行数字签名。通常应该仅由CA拥有人访问,因为它可以用于签发任何证书,并将其认为是受信任的证书。因此,如果私钥被泄露或丢失,就会使得签发的所有证书都不能被信任。也就是说,上面的服务器证书(比如,node1.crt
)内的数字签名,就是用ca.key
来加密签发的。
ca.crt
是CA的公钥证书,用于验证服务器证书的真实性和完整性。证书中包含了CA的公钥,以及签名信息。在验证服务器证书时,接收方可以使用ca.crt
来验证证书的签名是否可信。如果可信,就可以确认证书的真实性和完整性。比如,客户端在链接node1
时,node1的服务器证书node1.crt
内的数字签名,将使用ca.crt
中的CA的公钥来进行解密,如果解密出来的值是该服务器证书(node1.crt
)的哈希值,则表明服务器可信。
因此,我们会看到,在Kibana的配置中,我们会需要配置elasticsearch.ssl.certificateAuthorities
,因为我们需要它来验证我们链接的es就是我们期望链接的es。
elasticsearch.username: "kibana"
elasticsearch.password: "<kibana_password>"
elasticsearch.ssl.certificateAuthorities: [ "/etc/kibana/config/certs/ca.crt" ]
上面讲的比较粗浅,我们再来深入说明一下CA证书验证ES节点身份和证书(服务器证书)真实性的基本流程:
ca.crt
和ca.key
来生成node1.crt
node1.elastic.test.com
)、有效期限以及数字签名等信息。服务器证书的数字签名是由CA机构使用私钥对服务器证书的内容进行加密生成的,这个数字签名是证书真实性的关键。数字签名是通过公钥和私钥生成的。CA机构会使用自己的私钥为服务器证书的数字签名进行签名。因此,在验证服务器证书时,需要先使用CA机构的公钥对数字签名进行解密,得到服务器证书的哈希值,然后再将服务器证书的哈希值与服务器证书本身进行比对,如果一致,则表明该服务器证书是由该CA机构签发的,可以被信任。如果不一致,则说明该服务器证书可能被篡改或伪造,不应该被信任。这个过程可以通过证书链(certificate chain)的方式完成,即通过验证服务器证书的数字签名是否能够成功地与CA机构的证书相匹配来确认服务器证书的可信度。
上面,我们提到了服务器证书中包含了公钥、网站的名称、有效期限以及数字签名等信息。具体来说,服务器证书包含了以下几个主要部分:
比如,es01的服务器证书的内容为:
base64解码后,内容为:
上面,我们提到了客户端通过持有ES的CA证书,然后以ES的CA证书来验证节点的服务器证书,以确保我们连接的节点确实是该集群的节点。起到一个认证的作用。
但HTTPS/TLS除了身份验证的功能外,还有通信加密的功能,这是如何实现的呢?
node1.crt
中的公钥)对一个称为"Pre-master secret"的随机数进行加密并发送给服务器。node1.key
)对其进行解密,得到"Pre-master secret"。接下来,服务器和客户端都使用这个"Pre-master secret"生成一个称为"Master secret"的密钥,该密钥将用于后续的通信加密。在这个过程中,服务器证书起到了验证服务器身份和提供公钥的作用,而私钥则用于解密客户端发送的数据。同时,"Pre-master secret"和"Master secret"这两个密钥也起到了加密和解密通信数据的作用。这些步骤共同确保了HTTPS连接的安全性和私密性。
在上面的配置中,我们看到node1和node2都有自己的服务器证书和私钥,这是因为,ES的集群由节点组成,节点和节点之间的transport通信,也需要基于TLS协议。在使用Elasticsearch的TLS层时,每个节点都需要拥有自己的证书和秘钥,以确保通信的安全性和私密性。
每个节点都有自己的IP地址或者主机名,需要使用相应的证书和秘钥来与其他节点或客户端(transport client)进行通信。如果所有节点共用同一份证书和秘钥,那么这个证书和秘钥的私密性就会被破坏,从而使得通信不再安全。
因此,在使用Elasticsearch的TLS层时,建议为每个节点都生成独立的证书和秘钥,以保障通信的安全性和私密性。可以使用相同的CA证书来生成节点证书,以确保证书的可信性和一致性。同时,也可以使用自动化工具来简化证书和秘钥的管理和部署过程,例如使用Elasticsearch自带的证书自动化工具或者第三方的证书管理工具。
上面,我们提到Elasticsearch提供配套的elasticsearch-certutil
工具,来生成自签名的CA证书,并用该证书来实现服务器证书的签发和管理。
具体来说,以下是使用自签名的CA证书颁发其他证书的步骤:
elasticsearch-certutil
创建自签名的CA证书。在创建证书时,需要填写一些基本信息,例如证书的名称、有效期限等等。这些信息都由elasticsearch-certutil
帮我们自动生成了。xpack.security.enabled: true
xpack.security.http.ssl.enabled: true
xpack.security.transport.ssl.enabled: true
xpack.security.http.ssl.key: certs/node1.key
xpack.security.http.ssl.certificate: certs/node1.crt
-> xpack.security.http.ssl.certificate_authorities: certs/ca.crt
xpack.security.transport.ssl.key: certs/node1.key
xpack.security.transport.ssl.certificate: certs/node1.crt
-> xpack.security.transport.ssl.certificate_authorities: certs/ca.crt
elasticsearch-certutil
创建一个证书请求,该请求包含服务器的公钥和一些基本信息,例如服务器的名称、域名等等。请求通常是一个包含公钥和证书信息的文件。
比如,./bin/elasticsearch-certutil cert \
--name node1 \
--ca-cert /path/to/ca/ca.crt \
--ca-key /path/to/ca/ca.key \
--dns your.host.name.here \
--ip 192.0.2.1 \
--pem
xpack.security.enabled: true
xpack.security.http.ssl.enabled: true
xpack.security.transport.ssl.enabled: true
-> xpack.security.http.ssl.key: certs/node1.key
-> xpack.security.http.ssl.certificate: certs/node1.crt
xpack.security.http.ssl.certificate_authorities: certs/ca.crt
-> xpack.security.transport.ssl.key: certs/node1.key
-> xpack.security.transport.ssl.certificate: certs/node1.crt
xpack.security.transport.ssl.certificate_authorities: certs/ca.crt
需要注意的是,自签名的CA证书在安全性方面可能不如购买的第三方CA证书可靠,因为自签名的CA证书并没有经过第三方机构的验证和认证。因此,在使用自签名的CA证书时,需要确保私钥的安全性,以避免证书被恶意使用或泄漏。
我们看到,无论是beats还是Logstash等工具,在连接ES的时候,为了避免将自签名的CA证书拷贝到所有的采集端上,我们会选择将ssl.verification_mode
参数配置为none
。这意味着,客户端将不执行服务器证书的验证。
这种情况是被允许的,这种方式也被称为不安全的HTTPS连接。但在不校验服务器证书的情况下,客户端可能会受到中间人攻击,导致传输的数据被篡改或窃取。因此,建议客户端始终验证服务器证书的有效性来确保安全通信。
verification_mode 控制服务器证书的验证。有效值为:
# full
验证提供的证书是否由可信机构 (CA) 签名,并验证服务器的主机名(或 IP 地址)是否与证书中标识的名称相匹配。
# strict
验证提供的证书是否由可信机构 (CA) 签名,并验证服务器的主机名(或 IP 地址)是否与证书中标识的名称相匹配。如果 Subject Alternative Name 为空,则返回错误。
# certificate
验证提供的证书是否由可信机构 (CA) 签名,但不执行任何主机名验证。
# none
不执行服务器证书的验证。此模式会禁用 SSL/TLS 的许多安全优势,应仅在谨慎考虑后使用。它主要用作尝试解决 TLS 错误时的临时诊断机制;强烈建议不要在生产环境中使用它。
即使客户端选择不校验服务器证书,HTTPS仍然可以提供加密通信的保护。在这种情况下,加密通信的步骤如下:
Elastic Cloud上使用的证书是由经过浏览器和操作系统信任的公共CA颁发的,因此您可以直接使用浏览器或API工具与Elastic Cloud上的Elasticsearch集群通信,而不需要进行额外的证书验证。这些公共CA包括像DigiCert、GlobalSign、Let's Encrypt等知名的第三方CA机构,他们的根证书已经预装在操作系统和浏览器中。这意味着在与Elastic Cloud上的Elasticsearch进行通信时,您的API工具会验证证书链是否可以追溯到其中一个信任的CA的根证书。
而现在,Elastic Cloud使用的是Let's Encrypt的CA证书。