配置 SSL、TLS 以及 HTTPS 来确保 Elasticsearch、Kibana、Beats 和 Logstash 的安全

运行的是 Elastic Stack 6.7.x/7.0.x 或更早版本? 然后查看博文“如何设置 TLS...”,以获得有关如何在您的版本中确保通信安全的帮助信息。如想使用本篇博文中所讲的免费安全功能,您需要使用 Elastic Stack 6.8/7.1 或更新版本。

从 Elastic Stack 6.8 和 7.1 开始,Elastic 在默认分发包(基础许可证)中发布了一些免费安全功能。 新推出的功能包括:使用 SSL 对网络流量进行加密、创建和管理用户、定义角色来保护索引级和集群级访问权限,以及为 Kibana 提供全面保护。我们在新版本推出后不久便发布了开始使用博文,向大家解释如何在 Elasticsearch 和 Kibana 之间使用 TLS 通信。下面的博文对这一指南进行了扩展,向您讲解如何将 TLS 应用于 Elastic Stack 中的其他组件(包括 Logstash 和 Beats)。本文讨论了如何在组件之间启用 TLS,以及如何加密 HTTP 客户端通信。

请注意,尽管在 HTTP 层启用 TLS 并非硬性要求,但我们强烈建议如此做以实现端到端安全,进而保护数据,尤其是保护用户名/密码信息免遭泄露(这种情况可致使集群不安全)。如希望详细了解 TLS 加密、身份验证、受限脚本或隔离的相关信息,请查看我们的博文通过加密、用户等功能免费确保 Elasticsearch 集群安全性的几点提示

额外补充一点,下方启用的安全功能在 Elasticsearch Service on Elastic Cloud 上为标配。所以如果您在 Elasticsearch Service 上进行操作,可直接跳转至第 5 步

确保 Elastic Stack 安全性的步骤

  1. 准备工作
  2. 在 node1 上创建 SSL 证书并为 Elasticsearch 启用 TLS
  3. 在 node1 上为 Kibana 启用 TLS
  4. 在 node2 上为 Elasticsearch 启用 TLS
  5. 在 node1 上准备 Logstash 用户
  6. 在 node1 上为 Logstash 启用 TLS
  7. 在 node1 上运行 Filebeat 并设置 TLS
  8. 使用 Filebeat 采集数据

Elastic Stack 示意图

第 1 步:准备工作

下载 Elastic Stack 7.1 或更新版本的下列组件:

[1-1] 配置 /etc/hosts 文件

在本例中,我们的 node1 已安装一个浏览器,所以 kibana.local 将允许访问 Kibana 网页。

# [node1] 的 /etc/hosts 文件(我们需要 kibana.local 和 logstash.local)
127.0.0.1 kibana.local logstash.local
192.168.0.2 node1.elastic.test.com node1
192.168.0.3 node2.elastic.test.com node2
# [node2] 的 /etc/hosts 文件(我们这里不需要 kibana.local 和 logstash.local)
192.168.0.2 node1.elastic.test.com node1
192.168.0.3 node2.elastic.test.com node2

第 2 步:在 node1 上创建 SSL 证书并为 Elasticsearch 启用 TLS

[2-1] 设置环境变量(请根据 Elasticsearch 的下载方式和存储位置调整这些变量路径)

[root@node1 ~]# ES_HOME=/usr/share/elasticsearch
[root@node1 ~]# ES_PATH_CONF=/etc/elasticsearch

[2-2] 创建 tmp 文件夹

[root@node1 ~]# mkdir tmp
[root@node1 ~]# cd tmp/
[root@node1 tmp]# mkdir cert_blog

[2-3] 创建实例 yaml 文件

[root@node1 cert_blog]# vi ~/tmp/cert_blog/instance.yml
# 将实例信息添加到 yml 文件
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' ]

[2-4] 生成 CA 和服务器证书(Elasticsearch 安装完毕之后)

[root@node1 tmp]# cd $ES_HOME
[root@node1 elasticsearch]# bin/elasticsearch-certutil cert ca --pem --in ~/tmp/cert_blog/instance.yml --out ~/tmp/cert_blog/certs.zip

