elasticsearch: configurando a segurança
Um dos pontos mais importantes na hora de implementar um cluster Elasticsearch são as configurações relacionadas a segurança, tanto a autenticação de usuários, quanto a forma como os nós se comunicam entre si e com os clientes.
Durante um bom tempo, a autenticação no Elasticsearch não era algo nativo, era necessário utilizar um plugin pago da própria Elastic, o antigo x-pack, um plugin de terceiros, como o Search Guard, ou implementar um proxy com autenticação básica para receber os requests e repassar para o cluster Elasticsearch.
Expor um cluster na internet sem autenticação é extremamente arriscado e é apenas uma questão de tempo para que ocorra algum vazamento ou perda de dados.
A partir das versões 6.8
e 7.1
a Elastic passou a incluir a possibilidade de habilitar a autenticação básica de forma nativa e sem custos com a licença Basic
e a partir da versão 8.0
as funcionalidades de segurança vem habilitadas por padrão.
Camadas de segurança
A Elastic define basicamente 3 camadas de segurança que podem ser aplicadas em um cluster.
minimal
Apenas a autenticação de usuário é habilitada, funcionada apenas para clusters que sejam single-node
, não é recomendado para produção.
basic security
Além da autenticação de usuário, a comunicação entre os nós (transport) é criptografada utilizando TLS, pode ser utilizado em produção, mas os requests de clientes para o Elasticsearch usam http
e portanto não são criptografados.
basic security + https
Utiliza TLS também para os requests feitos por clientes, é a configuração ideal para produção.
Configurando a Segurança
A versão 8
do Elasticsearch facilita bastante o processo de implementação de um cluster com a segurança habilitada, mas em alguns cenários talvez seja necessário configurar manualmente os parâmetros de segurança.
Nesse exemplo iremos configurar manualmente a segurança em um cluster de 3
nós de Elasticsearch e 1
Kibana.
Nessa configuração os nós de Elasticsearch se comunicam utilizando TLS, essa comunicação entre os nós utiliza um protocolo chamado de transport e a segurança é habilitada através dos parâmetros xpack.security.transport.ssl.*
, além disso a comunicação dos clientes com qualquer nó do cluster utiliza requisições REST via HTTPS, a segurança na comunicação com os clientes é habilitada através dos parâmetros xpack.security.http.ssl.*
.
Para que essa comunicação seja possível precisamos de certificados para cada nó e uma autoridade certificadora para criar os certificados.
Instalando o Elasticsearch
Nesse exemplo iremos utilizar servidores com Rocky Linux 8 e instalar o Elasticsearch a partir do pacote rpm
, sem adicionar o repositório.
$ wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.4.3-x86_64.rpm
$ sudo rpm -ivh elasticsearch-8.4.3-x86_64.rpm
Durante o processo de instalação é executada uma autoconfiguração de segurança que cria certificados para o nó e o arquivo elasticsearch.keystore
com as chaves para esses certificados, como queremos realizar uma configuração manual, iremos remover os certificados criados e também o arquivo elasticsearch.keystore
.
$ sudo rm -rf /etc/elasticsearch/certs
$ sudo rm -f /etc/elasticsearch/elasticsearch.keystore
Bootstrap Checks
Durante a inicialização o elasticsearch vai realizar algumas validações para saber se o processo consegue alocar memória suficiente, para isso precisamos alterar tanto o arquivo /etc/security/limits.conf
quanto adicionar uma configuração extra para o serviço systemd
do elasticsearch.
No arquivo /etc/security/limits.conf
adicionamos as linhas abaixo.
elasticsearch soft memlock unlimited
elasticsearch hard memlock unlimited
Para o serviço systemd
precisamos antes criar o diretório /etc/systemd/system/elasticsearch.service.d
$ sudo mkdir /etc/systemd/system/elasticsearch.service.d
Na sequência adicionamos as linhas abaixo no arquivo /etc/systemd/system/elasticsearch.service.d/override.conf
[Service]
LimitMEMLOCK=infinity
Como alteramos um serviço systemd
, precisamos executar um daemon-reload
.
$ sudo systemctl daemon-reload
Criando uma Autoridade Certificadora (CA)
Após a instalação do Elasticsearch, precisamos agora criar uma autoridade certificadora para gerar os certificados de cada nó, para isso iremos utilizar o comando elasticsearch-certutil
no modo ca
em um dos nós.
$ sudo /usr/share/elasticsearch/bin/elasticsearch-certutil ca --pem -pass
Esse comando irá gerar um arquivo .zip
contendo a chave privada e o certificado, será solicitado uma senha pra chave privada e o nome do arquivo.
This tool assists you in the generation of X.509 certificates and certificate
signing requests for use with SSL/TLS in the Elastic stack.
The 'ca' mode generates a new 'certificate authority'
This will create a new X.509 certificate and private key that can be used
to sign certificate when running in 'cert' mode.
Use the 'ca-dn' option if you wish to configure the 'distinguished name'
of the certificate authority
By default the 'ca' mode produces a single PKCS#12 output file which holds:
* The CA certificate
* The CA's private key
If you elect to generate PEM format certificates (the -pem option), then the output will
be a zip file containing individual files for the CA certificate and private key
Enter password for CA Private key :
Please enter the desired output file [elastic-stack-ca.zip]:
O arquivo elastic-stack-ca.zip
será criado no caminho /usr/share/elasticsearch
e iremos copiá-lo para o diretório /etc/elasticsearch/certs
.
$ sudo mkdir /etc/elasticsearch/certs
$ sudo cp /usr/share/elasticsearch/elastic-stack-ca.zip /etc/elasticsearch/certs
$ sudo unzip /etc/elasticsearch/certs/elastic-stack-ca.zip -d /etc/elasticsearch/certs/
Ao descompactarmos o arquivo elastic-stack-ca.zip
teremos os arquivos ca.crt
e ca.key
/etc/elasticsearch
└── certs
└── ca
├── ca.crt
└── ca.key
Criando os certificados para os nós
Podemos criar um certificado para as comunicações transport e outro certificado diferente para as comunicações https, mas nesse exemplo iremos criar apenas um certificado por nó.
Para criar os certificados utilizaremos novamente o comando elasticsearch-certutil
, dessa vez no modo cert
.
$ sudo /usr/share/elasticsearch/bin/elasticsearch-certutil cert --silent --pem \
--ca-key /etc/elasticsearch/certs/ca/ca.key \
--ca-cert /etc/elasticsearch/certs/ca/ca.crt --ca-pass SENHA-CHAVE-CA \
--in /tmp/instances.yml --out nodes.zip --pass PASSPHRASE-CERTIFICADOS
Onde os parâmetros são:
--silent
: exibe o mínimo possível como output--pem
: gera certificados no formato PEM, ou seja, um arquivo.crt
e um arquivo.key
--ca-key
: caminho para a chave privada da CA--ca-cert
: caminho para o certificado da CA--ca-pass
: senha da chave privada da CA--in
: arquivo.yml
com o nome, dns e ip de cada nó--out
: nome do arquivo zip onde os certificados serão salvos--pass
: passphrase para os certificados dos nós
Antes de executar o comando precisamos criar o arquivo instances.yml
no seguinte formato:
instances:
- name: "node-name"
ip: ["ip"]
dns: ["node-name", "node-name.domain.name]
Nesse arquivo colocamos todos os IPs que o nó possui e todas as entradas DNS que ele responde.
O arquivo instances.yml
do nosso exemplo é o seguinte.
instances:
- name: "es01"
ip: ["10.0.0.101"]
dns: ["es01", "es01.lab", "es01.lab.local"]
- name: "es02"
ip: ["10.0.0.102"]
dns: ["es02", "es02.lab", "es02.lab.local"]
- name: "es03"
ip: ["10.0.0.103"]
dns: ["es03", "es03.lab", "es03.lab.local"]
Após a execução do comando o arquivo nodes.zip
será criado no caminho /usr/share/elasticsearch
, vamos copiá-lo para o caminho /etc/elasticsearsh/certs
.
$ sudo cp /usr/share/elasticsearch/nodes.zip /etc/elasticsearch/certs/
$ sudo unzip /etc/elasticsearch/certs/nodes.zip -d /etc/elasticsearch/certs/
Será criado então um diretório para cada nó contendo o arquivo .crt
e .key
do nó.
Archive: /etc/elasticsearch/certs/nodes.zip
creating: /etc/elasticsearch/certs/es01/
inflating: /etc/elasticsearch/certs/es01/es01.crt
inflating: /etc/elasticsearch/certs/es01/es01.key
creating: /etc/elasticsearch/certs/es02/
inflating: /etc/elasticsearch/certs/es02/es02.crt
inflating: /etc/elasticsearch/certs/es02/es02.key
creating: /etc/elasticsearch/certs/es03/
inflating: /etc/elasticsearch/certs/es03/es03.crt
inflating: /etc/elasticsearch/certs/es03/es03.key
Na sequência precisamos copiar o conteúdo do caminho /etc/elasticsearch/certs
no nó onde criamos a CA e o certificado para os outros nós que farão parte do cluster.
Configurando a segurança e iniciando o cluster
Antes de iniciarmos os nós do cluster, precisamos configurar as opções de segurança no arquivo elasticsearch.yml
de cada nó, criar o arquivo elasticsearch.keystore
e adicionar a passphrase da chave de cada nó.
Para criarmos o arquivo elasticsearch.keystore
usamos o seguinte comando em cada um dos nós.
$ sudo /usr/share/elasticsearch/bin/elasticsearch-keystore create
$ sudo sh -c 'echo "passphrase" | /usr/share/elasticsearch/bin/elasticsearch-keystore add --stdin xpack.security.transport.ssl.secure_key_passphrase -f'
$ sudo sh -c 'echo "passphrase" | /usr/share/elasticsearch/bin/elasticsearch-keystore add --stdin xpack.security.http.ssl.secure_key_passphrase -f'
$ sudo chmod 0660 /etc/elasticsearch/elasticsearch.keystore
Com o keystore criado e configurado, usamos o seguinte arquivo elasticsearch.yml
em cada um dos nós, alterando os valores específicos para cada nó.
Como exemplo para o nó es01
temos a seguinte configuração.
# es01
#
path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch
bootstrap.memory_lock: true
cluster.name: es
node.name: es01
network.host: ['10.0.0.101']
http.port: 9200
cluster.initial_master_nodes: ['es01', 'es02', 'es03']
discovery.seed_hosts: ['es01', 'es02', 'es03']
# security settings
xpack.security.enabled: true
xpack.security.autoconfiguration.enabled: false
# transport ssl
xpack.security.transport.ssl.enabled: true
xpack.security.transport.ssl.key: certs/es01/es01.key
xpack.security.transport.ssl.certificate: certs/es01/es01.crt
xpack.security.transport.ssl.certificate_authorities: certs/ca/ca.crt
## http ssl
xpack.security.http.ssl.enabled: true
xpack.security.http.ssl.key: certs/es01/es01.key
xpack.security.http.ssl.certificate: certs/es01/es01.crt
xpack.security.http.ssl.certificate_authorities: certs/ca/ca.crt
Após alterar a configuração nos 3
nós, podemos iniciar cada um.
$ sudo systemctl start elasticsearch
Criando senha para os usuários de sistema
Com o cluster no ar precisamos agora de um usuário para podermos nos autenticar, sendo assim iremos resetar a senha do usuário de sistema elastic
.
$ sudo /usr/share/elasticsearch/bin/elasticsearch-reset-password --url "https://es01:9200" -u elastic
Esse comando irá se conectar no Elasticsearch do nó es01
e resetar a senha do usuário elastic
para um valor aleatório que será exibido na tela, caso deseje escolher uma senha, basta utilizar o parâmetro -i
no final do comando.
Com o usuário e senha iremos validar o estado do cluster utilizando o curl
, mas como estamos utilizando uma CA local precisaremos passar o parâmetro -k
ou apontar para o certificado da CA.
$ sudo curl -XGET https://es01:9200/_cluster/health?pretty -u elastic:SENHA -k
ou
$ sudo curl -XGET https://es01:9200/_cluster/health?pretty -u elastic:SENHA --cacert /etc/elasticsearch/certs/ca/ca.crt
RESPOSTA
{
"cluster_name" : "es",
"status" : "green",
"timed_out" : false,
"number_of_nodes" : 3,
"number_of_data_nodes" : 3,
"active_primary_shards" : 2,
"active_shards" : 4,
"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
}
Instalando o Kibana
Para o Kibana iremos utilizar apenas um servidor, também com Rocky Linux 8.
$ wget https://artifacts.elastic.co/downloads/kibana/kibana-8.4.3-x86_64.rpm
$ sudo rpm -ivh kibana-8.4.3-x86_64.rpm
Criando certificado para o Kibana
O certificado para o Kibana pode ser criado da mesma forma que os certificados dos nós, apenas alterando o arquivo instance.yml
.
instances:
- name: "kibana"
ip: ["10.0.0.104"]
dns: ["kibana", "kibana.lab", "kibana.lab.local"]
$ sudo /usr/share/elasticsearch/bin/elasticsearch-certutil cert --silent --pem \
--ca-key /etc/elasticsearch/certs/ca/ca.key \
--ca-cert /etc/elasticsearch/certs/ca/ca.crt --ca-pass SENHA-CHAVE-CA \
--in /tmp/instances.yml --out kibana.zip --pass PASSPHRASE-CERTIFICADOS
No Kibana temos duas configurações de TLS, a da comunicação com o Elasticsearch, onde o Kibana se comporta como um cliente qualquer, e a comunicação com o usuário através do browser, assim como no caso das configurações de transport e https dos nós de Elasticsearch, também podemos utilizar certificados diferentes se quisermos.
Configurando a segurança no Kibana
Na versão 8
do Elasticsearch não é mais possível utilizar o usuário elastic
na configuração do Kibana, devemos utilizar o usuário kibana_system
ou utilizar uma conta de serviço.
Para utilizar a conta kibana_system
será precisar resetar a senha da mesma forma que foi feito para o usuário elastic
.
Nesse exemplo iremos criar uma conta de serviço para a comunicação entre o Kibana e o Elasticsearch.
$ curl -X POST "https://es01:9200/_security/service/elastic/kibana/credential/token/kibanatoken?pretty" -u elastic:senha -k
RESPOSTA
{
"created" : true,
"token" : {
"name" : "kibanatoken",
"value" : "token"
}
}
Iremos adicionar o token e a passphrase do certificado no keystore do Kibana, que é criado automaticamente durante a instalação.
$ sudo sh -c 'echo "passphrase" | /usr/share/kibana/bin/kibana-keystore add elasticsearch.ssl.keyPassphrase --stdin'
$ sudo sh -c 'echo "passphrase" | /usr/share/kibana/bin/kibana-keystore add server.ssl.keyPassphrase --stdin'
$ sudo sh -c 'echo "token" | /usr/share/kibana/bin/kibana-keystore add elasticsearch.serviceAccountToken --stdin'
Antes de editarmos o arquivo kibana.yml
, precisamos copiar o certificado da CA e os certificados do Kibana para o servidor do Kibana, para isso é preciso criar o caminho /etc/kibana/certs
.
kibana.yml
server.port: 5601
server.host: "10.0.0.104"
server.publicBaseUrl: "https://kibana:5601"
server.maxPayload: 5048576
server.name: "kibana"
# elasticsearch
elasticsearch.hosts: ["https://es01:9200", "https://es02:9200", "https://es03:9200"]
elasticsearch.ssl.certificate: /etc/kibana/certs/kibana/kibana.crt
elasticsearch.ssl.key: /etc/kibana/certs/kibana/kibana.key
elasticsearch.ssl.certificateAuthorities: [ "/etc/kibana/certs/ca/ca.crt" ]
# server https
server.ssl.enabled: true
server.ssl.certificate: /etc/kibana/certs/kibana/kibana.crt
server.ssl.key: /etc/kibana/certs/kibana/kibana.key
server.ssl.certificateAuthorities: [ "/etc/kibana/certs/ca/ca.crt" ]
Para iniciar o Kibana usamos o systemctl
.
$ sudo systemctl start kibana
Após iniciar o Kibana podemos acessar o servidor via navegador para validar que a conexão está usando TLS, será mostrado um alerta de que a conexão não é privada já que o navegador não conhece a CA local que utilizamos para gerar o certificado do Kibana, se necessário isso pode ser solucionado importando a CA local para o navegador utilizado.
Mais informações
Mais informações sobre como configurar a Segurança no Elasticsearch e outras formas de autenticação disponíveis dependendo da licença em uso podem ser encontradas na documentação oficial.