• Link zu Youtube
  • Link zu Mail
  • ÜBER MICH
  • ARCHIV
www.vguru.de
  • Training
  • Blog
  • Click to open the search input field Click to open the search input field Suche
  • Menü Menü

Zertifikatsbericht per NITRO: warum abgelaufene Zertifikate fehlen

21. Oktober 2026/0 Kommentare/von Lars

Ein Skript fragt über NITRO, die REST-Schnittstelle der NetScaler, alle Zertifikate einer Appliance ab und sortiert sie nach Restlaufzeit. Es läuft ohne Fehler, der Zertifikatsbericht ist sauber formatiert, und trotzdem tauchen abgelaufene Zertifikate darin nicht auf. Der Grund liegt in einem einzigen Feld der API, und die Lösung ist, ein anderes Feld zur Grundlage zu machen.

Die Werte in diesem Beitrag stammen von meiner Testinstanz mit NetScaler 14.1, auf der ich dafür Testzertifikate mit bekanntem Ablaufdatum angelegt habe.

Warum abgelaufene Zertifikate im Zertifikatsbericht fehlen

Die Ressource sslcertkey liefert je Zertifikat unter anderem drei Felder, die für einen Bericht interessant sind: status, daystoexpiration und clientcertnotafter. Die Dokumentation beschreibt daystoexpiration als die Tage, die dem Zertifikat bis zum Ablauf bleiben. Was sie nicht sagt: Der Wert wird nie negativ.

So sieht das für fünf Zertifikate aus, abgefragt am 02.10.2026 gegen 13:40 UTC:

Zertifikatclientcertnotafterstatusdaystoexpiration
seit vier Wochen abgelaufenSep 5 12:00:00 2026 GMTExpired0
läuft am selben Abend abOct 2 22:00:00 2026 GMTValid0
läuft in knapp sieben Tagen abOct 9 12:00:00 2026 GMTValid6
läuft in einem Jahr abOct 2 13:36:23 2027 GMTValid364
internes Zertifikat der ApplianceJan 17 20:33:25 4764 GMTValid999775

Ein Filter wie daystoexpiration -lt 0 liefert damit keinen einzigen Treffer, obwohl ein abgelaufenes Zertifikat in der Liste steht. Es gibt keine Fehlermeldung und keine Warnung. Das Ergebnis ist einfach leer.

Ein Skript, das mit einem Fehler abbricht, fällt sofort auf. Ein leeres Ergebnis dagegen sieht aus wie die Meldung „keine abgelaufenen Zertifikate“.

Null heißt nicht abgelaufen

Die Tabelle zeigt eine zweite Eigenheit: Den Wert 0 tragen zwei Zertifikate, ein abgelaufenes und ein gültiges. Der Zähler wird auf ganze Tage abgeschnitten, ein Zertifikat mit sechs Tagen und 22 Stunden Restlaufzeit steht auf 6, eines mit acht Stunden auf 0.

Ein Filter auf daystoexpiration -eq 0 findet also das abgelaufene Zertifikat, meldet aber zugleich ein gültiges als abgelaufen. Unterscheiden lassen sich die beiden nur über status oder über das Ablaufdatum.

Auf der Kommandozeile ist der Unterschied sichtbar, weil show ssl certkey bei einem abgelaufenen Zertifikat gar keine Tage ausgibt:

Name: tz_abgel    Status: -->Expired<--
Name: tz_bald     Status: Valid,   Days to expiration:6

Wer den Bericht aus der API baut, sieht nur die Zahl.

Zertifikate mit Ablauf im Jahr 4764

Am anderen Ende der Skala stehen die internen Zertifikate der Appliance. Auf meiner Testinstanz läuft ns-sftrust-certificate im Jahr 4764 ab, daystoexpiration steht entsprechend auf 999775. Der Wert ist echt gerechnet und wird jeden Tag um eins kleiner.

Ungefiltert landen solche Einträge am Ende jeder Sortierung, und im Bericht steht ein Ablauf in gut 2700 Jahren. Solche Zeilen lenken vom Wesentlichen ab. Weil der Wert sich ändert, taugt er nicht als fester Vergleichswert. Eine Schwelle tut es: Alles, was weiter als 100 Jahre in der Zukunft liegt, kommt in eine eigene Stufe.

Die Restlaufzeit ist eine Momentaufnahme

