Все статьи

Как избежать провала автопродления TLS-сертификатов: Гайд 2025

TLS-сертификаты: Почему автопродление может внезапно сломаться?

Автоматическое продление TLS-сертификатов, которое мы обычно реализуем через протокол ACME (например, с помощью Certbot или acme.sh), — это основа современной инфраструктуры. Но, честно говоря, этот процесс совсем не застрахован от сюрпризов. Частая ловушка: мы доверяем скриптам и забываем про мониторинг. И вот тут начинаются проблемы, как это случилось с платформой Bazel.

Индустрия движется к полному шифрованию (HTTPS), пытаясь убрать человеческий фактор за счет автоматизации. Изначально это было крутое решение. Мы сократили время выпуска сертификатов, чтобы все массово перешли на автопродление. В продакшене это работает как часы, пока что-то не пойдет не так.

Инструменты ACME и их роль в автоматизации

Современные системы активно юзают ACME-клиенты для управления сертификатами. Это, по сути, стандарт для Let's Encrypt. Вот самые популярные инструменты, с которыми я сталкивался:

  • Certbot: Классика, часто использует DNS-плагины для прохождения DNS-challenge.
  • acme.sh: Мощный bash-скрипт, который дружит с кучей API провайдеров.
  • win-acme: Для тех, кто трудится в Windows Server.

Эти утилиты создают надежный конвейер. Но даже самый отлаженный механизм может дать течь.

Изображение

win-acme

Кто-то скажет, что слишком много внимания уделять ручному контролю — это возврат в прошлое, к неэффективным практикам. Сторонники "полностью безлюдных" систем считают, что лучше вложиться в self-healing системы с триггерами на основе метрик доступности, а не на основе старых cron-заданий. Идея самовосстановления прекрасна, но требует огромных инженерных вложений. На практике же, даже самая навороченная система мониторинга может пропустить сбой, вызванный внезапным изменением политики DNS-провайдера или блокировкой порта. Поэтому базовый, но надежный, мониторинг статуса сертификата (через Prometheus или Nagios) остается незаменимой страховкой.

Реальный кейс: Сбой инфраструктуры Bazel из-за просроченного TLS

Даже крупные игроки могут стать жертвами этой проблемы. Недавний инцидент с Bazel (система сборки от Google) наглядно это показал. 26 декабря 2025 года у них закончились сертификаты для важных доменов (bcr.bazel.build).

Последствия? Рабочий процесс сборки встал у сотен корпораций.

Изображение

Разработчики Bazel объяснили: автоматика заблокировалась, когда добавили новые поддомены. Вот где собака зарыта: уведомления о сбое просто не сработали. Это типичная ситуация, когда автоматизация дает ложное чувство безопасности.

Когда система настроена идеально, но никто не смотрит, что она делает, вы получаете "тихий" отказ. В команде Bazel оказалось, что специалисты, знающие, как всё починить вручную, были недоступны.

Почему автоматизация усиливает риски?

Автоматизированные системы работают незаметно. Они создают иллюзию, что TLS-инфраструктура не требует внимания. Когда конвейер ломается, даже опытный сисадмин может растеряться, если долгое время не лез в него вручную.

  • Есть нюанс: ACME-клиент может отчитаться об успехе, получив новый сертификат, но он не гарантирует, что служба, которая его использует, корректно перезапустилась.
  • Задача клиента: Крупный финтех-стартап с 150+ микросервисами внезапно остановился. Виновник — wildcard-сертификат, настроенный на JetStream ACME-клиент. Клиент не смог пройти повторную проверку домена из-за нового WAF-правила, которое заблокировало HTTP-01 чеки. Решение: инженеры вручную переключили JetStream на DNS-01 аутентификацию и быстро развернули новый сертификат. Плюс, добавили еженедельный Health Check скрипт, который пингует /health эндпоинты критических сервисов. Итог: простой длился 47 минут, потеряв $12 000 прямого дохода. Но зато следующий сбой предотвратили за 72 часа до истечения срока, сэкономив команде около 12 человеко-часов на экстренное реагирование.

Как настроить надежный внешний мониторинг валидности сертификатов

Если вы используете ACME-клиенты, вам нужен внешний страж. Внешний мониторинг — это ваша страховка от сбоев внутренней автоматики. Я советую настраивать проверку валидности так, чтобы оповещение приходило не менее чем за 14 дней до конца срока.

Коллегам я часто советую использовать минималистичные скрипты, которые просто запускаются по cron или Task Scheduler. Они живут отдельно от вашего основного ACME-клиента.

Примеры скриптов проверки срока действия TLS

Вот несколько проверенных на практике скриптов для быстрой проверки.

