🢂SSL ‑ Monitoring wygaśnięcia certyfikatu

Tworzymy skrypt w PHP i Python monitorujący certyfikat SSL dla wybranej domeny.

Aby stworzyć skrypt monitorujący certyfikat SSL dla wybranej domeny w PHP, wykonaj poniższe kroki:

  1. Użyj funkcji stream_socket_client() do połączenia z domeną przez protokół SSL. Umożliwi to uzyskanie informacji o certyfikacie.
  2. Wykorzystaj stream_context_get_params() do pobrania szczegółów certyfikatu z połączenia.
  3. Sprawdź datę wygaśnięcia certyfikatu, porównując ją z aktualną datą.
  4. Na podstawie wyniku sprawdzenia, podejmij odpowiednie działania, np. wyślij powiadomienie, jeśli certyfikat jest bliski wygaśnięcia.

Skrypt monitorujący datę wygaśnięcia certyfikatu SSL

<?php
$domena = 'example.com:443';
$kontekst = stream_context_create(['ssl' => ['capture_peer_cert' => true]]);
$polaczenie = @stream_socket_client('ssl://' . $domena, $bladNr, $bladStr, 30, STREAM_CLIENT_CONNECT, $kontekst);

if ($polaczenie) {
    $params = stream_context_get_params($polaczenie);
    $certyfikat = openssl_x509_parse($params['options']['ssl']['peer_certificate']);

    if ($certyfikat) {
        $dataWygasniecia = $certyfikat['validTo_time_t'];
        $teraz = time();

        if ($dataWygasniecia > $teraz) {
            echo "Certyfikat jest ważny do " . date('Y-m-d H:i:s', $dataWygasniecia) . ".\n";
        } else {
            echo "Certyfikat wygasł.\n";
        }
    } else {
        echo "Nie udało się pobrać danych certyfikatu.\n";
    }
} else {
    echo "Błąd połączenia: $bladStr ($bladNr)\n";
}
?>

Zastąp example.com:443rzeczywistą domeną, którą chcesz monitorować. Ten skrypt pokazuje, jak nawiązać połączenie z serwerem, pobrać informacje o certyfikacie SSL i sprawdzić jego ważność.

Wersja python

import ssl
import socket
from datetime import datetime

domena = 'example.com'
port = 443

context = ssl.create_default_context()

try:
    with socket.create_connection((domena, port)) as sock:
        with context.wrap_socket(sock, server_hostname=domena) as secured_sock:
            certyfikat = secured_sock.getpeercert()
            data_wygasniecia = datetime.strptime(certyfikat['notAfter'], '%b %d %H:%M:%S %Y %Z')
            teraz = datetime.now()

            if data_wygasniecia > teraz:
                print(f"Certyfikat jest ważny do {data_wygasniecia.strftime('%Y-%m-%d %H:%M:%S')}.")
            else:
                print("Certyfikat wygasł.")
except Exception as e:
    print(f"Błąd połączenia: {e}")

Wersja rozbudowana

Ten skrypt przegląda każdą domenę w tablicy $domeny, nawiązuje połączenie SSL w celu pobrania danych certyfikatu, a następnie sprawdza, czy certyfikat wygaśnie w ciągu najbliższych ($ileDni) 10 dni. Jeśli tak jest, wysyła powiadomienie e-mail na zdefiniowany adres.

Przed użyciem skryptu, upewnij się, że konfiguracja serwera PHP pozwala na wysyłanie maili za pomocą funkcji mail(). W rzeczywistych zastosowaniach, zalecane jest użycie bardziej zaawansowanego mechanizmu wysyłki e-maili, na przykład przez SMTP z wykorzystaniem biblioteki PHPMailer lub podobnej, aby zwiększyć niezawodność i kontrolę nad procesem wysyłania.

<?php
$ileDni = 10;
$domeny = ['example.com:443', 'anotherdomain.com:443'];
$adresEmailDoPowiadomien = 'twojemail@example.com';

