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

前言
  • es在 6.8 和 7.1 版本后,核心安全功能(例如 TLS、文件和原生 Realm 身份验证,以及基于角色的访问控制)免费提供,如果使用的是高版本es则是开箱即用的,对于低版本的es安全功能是收费的,这里使用第三方的安全框架searchguard来加固低版本的es.但本次用es7.1.1来演示。
    网上容器化安装的资料很少,这里 记录一下使用docker来安装。
  • 所有操作均在考虑无外部网情况下离线安装(除了依赖的操作系统镜像)。
准备
  • 数据卷目录映射

    • 方便配置修改
    • 数据需要持久化到宿主机。
  • 材料清单

es_guard_variable
├── Dockerfile
├── elasticsearch-7.1.1-linux-x86_64.tar.gz
├── search-guard-7-7.1.1-35.0.0.zip
└── start.sh

search-guard-ssl-es-7.0.0.zip

编写dockerfile和启动脚本
  • dockerfile
FROM nimmis/java-centos:oracle-8-jdk
ENV ES_VERSION=7.1.1 \
	SG_PREFIX=7 \
	SG_VERSION=7.1.1-35.0.0 

#添加es并解压到目录
ADD ./elasticsearch-$ES_VERSION-linux-x86_64.tar.gz /data/es
#RUN mv elasticsearch-$ES_VERSION /data/es/elasticsearch

#使用COPY避免解压,方便后续使用isntall安装zip包
COPY ./search-guard-$SG_PREFIX-$SG_VERSION.zip /data/es
COPY ./start.sh  /data/es

#由于es不能使用root启动,创建一个elasticsearch用户
RUN chmod +x /data/es/start.sh \
  && groupadd -g 1003 elasticsearch \
  && adduser -u 1003 -g 1003  -s /sbin/nologin elasticsearch \
  && chown -R elasticsearch:elasticsearch /data/es  

EXPOSE 9200 9300
ENTRYPOINT ["/data/es/start.sh"]

  • start.sh脚本
#!/bin/bash
ES_HOME=/data/es/elasticsearch-$ES_VERSION
SG_ZIP_PATH=/data/es/search-guard-$SG_PREFIX-$SG_VERSION.zip

#es和searchguard插件的配置目录
ES_CONFIG=$ES_HOME/config
SG_CONFIG=$ES_HOME/plugins/search-guard-$SG_PREFIX/sgconfig

#替换变量(运行时替换没有必要了,由于有数据卷,改的都在宿主机上了)
#sed -i "s/Xms_var/${Xms_size:-200m}/g" $ES_CONFIG/jvm.options
#sed -i "s/Xmx_var/${Xmx_size:-200m}/g" $ES_CONFIG/jvm.options


#判断是否已经安装过sg
if [ -d "$ES_HOME/plugins/search-guard-$SG_PREFIX" ]; then
 rm -rf $ES_HOME/plugins/search-guard-$SG_PREFIX
fi
rm -rf $SG_CONFIG

#使用elasticsearch用户 安装,安装时需要手动输入 y并回车,这里用脚本代替
su elasticsearch -s /bin/bash -c "/bin/echo -e 'y\n' | $ES_HOME/bin/elasticsearch-plugin install file://$SG_ZIP_PATH"