[2-5] 解压缩证书

[root@node1 elasticsearch]# cd ~/tmp/cert_blog
[root@node1 cert_blog]# unzip certs.zip -d ./certs

[2-6] Elasticsearch TLS 设置

[2-6-1] 将 cert 文件复制到 config 文件夹

[root@node1 ~]# cd $ES_PATH_CONF
[root@node1 elasticsearch]# pwd
/etc/elasticsearch
[root@node1 elasticsearch]# mkdir certs
[root@node1 elasticsearch]# cp ~/tmp/cert_blog/certs/ca/ca* ~/tmp/cert_blog/certs/node1/* certs
[root@node1 elasticsearch]# ll certs
total 12
-rw-r--r--. 1 root elasticsearch 1834 Apr 12 08:47 ca.crt
-rw-r--r--. 1 root elasticsearch 1834 Apr 12 08:47 ca.key
-rw-r--r--. 1 root elasticsearch 1509 Apr 12 08:47 node1.crt
-rw-r--r--. 1 root elasticsearch 1679 Apr 12 08:47 node1.key
[root@node1 elasticsearch]#

[2-6-2] 配置 elasticsearch.yml

[root@node1 elasticsearch]# vi elasticsearch.yml 
## add the following contents
node.name: node1
network.host: node1.elastic.test.com
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
discovery.seed_hosts: [ "node1.elastic.test.com" ]
cluster.initial_master_nodes: [ "node1" ]

[2-6-3] 启动并查看集群日志

[root@node1 elasticsearch]# grep '\[node1\] started' /var/log/elasticsearch/elasticsearch.log 
[o.e.n.Node               ] [node1] started

[2-6-4] 设置内置用户的密码

[root@node1 elasticsearch]# cd $ES_HOME
[root@node1 elasticsearch]# bin/elasticsearch-setup-passwords auto -u "https://node1.elastic.test.com:9200"
Initiating the setup of passwords for reserved users elastic,apm_system,kibana,logstash_system,beats_system,remote_monitoring_user.
The passwords will be randomly generated and printed to the console.
Please confirm that you would like to continue [y/N] y
Changed password for user apm_system
PASSWORD apm_system = <apm_system_password>
Changed password for user kibana
PASSWORD kibana = <kibana_password>
Changed password for user logstash_system
PASSWORD logstash_system = <logstash_system_password>
Changed password for user beats_system
PASSWORD beats_system = <beats_system_password>
Changed password for user remote_monitoring_user
PASSWORD remote_monitoring_user = <remote_monitoring_user_password>
Changed password for user elastic
PASSWORD elastic = <elastic_password>

[2-6-5] 通过 HTTPS 访问 _cat/nodes API

[root@node1 elasticsearch]# curl --cacert ~/tmp/cert_blog/certs/ca/ca.crt -u elastic 'https://node1.elastic.test.com:9200/_cat/nodes?v'
Enter host password for user 'elastic':
ip          heap.percent ram.percent cpu load_1m load_5m load_15m node.role master name
192.168.0.2           16          95  10    0.76    0.59     0.38 mdi       *      node1
在步骤 2-4 中生成 SSL 证书时,我们提供--keep-ca-key</code选项,这意味着 <code>certs.zip 文件中包含 ca/ca.key 文件以及 ca/ca.crt 文件。只要您决定在 Elasticsearch 集群中添加更多节点,您将需要生成额外的节点证书,为此,您将需要上述两个“ca”文件以及用于生成这两个文件的密码。请将这两个“ca”文件的副本以及用于生成这两个文件的密码保存在安全的位置。

第 3 步:在 node1 上为 Kibana 启用 TLS

[3-1] 设置环境变量

根据 Kibana 的下载方式和存储位置调整这些变量路径:

[root@node1 ~]# KIBANA_HOME=/usr/share/kibana
[root@node1 ~]# KIBANA_PATH_CONFIG=/etc/kibana

[3-2] 创建 config 和 config/certs 文件夹并复制 certs(Kibana 安装完毕后)