foreach ($domeny as $domena) {
    $kontekst = stream_context_create(['ssl' => ['capture_peer_cert' => true]]);
    $polaczenie = @stream_socket_client('ssl://' . $domena, $bladNr, $bladStr, 30, STREAM_CLIENT_CONNECT, $kontekst);

    if ($polaczenie) {
        $params = stream_context_get_params($polaczenie);
        $certyfikat = openssl_x509_parse($params['options']['ssl']['peer_certificate']);

        if ($certyfikat) {
            $dataWygasniecia = $certyfikat['validTo_time_t'];
            $teraz = time();
            $roznicaDni = ($dataWygasniecia - $teraz) / 86400; // 86400 sekund = 1 dzień

            if ($roznicaDni <= $ileDni) {
                $wiadomosc = "Certyfikat dla domeny $domena wygaśnie za $roznicaDni dni.\n";
                mail($adresEmailDoPowiadomien, "Certyfikat SSL wygasa", $wiadomosc);
            }### Wersja python
        } else {
            echo "Nie udało się pobrać danych certyfikatu dla $domena.\n";
        }
    } else {
        echo "Błąd połączenia z $domena: $bladStr ($bladNr)\n";
    }
}
?>

Wersja rozbudowana w python

import ssl
import socket
from datetime import datetime
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart

ile_dni = 10
domeny = ['example.com:443', 'anotherdomain.com:443']
adres_email_do_powiadomien = 'twojemail@example.com'
smtp_server = 'smtp.example.com'
smtp_port = 587
smtp_uzytkownik = 'twojemail@example.com'
smtp_haslo = 'twoje_haslo'

def wyslij_email(odbiorca, temat, tresc):
    wiadomosc = MIMEMultipart()
    wiadomosc['From'] = smtp_uzytkownik
    wiadomosc['To'] = odbiorca
    wiadomosc['Subject'] = temat
    wiadomosc.attach(MIMEText(tresc, 'plain'))
    try:
        serwer = smtplib.SMTP(smtp_server, smtp_port)
        serwer.starttls()
        serwer.login(smtp_uzytkownik, smtp_haslo)
        serwer.sendmail(smtp_uzytkownik, odbiorca, wiadomosc.as_string())
        serwer.quit()
        return "E-mail został wysłany."
    except Exception as e:
        return f"Błąd wysyłania e-maila: {e}"

def sprawdz_i_powiadom_o_wygasajacych_certyfikatach():
    wyniki = []

    for domena_port in domeny:
        domena, port = domena_port.split(':')
        context = ssl.create_default_context()

        try:
            with socket.create_connection((domena, int(port))) as sock:
                with context.wrap_socket(sock, server_hostname=domena) as secured_sock:
                    certyfikat = secured_sock.getpeercert()
                    data_wygasniecia = datetime.strptime(certyfikat['notAfter'], '%b %d %H:%M:%S %Y %Z')
                    teraz = datetime.now()
                    roznica_dni = (data_wygasniecia - teraz).days

                    if roznica_dni <= ile_dni:
                        tresc_wiadomosci = f"Certyfikat dla domeny {domena} wygaśnie za {roznica_dni} dni."
                        wyniki.append(tresc_wiadomosci)
                        rezultat_wysylki = wyslij_email(adres_email_do_powiadomien, "Certyfikat SSL wygasa", tresc_wiadomosci)
                        wyniki.append(rezultat_wysylki)
                    else:
                        wyniki.append(f"Certyfikat dla domeny {domena} jest ważny przez więcej niż {ile_dni} dni.")

        except Exception as e:
            wyniki.append(f"Błąd połączenia z {domena}: {e}")

    if not wyniki:
        wyniki.append("Nie wykonano żadnych operacji.")

    return wyniki

wynik = sprawdz_i_powiadom_o_wygasajacych_certyfikatach()
for komunikat in wynik:
    print(komunikat)