Der Tageswert stimmt im Moment der Abfrage. Ein Bericht, der drei Wochen später aus dem Postfach geholt wird, nennt eine Restlaufzeit, die es nicht mehr gibt. Wer Ablaufdatum und Zeitpunkt des Laufs mit ausgibt, macht den Bericht auch später noch lesbar.

Wie du es löst: das Ablaufdatum als Grundlage

Das Ablaufdatum in clientcertnotafter ist ein absoluter Wert. Es bleibt nicht bei null stehen, kennt keine Sonderwerte und altert nicht zwischen Abfrage und Lektüre. Die Restlaufzeit lässt sich daraus jederzeit neu berechnen, umgekehrt geht das nicht.

  1. Das Ablaufdatum in einen echten Datumstyp umwandeln, nicht als Zeichenkette weiterreichen.
  2. Abgelaufen ist, was ein Ablaufdatum in der Vergangenheit hat. Kein Zählerfilter.
  3. Sehr ferne Ablaufdaten über eine Schwelle abfangen und in eine eigene Stufe legen.
  4. Ablaufdatum, Resttage und den Zeitpunkt des Laufs gemeinsam ausgeben.

Die Falle im Datumsformat

clientcertnotafter füllt einen einstelligen Tag mit einem zusätzlichen Leerzeichen auf: Sep 5 12:00:00 2026 GMT. Ein festes Muster wie MMM d HH:mm:ss yyyy 'GMT' scheitert daran mit String was not recognized as a valid DateTime, und zwar nur an den Tagen 1 bis 9 eines Monats. Ein Skript, das im Test am 15. lief, fällt dann am 5. des Folgemonats aus.

Vor dem Parsen die Leerzeichen auf eines reduzieren:

$text = $text -replace '\s+', ' '

Alles in einer Bewertungsfunktion

Die Sonderfälle gehören an eine Stelle, ganz an den Anfang der Verarbeitung. Eine kleine Funktion macht aus dem Ablaufdatum eine eindeutige Stufe: abgelaufen, kritisch, demnächst, unkritisch oder ohne praktisches Ablaufdatum. Ab da arbeitet der Rest des Skripts nur noch mit der Stufe, nie mehr mit den Rohwerten.

Dazu kommt eine Prüfung, die wenige Zeilen kostet: ein Referenzobjekt. Ein Zertifikat, von dem feststeht, dass es existiert. Fehlt es im Ergebnis, bricht der Lauf ab, statt einen Bericht zu erzeugen. ns-server-certificate eignet sich dafür, weil es auf jeder Appliance vorhanden ist.

Der folgende Block läuft unter Windows PowerShell 5.1 und PowerShell 7. Er meldet sich per NITRO über HTTPS am FQDN an, mit regulärer Zertifikatsprüfung, fragt die Zertifikate ab und meldet sich wieder ab. Leserechte genügen.

$Appliance = 'adc01.example.com'          # FQDN, passend zum Zertifikat der Verwaltung
$Referenz  = 'ns-server-certificate'      # gibt es auf jeder Appliance
$Kultur    = [Globalization.CultureInfo]::InvariantCulture

function Get-ZertifikatsStufe {
    param([string]$NotAfter, [datetime]$Jetzt)
    $text   = $NotAfter -replace '\s+', ' '          # "Sep  5" wird zu "Sep 5"
    $ablauf = [datetime]::ParseExact($text, "MMM d HH:mm:ss yyyy 'GMT'", $Kultur,
                  [Globalization.DateTimeStyles]'AssumeUniversal, AdjustToUniversal')
    $tage   = ($ablauf - $Jetzt).TotalDays
    $stufe  = if     ($tage -lt 0)     { 'abgelaufen' }
              elseif ($tage -lt 14)    { 'kritisch' }
              elseif ($tage -lt 60)    { 'demnaechst' }
              elseif ($tage -gt 36500) { 'ohne praktisches Ablaufdatum' }
              else                     { 'unkritisch' }
    [pscustomobject]@{ Ablauf = $ablauf; Tage = [int][math]::Truncate($tage); Stufe = $stufe }
}