复制之前在步骤 2-4 中创建的证书文件,并粘贴到 kibana/config/certs 中。

[root@node1 kibana]# ls config/certs
total 12
ca.crt
my-kibana.crt
my-kibana.key

[3-3] 配置 kibana.yml

切记使用在上面为内置用户生成的密码。您需要将 替换为在步骤 2-6-4 中定义的密码。

[root@node1 kibana]# vi kibana.yml 
server.name: "my-kibana"
server.host: "kibana.local"
server.ssl.enabled: true
server.ssl.certificate: /etc/kibana/config/certs/my-kibana.crt
server.ssl.key: /etc/kibana/config/certs/my-kibana.key
elasticsearch.hosts: ["https://node1.elastic.test.com:9200"]
elasticsearch.username: "kibana"
elasticsearch.password: "<kibana_password>"
elasticsearch.ssl.certificateAuthorities: [ "/etc/kibana/config/certs/ca.crt" ]

[3-4] 启动 Kibana 并测试 Kibana 登录信息

从浏览器访问 https://kibana.local:5601/。使用在步骤 2-6-4 中定义的 elastic 用户名和密码登录。在本例中,我们的 node1 已安装一个浏览器,所以 kibana.local 将允许访问 Kibana。

登录 Kibana

公共可信证书颁发机构拥有非常严格的标准和审计实践,以确保只有在验证正确的身份所有权之后,才会创建证书。在本篇博文中,我们会为 Kibana 创建一个自签名证书(意味着所生成证书是使用自己的私钥签署的)。由于客户端不信任自签署 Kibana 证书,您会在 Kibana 日志中看到类似下面的一条消息,直到使用企业或公共 CA 生成的证书建立正确信任关系为止(此处为 Kibana 存储库中这一问题的链接)。但这一问题并不影响您在 Kibana 中完成工作:

[18:22:31.675] [error][client][connection] Error:4443837888:error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown:../deps/openssl/openssl/ssl/s3_pkt.c:1498:SSL alert number 46

第 4 步:在 node2 上为 Elasticsearch 启用 TLS

[4-1] 设置环境变量

[root@node2 ~]# ES_HOME=/usr/share/elasticsearch
[root@node2 ~]# ES_PATH_CONF=/etc/elasticsearch

[4-2] 在 node2 上设置 TLS

您可以使用 scp 命令将证书从 node1 复制到 node2。两个节点都需要证书和秘钥才能确保连接的安全性。在生产环境中,我们建议为每个节点使用按正确方式签署的秘钥。由于这里仅是演示,我们现在使用自动生成的 CA 证书,以及由所生成 CA 签署的多 DNS 主机名证书。

[root@node2 ~]# cd $ES_PATH_CONF
[root@node2 elasticsearch]# pwd
/etc/elasticsearch
[root@node2 elasticsearch]# mkdir certs
[root@node2 elasticsearch]# cp ~/tmp/cert_blog/certs/ca/ca.crt ~/tmp/cert_blog/certs/node2/* certs  
[root@node2 elasticsearch]# 
[root@node2 elasticsearch]# ll certs
total 12
-rw-r--r--.1 root elasticsearch 1834 Apr 12 10:55 ca.crt
-rw-r--r--.1 root elasticsearch 1509 Apr 12 10:55 node2.crt
-rw-r--r--.1 root elasticsearch 1675 Apr 12 10:55 node2.key

[4-3] 配置 elasticsearch.yml

[root@node2 elasticsearch]# vi elasticsearch.yml 
node.name: node2
network.host: node2.elastic.test.com
xpack.security.enabled: true
xpack.security.http.ssl.enabled: true
xpack.security.transport.ssl.enabled: true
xpack.security.http.ssl.key: certs/node2.key
xpack.security.http.ssl.certificate: certs/node2.crt
xpack.security.http.ssl.certificate_authorities: certs/ca.crt
xpack.security.transport.ssl.key: certs/node2.key
xpack.security.transport.ssl.certificate: certs/node2.crt
xpack.security.transport.ssl.certificate_authorities: certs/ca.crt
discovery.seed_hosts: [ "node1.elastic.test.com" ]

