作者简介
江榕,携程信息安全部高级信息安全工程师,目前主要负责公司运维安全日志分析平台搭建、参与日常运维安全事件响应、参与运维安全评审。
1、背景
随着大数据技术在互联网行业的快速发展,应用于日志分析领域的技术趋向于多元化,而elasticsearch以其作为开源分布式搜索引擎所带来的诸多特点与优势,逐渐成为各家互联网公司实时日志分析、甚至风控离线数据分析的主要战力。
然而在享受到elasticsearch带来便利和优势的同时,不可避免地存在将elasticsearch作为db用于存储敏感信息,由于elasticsearch本身不支持安全特性,带来极大的访问控制安全风险。
为了对elasticsearch的访问控制进行安全加固,我们针对市面上的仅有两款安全插件进行调研,由于shield为收费插件,故本文仅对searchguard开源插件的配置部署及落地进行详细阐述,希望提供给各位一个快速上手配置searchguard指南。
search-guard 更新到2.x后与 shield配置上很相似。 除了必须的RBAC认证授权外,searchguard 优点有:
在我们考虑正式落地前,需要确认必要的安全特性,例如字段级别访问控制、内网restful流量加密是否必要等。结合现有业务实际场景,最后选择仅做到索引级别的访问控制,且仅加密RPC流量。
2、安装
当前配置的是es5.1.1对应的版本,故对应的配置文件安装如下:
安装search-guard-5
https://search.maven.org/remotecontent?filepath=com/floragunn/search-guard-5/5.1.1-11/search-guard-5-5.1.1-11.zip
bin/elasticsearch-plugininstall file:/// search-guard-5-5.1.1-11.zip
下载:
https://codeload.github.com/floragunncom/search-guard-ssl/zip/es-5.1.1
解压文件,进入example-pki-scripts目录。
注意,该步骤用于制作节点用的truststore及keystore,故无需部署在生产节点上,创建完成上述文件后部署到对应节点即可。另外,记得备份example-pki-scripts生成后的相关内容。
创建 root ca
调整etc/root-ca.conf及signing-ca.conf中[ ca_dn ]内容,默认如下:
[ ca_dn ]
0.domainComponent = "com"
1.domainComponent = "example"
organizationName = "Example Com Inc."
organizationalUnitName ="Example Com Inc. Root CA"
commonName ="Example Com Inc. Root CA"
执行./gen_root_ca.shcapassword_use_a_strong_one truststorepassword 其中两个参数分别为ca密码及truststore密码,请将该密码设置足够强壮。
该操作完成后生成truststore.jks
创建 keystore
用于部署data/master节点执行命令
./gen_node_cert.sh nodenumkeystorepassword capassword_use_a_strong_one
用于部署client节点执行命令
./gen_client_node_cert.sh nodenamekeystorepassword capassword_use_a_strong_one
该操作完成后生成xxxkeystore.jks
将各自生成的truststore.jks及xxxkeystore.jks上传至各个节点的conf目录下。
在elasticsearch.yml进行配置:
searchguard.authcz.admin_dn:
-cn=admin,ou=Test,ou=ou,dc=company,dc=com
searchguard.ssl.transport.keystore_filepath:xxxkeystore.jks
searchguard.ssl.transport.keystore_password:keystorepassword
searchguard.ssl.transport.truststore_filepath:truststore.jks
searchguard.ssl.transport.truststore_password:truststorepassword
searchguard.ssl.transport.enforce_hostname_verification:false
重启elasticsearch服务。
searchguard 主要有5个配置文件在 plugins/search-guard-5/sgconfig 下:
sg_config.yml:
sg_internal_users.yml:
Kibana5:
hash: $2a$12$.kM9IYaRm1uWeywD0Xyo8eynR6fAjVnHKrkxEAfIlZ1PeszTUovW6
#password is: kibana5
roles:
- kibana5
logstash:
hash: $2a$12$pLs.IeT/Ea8w81xQPqSRwOXah6h736UVjyvaHgXp9IjNjDxjQkKb6
roles:
- logstash
#password is: logstash
密码hash用plugins/search-guard-5/tools/hash.sh生成。
sg_roles.yml:
sg_kibana5:
indices:
'*':#需要读权限目标索引,可通配
'*':#目标type,可通配
-'*'#具体权限
'?kibana':
'*':
-KIBANA_SERVER
cluster:
- cluster:monitor/nodes/info
- cluster:monitor/health
- CLUSTER_MONITOR
- CLUSTER_COMPOSITE_OPS
sg_logstash:
cluster:
- indices:admin/template/get
-indices:admin/template/put
-indices:data/write/bulk*
-CLUSTER_MONITOR
-CLUSTER_COMPOSITE_OPS
indices:
'*': #需要写权限目标索引,可通配
'*': #目标type,可通配
-CRUD
-CREATE_INDEX
关于详细权限,可参考shield的权限文档:
https://www.elastic.co/guide/en/shield/2.1/reference.html#ref-actions-list
sg_roles_mapping.yml:
sg_logstash:
users:
- logstash
sg_kibana5:
users:
- kibana5
sg_action_groups.yml:
KIBANA_SERVER:
- "indices:admin/exists*"
- "indices:admin/mapping/put*"
- "indices:admin/mappings/fields/get*"
- "indices:admin/refresh*"
- "indices:admin/validate/query*"
- "indices:data/read/get*"
- "indices:data/read/mget*"
- "indices:data/read/search*"
- "indices:data/write/delete*"
- "indices:data/write/index*"
- "indices:data/write/update*"
在任意节点执行sgadmin命令进行配置同步:
plugins/search-guard-5/tools/sgadmin.sh -cntestcluster -cd plugins/search-guard-5/sgconfig/ -ksconfig/node-0-keystore.jks -ts config/truststore.jks -nhnv
在logstash.conf中作如下设置:
output {
elasticsearch{
user =>logstash
password=> logstash
...
}
}
该设置中的用户名密码为sg_internal_users.yml对应用户
logstash用户名对应的权限在sg_roles.yml中设置:
sg_logstash:
cluster:
- indices:admin/template/get
- indices:admin/template/put
- CLUSTER_MONITOR
- CLUSTER_COMPOSITE_OPS
indices:
'logstash-*':
'*':
- CRUD
- CREATE_INDEX
'*beat*':
'*':
- CRUD
- CREATE_INDEX
在sg_roles_mapping.yml设置对应的logstash映射:
sg_logstash:
users:
- logstash
sgadmin命令加载配置。
kibana.yml内作如下配置:
elasticsearch.username: "kibanaserver"
elasticsearch.password:"kibanaserver"
sg_roles作如下配置:
sg_kibana5_server:
cluster:
- cluster:monitor/nodes/info
- cluster:monitor/health
- CLUSTER_MONITOR
- CLUSTER_COMPOSITE_OPS
indices:
'?kibana':
'*':
- ALL
sg_roles_mapping作如下配置:
sg_kibana5_server:
users:
-kibanaserver
sg_internal_users.yml作如下配置:
kibanaserver:
hash: $2a$12$4AcgAt3xwOWadA5s5blL6ev39OXDNhmOesEoo33eZtrq2N0YrU3H.
#password is:kibanaserver
sg_config作如下配置:
authc:
kibana_auth_domain:
enabled:true
order:1
http_authenticator:
type:basic
challenge:true
authentication_backend:
type:internal
sgadmin命令加载配置。
对于集群是否落地searchguard,可能更多考量在与是否会对性能有影响。
从searchguard工作原理上说,加入searchguard会分别从认证、授权及节点间流量加解密上有所消耗。对于性能强如物理机,认证授权这块可以忽略不计,但即使取消了restful的加密,仍然有rpc流量需要加解密(如背景中所述,该加密功能不可避免)。为了验证影响,我们采用了esrally进行相关测试。
测试方案为在两台物理机上各部署两个不同集群(有无searchguard)的节点,分别用esrally进行测试,比对测试结果如下,baseline为无searchguard集群,写入数据量为280w条,bulk size为5000,各位可以有个参考:
Metric Operation Baseline Contender Diff Unit
MinThroughput index-append 26188.1 19700.9 -6487.21094 docs/s
Median Throughput index-append 59589.7 53227.7 -6361.99219 docs/s
Max Throughput index-append 63968.8 57558.9 -6409.82812 docs/s
90.0th percentile latency index-append 699.846 882.144 +182.29781 ms
99.0th percentile latency index-append 797.955 1161.74 +363.78743 ms
100.0thpercentile latency index-append 802.317 1236.58 +434.26428 ms
90.0th percentile servicetime index-append 699.846 882.144 +182.29781 ms
99.0th percentile servicetime index-append 797.955 1161.74 +363.78743 ms
100.0th percentile servicetime index-append 802.317 1236.58 +434.26428 ms
由于能够支持es安全方案可选少,且searchguard这类开源方案对于性能上的影响需要时间去验证(实际落地情况复杂)。对于多业务集群(存在多个角色进行集群使用且有访问控制需求),可选择尝试searchguard,即使该方案的配置有点麻烦。