Skip to content

Repository files navigation

Certificate Expiry Checker 🔐

Скрипт для автоматического сканирования и анализа SSL/TLS сертификатов.

Возможности

  • Рекурсивное сканирование директорий для поиска .crt файлов
  • Анализ дат начала и истечения сертификатов
  • Группировка по статусу (просроченные, истекающие, действительные)
  • Отправка уведомлений в Telegram
  • Отправка email уведомлений (HTML + plain text)
  • Гибкая настройка через .env файл
  • Режим отладки с детальным логированием
  • Поддержка PEM и DER форматов

Требования

  • Python 3.12+
  • Пакеты общие: pip install poetry poetry-plugin-shell poetry-dotenv-plugin ruff mypy
  • Пакеты проекта: niquests, cryptography, pyOpenSSL, python-dotenv

Установка

git clone <repo-url>
cd certificate-expiry-checker
python -m venv venv
source venv/bin/activate
pip install niquests cryptography pyOpenSSL python-dotenv

Конфигурация

Создайте файл .env:

SCAN_DIRECTORY=/etc/ssl/certs
VERBOSE=false
EXPIRING_DAYS=30
TELEGRAM_BOT_TOKEN=your_token
TELEGRAM_CHAT_ID=your_chat_id
EMAIL_ENABLED=true
EMAIL_SMTP_HOST=smtp.gmail.com
EMAIL_SMTP_PORT=587
EMAIL_USE_TLS=true
EMAIL_USERNAME=your_email@gmail.com
EMAIL_PASSWORD=your_password
EMAIL_FROM=noreply@example.com
EMAIL_TO=admin@example.com

Использование

poetry run check-certs
poetry run check-certs /path/to/.env.custom
poetry run python src/check_expire_certs/main.py
poetry run python src/check_expire_certs/main.py /path/to/.env.custom

Аргументы командной строки

Аргумент Описание
env_file Путь к .env файлу (опционально)

Переменные окружения

Обязательные:

  • SCAN_DIRECTORY - путь к директории с сертификатами

Опциональные:

  • VERBOSE - режим отладки (false по умолчанию)
  • EXPIRING_DAYS - порог истечения в днях

Telegram:

  • TELEGRAM_BOT_TOKEN - токен бота
  • TELEGRAM_CHAT_ID - ID чата

Email:

  • EMAIL_ENABLED - включить email (false)
  • EMAIL_SMTP_HOST - SMTP сервер
  • EMAIL_SMTP_PORT - порт (587)
  • EMAIL_USE_TLS - использовать TLS (true)
  • EMAIL_USERNAME - имя пользователя
  • EMAIL_PASSWORD - пароль
  • EMAIL_FROM - отправитель
  • EMAIL_TO - получатели через запятую
  • EMAIL_SUBJECT - тема письма

Уведомления

Telegram использует Markdown с эмодзи:

  • 🔴 критично (7 дней и меньше)
  • 🟡 средне (8-14 дней)
  • 🟠 низко (15-30 дней)
  • ❌ просрочен

Email отправляется в HTML и plain text форматах.

Логирование

  • INFO - основная информация
  • DEBUG - детальная информация (при VERBOSE=true)

Формат: YYYY-MM-DD HH:MM:SS - LEVEL - message

Обработка ошибок

Ошибка Результат
Нет SCAN_DIRECTORY выход с кодом 1
Директория не существует выход с кодом 1
Нет прав на чтение выход с кодом 1
Ошибки сертификатов пропуск файла
Ошибки уведомлений логирование, продолжение

📜 Лицензия

MIT © 2026

Автоматически сгенерированная документация

Основной модуль для сканирования и анализа SSL/TLS сертификатов.

Этот модуль предоставляет функциональность для:

  • Парсинга аргумента командной строки, указание кастомного .env.custom
  • Загрузки переменных окружения из .env в корне проекта
  • Сканирования каталога с сертификатами
  • Анализа сроков действия сертификатов
  • Отправки уведомлений о проблемных сертификатах (telegram/email)

load_environment

def load_environment(env_file_path: str | None = None,
                     verbose: bool = False) -> None

Загружает переменные окружения из .env файла.

Логика:

  • Если передан env_file_path, загружается ТОЛЬКО этот файл (очищаются существующие переменные)
  • Если env_file_path не передан, ищется .env в стандартных местах

