ELK 数据安全加固

ELK 安全问题

对于日常使用到的 ELK 组件的系统,默认在 ELK 部署的时候默认都是没有安装配置任何权限管控插件,这对于存储在 es 之中的数据无异于“裸奔”。没有任何防护的话,只要稍微会一点 ELK 知识,网络探测到暴露在域外的 es 数据库后,可以直接对数据进行“增删改查”,这是致命的安全问题。以下为例:

假设我已经知道 119.29.11.49 这台机器上安装有 elasticsearch.

ELK 数据安全加固

那么,我可以查看它有哪些索引

ELK 数据安全加固
查看索引

插入脏数据

ELK 数据安全加固
写入数据

删除部分索引

ELK 数据安全加固
删除索引

以上的所有操作都不需要任何的授权,只要能远程连上这台机器的 9200 端口,这对数据安全来说是比较大的隐患。

x-pack 简介

这里引用腾讯云的一些介绍,具体可以查看原文 https://cloud.tencent.com/document/product/845/34926

“高级特性,是指 Elasticsearch 官方商业特性(原 X-Pack 商业版插件包含的特性),包含了安全(Security)、SQL、机器学习(Machine Learning)、监控(Monitor)等高级功能,可以为 Elasticsearch 服务的应用开发和运维管理,提供更有力的帮助。”

  • 安全(Security)

支持索引和字段级别,读写等细分权限的控制管理,实现数据安全防护、业务访问隔离,向正确的人员授予访问权限,阻止恶意破坏和数据泄露,有效地保障数据安全。

  • 监控

集群、节点、索引多个维度,全方位监控,实时了解集群运行情况,辅助应用开发及运维。
这里我们主要用到 security 和监控功能。

启用 x-pack 组件

了解以上 x-pack 的许多特性,那我们怎么使用呢?首先,修改集群的配置 Elasticsearch 配置文件,启用 x-pack 组件的 security 功能。

echo "xpack.security.enabled: true" >> config/elasticsearch.yml

生成安全证书

在 elasticsearch 部署时,需要修改我们机器的 hosts,具体 hosts 如下,这里以两个节点的集群环境为例

# [node1] 的 /etc/hosts 文件(我们需要 kibana.local 和 logstash.local)注意,kibana 因为需要域外访问,所以需要设置 0.0.0.0
0.0.0.0 kibana.local logstash.local
9.77.28.233 node1.elastic.com node1
9.134.72.182 node2.elastic.com node2
# [node2] 的 /etc/hosts 文件(我们这里不需要 kibana.local 和 logstash.local)
9.77.28.233 node1.elastic.com node1
9.134.72.182 node2.elastic.com node2

Elasticsearch 有两个通信协议:TCP 协议通信和 HTTP 层通信。TCP 协议用于 Elasticsearch 节点之间的内部通信,HTTP 协议用于从客户端到 Elasticsearch 集群的通信。我们日常请求 Elasticsearch 都是走的 http 协议,由于 Elasticsearch 集群中的每个节点都是客户端和集群中其他节点的服务器,因此所有传输证书都必须是客户端和服务器证书。

Elasticsearch 6.5 以上 x-pack 已经开源,并且提供了生成证书的工具包,放在 bin 目录,可以生成集群内部节点通信的自签名证书,证书生成命令如下,↵ 代表回车键:

mkdir /data/temp/cert_blog
↵
cd /data/temp/
# 创建我们需要生成的证书实例文件
vi temp/cert_blog/instance.yml
# 将实例信息添加到 yml 文件
instances:
- name: 'node1'
dns: [ 'node1.elastic.com' ]
- name: "node2"
dns: [ 'node2.elastic.com' ]
- name: 'kibana'
dns: [ 'kibana.local' ]
- name: 'logstash'
dns: [ 'logstash.local' ]
↵
bin/elasticsearch-certutil cert ca --pem --in /data/temp/cert_blog/instance.yml --out /data/temp/cert_blog/certs.zip
↵
cd /temp/cert_blog
↵
unzip certs.zip -d ./certs
Archive:  certs.zip
creating: ./certs/ca/
inflating: ./certs/ca/ca.crt
creating: ./certs/node1/
inflating: ./certs/node1/node1.crt
inflating: ./certs/node1/node1.key
creating: ./certs/node2/
inflating: ./certs/node2/node2.crt
inflating: ./certs/node2/node2.key
creating: ./certs/kibana/
inflating: ./certs/kibana/kibana.crt
inflating: ./certs/kibana/kibana.key
creating: ./certs/logstash/
inflating: ./certs/logstash/logstash.crt
inflating: ./certs/logstash/logstash.key