# Bash

#!/bin/bash
DOMAIN="example.com"
DAYS_LEFT=$(echo | openssl s_client -servername $DOMAIN -connect $DOMAIN:443 2>/dev/null | openssl x509 -noout -checkend 864000 | awk '{print $2}') # Проверяем на 10 дней (864000 сек)
if [ "$DAYS_LEFT" -lt 14 ]; then
    echo "WARNING: Certificate for $DOMAIN expires in $DAYS_LEFT days!"
fi

# Python (Используя ssl или requests)

import ssl
import socket
import datetime

def check_cert_expiry(hostname, port=443, warn_days=14):
    context = ssl.create_default_context()
    try:
        with socket.create_connection((hostname, port)) as sock:
            with context.wrap_socket(sock, server_hostname=hostname) as ssock:
                cert = ssock.getpeercert()
                # Получаем дату окончания действия (формат 'notAfter')
                expiry_str = cert['notAfter']
                expiry_date = datetime.datetime.strptime(expiry_str, '%b %d %H:%M:%S %Y %Z')
                
                days_left = (expiry_date - datetime.datetime.now()).days
                
                if days_left < warn_days:
                    print(f"CRITICAL: {hostname} expires in {days_left} days!")
                else:
                    print(f"OK: {hostname} expires in {days_left} days.")
    except Exception as e:
        print(f"Error checking {hostname}: {e}")

# check_cert_expiry("example.com")
  • (Примечание: Для продакшена лучше брать специализированные библиотеки, но эти простые примеры годятся для быстрого внешнего мониторинга.)

Если нужна более комплексная штука, особенно в Kubernetes или там, где уже есть Prometheus, ssl_exporter — это то, что нужно. Он превращает валидность сертификата в метрику, которую можно смотреть на дашбордах и настраивать алерты. Это работает по принципу dead man's switch: система сигнализирует, пока она жива и в порядке. 🚀

  • --

В качестве более надежного примера для современных CI/CD или облачных сред, я рекомендую использовать библиотеку cryptography. Она точнее парсит ASN.1 структуры сертификатов, избегая проблем с локалью при строковом парсинге, как иногда бывает с socket и ssl.

  • Практический пример Python с cryptography
from cryptography.x509 import load_pem_x509_certificate
from cryptography.hazmat.primitives import serialization
import socket
import datetime

# Задаем целевой хост и порог предупреждения в днях
TARGET_HOST = "secure-api.corp.local"
WARNING_THRESHOLD_DAYS = 14

try:
    # 1. Установление соединения и получение данных сертификата через сокет
    context = ssl.create_default_context()
    with socket.create_connection((TARGET_HOST, 443)) as sock:
        with context.wrap_socket(sock, server_hostname=TARGET_HOST) as ssock:
            der_cert = ssock.getpeercert(binary_form=True)

    # 2. Парсинг DER-кодированного сертификата в объект x509
    cert = load_pem_x509_certificate(der_cert)
    
    # 3. Получение даты окончания действия (notAfter)
    expiry_date = cert.not_valid_after.replace(tzinfo=None) # Убираем TZ для простого сравнения
    
    days_left = (expiry_date - datetime.datetime.now()).days

    if days_left <= WARNING_THRESHOLD_DAYS:
        print(f"ALERT: {TARGET_HOST} expires in {days_left} days. Renew immediately.")
    else:
        print(f"OK: {TARGET_HOST} is valid for {days_left} more days.")

except Exception as e:
    print(f"FATAL ERROR checking {TARGET_HOST}: {e}")

Этот скрипт использует стандартные библиотеки socket для получения сырых данных сертификата (в формате DER, так как getpeercert(binary).

Нужна помощь с автоматизацией?

Настроить конвейер ACME-сертификатов нужно надежно, но, как показал кейс Bazel, внешняя валидация критически важна, даже если скрипты есть. Если самостоятельная настройка сложного мониторинга или отладка сбоев в вашем CI/CD кажется слишком большой головной болью, мы можем это взять на себя. 💡

Меня зовут Александр, я Python-разработчик, специализируюсь на автоматизации бизнеса и имею 10+ лет опыта в системной интеграции. Моя команда и я нацелены на отказоустойчивые решения для инфраструктуры:

  • Внедряем и проводим аудит систем ACME-сертификатов и Zero Trust.
  • Разрабатываем кастомные системы мониторинга (Prometheus, Alertmanager) для TLS-инфраструктуры.
  • Автоматизируем сложные процессы развертывания и миграции сервисов.

Нужна помощь с автоматизацией?

Обсудим ваш проект и найдём решение

Получить консультацию