Arguments:

  • env_file_path str | None - Путь к .env файлу (из аргументов командной строки) может быть и None
  • verbose bool - Логировать ли процесс загрузки

Returns:

None

Raises:

  • SystemExit - Если указанный файл не существует

setup_logging

def setup_logging(verbose: bool = False) -> None

Настройка системы логирования.

Arguments:

  • verbose bool - Если True, устанавливается уровень DEBUG, иначе INFO

Returns:

None

scan_certificates

def scan_certificates(directory_path: str) -> list[Path]

Сканирует указанный каталог и возвращает список всех файлов с расширением .crt.

Arguments:

  • directory_path str - Путь к директории для сканирования

Returns:

  • List[Path] - Список путей к файлам сертификатов

Raises:

  • FileNotFoundError - Если указанный путь не существует
  • NotADirectoryError - Если указанный путь не является каталогом

get_certificate_expiry

def get_certificate_expiry(
        cert_path: Path) -> tuple[datetime, datetime] | None

Получает даты начала и истечения срока действия сертификата.

Arguments:

  • cert_path Path - Путь к файлу сертификата

Returns:

tuple[datetime, datetime] | None: Кортеж (дата_начала, дата_истечения) или None при ошибке

parse_certificates_expiry

def parse_certificates_expiry(
    certificate_paths: list[Path]
) -> list[tuple[Path, datetime | None, datetime | None]]

Анализирует список сертификатов и возвращает информацию о сроках их действия.

Arguments:

  • certificate_paths list[Path] - Список путей к сертификатам

Returns:

list[tuple[Path, datetime | None, datetime | None]]: Список кортежей (путь, дата_начала, дата_истечения)

display_certificate_detail

def display_certificate_detail(cert_path: Path, start_date: datetime | None,
                               expiry_date: datetime | None,
                               current_date_utc: datetime) -> None

Отображает детальную информацию об одном сертификате.

Arguments:

  • cert_path Path - Путь к файлу сертификата
  • start_date datetime | None - Дата начала действия
  • expiry_date datetime | None - Дата истечения
  • current_date_utc datetime - Текущая дата для расчета статуса

Returns:

None

build_notification_message

def build_notification_message(expired_certs: list[tuple[Path, datetime | None,
                                                         datetime | None]],
                               expiring_certs: list[tuple[Path,
                                                          datetime | None,
                                                          datetime | None]],
                               expiring_days: int,
                               format_type: str = "text") -> str

Формирует сообщение уведомления о проблемных сертификатах.

Arguments:

  • expired_certs list[tuple[Path, datetime | None, datetime | None]] - Список просроченных сертификатов
  • expiring_certs list[tuple[Path, datetime | None, datetime | None]] - Список сертификатов, истекающих в ближайшее время
  • expiring_days int - Количество дней для фильтрации "скоро истекающих"
  • format_type str - Формат сообщения ('text' или 'html')

Returns:

  • str - Сформированное сообщение

Raises:

  • ValueError - Если указан неподдерживаемый формат

send_email_notification

def send_email_notification(
        expired_certs: list[tuple[Path, datetime | None, datetime | None]],
        expiring_certs: list[tuple[Path, datetime | None, datetime | None]],
        expiring_days: int,
        smtp_host: str,
        smtp_port: int,
        use_tls: bool,
        username: str,
        password: str,
        from_addr: str,
        to_addrs: list[str],
        subject: str = "🔔 Уведомление о сертификатах") -> bool

Отправляет уведомление по email о проблемных сертификатах.

Arguments:

  • expired_certs list[tuple[Path, datetime | None, datetime | None]] - Список просроченных сертификатов
  • expiring_certs list[tuple[Path, datetime | None, datetime | None]] - Список сертификатов, истекающих в ближайшее время
  • expiring_days int - Количество дней для фильтрации "скоро истекающих"
  • smtp_host str - SMTP сервер
  • smtp_port int - Порт SMTP сервера
  • use_tls bool - Использовать ли TLS
  • username str - Имя пользователя для авторизации
  • password str - Пароль для авторизации
  • from_addr str - Email отправителя
  • to_addrs list[str] - Список email получателей
  • subject str - Тема письма

Returns:

  • bool - True если сообщение успешно отправлено, False в противном случае

send_telegram_notification