if (-not $Credential) { $Credential = Get-Credential -Message 'NetScaler-Anmeldung (Leserechte genuegen)' }
$basis = "https://$Appliance/nitro/v1/config"
$rumpf = @{ login = @{ username = $Credential.UserName.Split('\')[-1]
                       password = $Credential.GetNetworkCredential().Password } } | ConvertTo-Json
$null  = Invoke-RestMethod -Method Post -Uri "$basis/login" -Body $rumpf `
             -ContentType 'application/json' -SessionVariable sitzung
try {
    $lauf  = [datetime]::UtcNow
    $liste = (Invoke-RestMethod -Uri "$basis/sslcertkey?attrs=certkey,status,clientcertnotafter,daystoexpiration" `
                  -WebSession $sitzung).sslcertkey
    if ($liste.certkey -notcontains $Referenz) { throw "Referenz $Referenz fehlt im Ergebnis, kein Bericht" }

    $bericht = foreach ($z in @($liste)) {
        $s = Get-ZertifikatsStufe -NotAfter $z.clientcertnotafter -Jetzt $lauf
        [pscustomobject]@{ Zertifikat = $z.certkey; Stufe = $s.Stufe; Ablauf = $s.Ablauf.ToString('yyyy-MM-dd HH:mm')
                           Tage = $s.Tage; NITRO = "$($z.status), $($z.daystoexpiration)"; Lauf = $lauf.ToString('yyyy-MM-dd HH:mm') }
    }
    $bericht | Sort-Object Tage | Format-Table -AutoSize
}
finally {
    try { $null = Invoke-RestMethod -Method Post -Uri "$basis/logout" -Body '{"logout":{}}' `
                      -ContentType 'application/json' -WebSession $sitzung } catch { }
}

Auf meiner Testinstanz sieht das Ergebnis so aus (gekürzt):

Zertifikat             Stufe                        Ablauf             Tage NITRO         Lauf
----------             -----                        ------             ---- -----         ----
tz_abgel               abgelaufen                   2026-09-05 12:00    -27 Expired, 0    2026-10-02 13:38
tz_heute               kritisch                     2026-10-02 22:00      0 Valid, 0      2026-10-02 13:38
tz_bald                kritisch                     2026-10-09 12:00      6 Valid, 6      2026-10-02 13:38
ns-sftrust-certificate ohne praktisches Ablaufdatum 4764-01-17 20:33 999775 Valid, 999775 2026-10-02 13:38

Die Spalte NITRO steht nur zum Vergleich da: Zweimal derselbe Rohwert 0, zwei verschiedene Stufen. Die Schwellen von 14 und 60 Tagen sind ein Vorschlag und lassen sich an einer Stelle ändern.

Serverseitig filtern lässt sich sslcertkey übrigens nicht: Ein filter= auf status oder daystoexpiration beantwortet die Appliance mit Invalid filter in query parameters. Die ganze Liste abzuholen und lokal zu bewerten, ist deshalb ohnehin der Weg.

Wer die Abfrage über die NetScaler Console als Proxy an die Appliance weiterreicht, bekommt die Antwort der Appliance zurück. Was auf dem Weg dorthin schiefgehen kann, steht im Beitrag Instanz nicht verfügbar beim ADM-Proxy.

Wenn der Bericht trotzdem nicht stimmt

BildUrsache und Lösung
Ein bekannt abgelaufenes Zertifikat fehltFilter auf negative Resttage. Über das Ablaufdatum gehen
Ein gültiges Zertifikat steht als abgelaufen im BerichtFilter auf daystoexpiration -eq 0. Über das Ablaufdatum oder status gehen
Ein Eintrag läuft in über 2700 Jahren abInternes Zertifikat. Über eine Schwelle in eine eigene Stufe legen
Das Datum lässt sich an manchen Tagen nicht parsenDoppeltes Leerzeichen vor einstelligem Tag. Vor dem Parsen ersetzen
Der Bericht ist leer oder auffällig kurzAbfrage unvollständig. Referenzobjekt prüfen und den Lauf abbrechen lassen

Was du dir merkst

Bei einem abgelaufenen Zertifikat steht daystoexpiration auf 0, nicht auf einem negativen Wert, und ein gültiges Zertifikat mit weniger als einem Tag Restlaufzeit ebenso. Ein Filter auf negative Werte findet nie etwas. Grundlage eines Zertifikatsberichts ist das Ablaufdatum, die Restlaufzeit wird daraus berechnet.

Quellen

  • NITRO API: sslcertkey, NetScaler-Dokumentation: Felder clientcertnotafter, daystoexpiration, status

Gemessen an meiner Testinstanz mit NetScaler 14.1. Das Verhalten der Felder kann sich mit künftigen Builds ändern. Deshalb das Ablaufdatum als Grundlage nehmen und nicht den Zähler.

Eintrag teilen
  • Teilen auf Facebook
  • Teilen auf X
  • Teilen auf LinkedIn
  • Per E-Mail teilen
https://www.vguru.de/wp-content/uploads/2014/08/vguru03.png 0 0 Lars https://www.vguru.de/wp-content/uploads/2014/08/vguru03.png Lars2026-10-21 07:30:002026-10-20 20:23:48Zertifikatsbericht per NITRO: warum abgelaufene Zertifikate fehlen
Das könnte Dich auch interessieren
NetScaler CVE-2026-107406: SAML-IdP erneut aktualisieren
NetScaler CVE-2026-88779: SAML-Konfiguration prüfen
Citrix Shadowing Funktion geht nicht mehr und das Microsoft September Update ist unschuldig
NetScaler VPX Express unter VMWare Workstation 11
Importieren einer Citrix Netscaler VPX unter Hyper-V 2012 R2
SSL-Optimierung auf dem Citrix XenMobile Device Manager
0 Kommentare

Hinterlasse einen Kommentar

An der Diskussion beteiligen?
Hinterlasse uns deinen Kommentar!

Schreibe einen Kommentar Antwort abbrechen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Search Search

Neueste Beiträge

  • Zertifikatsbericht per NITRO: warum abgelaufene Zertifikate fehlen
  • Cross-Zertifikate in der Zertifikatskette: Ersetzen sie ein Intermediate?
  • RDP-Fehler 0xC000000D unter Windows 11: Administrator protection prüfen und gezielt abschalten
  • CVE, CVSS, KEV und EPSS: was die Begriffe im Sicherheitshinweis bedeuten
  • NetScaler CVE-2026-107406: SAML-IdP erneut aktualisieren

NetScaler-Sicherheitsstand

Aktuelle Citrix-Sicherheitsbulletins für NetScaler mit betroffenen Versionen und Zielbuilds: zur Übersicht

Copyright - www.vguru.de
  • Link zu Youtube
  • Link zu Mail
  • Impressum
  • Datenschutzerklärung
  • Kontakt
  • Cookie-Richtlinie (EU)
Link to: Cross-Zertifikate in der Zertifikatskette: Ersetzen sie ein Intermediate? Link to: Cross-Zertifikate in der Zertifikatskette: Ersetzen sie ein Intermediate? Cross-Zertifikate in der Zertifikatskette: Ersetzen sie ein Intermediate?
Nach oben scrollen Nach oben scrollen Nach oben scrollen
Mitgliederbereich mit DigiMember
Einwilligung verwalten
Um dir ein optimales Erlebnis zu bieten, verwenden wir Technologien wie Cookies, um Geräteinformationen zu speichern und/oder darauf zuzugreifen. Wenn du diesen Technologien zustimmst, können wir Daten wie das Surfverhalten oder eindeutige IDs auf dieser Website verarbeiten. Wenn du deine Einwilligung nicht erteilst oder zurückziehst, können bestimmte Merkmale und Funktionen beeinträchtigt werden.
Funktional Immer aktiv
Die technische Speicherung oder der Zugang ist unbedingt erforderlich für den rechtmäßigen Zweck, die Nutzung eines bestimmten Dienstes zu ermöglichen, der vom Teilnehmer oder Nutzer ausdrücklich gewünscht wird, oder für den alleinigen Zweck, die Übertragung einer Nachricht über ein elektronisches Kommunikationsnetz durchzuführen.
Präferenzen
Die technische Speicherung oder der Zugriff ist für den rechtmäßigen Zweck der Speicherung von Präferenzen erforderlich, die nicht vom Abonnenten oder Benutzer angefordert wurden.
Statistiken
Die technische Speicherung oder der Zugriff, der ausschließlich zu statistischen Zwecken erfolgt. Die technische Speicherung oder der Zugriff, der ausschließlich zu anonymen statistischen Zwecken verwendet wird. Ohne eine Vorladung, die freiwillige Zustimmung deines Internetdienstanbieters oder zusätzliche Aufzeichnungen von Dritten können die zu diesem Zweck gespeicherten oder abgerufenen Informationen allein in der Regel nicht dazu verwendet werden, dich zu identifizieren.
Marketing
Die technische Speicherung oder der Zugriff ist erforderlich, um Nutzerprofile zu erstellen, um Werbung zu versenden oder um den Nutzer auf einer Website oder über mehrere Websites hinweg zu ähnlichen Marketingzwecken zu verfolgen.
  • Optionen verwalten
  • Dienste verwalten
  • Verwalten von {vendor_count}-Lieferanten
  • Lese mehr über diese Zwecke
Einstellungen ansehen
  • {title}
  • {title}
  • {title}