Проверка сертификата сервера из bash

Проверка сертификата сервера из bashПроверка сертификата сервера из bash может быть полезна для мониторинга, чтобы не пропустить дату продления сертификата. Такие проблемы как продление доменного имени и продление SSL-сертификата достаточно распространены, даже серьезные организации иногда забывают проплатить домен или купить новый сертификат. Поэтому хорошей практикой является мониторинг даты окончания действия сертификата и доменного имени. С доменным именем разберемся в другой раз, а пока давайте посмотрим, как написать скрипт, который не только покажет поля сертификата на удаленном сервере, но и скажет, сколько дней осталось до окончания сертификата.

Что нам потребуется

Для проверки будем использовать, естественно, Linux. Именно на нем чаще всего стоят системы мониторинга, такие как Zabbix и Nagios. Кроме сервера с Linux’ом нам еще кое-что потребуется. Прежде всего OpenSSL (чем свежее, тем лучше), и, конечно же, bash, на котором мы и будем писать скрипт. Этот скрипт будет полезен как при ручной проверке, так и при автоматизированных проверках.

Проверка сертификата сервера из bash

Вот как будет организована проверка. Мы открываем SSL-соединение с сервером, получаем сертификат, передаем его на обработку OpenSSL (openssl x509), получая таким образом информацию по полям, а если нам нужно посчитать, сколько времени осталось до истечения срока действия сертификата, будет использовать отдельный параметр, который нам просто выведет количество дней в формате «N days».

Вот сам скрипт с комментариями:

#!/bin/bash

SERVERNAME=$1
PORT=$2
PARAMS=""

# Функция, которая выводит помощь по параметрам
print_help(){
cat << EOF
  Script that fetches SSL certificate information from remote server and prints out certificate fields.
  Can be used for certificate expiration date monitoring.

  Usage: certinfo.sh hostname.or.ip.address port [parameters]

  Parameters:

  --issuer      - Certificate issuer
  --subject     - Subject
  --serial      - Serial
  --email       - Email
  --start-date  - Certificate start date
  --end-date    - Certificate end date
  --expires-in  - Expiration in days
  --purpose     - Certificate purposes
  --dates       - Both start and end dates
  --fingerprint - Certificate fingerprint
  --alias       - Certificate aliases
  --modulus     - Modulus
  --pubkey      - Public key
  --all         - Full certificate information (the same as without any parameters)
  --help        - This help
EOF
exit 0
}

# Функция, которая показывает, сколько дней осталось до конца действия сертификата
expires_in(){
    EXP_DATE=$( 
    echo "" | openssl s_client -connect ${SERVERNAME}:${PORT} 2>/dev/null \
    | sed -n '/-----BEGIN CERTIFICATE-----/,/-----END CERTIFICATE-----/p' \
    | openssl x509 -noout -in - -enddate \
    | sed 's/notAfter=//' 
)
    DAYS_LEFT=$(( ($(date -d "$EXP_DATE" +%s) - $(date -d "now" +%s) ) / 86400 ))
    echo $DAYS_LEFT days
    exit
}

# Сдвигаем параметры, пропуская сервер и порт
shift 2
# Анализируем параметры скрипта в цикле
# Это позволяет указывать их в произвольном порядке
while [ "$1" != "" ]
do
    case "$1" in
        --issuer) PARAMS+="-issuer " ;;
        --subject) PARAMS+="-subject " ;;
        --serial) PARAMS+="-serial " ;;
        --email) PARAMS+="-email " ;;
        --start-date) PARAMS+="-startdate " ;;
        --end-date) PARAMS+="-enddate " ;;
        --purpose) PARAMS+="-purpose " ;;
        --dates) PARAMS+="-dates " ;;
        --fingerprint) PARAMS+="-fingerprint " ;;
        --alias) PARAMS+="-alias " ;;
        --modulus) PARAMS+="-modulus " ;;
        --pubkey) PARAMS+="-pubkey " ;;
        --all) PARAMS+="-text " ;;
        --help) print_help ;;
        --expires-in) expires_in ;;
        *) ;;
    esac
    shift
done

# Если параметры не указаны, то просто выводим полную информацию о сертификате
PARAMS=${PARAMS:-"-text "}

# Проверка сертификата сервера из bash
# Получаем сертификат удаленного сервера из вывода SSL клиента
# Выделяем само тело сертификата и передаем на обработку openssl x509
# Подставляем параметры, чтобы вывелась информация по нужным полям
echo "" | openssl s_client -connect ${SERVERNAME}:${PORT} 2>/dev/null \
| sed -n '/-----BEGIN CERTIFICATE-----/,/-----END CERTIFICATE-----/p' \
| openssl x509 -noout -in - $PARAMS

Что можно улучшить

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

Проверка сертификата сервера из bash: 6 комментариев

  1. Aleksey Antciferov

    Добавь сюда подписывание exe из Linux. На удивление очень популярный запрос
    osslsigntool

    1. Maxim Norin Автор записи

      Хм. Я, честно говоря, удивлён :-) Ни разу такое не надо еще было.

  2. Роман

    Спасибо, очень помогло. Искал как перевести дату в unix формат, нашел, плюс еще сравнение с текущей датой.

  3. Taras

    Error opening Certificate —
    140339159390112:error:02001002:system library:fopen:No such file or directory:bss_file.c:398:fopen(‘-‘,’r’)
    140339159390112:error:20074002:BIO routines:FILE_CTRL:system lib:bss_file.c:400:
    unable to load certificate

    1. Taras

      Ругается на дефис в 41-й строчке:
      | openssl x509 -noout -in — -enddate \

      1. Maxim Norin Автор записи

        Можно вызов скрипта целиком? С запуском скрипта и выводом ошибки

Обсуждение закрыто.