Skip to content

Instantly share code, notes, and snippets.

@dmi3mis
Created June 13, 2026 01:15
Show Gist options
  • Select an option

  • Save dmi3mis/b257b649676a620cc60fe7de3d9a405c to your computer and use it in GitHub Desktop.

Select an option

Save dmi3mis/b257b649676a620cc60fe7de3d9a405c to your computer and use it in GitHub Desktop.
Update elasticsearch and kibana certificates
#!/bin/bash
# Скрипт автоматического перевыпуска SSL-сертификатов Elastic Stack 8.x
# Запускать строго от пользователя root или через sudo.
set -e # Останавливать скрипт при любой необработанной ошибке
# --- НАСТРОЙКИ СЕРВЕРА (ОБЯЗАТЕЛЬНО ПРОВЕРЬТЕ) ---
NODE_NAME="elk" # Имя вашего сервера (hostname)
NODE_IP="192.168.1.50" # Реальный сетевой IP-адрес сервера
CERT_DAYS="1825" # Срок действия новых сертификатов (5 лет)
KIBANA_CA_FILE="/etc/kibana/certs/http_ca.crt" # Путь к CA-сертификату в вашей kibana.yml
# -------------------------------------------------
# Пути к рабочим файлам
ELASTIC_DIR="/etc/elasticsearch"
KIBANA_DIR="/etc/kibana"
CA_P12="$ELASTIC_DIR/certs/elastic-stack-ca.p12"
TRANSPORT_P12="$ELASTIC_DIR/certs/transport.p12"
HTTP_P12="$ELASTIC_DIR/certs/http.p12"
# Обработка параметров командной строки
FORCE_RENEW=0
if [[ "$1" == "--force" || "$1" == "-f" ]]; then
echo "=== Включен режим принудительного обновления (--force) ==="
FORCE_RENEW=1
fi
# Проверка: нужно ли обновлять сертификаты? (Идемпотентность)
NEED_RENEW=0
if [ $FORCE_RENEW -eq 1 ]; then
NEED_RENEW=1
else
# Проверяем физическое наличие файлов и их размер (чтобы не были 0 байт)
for file in "$CA_P12" "$TRANSPORT_P12" "$HTTP_P12" "$KIBANA_CA_FILE"; do
if [ ! -f "$file" ] || [ ! -s "$file" ]; then
echo "Файл $file отсутствует или пустой. Требуется генерация."
NEED_RENEW=1
fi
done
# Если файлы на месте, проверяем срок действия текущего HTTP-сертификата
if [ $NEED_RENEW -eq 0 ]; then
if openssl pkcs12 -in "$HTTP_P12" -clcerts -nokeys -passin pass: 2>/dev/null | openssl x509 -checkend 2592000 > /dev/null; then
echo "=== Сертификаты действительны (осталось более 30 дней). Действий не требуется. ==="
echo "Для принудительного перевыпуска запустите скрипт с флагом: $0 --force"
exit 0
else
echo "Срок действия сертификатов подходит к концу (< 30 дней). Запускаем перевыпуск."
NEED_RENEW=1
fi
fi
fi
echo "=== Шаг 1. Полная остановка служб и создание бэкапа ==="
systemctl stop elasticsearch kibana || true
BACKUP_DIR="$ELASTIC_DIR/certs_backup_$(date +%F_%H-%M-%S)"
mkdir -p "$BACKUP_DIR"
if [ -d "$ELASTIC_DIR/certs" ] && [ "$(ls -A $ELASTIC_DIR/certs)" ]; then
echo "Сохраняем старые сертификаты в $BACKUP_DIR"
cp -r "$ELASTIC_DIR/certs"/* "$BACKUP_DIR/"
rm -rf "$ELASTIC_DIR/certs"/*
else
mkdir -p "$ELASTIC_DIR/certs"
fi
echo "=== Шаг 2. Генерация нового корневого сертификата (CA) ==="
/usr/share/elasticsearch/bin/elasticsearch-certutil ca \
--out "$CA_P12" \
--pass "" \
--silent
echo "=== Шаг 3. Генерация транспортного сертификата (transport.p12) ==="
/usr/share/elasticsearch/bin/elasticsearch-certutil cert \
--ca "$CA_P12" \
--ca-pass "" \
--out "$TRANSPORT_P12" \
--pass "" \
--days "$CERT_DAYS" \
--silent
echo "=== Шаг 4. Подготовка конфигурации узла для HTTP ==="
TMP_DIR="/tmp/el-certs-automation"
rm -rf "$TMP_DIR" && mkdir -p "$TMP_DIR"
cat <<EOF > "$TMP_DIR/instances.yml"
instances:
- name: "http"
dns:
- "localhost"
- "$NODE_NAME"
ip:
- "127.0.0.1"
- "$NODE_IP"
EOF
echo "=== Шаг 5. Генерация HTTP-сертификатов (PEM-цепочка) ==="
/usr/share/elasticsearch/bin/elasticsearch-certutil cert \
--ca "$CA_P12" \
--ca-pass "" \
--in "$TMP_DIR/instances.yml" \
--out "$TMP_DIR/http-certs.zip" \
--days "$CERT_DAYS" \
--pem \
--silent
unzip -q "$TMP_DIR/http-certs.zip" -d "$TMP_DIR/extracted"
echo "=== Шаг 6. Сборка http.p12 для Elasticsearch ==="
openssl pkcs12 -export \
-in "$TMP_DIR/extracted/http/http.crt" \
-inkey "$TMP_DIR/extracted/http/http.key" \
-out "$HTTP_P12" \
-passout pass: \
-name "http"
echo "=== Шаг 7. Очистка старых сохраненных паролей (Keystore) ==="
/usr/share/elasticsearch/bin/elasticsearch-keystore remove xpack.security.transport.ssl.keystore.secure_password 2>/dev/null || true
/usr/share/elasticsearch/bin/elasticsearch-keystore remove xpack.security.transport.ssl.truststore.secure_password 2>/dev/null || true
/usr/share/elasticsearch/bin/elasticsearch-keystore remove xpack.security.http.ssl.keystore.secure_password 2>/dev/null || true
echo "=== Шаг 8. Права доступа для Elasticsearch ==="
chown -R root:elasticsearch "$ELASTIC_DIR/certs/"
chmod 750 "$ELASTIC_DIR/certs/"
chmod 640 "$ELASTIC_DIR/certs"/*
echo "=== Шаг 9. Обновление сертификата на стороне Kibana ==="
mkdir -p "$(dirname "$KIBANA_CA_FILE")"
# Извлекаем публичный корневой сертификат (CA) напрямую из созданного CA_P12 с флагом -clcerts
openssl pkcs12 -in "$CA_P12" \
-clcerts -nokeys -nodes \
-out "$KIBANA_CA_FILE" \
-passin pass:
# Настройка прав для Kibana
KIBANA_CERTS_DIR=$(dirname "$KIBANA_CA_FILE")
chown -R root:kibana "$KIBANA_CERTS_DIR/"
chmod 750 "$KIBANA_CERTS_DIR/"
chmod 640 "$KIBANA_CA_FILE"
echo "=== Шаг 10. Проверка ключей шифрования в kibana.yml ==="
if ! grep -q "xpack.encryptedSavedObjects.encryptionKey" "$KIBANA_DIR/kibana.yml"; then
echo "Ключи шифрования в kibana.yml не найдены. Генерируем..."
KEYS=$(/usr/share/kibana/bin/kibana-encryption-keys generate 2>/dev/null | grep -E '^xpack\.' || true)
if [ ! -z "$KEYS" ]; then
echo -e "\n# Автоматически добавленные ключи шифрования Kibana" >> "$KIBANA_DIR/kibana.yml"
echo "$KEYS" >> "$KIBANA_DIR/kibana.yml"
echo "Ключи успешно добавлены в конфигурацию kibana.yml"
fi
fi
echo "=== Шаг 11. Очистка временных файлов ==="
rm -rf "$TMP_DIR"
echo "=== Шаг 12. Запуск сервисов ==="
echo "Запуск Elasticsearch..."
systemctl start elasticsearch
echo "Ожидание инициализации API Elasticsearch (15 секунд)..."
sleep 15
echo "Запуск Kibana..."
systemctl start kibana
echo "=========================================================="
echo " Скрипт успешно выполнен! Сертификаты обновлены на 5 лет. "
echo "=========================================================="
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment