MaJ HowtoElastic + complements securisation

This commit is contained in:
Ludovic Poujol 2022-02-07 18:57:34 +01:00
parent ccd7ec2b5d
commit dfa80bf4cd

View file

@ -3,7 +3,7 @@ title: Howto Elasticsearch
categories: web bdd nosql
...
* Documentation : <https://www.elastic.co/guide/en/elasticsearch/reference/5.0/index.html>
* Documentation : <https://www.elastic.co/guide/en/elasticsearch/reference/7.17/index.html>
* Forum : <https://discuss.elastic.co/c/elasticsearch>
[Elasticsearch](https://www.elastic.co/fr/products/elasticsearch) est un serveur de base de données écrit en Java disposant dune interface REST HTTP. Elasticsearch est notamment utilisé dans [la stack Elastic avec Logstash et Kibana](HowtoELK).
@ -14,7 +14,7 @@ Vu le développement actif d'Elasticsearch, nous préconisons l'installation des
~~~
# apt install apt-transport-https
# echo "deb https://artifacts.elastic.co/packages/5.x/apt stable main" >> /etc/apt/sources.list.d/elastic.list
# echo "deb https://artifacts.elastic.co/packages/7.x/apt stable main" >> /etc/apt/sources.list.d/elastic.list
# wget -O /etc/apt/trusted.gpg.d/elastic.asc https://artifacts.elastic.co/GPG-KEY-elasticsearch
# dos2unix /etc/apt/trusted.gpg.d/elastic.asc
# chmod 644 /etc/apt/trusted.gpg.d/elastic.asc
@ -31,65 +31,35 @@ $ curl 127.0.0.1:9200
"cluster_name" : "my_cluster",
"cluster_uuid" : "RwTUfzym2fTq-URwSNGaeg",
"version" : {
"number" : "5.6.6",
"build_hash" : "7d99d36",
"build_date" : "2018-01-09T23:55:47.880Z",
"number" : "7.17.0",
"build_flavor" : "default",
"build_type" : "deb",
"build_hash" : "bee86328705acaa9a6daede7140defd4d9ec56bd",
"build_date" : "2022-01-28T08:36:04.875279988Z",
"build_snapshot" : false,
"lucene_version" : "6.6.1"
"lucene_version" : "8.11.1",
"minimum_wire_compatibility_version" : "6.8.0",
"minimum_index_compatibility_version" : "6.0.0-beta1"
},
"tagline" : "You Know, for Search"
}
~~~
### Java 1.8
Elasticsearch 5.x nécessite Java 1.8. Pour Jessie, il faut installer la machine virtuelle Java depuis les backports.
~~~
# echo "deb http://mirror.evolix.org/debian jessie-backports main " >> /etc/apt/sources.list.d/backports.list
~~~
Il vaut mieux aussi s'assurer que les backports aient une préférence basse, dans `/etc/apt/preferences.d/backports`
~~~
Package: *
Pin: release a=jessie-backports
Pin-Priority: 50
Package: openjdk-8-jre openjdk-8-jre-headless ca-certificates-java
Pin: release a=jessie-backports
Pin-Priority: 900
~~~
~~~
# apt install openjdk-8-jre-headless
# update-alternatives --set java /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java
~~~
### Breaking changes
Si vous faites la mise à jour depuis une version inférieure à 5.0, il faut penser à supprimer tous les plugins de type "site" comme _head_ ou _kopf_ qu'il faudra réinstaller différemment. :
~~~
# rm -rf /usr/share/elasticsearch/plugins/{kopf,head}
~~~
La liste complète des changements est diponible sur <https://www.elastic.co/guide/en/elasticsearch/reference/5.0/breaking-changes.html>.
### Démarrage
Pour activer le démarrage automatique :
~~~
# systemctl enable elasticsearch
Synchronizing state for elasticsearch.service with sysvinit using update-rc.d...
Executing /usr/sbin/update-rc.d elasticsearch defaults
Executing /usr/sbin/update-rc.d elasticsearch enable
Created symlink from /etc/systemd/system/multi-user.target.wants/elasticsearch.service to /usr/lib/systemd/system/elasticsearch.service.
# systemctl enable elasticsearch.service
Synchronizing state of elasticsearch.service with SysV service script with /lib/systemd/systemd-sysv-install.
Executing: /lib/systemd/systemd-sysv-install enable elasticsearch
Created symlink /etc/systemd/system/multi-user.target.wants/elasticsearch.service → /lib/systemd/system/elasticsearch.service.
# systemctl start elasticsearch
~~~
## Mise à jour
Selon la version de départ et la version d'arrivée, la procédure peut être triviale et sans coupure ou bien plus complexe et avec coupure. La grille des versions est disponible ici : [https://www.elastic.co/guide/en/elasticsearch/reference/current/setup-upgrade.html]().
@ -98,9 +68,19 @@ Lors de changements de versions, certaines fonctionnalités peuvent changer ou d
Il est important de noter qu'il n'est pas possible (sauf exceptions) de revenir en arrière après une montée de version.
### Mise à jour depuis une version inférieure à 5.0
Si vous faites la mise à jour depuis une version inférieure à 5.0, il faut penser à supprimer tous les plugins de type "site" comme _head_ ou _kopf_ qu'il faudra réinstaller différemment. :
~~~
# rm -rf /usr/share/elasticsearch/plugins/{kopf,head}
~~~
La liste complète des changements est diponible sur <https://www.elastic.co/guide/en/elasticsearch/reference/5.0/breaking-changes.html>.
## Configuration de base
Les paramètres système se trouvent dans le fichier `/etc/default/elasticsearch`, les paramètres liés à la JVM sont dans `/etc/elasticsearch/jvm.options` et les options applicatives (nom du cluster, nom du nœud, mémoire, réseau) se trouvent dans le fichier `/etc/elasticsearch/elasticsearch.yml`.
Les paramètres système se trouvent dans le fichier `/etc/default/elasticsearch`, les paramètres liés à la JVM sont dans `/etc/elasticsearch/jvm.options` et `/etc/elasticsearch/jvm.options.d` (*Note:* on privilégiera le deuxième) et les options applicatives (nom du cluster, nom du nœud, mémoire, réseau) se trouvent dans le fichier `/etc/elasticsearch/elasticsearch.yml`.
Il faut activer le redémarrage automatique en cas de mise à jour (classique sous Debian) dans `/etc/default/elasticsearch` :
@ -108,20 +88,6 @@ Il faut activer le redémarrage automatique en cas de mise à jour (classique so
RESTART_ON_UPGRADE=true
~~~
On peut aussi définir un **tmpdir** spécifique (utile quand `/tmp` est en `noexec`) dans `/etc/default/elasticsearch` :
~~~
ES_JAVA_OPTS="-Djava.io.tmpdir=/var/lib/elasticsearch/tmp"
~~~
Dans ce cas, assurez-vous de créer le répertoire avec les bons droits :
~~~
# mkdir /var/lib/elasticsearch/tmp
# chown elasticsearch: /var/lib/elasticsearch/tmp
# chmod 750 /var/lib/elasticsearch/tmp
~~~
Via le fichier `/etc/elasticsearch/elasticsearch.yml` vous devez au minimum configurer :
~~~{.yaml}
@ -130,35 +96,70 @@ node.name: bar
~~~
### Changement du dossier temporaire
On peut aussi définir un **tmpdir** spécifique (important quand `/tmp` est en `noexec`).
Dans ce cas, assurez-vous de créer le répertoire avec les bons droits :
~~~
# mkdir /var/lib/elasticsearch/tmp
# chown elasticsearch: /var/lib/elasticsearch/tmp
# chmod 750 /var/lib/elasticsearch/tmp
~~~
#### Version >= 6.x
Le **tmpdir** se change dans `/etc/default/elasticsearch` :
~~~
ES_TMPDIR=/var/lib/elasticsearch/tmp
~~~
Cette variable est ensuite utilisée par `/etc/elasticsearch/jvm.options` qui contient normalement la directive suivante :
~~~
-Djava.io.tmpdir=${ES_TMPDIR}
~~~
#### Version < 6.x
On force directement dans les options de la JVM via le fichier `/etc/elasticsearch/jvm.options.d/evolinux` :
~~~
ES_JAVA_OPTS="-Djava.io.tmpdir=/var/lib/elasticsearch/tmp"
~~~
### Mémoire allouée
La mémoire allouée au tas de la JVM pour ElasticSearch sont les lignes `-Xms` et `-Xmx` dans `/etc/elasticsearch/jvm.options`.
La mémoire allouée au tas de la JVM pour ElasticSearch sont les lignes `-Xms` et `-Xmx` dans `/etc/elasticsearch/jvm.options.d/evolinux`.
Les deux valeurs doivent être égales.
Pour plus d'informations sur la mémoire allouée au tas de la JVM : [HowtoJava#gestion-de-la-mémoire]().
## Configuration réseau
### Configuration réseau
Par défaut, Elasticsearch écoute sur 127.0.0.1 sur TCP/9200 pour son interface REST HTTP.
Par défaut, Elasticsearch écoute sur 127.0.0.1 sur TCP/9200 pour son interface client REST HTTP.
La directive de configuration suivante peut être positionnée pour qu'il écoute sur plusieurs interfaces réseau :
~~~{.yaml}
network.host: ["192.0.2.42", "198.51.100.42", "127.0.0.1"]
network.host: ["192.0.2.42", "10.0.42.21", "127.0.0.1"]
~~~
Il est possible d'utiliser des adresses virtuelles, telles que `_site_`, `_local_`
Il est possible d'utiliser des adresses virtuelles, telles que `_local_` (127.0.0.1 et ::1), `_site_` (IPs spécifiques à un réseau privé), `_global_`
Tous les détails sont su <https://www.elastic.co/guide/en/elasticsearch/reference/5.0/modules-network.html#network-interface-values>.
Tous les détails sont sur <https://www.elastic.co/guide/en/elasticsearch/reference/7.17/modules-network.html#network-interface-values>.
### mode "production"
### Mode "production"
Lorsqu'Elasticsearch est configuré pour écouter sur une IP non locale, il passe en mode "production".
Il active alors un certain nombre de "bootstrap checks" qui bloquent le démarrage s'ils ne sont pas tous respectés. Les éventuels échecs sont lisibles dans le fichier de log (généralement dans `/var/log/elasticsearch/_cluster_name_.log`).
On peut aussi forcer l'exécution de ces controles en activant `es.enforce.bootstrap.checks` à *true* dans les options de la JVM
## Configuration avancée
* Si on veut lancer Elasticsearch avec une JVM différente que celle par défaut sur le système, on peut définir JAVA_HOME dans `/etc/default/elasticsearch` :
@ -249,6 +250,231 @@ non_heap_used.value 175388648
heap_committed.value 2130051072
~~~
## Sécurisation
Par défaut, elasticsearch n'est absolument pas sécurisé. Il a donc plusieurs opérations à faire pour sécuriser un nœud ou un cluster.
Elastic définit 3 niveaux de sécurisation :
* Minimal : Authentification HTTP
* Basique (Environnement de production) : Authentification HTTP + Chiffrement inter-nœuds
* Basique avec chiffrement des connexion clients : Authentification HTTP + Chiffrement inter-nœuds + HTTPS sur l'interface REST
Pour aller plus loin, c'est expliqué en détail dans la documentation d'elasticsearch <https://www.elastic.co/guide/en/elasticsearch/reference/7.17/secure-cluster.html>
### Authentification HTTP
Il faut d'abord activer les fonctions de sécurité dans `/etc/elasticsearch/elasticsearch.yml` sur tous les membres du cluster :
~~~
xpack.security.enabled: true
~~~
Après un redémarrage d'elasticsearch pour la prise en compte de l'activation de xpack, on utilisera la commande `/usr/share/elasticsearch/bin/elasticsearch-setup-passwords auto` pour créer un mot de passe pour tous les comptes par défaut.
~~~
# /usr/share/elasticsearch/bin/elasticsearch-setup-passwords auto
Initiating the setup of passwords for reserved users elastic,apm_system,kibana_system,logstash_system,beats_system,remote_monitoring_user.
The passwords will be randomly generated and printed to the console.
Please confirm that you would like to continue [y/N]y
Changed password for user apm_system
PASSWORD apm_system = PASSWORD
Changed password for user kibana_system
PASSWORD kibana_system = PASSWORD
Changed password for user logstash_system
PASSWORD logstash_system = PASSWORD
Changed password for user beats_system
PASSWORD beats_system = PASSWORD
Changed password for user remote_monitoring_user
PASSWORD remote_monitoring_user = PASSWORD
Changed password for user elastic
PASSWORD elastic = PASSWORD
~~~
On conservera ces mots de passe avec précaution.
Les comptes ont tous des rôles (et donc des permissions) différents.
Chacun son usage :
* *elastic* : Super-utilisateur, administration du cluster
* *kibana_system* : Compte système pour le fonctionnement de Kibana
* *remote_monitoring_user* : Compte pour le monitoring du cluster
* etc
Par la suite, il faut s'assurer que **tous** les outils de la suite elastic (Kibana, logstash…), mais aussi le monitoring utilisent bien un compte pour s'authentifier, si non ils ne vont plus fonctionner !
Par la suite la gestion des comptes (ajout/suppression/…) se fait au travers de Kibana (après connexion) : Stack management > Users
On pourra ainsi créer des comptes applicatifs, avec
#### Ajustement configuration monitoring
On ajoutera l'argument suivant à la commande de check `--authorization 'remote_monitoring_user:PASSWORD'`
#### Ajustement configuration Kibana
Dans `/etc/kibana/kibana.yml`, on spécifie le compte a utiliser :
~~~diff
--- a/etc/kibana/kibana.yml
+++ b/etc/kibana/kibana.yml
@@ -44,7 +44,7 @@ elasticsearch.hosts: ["https://localhost:9200"]
# the username and password that the Kibana server uses to perform maintenance on the Kibana
# index at startup. Your Kibana users still need to authenticate with Elasticsearch, which
# is proxied through the Kibana server.
+elasticsearch.username: "kibana_system"
-#elasticsearch.username: "kibana_system"
#elasticsearch.password: "pass"
# Kibana can also authenticate to Elasticsearch via "service account tokens".
~~~
Pour le mot de passe, pour ne pas l'enregistrer en clair dans la configuration, on utilisera le keystore de Kibana
~~~
# /usr/share/kibana/bin/kibana-keystore add elasticsearch.password
Enter value for elasticsearch.password: PASSWORD
~~~
Puis redémarrer Kibana `systemctl restart kibana`
### Passage en HTTPS
Il y a plusieurs options pour. Le plus simple est de générer une PKI spéciale au cluster elastic avec les outils proposés.
#### Amorce de la PKI
~~~
# /usr/share/elasticsearch/bin/elasticsearch-certutil ca --days 7300
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
Please enter the desired output file [elastic-stack-ca.p12]:
Enter password for elastic-stack-ca.p12 :
~~~
Le certificat est enregistré par défaut dans `/usr/share/elasticsearch/elastic-stack-ca.p12`.
Comme ce n'est pas un dossier conventionnel, on peut choisir de le déplacer dans /etc/elasticsearch/
~~~
# mv /usr/share/elasticsearch/elastic-stack-ca.p12 /etc/elasticsearch/elastic-stack-ca.p12
~~~
#### Communication inter-nœuds
Pour chaque nœud elastic, il faut générer un certificat avec l'outil `/usr/share/elasticsearch/bin/elasticsearch-certutil`
On peut essayer, pour garder les choses au clair, d'avoir la nomenclature suivante pour les noms de certificats `$(hostname).$(service).p12`
~~~
# /usr/share/elasticsearch/bin/elasticsearch-certutil cert --ca elastic-stack-ca.p12 --days 7300
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 'cert' mode generates X.509 certificate and private keys.
* By default, this generates a single certificate and key for use
on a single instance.
* The '-multiple' option will prompt you to enter details for multiple
instances and will generate a certificate and key for each one
* The '-in' option allows for the certificate generation to be automated by describing
the details of each instance in a YAML file
* An instance is any piece of the Elastic Stack that requires an SSL certificate.
Depending on your configuration, Elasticsearch, Logstash, Kibana, and Beats
may all require a certificate and private key.
* The minimum required value for each instance is a name. This can simply be the
hostname, which will be used as the Common Name of the certificate. A full
distinguished name may also be used.
* A filename value may be required for each instance. This is necessary when the
name would result in an invalid file or directory name. The name provided here
is used as the directory name (within the zip) and the prefix for the key and
certificate files. The filename is required if you are prompted and the name
is not displayed in the prompt.
* IP addresses and DNS names are optional. Multiple values can be specified as a
comma separated string. If no IP addresses or DNS names are provided, you may
disable hostname verification in your SSL configuration.
* All certificates generated by this tool will be signed by a certificate authority (CA)
unless the --self-signed command line option is specified.
The tool can automatically generate a new CA for you, or you can provide your own with
the --ca or --ca-cert command line options.
By default the 'cert' mode produces a single PKCS#12 output file which holds:
* The instance certificate
* The private key for the instance certificate
* The CA certificate
If you specify any of the following options:
* -pem (PEM formatted output)
* -keep-ca-key (retain generated CA key)
* -multiple (generate multiple certificates)
* -in (generate certificates from an input file)
then the output will be be a zip file containing individual certificate/key files
Enter password for CA (elastic-stack-ca.p12) :
Please enter the desired output file [elastic-certificates.p12]: HOSTNAME.elasticsearch.p12
Enter password for HOSTNAME.elasticsearch.p12 :
Certificates written to /usr/share/elasticsearch/HOSTNAME.elasticsearch.p12
This file should be properly secured as it contains the private key for
your instance.
This file is a self contained file and can be copied and used 'as is'
For each Elastic product that you wish to configure, you should copy
this '.p12' file to the relevant configuration directory
and then follow the SSL configuration instructions in the product guide.
For client applications, you may only need to copy the CA certificate and
configure the client to trust this certificate.
~~~
Par la suite on va `mv` le certificat généré vers `/etc/elasticsearch` (ou le scp vers les nœud distants)
~~~
# mv /usr/share/elasticsearch/HOSTNAME.elasticsearch.p12 /etc/elasticsearch/
# chgrp elasticsearch /etc/elasticsearch/HOSTNAME.elasticsearch.p12
# chmod g+r /etc/elasticsearch/HOSTNAME.elasticsearch.p12
~~~
Puis on ajout la configuration de elasticsearch
~~~yaml
xpack.security.transport.ssl.enabled: true
xpack.security.transport.ssl.verification_mode: certificate
xpack.security.transport.ssl.keystore.path: HOSTNAME.elasticsearch.p12
xpack.security.transport.ssl.truststore.path: HOSTNAME.elasticsearch.p12
~~~
Après, un redémarrage avec `systemctl restart elasticsearch`
#### Communication client-serveur
**TODO**
## Snapshots et sauvegardes
### Configuration des snapshots
@ -471,7 +697,7 @@ find ${LOG_DIR} -type f -user ${USER} -name "logstash-*-????-??-??.log" -exec gz
## cluster
<https://www.elastic.co/guide/en/elasticsearch/reference/5.0/modules-cluster.html>
<https://www.elastic.co/guide/en/elasticsearch/reference/7.17/modules-cluster.html>
Si l'on compare à d'autres services (MySQL, PostgreSQL, MongoDB…) la gestion d'un cluster Elasticsearch est vraiment simple.
Il faut lancer plusieurs instances Elasticsearch sur un réseau avec le même **cluster.name** et un **node.name** différent, et il suffit d'indiquer une (ou plusieurs) adresse(s) IP qui va permettre à l'instance de communiquer avec un (ou plusieurs) autre(s) nœud(s) :