Изучаем ELK. Часть III — Безопасность
Вступительное слово
В первой и второй частях данной серии статей была описана процедура установки и настройки кластера Elasticsearch, Kibana и Logstash, но не был освящен вопрос безопасности.
В этой статье я расскажу, как настроить шифрование трафика между узлами кластера Elasticsearch и его клиентам, шифрование трафика между Kibana и клиентами, покажу, как создавать роли и пользователей, а так же выдавать API ключи для доступа к кластеру Elasticsearch.
План действий
«Включаем» безопасность.
Настраиваем шифрование между узлами Elasticsearch.
Настраиваем аутентификацию.
Настраиваем шифрование клиентского трафика Elasticsearch.
Подключаем Kibana к Elasticsearch.
Настраиваем шифрование трафика между Kibana и клиентами.
Создаем пользователей и роли.
Настраиваем пользовательские сессии в Kibana.
Настраиваем Logstash.
Создаем API ключи.
«Включаем» безопасность
Чтобы использовать функции безопасности в Elasticsearch, их необходимо активировать. Для этого на каждом узле в файле конфигурации указывается следующая настройка:
xpack.security.enabled: true
Настраиваем шифрование между узлами Elasticsearch
Следующим шагом необходимо настроить шифрование трафика между узлами Elasticsearch. Для этого выполняем несколько шагов:
Создаем CA (Certificate Authority) для кластера Elasticsearch:
./bin/elasticsearch-certutil ca
Для установки из пакетов
Deb
иRPM
исполняемые файлы Elasticsearch лежат в каталоге/usr/share/elasticsearch/bin/
. Для установки из архива — в каталоге$ES_HOME/bin/
.В примерах все команды выполнены из каталога
/usr/share/elasticsearch/
.
Во время генерации корневого сертификата можно задать имя PKCS#12 файла, по умолчанию это elastic-stack-ca.p12
и пароль к нему.
Для получения сертификата и ключа в PEM формате укажите ключ --pem
. На выходе будет ZIP архив с .crt
и .key
файлами.
С помощью ключа --out
можно указать каталог для создаваемого файла.
Полученный корневой сертификат (для PEM формата еще и ключ) надо переместить на все узлы кластера для генерации сертификата узла.
Генерируем на каждом узле кластера сертификат и ключ:
./bin/elasticsearch-certutil cert --ca elastic-stack-ca.p12 --ip 10.0.3.11 --dns es-node01
Ключ --ca
указывает путь к корневому сертификату CA в формате PKCS#12. Если сертификат и ключ были получены в PEM формате, то необходимо использовать ключи --ca-cert
и --ca-key
соответственно.
Ключи --dns
и --ip
добавляют проверку по имени узла и IP адресу и являются опциональными. Если вы указываете их, то укажите эти параметры для каждого узла.
Ключ
--pass
позволяет установитьpassphrase
для ключа.
Включаем TLS в файле конфигурации Elasticsearch:
xpack.security.transport.ssl.enabled: true
xpack.security.transport.ssl.verification_mode: full
xpack.security.transport.ssl.keystore.path: es-node01-cert.p12
xpack.security.transport.ssl.truststore.path: elastic-stack-ca.p12
Где:
xpack.security.transport.ssl.enabled
— включаем TLS/SSL
xpack.security.transport.ssl.verification_mode
— режим проверки сертификатов. none
— проверка не выполняется, certificate
— выполняется проверка сертификата без проверки имени узла и IP адреса, full
— проверка сертификата, а также имени узла и адреса указанных в сертификате.
xpack.security.transport.ssl.keystore.path
— путь к файлу с сертификатом и ключем узла.
xpack.security.transport.ssl.truststore.path
— путь к доверенному сертификату (CA).
Если сертификаты CA и/или узла в формате PEM, то необходимо изменить последние два параметра на следующие:
xpack.security.transport.ssl.key
— путь к закрытому ключу узла
xpack.security.transport.ssl.certificate
— путь к сертификату узла
xpack.security.transport.ssl.certificate_authorities
— список путей к сертифкатам CA.
Cоздаем keystore и добавляем пароли от сертификатов (если они были заданы):
./bin/elasticsearch-keystore create -p
Ключ -p требуется для установки пароля keystone во время создания
Для PKCS#12 формата:
./bin/elasticsearch-keystore add xpack.security.transport.ssl.keystore.secure_password
./bin/elasticsearch-keystore add xpack.security.transport.ssl.truststore.secure_password
Для PEM сертификата:
./bin/elasticsearch-keystore add xpack.security.transport.ssl.securekeypassphrase
Чтобы запустить Elasticsearch с keystore, на который установлен пароль, необходимо передать этот пароль Elasticsearch. Это делается с помощью файла на который будет ссылаться переменная ES_KEYSTORE_PASSPHRASE_FILE
. После запуска файл можно удалить, но при каждом последующим запуске файл необходимо создавать.
echo "password" > /etc/elasticsearch/ks_secret.tmp
chmod 600 /etc/elasticsearch/ks_secret.tmp
sudo systemctl set-environment ES_KEYSTORE_PASSPHRASE_FILE=/etc/elasticsearch/ks_secret.tmp
Перезапускаем Elasticsearch
В логах Elasticsearch должны появится записи о создании кластера:
[INFO ][o.e.c.s.ClusterApplierService] [es-node01] master node changed {previous [], current [{es-node02}{L1KdSSwCT9uBFhq0QlxpGw}{ujCcXRmOSn-EbqioSeDNXA}{10.0.3.12}{10.0.3.12:9300}...
Если обратиться к API, то будет ошибка »missing authentication credentials for REST request». С момента включения функций безопасности для обращения к кластер необходимо пройти аутентификацию.
Настраиваем аутентификацию
Elasticsearch имеет несколько встроенных пользователей:
Пользователь | Описание |
elastic | Суперпользователь |
kibana_system | Используется для коммуникации между Kibana и Elasticsearch |
logstash_system | Пользователь, которого использует Logstash сервер, когда сохраняет информацию в Elasticsearch |
beats_system | Пользователь, которого использует агент Beats, когда сохраняет информацию в Elasticsearch |
apm_system | Пользователь, которого использует APM сервер, когда сохраняет информацию в Elasticsearch |
remote_monitoring_user | Пользователь Metricbeat, который используется при сборе и хранении информации мониторинга в Elasticsearch |
Прежде чем воспользоваться перечисленными пользователями, необходимо установить для них пароль. Для этого используется утилита elasticsearch-setup-passwords
. В режиме interactive
для каждого пользователя необходимо ввести пароли самостоятельно, в режиме auto
Elasticsearch создаст пароли автоматически:
./bin/elasticsearch-setup-passwords auto
Initiating the setup of passwords for reserved users elastic,apm_system,kibana,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 = NtvuRYhwbKpIEVUmHsZB
Changed password for user kibana_system
PASSWORD kibana_system = ycXvzXglaLnrFMdAFsvy
Changed password for user kibana
PASSWORD kibana = ycXvzXglaLnrFMdAFsvy
Changed password for user logstash_system
PASSWORD logstash_system = vU3CuRbjBpax1RrsCCLF
Changed password for user beats_system
PASSWORD beats_system = c9GQ85qhNL59H2AXUvcA
Changed password for user remote_monitoring_user
PASSWORD remote_monitoring_user = wB320seihljmGsjc29W5
Changed password for user elastic
PASSWORD elastic = iOrMTBbfHOAkm5CPeOj7
Второй раз
elasticsearch-setup-passwords
запустить не получится, так как bootstrap password изменился. Чтобы изменить пароль пользователям можно воспользоваться API.
Попробуем сделать API запрос к любому узлу Elasticsearch с использованием учетной записи elastic
и пароля к от неё:
curl -u 'elastic' -X GET "http://10.0.3.1:9200/_cluster/health?pretty"
Enter host password for user 'elastic':
{
"cluster_name" : "es_cluster",
"status" : "green",
"timed_out" : false,
"number_of_nodes" : 4,
"number_of_data_nodes" : 3,
"active_primary_shards" : 9,
"active_shards" : 18,
"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
}
Как видно из примера все работает, но мы обращались через http
, значит трафик между клиентом и кластером Elasticsearch не шифрованный.
Настраиваем шифрование клиентского трафика Elasticsearch
Для шифрования клиентского трафика необходимо выпустить сертификат, который будет использоваться для шифрования трафика между узлом Elasticsearch и клиентом. При этом для Kibana будет сформирован отдельный сертификат, чтобы настроить соединение с Elasticsearch. Для этого делаем следующее:
Генерируем сертификат:
./bin/elasticsearch-certutil http
В процессе генерации необходимо определить:
1) Необходимо ли сгенерировать Certificate Signing Request (CSR). Потребуется, если сертификат будет выпускаться сторонним CA (Certificate Authority).
2) Использовать ли собственный CA (Certificate Authority). Если да, то указываем путь до ключа, которым будет подписаны будущие сертификаты.
3) Срок действия сертификата. По умолчанию 5 лет. Можно определить дни (D), месяцы (M), года (Y).
4) Как выпустить сертификат, на каждый узел или общий. Если все узлы имеют общий домен, то можно выпустить wildcard
сертификат (например *.domain.local). Если общего домена нет и в будущем возможно добавление узлов, то необходимо генерировать на каждый узел, указав имя узла и его адрес. В будущем можно выпустить отдельный сертификат для нового узла.
На выходе получаем архив сертификатами, в моём случае со всеми сертификатам для каждого узла Elasticsearch, а так же сертификат для подключения Kibana к Elasticsearch:
.
├── elasticsearch
│ ├── es-nlb01
│ │ ├── README.txt
│ │ ├── http.p12
│ │ └── sample-elasticsearch.yml
│ ├── es-node01
│ │ ├── README.txt
│ │ ├── http.p12
│ │ └── sample-elasticsearch.yml
│ ├── es-node02
│ │ ├── README.txt
│ │ ├── http.p12
│ │ └── sample-elasticsearch.yml
│ └── es-node03
│ ├── README.txt
│ ├── http.p12
│ └── sample-elasticsearch.yml
└── kibana
├── README.txt
├── elasticsearch-ca.pem
└── sample-kibana.yml
В архиве также лежит инструкция по дальнейшим действиям с сертификатом (README.txt) и пример конфигурационного файла (sample-…yml).
Сертификат
elasticsearch-ca.pem
из директорииkibana
потребуется в следующем шаге.
Размещаем сертификаты на узлах и добавляем необходимые настройки в файле конфигурации:
xpack.security.http.ssl.enabled: true xpack.security.http.ssl.keystore.path: "http.p12"
Добавляем пароль от сгенерированного сертификата в keystore:
./bin/elasticsearch-keystore add xpack.security.http.ssl.keystore.secure_password
Проверяем, что все работает по
https
:
curl -u 'elastic' -k -X GET "https://10.0.3.1:9200/_cluster/health?pretty"
Enter host password for user 'elastic':
{
"cluster_name" : "es_cluster",
"status" : "green",
"timed_out" : false,
"number_of_nodes" : 4,
"number_of_data_nodes" : 3,
"active_primary_shards" : 9,
"active_shards" : 18,
"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
}
Подключаем Kibana к Elasticsearch
Если сейчас обратиться к Kibana, то ответом будет »Kibana server is not ready yet».
Это связанно с тем, что сейчас Kibana не может получить доступ к Elasticsearch по http
, для этого необходим сертификат Kibana, который был получен в предыдущем шаге, а также требуется пройти аутентификацию. Чтобы настроить работу Kibana:
В конфигурационном файле Kibana указываем ключ к сертификату
elasticsearch-ca.pem
(из предыдущего шага) и меняем протоколhttp
наhttps
:
elasticsearch.hosts: ['https://10.0.3.1:9200']
elasticsearch.ssl.certificateAuthorities: [ "/etc/kibana/elasticsearch-ca.pem" ]
В примере выше я использую адрес
Coordinating only
узла для балансировки нагрузки между Kibana и Elasticsearch, который был настроен в предыдущей части.
Создаем keystore для хранения пользователя и пароля:
sudo ./bin/kibana-keystore create --allow-root
Команда выполняются из директории
/usr/share/kibana
Так как keystore будет создан в каталоге
/etc/kibana/
, и keystone требуется файл конфигурации/etc/kibana/kibana.yml
, то пользователю, запускающему команду, необходим доступ к этому каталогу и файлу. Я используюsudo
и ключ--allow-root
. Ключ необходим, так как запускать из под пользователяroot
нельзя.Kibana keystore не имеет пароля. Для ограничения доступа используем стандартные средства Linux.
Добавляем пользователя kibana_system(встроенный пользователь Elasticsearch) и пароль учетной записи в Kibana keystore:
sudo ./bin/kibana-keystore add elasticsearch.username --allow-root
sudo ./bin/kibana-keystore add elasticsearch.password --allow-root
Можно использовать так же пользователя kibana, однако, он в системе считается устаревшим (deprecated).
перезапускаем Kibana и проверяем открыв нужный адрес в браузере:
Для входа используем учетную запись elastic.
Как можно заменить, трафик между браузером и Kibana не шифруется.
Настраиваем шифрование трафика между Kibana и клиентами
Данная процедура максимально похожа на ту, которую выполняли для получения сертификатов для узлов Elasticsearch.
Получаем сертификат при помощи
elsticsearch-certutil
:
./bin/elasticsearch-certutil cert -ca /etc/elasticsearch/elastic-stack-ca.p12 -name kibana-certificate -dns kibana01,10.0.3.1,127.0.0.1,localhost -ip 10.0.3.1
При необходимости можем использовать CA (Certificate Authority). В процессе генерации сертификата указываем пароль от CA, если используется, имя будущего сертификата и пароль к нему.
Через -dns
и -ip
указываем DNS имена и адрес Kibana.
Указываем путь к сертификату в файле
kibana.yml
:
Так как я использовал ранее полученный CA, то указываю путь и к нему (server.ssl.truststore.path
).
server.ssl.keystore.path: "/etc/kibana/kibana-certificate.p12"
server.ssl.truststore.path: "/etc/elasticsearch/elastic-stack-ca.p12"
Не забывайте о правах доступа, пользователь kibana должен иметь права на чтения.
Включаем использование TLS:
server.ssl.enabled: true
Добавляем пароли от сертификатов в keystore:
sudo ./bin/kibana-keystore add server.ssl.keystore.password --allow-root
sudo ./bin/kibana-keystore add server.ssl.truststore.password --allow-root
Перезагружаем Kibana и проверяем:
Теперь для подключения к Kibana используем https
.
Создаем пользователей и роли
Ранее мы активировали встроенные учетные записи и сгенерировали для них пароли, но использовать пользователя elastic (superuser) не лучшая практика, поэтому рассмотрим, как создавать пользователей и роли к ним.
Для примера создадим администратора Kibana. Открываем Menu > Management > Stack Management, выбираем Users и нажимаем Create user. Заполняем все поля и жмем Create User.
Создание пользователя в KibanaИли же можно воспользоваться API. Делать запросы к кластеру можно через консоль Dev Tools инструмента Kibana. Для этого перейдите Menu > Management > Dev Tools. В открывшейся консоли можно писать запросы к Elasticsearch.
POST /_security/user/kibana_admin
{
"password" : "password",
"roles" : [ "kibana_admin" ],
"full_name" : "Kibana Administrator",
"email" : "kibana.administrator@example.local"
}
Создание пользователя kibana_admin через APIПосле создания пользователя, можно его использовать.
Роль kibana_admin не может создавать пользователей и роли. Для создания пользователей и роли необходима привилегия кластера
manage_security
. С перечнем всех встроенных ролей можно ознакомится тут.
Далее создадим роль для работы с данными в ранее созданном индексом logstash-logs*. Открываем Menu > Management > Stack Management. Слева выбираем Roles и нажимаем Create role. Настраиваем привилегии, указав в качестве индекса logstash-logs*:
Index privileges | read | Read only права на индекс |
Предоставляем пользователю доступ к Kibana, для этого ниже наживаем Add Kibana privilege и выбираем требуемые привилегии:
В поле Spaces указываю All spaces. Что такое Space (пространства) можно почитать на официальном сайте. В рамках данной серии статей Space будет описан в статье о Kibana dashboard.
Чтобы создать роль с привилегиями в Elasticsearch и Kibana через API, делаем запрос к Kibana:
curl -k -i -u 'elastic' -X PUT 'https://10.0.3.1:5601/api/security/role/logstash_reader' \
--header 'kbn-xsrf: true' \
--header 'Content-Type: application/json' \
--data-raw '{
"elasticsearch": {
"cluster" : [ ],
"indices" : [
{
"names": [ "logstash-logs*" ],
"privileges": ["read"]
}
]
},
"kibana": [
{
"base": [],
"feature": {
"discover": [
"all"
],
"visualize": [
"all"
],
"dashboard": [
"all"
],
"dev_tools": [
"read"
],
"indexPatterns": [
"read"
]
},
"spaces": [
"*"
]
}
]
}'
Создаем пользователя logstash_reader и связываем его с созданной ролью (это мы уже научились делать) и заходим данным пользователем в Kibana.
Главная страница Kibana для пользователя logstash_readerКак видно, у данного пользователя не так много прав. Он может просматривать индексы logstash-logs*, строить графики, создавать панели и делать GET запросы к этому индексам через Dev Tools.
Настраиваем пользовательские сессии Kibana
Закрываем неактивные сессии:
xpack.security.session.idleTimeout: "30m"
Устанавливаем максимальную продолжительность одной сессии:
xpack.security.session.lifespan: "1d"
Настраиваем интервал принудительной очистки данных о неактивных или просроченных сессиях из сессионного индекса:
xpack.security.session.cleanupInterval: "8h"
Для всех параметров формат времени может быть следующим: ms | s | m | h | d | w | M | Y
Данные о сессии удаляются после того, как пользователь осуществляет закрытие сессии. Если не настроить закрытие неактивных сессий или не ограничить максимальную длительность сессии, то информация об этих сессиях будет накапливаться в сессионном индексе, и Kibana не сможет автоматически удалить данные.
Настраиваем Logstash
На данный момент Logstash не отправляет данные в кластер Elasticsearch, и чтобы это исправить, сделаем несколько настроек.
Создаем роль для подключения к кластеру:
В Kibana открываем Menu > Management > Stack Management. Слева выбираем Roles и нажимаем Create role. Указываем имя роли и настраиваем привелегии:
Cluster privileges | manage_index_templates | Все операции над шаблонами индексов |
monitor | Read-only права на получение информации о кластере | |
Index privileges | create_index | Создание индексов |
write | Индексирование, обновление и удаление индексов | |
manage | Мониторинг и управление индексом | |
manage_ilm | Управление жизненным циклом индексов (IML) |
Создаем пользователя для подключения к кластер:
Открываем Menu > Management > Stack Management, выбираем Users и нажимаем Create user. Заполняем требуемые данные, указав в качестве роли созданную выше роль.
Создание пользователя logstash_userСоздаем Logstash keystore, и добавляем туда пользователя и пароль от него:
# Создаем keystore с паролем
set +o history
export LOGSTASH_KEYSTORE_PASS=mypassword
set -o history
sudo /usr/share/logstash/bin/logstash-keystore create --path.settings /etc/logstash/
# Добавляем данные
sudo /usr/share/logstash/bin/logstash-keystore add ES_USER --path.settings /etc/logstash/
sudo /usr/share/logstash/bin/logstash-keystore add ES_PWD --path.settings /etc/logstash/
Настраиваем аутентификацию в
output
плагине:
output {
elasticsearch {
...
user => "${ES_USER}"
password => "${ES_PWD}"
}
}
Настраиваем TLS в Logstash:
Для подключения по https
к Elasticsearch необходимо настроить использование ssl
и установить .pem
сертификат, который был получен для Kibana.
output {
elasticsearch {
...
ssl => true
cacert => '/etc/logstash/elasticsearch-ca.pem'
}
}
Перезагружаем Logstash и проверяем новые записи в индексе
Проверку можно сделать в Kibana через Discovery, как делали в прошлой статье, или через API:
Dev Tools — Console в KibanaСоздание API ключей
Для работы с Elasticsearch можно не только использовать учетные записи пользователей, но и генерировать API ключ. Для этого необходимо сделать POST
запрос:
POST /_security/api_key
В качестве параметров указывают:
name
— имя ключа
role_descriptors
— описание роли. Структура совпадает с запросом на создание роли.
expiration
— Срок действия ключа. По умолчанию без срока действия.
Для примера заменим базовую аутентификацию в Logstash на API ключ.
Создаем API ключ в Kibana Dev Tool:
POST /_security/api_key
{
"name": "host_logstash01",
"role_descriptors": {
"logstash_api_writer": {
"cluster": ["manage_index_templates", "monitor"],
"index": [
{
"names": ["logstash-logs*"],
"privileges": ["create_index", "write", "manage", "manage_ilm"]
}
]
}
},
"expiration": "365d"
}
Получаем следующий результат:
{
"id" : "979DkXcBv3stdorzoqsf",
"name" : "host_logstash01",
"expiration" : 1644585864715,
"api_key" : "EmmnKb6NTES3nlRJenFKrQ"
}
Помещаем ключ в формате
id:api_key
в Keystore:
sudo /usr/share/logstash/bin/logstash-keystore add API_KEY --path.settings /etc/logstash/
Указываем API ключ в конфигурационном файле конвейера:
output {
elasticsearch {
hosts => ["https://10.0.3.11:9200","https://10.0.3.12:9200","https://10.0.3.13:9200"]
index => "logstash-logs-%{+YYYY.MM}"
ssl => true
api_key => "${API_KEY}"
cacert => '/etc/logstash/elasticsearch-ca.pem'
}
}
Информацию по ключам можно получить в Kibana Menu > Management > API Keys или через API запрос:
GET /_security/api_key?name=host_logstash01
{
"api_keys" : [
{
"id" : "9r8zkXcBv3stdorzZquD",
"name" : "host_logstash01",
"creation" : 1613048800876,
"expiration" : 1613049520876,
"invalidated" : false,
"username" : "elastic",
"realm" : "reserved"
}
]
}
Заключение
В рамках данной статьи были рассмотрены основные функции безопасности стека Elastic, позволяющие обезопасить работу нашего кластера, научились создавать пользователей и пользовательские роли, производить настройку пользовательских сессий, настройку шифрования трафика между узлами кластера и между кластером и клиентами, работать с API ключами и keystore.
В следующей статье будет рассмотрена процедура создание кластера ELK с помощью Docker.