查看原文
其他

docker下elasticsearch安全插件searchguard的安装笔记

侠梦的星尘 侠梦的开发笔记 2022-09-11
前言
  • es在 6.8 和 7.1 版本后,核心安全功能(例如 TLS、文件和原生 Realm 身份验证,以及基于角色的访问控制)免费提供,如果使用的是高版本es则是开箱即用的,对于低版本的es安全功能是收费的,这里使用第三方的安全框架searchguard来加固低版本的es.但本次用es7.1.1来演示。 网上容器化安装的资料很少,这里 记录一下使用docker来安装。

  • 所有操作均在考虑无外部网情况下离线安装(除了依赖的操作系统镜像)。

准备

    数据卷目录映射

  • 方便配置修改

  • 数据需要持久化到宿主机。

材料清单

  1. es_guard_variable

  2. ├── Dockerfile

  3. ├── elasticsearch-7.1.1-linux-x86_64.tar.gz

  4. ├── search-guard-7-7.1.1-35.0.0.zip

  5. └── start.sh


  6. search-guard-ssl-es-7.0.0.zip

编写dockerfile和启动脚本
  • dockerfile

  1. FROM nimmis/java-centos:oracle-8-jdk

  2. ENV ES_VERSION=7.1.1 \

  3. SG_PREFIX=7 \

  4. SG_VERSION=7.1.1-35.0.0


  5. #添加es并解压到目录

  6. ADD ./elasticsearch-$ES_VERSION-linux-x86_64.tar.gz /data/es

  7. #RUN mv elasticsearch-$ES_VERSION /data/es/elasticsearch


  8. #使用COPY避免解压,方便后续使用isntall安装zip包

  9. COPY ./search-guard-$SG_PREFIX-$SG_VERSION.zip /data/es

  10. COPY ./start.sh /data/es


  11. #由于es不能使用root启动,创建一个elasticsearch用户

  12. RUN chmod +x /data/es/start.sh \

  13. && groupadd -g 1003 elasticsearch \

  14. && adduser -u 1003 -g 1003 -s /sbin/nologin elasticsearch \

  15. && chown -R elasticsearch:elasticsearch /data/es


  16. EXPOSE 9200 9300

  17. ENTRYPOINT ["/data/es/start.sh"]

  • start.sh脚本

  1. #!/bin/bash

  2. ES_HOME=/data/es/elasticsearch-$ES_VERSION

  3. SG_ZIP_PATH=/data/es/search-guard-$SG_PREFIX-$SG_VERSION.zip


  4. #es和searchguard插件的配置目录

  5. ES_CONFIG=$ES_HOME/config

  6. SG_CONFIG=$ES_HOME/plugins/search-guard-$SG_PREFIX/sgconfig


  7. #替换变量(运行时替换没有必要了,由于有数据卷,改的都在宿主机上了)

  8. #sed -i "s/Xms_var/${Xms_size:-200m}/g" $ES_CONFIG/jvm.options

  9. #sed -i "s/Xmx_var/${Xmx_size:-200m}/g" $ES_CONFIG/jvm.options



  10. #判断是否已经安装过sg

  11. if [ -d "$ES_HOME/plugins/search-guard-$SG_PREFIX" ]; then

  12. rm -rf $ES_HOME/plugins/search-guard-$SG_PREFIX

  13. fi

  14. rm -rf $SG_CONFIG


  15. #使用elasticsearch用户 安装,安装时需要手动输入 y并回车,这里用脚本代替

  16. su elasticsearch -s /bin/bash -c "/bin/echo -e 'y\n' | $ES_HOME/bin/elasticsearch-plugin install file://$SG_ZIP_PATH"


  17. #将客户端证书和信任证书移动到plugins/search-guard-$SG_PREFIX/sgconfig目录下

  18. #由于后续可能会修改增加权限,改为映射数据卷,数据卷也不得行,容器被删除后,宿主机文件也没了

  19. cp $ES_CONFIG/searchguard/* $SG_CONFIG

  20. cp $ES_CONFIG/truststore.jks $SG_CONFIG


  21. #如果直接映射SG_HOME,则会在创建容器时就创建目录,采用映射一个临时目录,然后在脚本中拷贝sg配置

  22. #cp -rf $ES_HOME/temp_sgconfig/* $SG_CONFIG



  23. #给sgadmin授权,es运行起来后需要用这个脚本来插入配置。

  24. chown -R elasticsearch:elasticsearch $ES_HOME

  25. chmod -R 777 $ES_HOME

  26. echo "es配置目录:"

  27. ls $ES_CONFIG


  28. echo "=========================="


  29. echo "sg插件目录:"

  30. ls $SG_CONFIG


  31. #运行es

  32. su elasticsearch -s /bin/bash -c "$ES_HOME/bin/elasticsearch"

配置searchguard证书

  • 解压ssl配置文件,修改脚本:search-guard-ssl-es-7.0.0/example-pki-scripts/example.sh


  • 脚本文件介绍

    • CA密码:根证书密码

    • TS密码:信任证书密码

    • Ks密码:keystore密码


  • 如果分不清,可以将密码全部设置成一样的,如下:


  • 宿主机外部配置

  • 我设置了log4j2日志级别为debug,方便安装过程中排查问题。

  • ssl中执行example.sh生成的3个脚本:

    • hyq_cluster2-keystore.jks

    • node-0-keystore.jks

    • truststore.jks


  • 将生成文件复制到宿主机路径:/data/volumn/es/config,目录结构如下:


  1. ├── config ==============》 es的配置目录

  2. │   ├── data

  3. │   ├── elasticsearch.keystore

  4. │   ├── elasticsearch.yml

  5. │   ├── jvm.options

  6. │   ├── log4j2.properties

  7. │   ├── logs

  8. │   ├── node-0-keystore.jks

  9. │   ├── scripts

  10. │   └── truststore.jks

  11. └── sgconfig ==============》searchguard的配置目录

  12. ├── hyq_cluster2-keystore.jks

  13. ├── sg_action_groups.yml

  14. ├── sg_config.yml

  15. ├── sg_internal_users.yml

  16. ├── sg_roles_mapping.yml

  17. ├── sg_roles.yml

  18. ├── sg_tenants.yml

  19. └── truststore.jks

  • elasticsearch.yml中配置

  1. #transport层

  2. searchguard.ssl.transport.enabled: true

  3. searchguard.ssl.transport.keystore_filepath: node-0-keystore.jks

  4. searchguard.ssl.transport.keystore_password: 12345678

  5. searchguard.ssl.transport.truststore_filepath: truststore.jks

  6. searchguard.ssl.transport.truststore_password: 12345678

  7. searchguard.ssl.transport.enforce_hostname_verification: false

  8. searchguard.ssl.transport.resolve_hostname: false



  9. #http层

  10. searchguard.ssl.http.enabled: false

  11. searchguard.ssl.http.keystore_filepath: node-0-keystore.jks

  12. searchguard.ssl.http.keystore_password: 12345678

  13. searchguard.ssl.http.truststore_filepath: truststore.jks

  14. searchguard.ssl.http.truststore_password: 12345678


  15. searchguard.authcz.admin_dn:

  16. - CN=hyq_cluster2, OU=client, O=client, L=Test, C=DE

构建运行
  • 构建镜像,运行容器

  1. docker rm es_with_sg1

  2. docker rmi es_with_sg:1.0

  3. docker build -t es_with_sg:1.0 .



  4. docker run -h es_with_sg1 -it \

  5. --name es_with_sg1 \

  6. --network=host \

  7. -p 9200:9200 -p 9300:9300 \

  8. -e client_node_cert_name=hyq_cluster2 \

  9. -v /data/volumn/es/config:/data/es/elasticsearch-7.1.1/config \

  10. es_with_sg:1.0

  • 将配置写入运行中的es

  1. docker exec -it es_with_sg1 /bin/bash


  2. ./plugins/search-guard-7/tools/sgadmin.sh -cn hyq_cluster -h 0.0.0.0 -cd plugins/search-guard-7/sgconfig -ks plugins/search-guard-7/sgconfig/hyq_cluster2-keystore.jks -kspass 12345678 -ts plugins/search-guard-7/sgconfig/truststore.jks -tspass 12345678 -nhnv


  • 修改密码

  • 使用plugins/search-guard-7/tools/hash.sh,生成密码。

  • 如:hbash -p huangyq@123

  • 修改内置用户密码(search-guard-7/sgconfig/sginternalusers.yml)

客户端连接(不启用https)

  • The TransportClient is deprecated in favour of the Java High Level REST Client and will be removed in Elasticsearch 8.0. The migration guide describes all the steps needed to migrate

    • 官方文档显示将在8.0以后的版本移除transport连接方式,所以我们连接es使用Rest的方式。


  • elasticsearch.yml中配置searchguard.ssl.http.enabled: false

  • 使用logstash的generator生成测试数据,入es

  1. input {

  2. generator {

  3. count => 100

  4. message => '{"a":"1","b":"huangyunquan"}'

  5. codec => json

  6. }

  7. }

  8. output {

  9. elasticsearch {

  10. hosts => ["http://localhost:9200"]

  11. index => "hyq-%{+YYYY.MM.dd}"

  12. user => "admin"

  13. password => "huangyq@123"

  14. }

  15. }


  16. bin/logstash -f config/test_es.conf


  • java客户端

    • 没有开启https,只需要认证用户名密码即可。

    • 开启https,需要添加信任证书。

  1. public static void init_with_https_auth() throws Exception {

  2. Path keyStorePath = Paths.get(Rest.class.getClass().getResource("/truststore.jks").toURI());

  3. String keyStorePass = "12345678";

  4. KeyStore truststore = KeyStore.getInstance("jks");

  5. try (InputStream is = Files.newInputStream(keyStorePath)) {

  6. truststore.load(is, keyStorePass.toCharArray());

  7. }


  8. SSLContextBuilder sslBuilder = SSLContexts.custom()

  9. .loadTrustMaterial(truststore, null);

  10. final SSLContext sslContext = sslBuilder.build();

  11. HttpHost[] htps = new HttpHost[]{

  12. new HttpHost(host,port,"https")};


  13. final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();

  14. credentialsProvider.setCredentials(AuthScope.ANY,

  15. new UsernamePasswordCredentials(username, password));

  16. restClient = RestClient.builder(htps)

  17. .setHttpClientConfigCallback(httpClientBuilder ->{

  18. httpClientBuilder.setSSLContext(sslContext);

  19. httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);

  20. return httpClientBuilder;

  21. } ).build();

  22. }

疑难解答
  1. Q: java.nio.file.AccessDeniedException,unable to create temporary keystore at ..elasticsearch.keystore.tmp], please check filesystem permissions?

  2. A: 由于在容器中创建了一个用户,同时又映射了数据卷,所以在config目录下需要给目录授权。容器内的用户和宿主机用户,是通过uid和gid来验证


  3. Q: Keystore was tampered with, or password was incorrect?

  4. A:使用example生成的密码一定要和elasticsearch.yml配置的一样,还有就是truststore_password、keystore_password配置项不能少,否则也会报这个错,笔者被这个问题坑惨了。


  5. Q: ERR

  6. Seems you use a client certificate but this one is not registered as admin_dn

  7. Make sure elasticsearch.yml on all nodes contains:

  8. searchguard.authcz.admin_dn?

  9. A: gen_client_node_cert的第一个参数一定要和elasticsearch.yml中配置的searchguard.authcz.admin_dn配置项下的 CN相同。


  10. Q: searchguard index does not exist yet,

  11. so no need to load config on node startup. Use sgadmin to initialize cluster?

  12. A: 容器运行起来后,使用sgadmin.sh 写入配置。




  13. Q: the default discovery settings are unsuitable for production use;

  14. at least one of [discovery.seed_hosts,

  15. discovery.seed_providers, cluster.initial_master_nodes] must be configured?

  16. A: 三个属性必须在elasticsearch.yml中配置一个。


  17. Q:Host name 'xxx.ip' does not match the certificate subject provided by the peer (CN=node-0.example.com, OU=SSL, O=Test, L=Test, C=DE)?

  18. A: 本地host配置 xxx.ip node-0.example.com。


  19. Q: Search Guard not initialized (SG11). See https://docs.search-guard.com/latest/sgadmin?

  20. A: 进入容器内部es根目录下,执行sgadmin脚本写入配置。



您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存