前言
在之前的一篇 集中式日志分析平臺(tái) - ELK Stack - 安全解決方案 X-Pack 里講解了官方收費(fèi)安全套件,官方套件很強(qiáng)大啊,但是完全收費(fèi)。業(yè)界比較有名的一款開源產(chǎn)品 SearchGuard 卻是部分收費(fèi),專注于 ES 的安全加固以及順帶做做 ELK 棧的 security,功能包括:
和認(rèn)證和授權(quán)有關(guān)的:
- 支持基礎(chǔ) Http 認(rèn)證;
- 支持 LDAP 和 AD,可以用于認(rèn)證和授權(quán)的用戶角色信息元數(shù)據(jù)集中式存儲(chǔ);(收費(fèi))
- 支持 Kerberos 雙邊認(rèn)證;(收費(fèi))
- 支持 JWT;(收費(fèi))
- 支持代理認(rèn)證,可以很方便的實(shí)現(xiàn) SSO 系統(tǒng)對(duì)接;
ES 行(document)和列(field)級(jí)別的安全訪問控制;
日志審計(jì)功能;(收費(fèi))
和 ELK 棧其他組件有關(guān)的:
- 和 Kibana 完美整合,包括添加了 x-pack 插件的情況下,支持 Kerberos 認(rèn)證、代理認(rèn)證、JWT、用戶名/密碼登錄認(rèn)證、Https 加密、對(duì) ES 訪問的 ACL 等,并且可以自定義登錄首頁(yè)樣式;
- 支持 Kibana 的 visualization、dashboard 的多租戶模式;(收費(fèi))
- 和 logstash 完美整合,支持 logstash 可以通過 Https 訪問 ES;
- 和 x-pack monitoring 整合;
- 支持 Tribe nodes 模式,也就是說支持多個(gè) ES 集群的級(jí)聯(lián)查詢;
- 支持 indices 的快照和恢復(fù)操作,默認(rèn)只有 admin 用戶具備權(quán)限;
- 可以和開源 ES 報(bào)警組件 ElastAlert 整合;
本文描述的是如何把關(guān)鍵性的幾個(gè)免費(fèi)功能整合到我們的 ELK 棧里去,涵蓋了:
- 如何以腳本的形式 quickstart 整合 search guard 至 elasticsearch (Https & indices 粒度 ACL);
- 如何讓 kibana 訪問安全 elasticsearch 集群;
- 如何讓 logstash 訪問安全 elasticsearch 集群;
- 一個(gè)簡(jiǎn)單的鏈路調(diào)試?yán)樱?/li>
Integration with ES(Https & indices 粒度 ACL)
假設(shè)我們已經(jīng)有一個(gè) ELK 集群(部署方式請(qǐng)參考我之前的文章),它的節(jié)點(diǎn)分布是這樣的(版本統(tǒng)一為 5.2.1):
IP | Role |
---|---|
172.16.134.34 | ES/Logstash/Kibana |
172.16.134.37 | ES/Logstash/Zookeeper/Kafka/Filebeat |
服務(wù)的安裝路徑統(tǒng)一為 /home/admin/server/${SERVICE_NAME}
,日志的統(tǒng)一路徑為 /home/admin/logs/${SERVICE_NAME}
。
互聯(lián)網(wǎng)聯(lián)通情況下的安裝:
/home/admin/server/elasticsearch-current/bin/elasticsearch-plugin install -b com.floragunn:search-guard-5:5.2.1-12
請(qǐng)按照您自己的 es 版本進(jìn)行版本選擇:https://github.com/floragunncom/search-guard/wiki
離線環(huán)境下的安裝:
在可以訪問互聯(lián)網(wǎng)的機(jī)器上下載 https://oss.sonatype.org/content/repositories/releases/com/floragunn/search-guard-5/5.2.1-12/search-guard-5-5.2.1-12.zip,然后上傳至內(nèi)網(wǎng)環(huán)境。
/home/admin/server/elasticsearch-current/bin/elasticsearch-plugin install -b file:///home/admin/soft/search-guard-5-5.2.1-12.zip
運(yùn)行命令進(jìn)行腳本式初始化:
cd /home/admin/server/elasticsearch-current/plugins/search-guard-5/tools
chmod +x install_demo_configuration.sh
./install_demo_configuration.sh
完成后會(huì)在 config
目錄下生成測(cè)試用的 3 個(gè) jks 文件:
-
truststore.jks
—根 CA; -
keystore.jks
—節(jié)點(diǎn)證書; -
kirk.jks
—運(yùn)行sgadmin
必備的管理員證書;
完成后也會(huì)自動(dòng)設(shè)置一些默認(rèn)配置至 elasticsearch.yml
中:
######## Start Search Guard Demo Configuration ########
searchguard.ssl.transport.keystore_filepath: keystore.jks
searchguard.ssl.transport.truststore_filepath: truststore.jks
searchguard.ssl.transport.enforce_hostname_verification: false
searchguard.ssl.http.enabled: true
searchguard.ssl.http.keystore_filepath: keystore.jks
searchguard.ssl.http.truststore_filepath: truststore.jks
searchguard.authcz.admin_dn:
- CN=kirk,OU=client,O=client,L=test, C=de
cluster.name: searchguard_demo
network.host: 0.0.0.0
但是如果現(xiàn)在重新啟動(dòng) es 可能會(huì)報(bào)錯(cuò),因?yàn)樵鹊呐渲美锖w了 cluster.name
network.host
等配置,報(bào)錯(cuò)可能如下:
Exception in thread "main" ElasticsearchParseException[duplicate settings key [cluster.name] found at line number [21], column number [15], previous value [lw-daily], current value [search
guard_demo]]
這里 lw-daily 是我們默認(rèn)的集群名稱。
我們需要?jiǎng)h除相應(yīng)報(bào)錯(cuò)配置項(xiàng),然后重啟 es:
######## Start Search Guard Demo Configuration ########
searchguard.ssl.transport.keystore_filepath: keystore.jks
searchguard.ssl.transport.truststore_filepath: truststore.jks
searchguard.ssl.transport.enforce_hostname_verification: false
searchguard.ssl.http.enabled: true
searchguard.ssl.http.keystore_filepath: keystore.jks
searchguard.ssl.http.truststore_filepath: truststore.jks
searchguard.authcz.admin_dn:
- CN=kirk,OU=client,O=client,L=test, C=de
network.host: 0.0.0.0
如果重啟過程中還遇到如下報(bào)錯(cuò)說明 openssl 運(yùn)行缺少 jar:
[2017-07-12T12:56:23,987][INFO ][c.f.s.s.DefaultSearchGuardKeyStore] Open SSL not available (this is not an error, we simply fallback to built-in JDK SSL) because of java.lang.ClassNotFoundException: org.apache.tomcat.jni.SSL
該情況需要去官方下載對(duì)應(yīng)版本的 jar 包(https://github.com/floragunncom/search-guard-docs/blob/master/tls_openssl.md),比如我們的版本對(duì)應(yīng)的是 http://repo1.maven.org/maven2/io/netty/netty-tcnative/1.1.33.Fork25,然后放置到 plugins/search-guard-5/
:
mv netty-tcnative-1.1.33.Fork25-linux-x86_64.jar /home/admin/server/elasticsearch-current/plugin/search-gurad-5/
修改 tools/sgadmin_demo.sh
,使其中一行匹配我們默認(rèn)的集群名稱:
/home/admin/server/elasticsearch-current/plugins/search-guard-5/tools/sgadmin.sh -cd /home/admin/server/elasticsearch-current/plugins/search-guard-5/sgconfig -cn lw-daily -ks /home/admin/server/elasticsearch-current/config/kirk.jks -ts /home/admin/server/elasticsearch-current/config/truststore.jks -nhnv
我們把 -cn 參數(shù)修改為了 lw-daily。
然后我們執(zhí)行腳本:
./sgadmin_demo.sh
執(zhí)行腳本之后會(huì)根據(jù) plugins/search-guard-5-5.2.1-12/sgconfig
的配置初始化 search guard index,初始化的包括內(nèi)部用戶、角色、用戶和角色的映射、權(quán)限組等等。
到這一步之后安裝就算完成了,我們可以通過接口觀察是否配置正確:
https://172.16.134.34:9200/_searchguard/authinfo
這里默認(rèn)的用戶名和密碼可以選擇 admin
,admin
,如果通過認(rèn)證,那么就會(huì)返回如下結(jié)果:
{
user: "User [name=admin, roles=[]]",
user_name: "admin",
user_requested_tenant: null,
remote_address: "172.16.129.61:50317",
sg_roles: [
"sg_all_access",
"sg_own_index",
"sg_public"
],
sg_tenants: {
test_tenant_ro: true,
admin: true,
adm_tenant: true
},
principal: null,
peer_certificates: "0"
}
Integration with Kibana
ES 做了加固,原先的普通訪問方式就歇菜了,首先是 Https 然后是 ACL,那么就會(huì)沒通過認(rèn)證和得到相應(yīng)的權(quán)限訪問資源。我們需要對(duì) Kibana 做相應(yīng)的配置:
下載 plugin:
https://github.com/floragunncom/search-guard-kibana-plugin/releases/download/v5.2.1-3/searchguard-kibana-5.2.1-3.zip
安裝 plugin:
/home/admin/server/kibana-current/bin/kibana-plugin install file:///home/admin/soft/searchguard-kibana-5.2.1-3.zip
修改 kibana.yml
:
elasticsearch.url: "https://v134034.yn1.lwsite.net:9200"
server.host: "v134034.yn1.lwsite.net"
searchguard.basicauth.enabled: true
searchguard.cookie.secure: false
searchguard.cookie.name: 'searchguard_authentication'
searchguard.cookie.password: 'searchguard_cookie_default_password'
searchguard.cookie.ttl: 3600000
searchguard.session.ttl: 3600000
searchguard.session.keepalive: true
elasticsearch.username: "kibanaserver"
elasticsearch.password: "kibanaserver"
elasticsearch.ssl.verify: false
console.proxyConfig:
- match:
protocol: "https"
ssl:
verify: false
重啟 kibana:
sudo kill -9 $(sudo lsof -i:5601 | awk '{print$2}' | tail -1 )
/home/admin/server/kibana-current/bin/kibana >> /home/admin/logs/kibana/kibana.log 2>&1 &
使用 kibanaserver 查看是否可以登錄,密碼默認(rèn)為 kibanaserver。(該用戶是在整合 searchguard 至 es 之后在運(yùn)行 demo 腳本中生成的,同樣的 logstash 用戶也是)
Integration with Logstash
同樣,我們需要修改 logstash ,以使其可以訪問 es。以下是一個(gè)簡(jiǎn)單的示例配置,數(shù)據(jù)來自 kafka 的 stdin_test:
input {
kafka {
bootstrap_servers => 'v134037.yn1.lwsite.net:9092'
consumer_threads => 1
topics => ["stdin_test"]
type => "stdin_test"
codec => "json"
}
}
output {
elasticsearch {
hosts => ["v134034.yn1.lwsite.net:9200","v134037.yn1.lwsite.net:9200"]
manage_template => false
index => "stdin_test-%{+YYYY.MM.dd}"
document_type => "stdin_test"
ssl => true
ssl_certificate_verification => false
truststore => "/home/admin/server/elasticsearch-current/config/truststore.jks"
truststore_password => changeit
user => logstash
password => logstash
}
}
其中,/home/admin/server/elasticsearch-current/config/truststore.jk
s 也是由之前的 demo 腳本生成的。
重啟 logstash 之后可以正確訪問。
即使 ssl_certificate_verification 設(shè)置為 false,也必須配置 truststore ,否則會(huì)報(bào)錯(cuò):
logstash unable to find valid certification path to requested target,參考 issue 鏈接:https://github.com/logstash-plugins/logstash-output-http/issues/21,我們必須保證 truststore 文件存在可讀。
一個(gè)簡(jiǎn)單的例子
上一節(jié)我們介紹了如何整合 logstash 至 searchguard,現(xiàn)在我們要在 stdin_test 這個(gè) topic 里面造些數(shù)據(jù)進(jìn)行集成測(cè)試,我們當(dāng)然用 filebeat 推送數(shù)據(jù)至 kafka,filebeat 部署在 172.16.134.37,配置如下:
首先是主配置文件 /home/admin/server/filebeat-current/filebeat.yml
:
filebeat:
config_dir: /home/admin/server/filebeat-current/conf.d
output.kafka:
hosts: ["v134037.yn1.lwsite.net:9092"]
topic: '%{[type]}'
partition.round_robin:
reachable_only: false
required_acks: 1
compression: gzip
max_message_bytes: 10485760
然后是對(duì)應(yīng)的采集 stdin_test 的配置文件 /home/admin/server/filebeat-current/conf.d/stdin_test.yml
:
filebeat.prospectors:
- input_type: log
paths:
- /tmp/stdin_test.log
document_type: stdin_test
OK,接下來我們灌簡(jiǎn)單數(shù)據(jù)至文件:
echo "1" >> /tmp/stdin_test.log
在 Kibana 添加 index 的時(shí)候發(fā)現(xiàn)無法獲取,排查了一下可以得知 Kafka 是有 topic 新建并且有數(shù)據(jù)的:
/home/admin/server/kafka-current/bin/kafka-topics.sh --list --zookeeper 172.16.134.37:2181
/home/admin/server/kafka-current/bin/kafka-console-consumer.sh --zookeeper 127.0.0.1:2181 --topic stdin_test --from-beginning
然后排查下 logstash DEBUG 日志:
[2017-07-13T15:06:14,376][WARN ][logstash.outputs.elasticsearch] Failed action. {:status=>403, :action=>["index", {:_id=>nil, :_index=>"stdin_test-2017.07.13", :_type=>"stdin_test", :_routing=>nil}, 2017-07-13T07:06:14.280Z %{host} {
"@timestamp":"2017-07-13T07:06:13.054Z","beat":{"hostname":"v134037.yn1","name":"v134037.yn1","version":"5.2.1"},"input_type":"log","message":"1","offset":6,"source":"/tmp/stdin_test.log","type":"stdin_test"}], :response=>{"index"=>{
"_index"=>"stdin_test-2017.07.13", "_type"=>"stdin_test", "_id"=>nil, "status"=>403, "error"=>{"type"=>"security_exception", "reason"=>"no permissions for indices:admin/create"}}}}
注意最后的報(bào)錯(cuò) no permissions for indices:admin/create
,可以得知 logstash 沒有對(duì)應(yīng)權(quán)限進(jìn)行 indices 新建。按照官方的建議,對(duì) searchguard 的配置文件進(jìn)行修改 /home/admin/server/elasticsearch-5.2.1/plugins/search-guard-5/sgconfig/sg_roles.yml
,注意只修改 sg_logstash
這個(gè)角色的配置:
...
sg_logstash:
cluster:
- indices:admin/template/get
- indices:admin/template/put
- CLUSTER_MONITOR
- CLUSTER_COMPOSITE_OPS
indices:
'logstash-*':
'*':
- CRUD
- CREATE_INDEX
'stdin_test-*': # 修改這里,添加對(duì)應(yīng)權(quán)限
'*':
- CRUD
- CREATE_INDEX
'*beat*':
'*':
- CRUD
- CREATE_INDEX
...
發(fā)現(xiàn)修改后重啟沒有卵用,看到了官方的建議說需要用腳本刷下配置:
/home/admin/server/elasticsearch-current/plugins/search-guard-5/tools/sgadmin.sh -cd /home/admin/server/elasticsearch-current/plugins/search-guard-5/sgconfig -cn lw-daily -ks /home/admin/server/elasticsearch-current/config/kirk.jks -ts /home/admin/server/elasticsearch-current/config/truststore.jks -nhnv
官方說只要一個(gè)節(jié)點(diǎn)刷就可以全局生效,但是我發(fā)現(xiàn)不行,所以我是全局所有節(jié)點(diǎn)都進(jìn)行了這個(gè)操作的。重啟試下是否數(shù)據(jù)可以被 Kibana 識(shí)別,發(fā)現(xiàn)還是不行,這個(gè)時(shí)候看了下 Kibana 的日志發(fā)現(xiàn)如下報(bào)錯(cuò):
[2017-07-13T15:49:28,591][INFO ][c.f.s.c.PrivilegesEvaluator] No index-level perm match for User [name=kibanaserver, roles=[]] [IndexType [index=stdin_test-2017.07.13, type=*]] [Action [indices:admin/mappings/fields/get]] [RolesCheck
ed [sg_kibana_server, sg_own_index, sg_public]]
[2017-07-13T15:49:28,591][INFO ][c.f.s.c.PrivilegesEvaluator] No permissions for {sg_public=[IndexType [index=stdin_test-2017.07.13, type=*]], sg_own_index=[IndexType [index=stdin_test-2017.07.13, type=*]], sg_kibana_server=[IndexTyp
e [index=stdin_test-2017.07.13, type=*]]}
也是權(quán)限的問題,按照和之前一樣的方式修改權(quán)限:
...
sg_kibana:
cluster:
- CLUSTER_COMPOSITE_OPS_RO
indices:
'*':
'*':
- READ
- indices:admin/mappings/fields/get*
'?kibana':
'*':
- ALL
...
并且刷新后,重啟 Kibana,以 kibanaro 角色登錄(默認(rèn)密碼 kibanaro),再灌入測(cè)試數(shù)據(jù)至日志文件后,就可以正確獲取 indices 數(shù)據(jù)。
小結(jié)
本文介紹了如何使用 searchguard 對(duì) ES 進(jìn)行 https 和 indices 粒度 ACL 的安全賦能,以及一個(gè)短小的例子。下一篇我將寫一下如何整合 Kerberos 雙邊認(rèn)證進(jìn)行進(jìn)一步加固,以及如何使用 restful API 對(duì) ES 進(jìn)行訪問。
參考文獻(xiàn)
- http://floragunncom.github.io/search-guard-docs/installation.html
- http://floragunncom.github.io/search-guard-docs/quickstart.html
- http://floragunncom.github.io/search-guard-docs/kibana.html
- http://floragunncom.github.io/search-guard-docs/logstash.html
- http://floragunncom.github.io/search-guard-docs/sgadmin.html