[4-4] 启动并查看集群日志

[root@node2 elasticsearch]# grep '\[node2\] started' /var/log/elasticsearch/elasticsearch.log 
[o.e.n.Node               ] [node2] started

[4-5] 通过 HTTPS 访问 _cat/nodes API

[root@node2 elasticsearch]# curl --cacert ~/tmp/cert_blog/certs/ca/ca.crt -u elastic:<password set previously> 'https://node2.elastic.test.com:9200/_cat/nodes?v'
ip          heap.percent ram.percent cpu load_1m load_5m load_15m node.role master name
192.168.0.2           25          80   5    0.18    0.14     0.30 mdi       *      node1
192.168.0.3           14          96  44    0.57    0.47     0.25 mdi       -      node2

第 5 步:在 node1 上准备 Logstash 用户

[5-1] 创建 logstash_write_role

您可以通过多种方式创建角色。

既可以使用 Kibana Roles UI(Kibana 角色 UI)创建: 

创建 logstash_write_role

也可以使用 Kibana Dev Tools(Kibana 开发工具)标签卡中的 API 创建:

POST /_security/role/logstash_write_role
{
    "cluster": [
      "monitor",
      "manage_index_templates"
    ],
    "indices": [
      {
        "names": [
          "logstash*"
        ],
        "privileges": [
          "write",
          "create_index"
        ],
        "field_security": {
          "grant": [
            "*"
          ]
        }
      }
    ],
    "run_as": [],
    "metadata": {},
    "transient_metadata": {
      "enabled": true
    }
}

随后您会收到响应:

{"role":{"created":true}}

分配至此角色的用户将无法删除任何文档。此角色存在限制:只有用户在索引中以 logstash 或索引文档开始时,此角色才允许用户创建索引。

ILM 用户注意事项: 要使 logstash_writer_role索引生命周期管理 (ILM)(在 7.3+ 中默认启用)协同工作,必须包含以下权限:


"privileges": ["write","create","delete","create_index","manage","manage_ilm"]
        

[5-2] 创建 logstash_writer 用户(请为用户 logstash_writer 更改密码)

您可以通过多种方式创建用户。

既可以使用 Kibana Users UI(Kibana 用户 UI)创建:

创建 logstash_writer 用户

也可以使用 Kibana Dev Tools(Kibana 开发工具)标签卡中的 API 创建:

POST /_security/user/logstash_writer
{
  "username": "logstash_writer",
  "roles": [
    "logstash_write_role"
  ],
  "full_name": null,
  "email": null,
  "password": "<logstash_system_password>",
  "enabled": true
}

随后您会收到响应:

{"user":{"created":true}}

第 6 步:在 node1 上为 Logstash 启用 TLS

[6-1] 创建文件夹并复制证书

[root@node1 logstash]# ls -l
total 24
ca.crt
logstash.crt
logstash.key

[6-2] 针对 Beats 输入插件,将 logstash.key 转换为 PKCS#8 格式

[root@node1 logstash]# openssl pkcs8 -in config/certs/logstash.key -topk8 -nocrypt -out config/certs/logstash.pkcs8.key

[6-3] 配置 logstash.yml

切记对于 logstash_system 用户,要使用自动生成的密码。使用在步骤 2-6-4 中定义的密码。

[root@node1 logstash]# vi logstash.yml

然后编辑:

node.name: logstash.local
path.config: /etc/logstash/conf.d/*.conf
xpack.monitoring.enabled: true
xpack.monitoring.elasticsearch.username: logstash_system
xpack.monitoring.elasticsearch.password: '<logstash_system_password>'
xpack.monitoring.elasticsearch.hosts: [ 'https://node1.elastic.test.com:9200' ]
xpack.monitoring.elasticsearch.ssl.certificate_authority: /etc/logstash/config/certs/ca.crt

[6-4] 创建并配置 conf.d/example.conf

在 Elasticsearch 输出上,使用在步骤 5-2 中定义的密码。

[root@node1 logstash]# vi conf.d/example.conf 
input {
  beats {
    port => 5044
    ssl => true
    ssl_key => '/etc/logstash/config/certs/logstash.pkcs8.key'
    ssl_certificate => '/etc/logstash/config/certs/logstash.crt'
  }
}
output {
  elasticsearch {
    hosts => ["https://node1.elastic.test.com:9200","https://node2.elastic.test.com:9200"]
    cacert => '/etc/logstash/config/certs/ca.crt'
    user => 'logstash_writer'
    password => <logstash_writer_password>
  }
}

[6-5] 使用示例配置启动 Logstash 并查看 Logstash 日志

您应该会看到下面的日志消息:

[INFO ][logstash.pipeline        ] Pipeline started successfully {:pipeline_id=>".monitoring-logstash", :thread=>"#<Thread:0x640c14d2@/usr/share/logstash/logstash-core/lib/logstash/pipeline.rb:246 run

然后在 Kibana Monitoring 标签卡中,将会显示 Logstash(节点信息、管道设置、OS 信息、JVM 信息、进程统计数据,以及管道运行时间统计数据):

Kibana Monitoring 标签卡,正显示 Logstash

第 7 步:在 node1 上运行 Filebeat 并设置 TLS

[7-1] 创建 config 文件夹并复制证书

[root@node1 filebeat]# mkdir config
[root@node1 filebeat]# mkdir config/certs
[root@node1 filebeat]# cp ~/tmp/cert_blog/certs/ca/ca.crt config/certs
[root@node1 filebeat]# ll config/certs/
total 4
-rw-r--r--.1 root root 1834 Apr 20 00:18 ca.crt

[7-2] 创建一个新的 filebeat.yml

[root@node1 filebeat]# pwd
/etc/filebeat
[root@node1 filebeat]# mv filebeat.yml filebeat.yml.old

[7-3] 编辑您的新配置文件 filebeat.yml

filebeat.inputs:
- type: log
  paths:
    - /etc/filebeat/logstash-tutorial-dataset
output.logstash:
  hosts: ["logstash.local:5044"]
  ssl.certificate_authorities:
    - /etc/filebeat/config/certs/ca.crt

第 8 步:使用 Filebeat 采集数据

[8-1] 准备 Filebeat 要用的输入日志数据 (logstash-tutorial.log)

首先请下载输入日志数据

[root@node1 filebeat]# pwd
/etc/filebeat
[root@node1 filebeat]# mkdir logstash-tutorial-dataset
[root@node1 filebeat]# cp /root/logstash-tutorial.log logstash-tutorial-dataset/.
[root@node1 filebeat]# ll logstash-tutorial-dataset/
total 24
-rwxr-x---.1 root root 24464 Apr 20 00:29 logstash-tutorial.log

[8-2] 启动 Filebeat

[root@node1 filebeat]# systemctl start filebeat
[root@node1 filebeat]# systemctl enable filebeat
Created symlink from /etc/systemd/system/multi-user.target.wants/filebeat.service to /usr/lib/systemd/system/filebeat.service.

[8-3] 查看日志

您应该会看到下面的日志消息:

INFO    log/harvester.go:216    Harvester started for file: /etc/filebeat/logstash-tutorial-dataset/logstash-tutorial.log

[8-4] 创建索引模式

接下来,创建与所采集数据相匹配的索引模式。这将允许您在 Kibana 中对数据进行可视化,例如使用 Graph 或 Discover。

在 Kibana 中创建索引模式。

然后选择 Time Filter field name(时间筛选器字段名)。在我们的例子中,其为 @timestamp

指定一个 Time Filter field name(时间筛选器字段名)。

大功告成!您已对 Elastic Stack 不同部分之间的通信进行加密,现在可以安心且安全地采集日志数据了。

最后几点提示……

如果您在配置安全性的过程中遇到任何问题,建议您首先查看我们文档中的安全故障排查页面。该页面能帮助解决很多常见问题。如果问题仍未得到解决,您可查看我们的 Elastic 论坛以寻求更多帮助。或者如果您想直接与 Elastic 支持团队对话,欢迎立即订阅 Elastic 服务,然后便可直接向我们的专家团队寻求帮助。祝您拥有安全的使用体验!