def send_telegram_notification(expired_certs: list[tuple[Path, datetime | None,
                                                         datetime | None]],
                               expiring_certs: list[tuple[Path,
                                                          datetime | None,
                                                          datetime | None]],
                               expiring_days: int, bot_token: str,
                               chat_id: str) -> bool

Отправляет уведомление в Telegram о проблемных сертификатах.

Arguments:

  • expired_certs list[tuple[Path, datetime | None, datetime | None]] - Список просроченных сертификатов
  • expiring_certs list[tuple[Path, datetime | None, datetime | None]] - Список сертификатов, истекающих в ближайшее время
  • expiring_days int - Количество дней для фильтрации "скоро истекающих"
  • bot_token str - Токен Telegram бота
  • chat_id str - ID чата/канала для отправки сообщения

Returns:

  • bool - True если сообщение успешно отправлено, False в противном случае

display_grouped_certificate_info

def display_grouped_certificate_info(
        expired_certs: list[tuple[Path, datetime | None, datetime | None]],
        expiring_certs: list[tuple[Path, datetime | None, datetime | None]],
        valid_certs: list[tuple[Path, datetime | None, datetime | None]]
    | None = None,
        expiring_days: int = 30) -> None

Отображает информацию о сертификатах в сгруппированном виде с единой статистикой.

Arguments:

  • expired_certs list[tuple[Path, datetime | None, datetime | None]] - Список просроченных сертификатов
  • expiring_certs list[tuple[Path, datetime | None, datetime | None]] - Список сертификатов, истекающих в ближайшее время
  • valid_certs list[tuple[Path, datetime | None, datetime | None]] | None = None - Список действительных сертификатов (опционально)
  • expiring_days int - Количество дней для фильтрации "скоро истекающих"

Returns:

None

parse_arguments

def parse_arguments() -> argparse.Namespace

Парсинг аргументов командной строки - принимает только путь к .env файлу.

Returns:

  • argparse.Namespace - Объект с аргументами командной строки

main

def main() -> None

Основная функция программы для сканирования и анализа сертификатов.

Выполняет следующие шаги:

  1. Парсит аргументы командной строки (путь к .env файлу)
  2. Загружает переменные окружения из .env файла
  3. Настраивает систему логирования
  4. Проверяет наличие обязательных параметров (SCAN_DIRECTORY)
  5. Сканирует указанный каталог для поиска .crt файлов
  6. Анализирует каждый найденный сертификат (даты начала и истечения)
  7. Фильтрует сертификаты по сроку истечения (если указан EXPIRING_DAYS)
  8. Отображает результаты проверки в консоли
  9. Отправляет уведомления о проблемных сертификатах в Telegram и/или Email
  10. Завершает работу с соответствующим кодом возврата

Arguments:

None (использует аргументы командной строки и переменные окружения)

Returns:

None

Raises:

  • SystemExit - Выход из программы с кодом:
    • 0: Успешное завершение, ошибок нет
    • 1: Ошибка (отсутствует SCAN_DIRECTORY, файл не найден, ошибка доступа и т.д.)

Notes:

Переменные окружения, используемые в функции:

  • SCAN_DIRECTORY (обязательный): Путь к каталогу с сертификатами
  • VERBOSE (опциональный): Режим отладки (true/false, по умолчанию false)
  • EXPIRING_DAYS (опциональный): Порог истечения в днях для фильтрации
  • TELEGRAM_BOT_TOKEN (опциональный): Токен Telegram бота
  • TELEGRAM_CHAT_ID (опциональный): ID чата Telegram
  • EMAIL_ENABLED (опциональный): Включить Email уведомления
  • EMAIL_SMTP_HOST (опциональный): SMTP сервер
  • EMAIL_SMTP_PORT (опциональный): Порт SMTP (по умолчанию 587)
  • EMAIL_USE_TLS (опциональный): Использовать TLS (по умолчанию true)
  • EMAIL_USERNAME (опциональный): Имя пользователя для SMTP
  • EMAIL_PASSWORD (опциональный): Пароль для SMTP
  • EMAIL_FROM (опциональный): Email отправителя
  • EMAIL_TO (опциональный): Список получателей (через запятую)
  • EMAIL_SUBJECT (опциональный): Тема письма

Examples:

Базовый запуск: $ python main.py

Запуск с конкретным .env файлом: $ python main.py /path/to/.env

Запуск с переменными окружения: $ SCAN_DIRECTORY=/etc/ssl/certs python main.py

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages