Проверка сертификата сервера из 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

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

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

Licensed under GPL v2

Repo link: https://github.com/mnorin/mnorin.github.io