TLS monitoring für unsere infrastruktur

Wir kennen das seit es Let’s Encrypt gitbt ja alle: man setzt das auf und drei monate später geht auf einmal nix mehr!

Zwar bekommt man wenn bei der LE registrierung eine email addresse angibt benachrichtigungen wenn ein monat vor ablauf kein neues zertifikat für eine domain generiert wurde (siehe LE docs zum thema Expiration Emails). Das reine renewen der certs ist aber oft nicht die ganze story. Eventuell muss man mit deploy hooks auch noch die certs mit richtigen permissions irgendwo hin kopieren oder den server mit einem obskuren signal dazu anregen das cert und den private key neu zu laden. Dabei kann also doch noch einiges schief gehn.

Um dieses problem zu lösen haben wir jetzt einen sehr simplen monitoring cron job laufen der zwei kleine aber feine tricks verwendet.

Auf yxorp.parabox.it-syndikat.org haben wir in /etc/cron.daily/its-monitor-yxorp-tls:

#!/bin/sh
# Bitte bei aenderungen ins meta kopieren: https://meta.it-syndikat.org/t/2492
HC_URL=${HC_URL:-https://hc-ping.com/<uuid>}

set -e

check_tls () {
        # Check two weeks in the future to give us time to fix certs
        faketime +14days \
                openssl s_client -showcerts -verify_return_error "$@" \
                </dev/null
}

cronic () {
        if ! "$@" >/dev/null 2>/dev/null; then
                # Print output on error
                set -x
                "$@"
                printf '\n\n\n\n\n'
        fi
}

for af in -4 -6; do
        for connect in \
                it-syndikat.org:443 \
                www.it-syndikat.org:443 \
                meta.it-syndikat.org:443 \
                meta.it-syndikat.org:443 \
                \
                git.it-syndikat.org:443 \
                mailtrain.it-syndikat.org:443 \
                \
                it-syndik.at:443 \
                matrix.it-syndik.at:443 \
                riot.it-syndik.at:443 \
                1.riot.it-syndik.at:443 \
                2.riot.it-syndik.at:443 \
                3.riot.it-syndik.at:443 \
                \
                mail.it-syndikat.org:465 \
                mail.it-syndikat.org:993 \
                ;
        do
                cronic check_tls $af -connect $connect
        done

        cronic check_tls $af -starttls smtp -connect mail.it-syndikat.org:25
        cronic check_tls $af -starttls smtp -connect mail.it-syndikat.org:587

        #cronic check_tls $af -starttls imap -connect mail.it-syndikat.org:143
done

[ -z "$HC_URL" ] || curl -s -m 10 --retry 5 "$HC_URL" >/dev/null

Das script verwendet ganz einfach openssl s_client um die TLS verbindung zu testen. Per default gibt das jedoch keinen brauchbaren exit code her, die -verify_return_error stellt das um. Normalerweise würde dieses script jetzt genau dann schreien anfangen wenn auch jeder andere das problem schon im browser sieht. Mit dem faketime programm können wir aber s_client in die zukunft schicken und somit zeit bekommen das problem zu lösen.

So weit so gut. Zuletzt verwenden wir dann noch healthchecks.io um benachrichtigt zu werden wenn dieser cronjob nicht sauber durchläuft. Wir haben da ein projekt, aktuell werden @dxld und @gwrx benachrichtigt. Wer zugriff haben will bitte melden.

Auf matrix.parabox.it-syndikat.org läuft ein ähnliches script dass sich um *.it-syndik.at kümmert.

Hab das jetzt mal auf die website gesetzt als blog-projects gesetzt.

Kleines update: das aktuelle script verifiziert nicht ob der angegebene hostname mit einem subject aus dem cert zusammen passt. Nach lang suchen bin ich auf die openssl-verification-options(1) man page gestoßen in der die -verify_hostname option dokumentiert is mit der man das machen kann. Muss das script mal bei gelegenheit anpassen.