看了这么多关于ES安全认证的文,我决定自己动手写一篇

16,877 阅读4分钟

如题,这两天接到一个新的业务需求,需要给自建集群的elasticsearch增加安全认证。如果你不了解elasticsearch的话,建议可以自行Google一下,或者看这里->elasticsearch

接到新需求后,先将需求拆分。现有的情况是自建集群中的elasticsearch不支持TLS加密通信,且现有的访问方式是可以匿名访问。那我们增加安全认证的话,主要就是要实现以下两个目标:

  • 支持TLS加密通信,禁止http的方式访问集群
  • 提供自定义内置用户的功能,支持自定义用户名与密码,禁止匿名访问

然后我就一顿 Google,发现网上关于elasticsearch的文章都是一个样,而且普遍是抄袭官方文档的,Google一下就发现,内容都是一样的,真的是无了大语。于是我就下苦功,狠啃官方文档,终于搞明白了如何通过eck- operator的方式来给es集群增加安全认证。


支持TLS加密通信

elasticsearch从6.8.0和7.1.0之后的版本,都是默认支持安全功能,如下所示:

  • TLS 功能,可对通信进行加密
  • 文件和原生 Realm,可用于创建和管理用户
  • 基于角色的访问控制,可用于控制用户对集群 API 和索引的访问权限;通过针对 Kibana Spaces 的安全功能,还可允许在 Kibana 中实现多租户

如果你发现的你自建的es集群不支持,那很有可能是配置eck-operator的时候将其禁用掉了,这个很好解决,通过配置项即可解决。

xpack.security.enabled: true

xpack.security.transport.ssl.enabled: true

xpack.security.http.ssl.enabled: true

需要注意的是,xpack.security.enabled默认是true,如果设置为false,则关闭了安全功能,此时es集群则可以通过http直接访问,在生产模式中不推荐这么使用。

按照如上配置之后,重启es集群,你就会发现无法再通过http的方式访问了,但巧的是,你用https的方式也访问不了,咋回事呢,继续往下看。

关于xpack的更多可选配置项,可参考文档 -> anonymous-access-settings

自定义用户

书接上文,开启TLS加密通信之后,则无法通过http的方式访问,只能通过https+用户名密码的方式访问。 市面上能过查到的文章大多数是通过docker run的方式来配置生成自定义用户的,但是这种方法在实际的生产生产中是不太适用的,因为实际在集群中配置elasticsearch我们是通过eck-operator的方式来配置拉起的,而我们也旨在通过配置来创建我们的自定义用户,而非再多此一举通过docker run的方式来。

市面上常见的方式(十篇博客有十一篇是这种方式:

# create a folder with the 2 files
mkdir filerealm
touch filerealm/users filerealm/users_roles

# create user 'myuser' with role 'monitoring_user'
docker run \
    -v $(pwd)/filerealm:/usr/share/elasticsearch/config \
    docker.elastic.co/elasticsearch/elasticsearch:8.3.3 \
    bin/elasticsearch-users useradd myuser -p mypassword -r monitoring_user

# create a Kubernetes secret with the file realm content
kubectl create secret generic my-file-realm-secret --from-file filerealm

这种方式的出处是哪里呢,当然是在官方文档中了

见这里:Users and Roles

而我更推荐的方法是这一种(同样也在官方文档中有介绍:

新建一个文件:

vim secret-basic-auth.yaml

写入以下内容,可以自行配置username,password等字段:

apiVersion: v1
kind: Secret
metadata:
  name: secret-basic-auth
type: kubernetes.io/basic-auth
stringData:
  username: test    # required field for kubernetes.io/basic-auth
  password: test123 # required field for kubernetes.io/basic-auth
  roles: superuser  # optional, not part of kubernetes.io/basic-auth

创建secret:

kubectl apply -f secret-basic-auth.yaml

再新建一个文件

vim es-main.yaml

写入以下内容

apiVersion: elasticsearch.k8s.elastic.co/v1
kind: Elasticsearch
metadata:
  name: es-main
spec:
  version: 8.3.3
  auth:
    fileRealm:
    - secretName: secret-basic-auth
  nodeSets:
  - name: default
    count: 1

创建elasticsearch

kubectl apply -f es-main.yaml

在es-main创建成功之后,我们再次通过用户名密码+https的方式访问es集群

curl -u "test:test123" -k "https://localhost:9200"
{
apiVersion: elasticsearch.k8s.elastic.co/v1
  "name" : "es-main-es-default-0",
  "cluster_name" : "es-main",
  "cluster_uuid" : "jnnz24HzR3uuTT3o6ReQDA",
  "version" : {
    "number" : "8.3.3",
    "build_flavor" : "default",
    "build_type" : "docker",
    "build_hash" : "801fed82df74dbe537f89b71b098ccaff88d2c56",
    "build_date" : "2022-07-23T19:30:09.227964828Z",
    "build_snapshot" : false,
    "lucene_version" : "9.2.0",
    "minimum_wire_compatibility_version" : "7.17.0",
    "minimum_index_compatibility_version" : "7.0.0"
  },
  "tagline" : "You Know, for Search"
}

我们可以看到此时可以成功访问的到我们的es集群。

当然了,以上只是一个简单的demo,在实际的生产环境中,还要考虑的es组件的配置要适配其他的组件,以及考虑到上下游的一个调用情况。