以上,会生成加密通信的 TSL 证书,这里需要将证书复制到各个节点的 config/certs 目录中,如果没有该目录需要先新建目录。

# 复制 node1 节点证书
cp /data/temp/cert_blog/certs/ca/ca.crt /data/temp/cert_blog/certs/node1/* /data/config/certs/
# 复制 node2 节点证书
scp /data/temp/cert_blog/certs/ca/ca.crt /data/temp/cert_blog/certs/node2/* user@node2.elastic.com:/data/es/config/certs

节点之间启用 ssl 通信

生成 ssl 证书之后,需要在集群中启用 ssl 通信,修改集群配置。

# node1 配置
{
echo "node.name: node1"
echo "network.host: node1.elastic.com"
echo "xpack.security.enabled: true"
echo "xpack.security.http.ssl.enabled: true"
echo "xpack.security.transport.ssl.enabled: true"
echo "xpack.security.http.ssl.key: certs/node1.key"
echo "xpack.security.http.ssl.certificate: certs/node1.crt"
echo "xpack.security.http.ssl.certificate_authorities: certs/ca.crt"
echo "xpack.security.transport.ssl.key: certs/node1.key"
echo "xpack.security.transport.ssl.certificate: certs/node1.crt"
echo "xpack.security.transport.ssl.certificate_authorities: certs/ca.crt"
}  >> config/elasticsearch.yml
# node2 配置
{
echo "node.name: node2"
echo "network.host: node2.elastic.com"
echo "xpack.security.enabled: true"
echo "xpack.security.http.ssl.enabled: true"
echo "xpack.security.transport.ssl.enabled: true"
echo "xpack.security.http.ssl.key: certs/node2.key"
echo "xpack.security.http.ssl.certificate: certs/node2.crt"
echo "xpack.security.http.ssl.certificate_authorities: certs/ca.crt"
echo "xpack.security.transport.ssl.key: certs/node2.key"
echo "xpack.security.transport.ssl.certificate: certs/node2.crt"
echo "xpack.security.transport.ssl.certificate_authorities: certs/ca.crt"
}  >> config/elasticsearch.yml

修改完以上配置后,依次重启集群中的节点,为了防止集群节点有问题,可以先启动 data node 最后再启动 master node

设置默认用户密码

重启完成后,elasticsearch 需要新建初始的内部用户,可以指定用户的密码,也可以自动生成,一般推荐自动生成。具体操作命令如下:

# 手动指定用户密码
bin/elasticsearch-setup-passwords interactive -u "https://node1.elastic.com:9200"
# 自动生成并设置密码
bin/elasticsearch-setup-passwords auto -u "https://node1.elastic.com:9200"

自动生成的用户密码在最后会有以下提示(为了安全,隐去密码):

Changed password for user apm_system
PASSWORD apm_system = xxxx
Changed password for user kibana
PASSWORD kibana = xxx
Changed password for user logstash_system
PASSWORD logstash_system = xxx
Changed password for user beats_system
PASSWORD beats_system = xxx
Changed password for user remote_monitoring_user
PASSWORD remote_monitoring_user = xxx
Changed password for user elastic
PASSWORD elastic = xxx

配置 https 协议

对于 HTTP 层通信,Elasticsearch 节点仅用作服务器,因此可以使用服务器证书,即 TLS/SSL 证书不需要启用客户端身份验证。在 elasticsearch.yml 文件中配置如下,这在之前的配置中已经设置,无需重复设置,这里只是突出强调:

"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 发现所有的操作都需要授权了,并且还需要访问 https 地址的证书。

ELK 数据安全加固

我们直接浏览器访问,返回证书不受信任,因为证书是我们Elastic 签发生成的,并不是证书机构颁发,所以会出现以下告警

ELK 数据安全加固

修改 kibana 配置

ELK 中,kibana 也是比较重要的组件。有了 kibana 所有的操作就不需要通过 curl 执行了。所以 kibana 也需要配置相应的安全访问。

因为我们已经使用了自签名 CA,所以我们必须还使用之前生成的 kibana 证书,具体如下:

cp ../../temp/cert_blog/certs/kibana/* ../temp/cert_blog/certs/ca/ca.crt ./config/certs/

现在 Elasticsearch 集群上启用了安全特性,因此必须启用 Kibana 安全特性并配置为通过 HTTPS 向集群进行身份验证。在 Kibana 中创建 config/certs 目录,并将生成的客户端证书复制到目录中,并将以下行添加到我们的 kibana.yml 文件中,修改 kibana 的配置,并重启。用户名密码填写上一步生成的 kibana 账户。

#ensure https
{
echo "server.name: "kibana""
echo "server.host: "kibana.local""
echo "server.ssl.enabled: true"
echo "server.ssl.certificate: config/certs/kibana.crt"
echo "server.ssl.key: config/certs/kibana.key"
echo "elasticsearch.hosts: ["https://node1.elastic.com:9200"]"
echo "elasticsearch.username: "kibana""
echo "elasticsearch.password: "xxxxxxx""
echo "elasticsearch.ssl.certificateAuthorities: [ "/config/certs/ca.crt" ]"
} >> config/kibana.yml

修改以上配置,重启 kibana 之后再访问 kibana 地址,已经显示需要登陆。

ELK 数据安全加固

输入用户名和密码,登陆 kibana

从 kibana 中我们可以监控集群的状态。

ELK 数据安全加固

查看每个节点的内存,cpu 使用情况

ELK 数据安全加固

查看节点的 gc 情况,等等,kibana 的监控基本上能满足大部分的集群监控需求

ELK 数据安全加固

修改 logstash 配置

在数据采集写入过程中我们用到的是 logstash 组件,当我们启用了 https 访问时也需要修改 logstash 的配置,不然会报数据无法写入。

ELK 数据安全加固

因为我们已经使用了自签名 CA,所以我们必须还使用之前生成的 logstash 证书。修改 logstash 配置,启用 x-pack 监控。

cp ../temp/cert_blog/certs/logstash/* ../temp/cert_blog/certs/ca/ca.crt ./config/certs/
node.name: logstash.local
# 启用 x-pack 监控
xpack.monitoring.enabled: true
xpack.monitoring.elasticsearch.username: logstash_system
xpack.monitoring.elasticsearch.password: 'xxxx'
xpack.monitoring.elasticsearch.hosts: [ 'https://node1.elastic.com:9200' ]
xpack.monitoring.elasticsearch.ssl.certificate_authority: config/certs/ca.crt

同时还需要修改数据采集的 config 文件

vim conf/logstash.conf
output {
elasticsearch {
hosts => ["https://node1.elastic.com:9200","https://node2.elastic.com:9200"]
index => "logstash-%{+yyyy.MM.dd}"
user => elastic
password => xxxxx
cacert => 'config/certs/ca.crt'
}
}

最后,启动 logstash,可以看到 logstash 已经启动起来并开始采集数据。

ELK 数据安全加固

同时,我们还可以在 kibana 中监控我们的 logstash 数据采集状态。

ELK 数据安全加固

用户角色管控

对于数据的访问,我们也需要加固访问权限,根据不同的用户角色设置不同类别的数据查询权限。

登陆 kibana,在左侧的 setting 栏目,设置用户角色。默认会生成好几种用户

  • apm,应用性能管理用户,可以查看更新相关应用性能索引
  • kibana dashboard user ,kibana 视图管理用户
  • logstash 用户,拥有读写 logstash 前缀索引权限
  • ... 等等其他的一些常用的用户,具体如下
ELK 数据安全加固

这里可以设置用户角色能够访问的数据权限以及能够查看的面板。

同时,我们还可以新建低权用户,分配他所属的用户组,具体操作类似用户角色设置。

ELK 数据安全加固