#将客户端证书和信任证书移动到plugins/search-guard-$SG_PREFIX/sgconfig目录下
#由于后续可能会修改增加权限,改为映射数据卷,数据卷也不得行,容器被删除后,宿主机文件也没了
cp $ES_CONFIG/searchguard/*  $SG_CONFIG
cp $ES_CONFIG/truststore.jks $SG_CONFIG

#如果直接映射SG_HOME,则会在创建容器时就创建目录,采用映射一个临时目录,然后在脚本中拷贝sg配置
#cp -rf $ES_HOME/temp_sgconfig/* $SG_CONFIG


#给sgadmin授权,es运行起来后需要用这个脚本来插入配置。
chown -R elasticsearch:elasticsearch  $ES_HOME
chmod -R 777 $ES_HOME
echo "es配置目录:"
ls $ES_CONFIG

echo "=========================="

echo "sg插件目录:"
ls $SG_CONFIG

#运行es
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密码
文件名 含义 参数
gen_client_node_cert.sh 客户端证书 客户端节点名称,ks_pass,ca_pass
gen_root_ca.sh 根证书 ca_pass,ts_pass
gen_node_cert.sh 节点证书 节点编号,ks_pass,capass
  • 如果分不清,可以全部设置成一样的,如下:

配置

  • 宿主机外部配置

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

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

    • hyq_cluster2-keystore.jks
    • node-0-keystore.jks
    • truststore.jks
  • 将生成文件复制到宿主机路径:/data/volumn/es/config,目录结构如下:

├── config ==============》 es的配置目录
│   ├── data
│   ├── elasticsearch.keystore
│   ├── elasticsearch.yml
│   ├── jvm.options
│   ├── log4j2.properties
│   ├── logs
│   ├── node-0-keystore.jks
│   ├── scripts
│   └── truststore.jks
└── searchguard ==============》searchguard的配置目录
    ├── hyq_cluster2-keystore.jks
    ├── sg_action_groups.yml
    ├── sg_config.yml
    ├── sg_internal_users.yml
    ├── sg_roles_mapping.yml
    ├── sg_roles.yml
    ├── sg_tenants.yml
    └── truststore.jks
  • elasticsearch.yml中配置
#transport层
searchguard.ssl.transport.enabled: true
searchguard.ssl.transport.keystore_filepath: node-0-keystore.jks
searchguard.ssl.transport.keystore_password: 12345678
searchguard.ssl.transport.truststore_filepath: truststore.jks
searchguard.ssl.transport.truststore_password: 12345678
searchguard.ssl.transport.enforce_hostname_verification: false
searchguard.ssl.transport.resolve_hostname: false


#http层
searchguard.ssl.http.enabled: false
searchguard.ssl.http.keystore_filepath: node-0-keystore.jks
searchguard.ssl.http.keystore_password: 12345678
searchguard.ssl.http.truststore_filepath: truststore.jks
searchguard.ssl.http.truststore_password: 12345678

searchguard.authcz.admin_dn: 
- CN=hyq_cluster2, OU=client, O=client, L=Test, C=DE
构建运行
  • 构建镜像,运行容器
docker rm es_with_sg1
docker rmi es_with_sg:1.0
docker build -t es_with_sg:1.0 .


docker run -h es_with_sg1  -it \
 --name es_with_sg1 \
 --network=host \
 -p 9200:9200 -p 9300:9300 \
-e client_node_cert_name=hyq_cluster2 \
-v /data/volumn/es/config:/data/es/elasticsearch-7.1.1/config \
es_with_sg:1.0

  • 将配置写入运行中的es
docker exec -it es_with_sg1 /bin/bash

./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/sg_internal_users.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

input {
        generator {
                count => 100
                message => '{"a":"1","b":"huangyunquan"}'
                codec => json
        }
}
output {
  elasticsearch {
    hosts => ["http://localhost:9200"]
    index => "hyq-%{+YYYY.MM.dd}"
    user => "admin"
    password => "huangyq@123"
  }
}

bin/logstash -f config/test_es.conf 
  • java客户端

    • 没有开启https,只需要认证用户名密码即可。
    • 开启https,需要添加信任证书。
    public static void init_with_https_auth() throws Exception {
        Path keyStorePath = Paths.get(Rest.class.getClass().getResource("/truststore.jks").toURI());
        String keyStorePass = "12345678";
        KeyStore truststore = KeyStore.getInstance("jks");
        try (InputStream is = Files.newInputStream(keyStorePath)) {
            truststore.load(is, keyStorePass.toCharArray());
        }

        SSLContextBuilder sslBuilder = SSLContexts.custom()
                .loadTrustMaterial(truststore, null);
        final SSLContext sslContext = sslBuilder.build();
        HttpHost[] htps = new HttpHost[]{
                new HttpHost(host,port,"https")};

        final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(AuthScope.ANY,
                new UsernamePasswordCredentials(username, password));
        restClient = RestClient.builder(htps)
                .setHttpClientConfigCallback(httpClientBuilder ->{
                    httpClientBuilder.setSSLContext(sslContext);
                    httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
                    return httpClientBuilder;
                } ).build();
    }

疑难解答
 Q: java.nio.file.AccessDeniedException,unable to create temporary keystore at ..elasticsearch.keystore.tmp], please check filesystem permissions?
 A:  由于在容器中创建了一个用户,同时又映射了数据卷,所以在config目录下需要给目录授权。容器内的用户和宿主机用户,是通过uid和gid来验证
    
Q: Keystore was tampered with, or password was incorrect?
A:使用example生成的密码一定要和elasticsearch.yml配置的一样,还有就是truststore_password、keystore_password配置项不能少,否则也会报这个错,笔者被这个问题坑惨了。
   
Q: ERR
Seems you use a client certificate but this one is not registered as admin_dn
Make sure elasticsearch.yml on all nodes contains:
searchguard.authcz.admin_dn?
A: gen_client_node_cert的第一个参数一定要和elasticsearch.yml中配置的searchguard.authcz.admin_dn配置项下的 CN相同。

Q: searchguard index does not exist yet, 
so no need to load config on node startup. Use sgadmin to initialize cluster?
A: 容器运行起来后,使用sgadmin.sh 写入配置。
   


Q: the default discovery settings are unsuitable for production use;
at least one of [discovery.seed_hosts,
discovery.seed_providers, cluster.initial_master_nodes] must be configured?
A: 三个属性必须在elasticsearch.yml中配置一个。
    
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)?
A: 本地host配置 xxx.ip node-0.example.com。

Q: Search Guard not initialized (SG11). See https://docs.search-guard.com/latest/sgadmin?
A: 进入容器内部es根目录下,执行sgadmin脚本写入配置。

发布了106 篇原创文章 · 获赞 21 · 访问量 19万+

猜你喜欢

转载自blog.csdn.net/u012811805/article/details/91348067
今日推荐