ElasticSearch是一个基于Lucene的分布式搜索和分析引擎。Elasticsearch能够以快速有效的方式对各种数据进行存储和索引。当前ES已经广泛应用于各个领域,包括应用程序搜索、网站搜索、企业搜索、日志处理和分析、基础设施指标和容器监测、应用程序性能监测、地理空间数据分析和可视化、安全分析、业务分析等。由于大部分ES没有增加安全策略,导致数据可能被别人随意访问。简单放一则案例:在线交易经纪商FBS曝光20TB数据,160亿条记录。所以我们使用ES的时候要注意数据安全问题。一般来说我们的ES如果运行在内网,相对来说是比较安全的。为了保证Elasticsearch数据安全,我们需要对ES进行鉴权设计。
ES鉴权方式包括但不限于以下几种方式:
X-Pack is an Elastic Stack extension that provides security, alerting, monitoring, reporting, machine learning, and many other capabilities. By default, when you install Elasticsearch, X-Pack is installed.
X-Pack是一个Elastic Stack的扩展组建,提供了安全、警报、监视、报告、机器学习和许多其他功能。默认情况下Elasticsearch安装就会安装X-Pack。
X-pack免费提供了的账号密码认证功能,可通过在elasticsearch.yml进行本地配置。也可以通过ES的security api进行设置。
X-pack提供基于LDAP/kerbors/SAML/AD等认证收费方式。
单机版Elasticsearch认证相对来说比较简单粗暴。
打开Elasticsearch根目录下config/elasticsearch.yml文件,将xpack.security.enabled值改为true,默认ES是关闭X-pack安全配置的。
# 开启xpack安全认证,默认为false
xpack.security.enabled: true
通过systemctl 重启 ES服务,并通过浏览器访问当前ES服务,会发现弹出了用户名密码输入框。因为已经启用了安全认证,所以需要用户名密码。
为ES内置用户生成密码有两种方式:一是通过默认方式自动生成密码,一种是手动一个个用户输入密码;
设置默认密码命令:
./bin/elasticsearch-setup-passwords auto
手动输入密码命令:
./bin/elasticsearch-setup-passwords interactive
两种方式分别对内置用户:elastic、apm_system、kibana、logstash_system、beats_system、remote_monitoring_user,设置了密码。
通过浏览器访问当前ES服务,弹出用户名密码输入框,使用elastic用户及其密码进行登录。elastic用户拥有superadmin权限,自然包括web访问权限。
请参考:https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api.html
进入其中一台es安装机器,进入es安装目录(例如:/opt/elasticsearch-7.7.1),执行ll命令查看es所属用户,并执行su命令切换至es所属用户;
在es安装目录执行“./bin/elasticsearch-certutil ca”命令,生成CA证书;执行过程中需要输入CA的密码和输出文件,直接回车CA密码默认为空,输出文件位置为默认位置;
继续执行“./bin/elasticsearch-certutil cert --ca elastic-stack-ca.p12”命令,需要输入CA密码时直接回车为空,需要输入文件位置默认为空,生成证书和私钥,执行完之后证书和私钥将会生成在上一步的elastic-stack-ca.p12文件中;
移动elastic-certificates.p12文件到config目录下,复制证书elastic-certificates.p12文件到集群其他机器es目录的config目录下,特别注意,是elastic-certificates.p12;
使用es所属用户,编辑es安装目录下config/elasticsearch.yml文件,新增如下配置:
xpack.security.enabled: true
xpack.security.transport.ssl.enabled: true
xpack.security.transport.ssl.verification_mode: certificate
xpack.security.transport.ssl.keystore.path: /opt/elasticsearch-7.7.1/config/elastic-certificates.p12
xpack.security.transport.ssl.truststore.path: /opt/elasticsearch-7.7.1/config/elastic-certificates.p12
所有集群机器都需要新增;
注:/opt/elasticsearch-7.7.1/config/elastic-certificates.p12 需要改为es安装机器实际目录
执行“systemctl restart elasticsearch”重启集群所有es,稍等一会执行“systemctl status elasticsearch”查看是否重启成功,需要保证三台机器全部重启成功;(systemctl 命令切到root用户执行,执行完切回来)
在es的安装目录执行“./bin/elasticsearch-setup-passwords interactive”命令生成密码;需要对elastic、apm_system、kibana、logstash_system、beats_system、remote_monitoring_user等用户生成密码,我们密码统一用123456;
报下面这个错,请稍等一会儿再试,表示223机器es还没有重启好:
Connection failure to: http://x.x.x.x:9200/_security/_authenticate?pretty failed: 拒绝连接 (Connection refused)`
报下面这个错,表示集群没有全部重启成功
ERROR: Failed to set password for user [apm_system].
浏览器访问“http://${ip}:9200/_cluster/healthpretty”,输入用户:elastic密码:123456登陆验证集群是否开启x-pack认证成功,如果成功将会有类似如下返回:
{
"cluster_name" : "ES-cluster",
"status" : "green",
"timed_out" : false,
"number_of_nodes" : 3,
"number_of_data_nodes" : 3,
"active_primary_shards" : 5,
"active_shards" : 10,
"relocating_shards" : 0,
"initializing_shards" : 0,
"unassigned_shards" : 0,
"delayed_unassigned_shards" : 0,
"number_of_pending_tasks" : 0,
"number_of_in_flight_fetch" : 0,
"task_max_waiting_in_queue_millis" : 0,
"active_shards_percent_as_number" : 100.0
}
注:${ip}需要改成实际es安装机器ip。
Caused by: java.security.UnrecoverableKeyException: Encrypt Private Key failed: unrecognized algorit 见博客
org.elasticsearch.client
elasticsearch-rest-high-level-client
7.1.0
org.elasticsearch.client
elasticsearch-rest-client
7.1.0
org.elasticsearch
elasticsearch
7.1.0
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestClientBuilder.HttpClientConfigCallback;
import org.elasticsearch.client.RestHighLevelClient;
public class EsUtil {
public static RestHighLevelClient getClient() {
/** 用户认证对象 */
final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
/** 设置账号密码 */
credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials("elastic", "123456"));
/** 创建rest client对象 */
RestClientBuilder builder = RestClient.builder(new HttpHost("127.0.0.1", 9200))
.setHttpClientConfigCallback(new HttpClientConfigCallback() {
@Override
public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {
return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
}
});
RestHighLevelClient client = new RestHighLevelClient(builder);
return client;
}
/**
* 单条保存
* @param index
* @param id
* @param m
*/
public static void saveData(String index,String id,Map m){
try {
RestHighLevelClient client = getClient();
IndexRequest indexRequest = new IndexRequest(index)
.id( id)
.source(m);
client.index(indexRequest, RequestOptions.DEFAULT);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Date d = new Date();
String id = d.getTime()+"";
Map m = new HashMap();
m.put("id", id);
m.put("area_id", 1);
m.put("camera_id", 1);
m.put("log_time","2019-08-01 11:11:11");
m.put("age", 1);
EsUtil.saveData("global_house_list",id,m);
}
}
#是否启用es
elasticsearch.enabled = true
# es集群名称
elasticsearch.clusterName = cluster-assetMap
#es数据库用户名
elasticsearch.userName = elastic
#es数据库密码
elasticsearch.password = 123456
# es host ip 地址(单机)
elasticsearch.hosts[0] = 10.x.x.171:9200
# es host ip 地址
elasticsearch.hosts[1] = 10.x.x.172:9200
# es host ip 地址
elasticsearch.hosts[2] = 10.x.x.173:9200
# es 请求方式
elasticsearch.scheme = http
# es 连接超时
elasticsearch.connectTimeOut = 1000
# es socket 连接超时
elasticsearch.socketTimeOut = 30000
# es 请求超时
elasticsearch.connectionRequestTimeOut = 500
# es 最大连接数
elasticsearch.maxConnectNum = 100
# es 每个路由的最大连接数
elasticsearch.maxConnectNumPerRoute = 100