MIKE Status & ServiceANBINDUNG← Zur Statusseite

Worum es geht

Ein System wird überwacht, indem es einen kleinen Endpunkt bereitstellt, den der Statusdienst regelmäßig abfragt. Der Endpunkt läuft auf einem eigenen Port und ist per Firewall ausschließlich für die IP des Statusservers erreichbar.

Eine einzige Abfrage kann mehrere Komponenten speisen: Der Endpunkt meldet beliebig viele Einzelprüfungen — Datenbank, Mailversand, Speicherplatz — und jede davon kann im Statusdienst zu einer eigenen Zeile werden.

1. Endpunkt bereitstellen

Pfad und Fassung sind festgelegt:

GET https://<host>:9443/mike-status/v1/health
Authorization: Bearer <projektspezifisches Token>

Die Antwort ist JSON und sieht so aus:

{
  "schema": 1,
  "dienst": "technikerportal",
  "version": "1.4.2",
  "gestartet": "2026-08-20T04:12:00Z",
  "geprueft": "2026-08-22T10:00:03Z",
  "status": "ok",
  "pruefungen": [
    { "schluessel": "db",   "name": "Datenbank",  "status": "ok",       "dauerMs": 3 },
    { "schluessel": "mail", "name": "Mail-Relay", "status": "degraded", "dauerMs": 1240,
      "hinweis": "Warteschlange bei 412 Nachrichten" },
    { "schluessel": "disk", "name": "Speicher",   "status": "ok",       "dauerMs": 1, "wert": "38%" }
  ]
}
Immer HTTP 200 antworten — auch dann, wenn der Dienst selbst eine Störung meldet. Nur so kann der Statusdienst zwei grundverschiedene Fälle unterscheiden: „die Anwendung meldet einen Defekt" und „die Anwendung antwortet gar nicht". Ein 503 vermischt beides. Nicht erreichbar ist ohnehin dadurch definiert, dass keine gültige Antwort ankommt.

Felder

FeldPflichtBedeutung
schemajaFassung des Vertrags. Derzeit immer 1.
dienstjaKurzname des Systems, klein geschrieben, stabil.
versionneinAusgelieferte Version, rein informativ.
gestartetneinStartzeitpunkt des Prozesses, ISO-8601 in UTC.
geprueftneinZeitpunkt der Messung, ISO-8601 in UTC.
statusjaGesamtstatus: ok, degraded oder down.
pruefungenneinListe der Einzelprüfungen. Fehlt sie, zählt nur der Gesamtstatus.
pruefungen[].schluesseljaStabiler Schlüssel. Er verbindet die Prüfung mit einer Komponente und darf sich nie ändern.
pruefungen[].nameneinAnzeigetext für Mitarbeiter. Darf sich jederzeit ändern.
pruefungen[].statusjaok, degraded oder down.
pruefungen[].dauerMsneinLaufzeit dieser Einzelprüfung.
pruefungen[].hinweisneinKurzer Klartext für Mitarbeiter. Keine Fehlerausgabe.
pruefungen[].wertneinMesswert als Text, z. B. 38%.

2. Regeln für die Umsetzung

  1. Antwort in unter zwei Sekunden. Jede Einzelprüfung bekommt ein eigenes Timeout, Richtwert eine Sekunde, und darf niemals blockieren.
  2. Ergebnis 5–10 Sekunden zwischenspeichern. Ohne Cache ist der Endpunkt ein Hebel, um die Anwendung über ihre eigenen Prüfungen lahmzulegen.
  3. Keine internen Angaben ausgeben. Keine Verbindungszeichenfolgen, keine Stacktraces, keine internen Hostnamen, IPs oder Benutzerdaten.
  4. Nur lesen. Der Endpunkt schreibt nichts, legt nichts an und verändert keinen Zustand.
  5. Eigener Port, eigener Listener. Nicht unter der öffentlichen Domain und nicht hinter dem öffentlichen Reverse-Proxy.
  6. Rate-Limit auf dem Endpunkt. Unabhängig von der Firewall — zwei Schlösser, nicht eins.
  7. Schlüssel stabil halten. Ein umbenannter Schlüssel gilt als neue Prüfung; die alte Komponente verliert ihre Datenquelle.

3. Zugang absichern

Zwei unabhängige Sperren. Die Firewall ist die Hauptabsicherung, das Token die zweite Linie: IP-Adressen wechseln, und auf geteilter Infrastruktur ist „die IP" nicht dasselbe wie „dieser Dienst".

Firewall (nftables)

table inet filter {
  chain input {
    type filter hook input priority 0; policy drop;

    # Statusdienst darf den Health-Port abfragen - sonst niemand.
    ip saddr <IP-DES-STATUSSERVERS> tcp dport 9443 accept
  }
}

Token

32 Byte Zufall, in der .env des Projekts, Vergleich in konstanter Zeit:

openssl rand -base64 32

TLS

Auch intern verschlüsselt. Ein selbstsigniertes Zertifikat genügt: Im Statusdienst wird dessen SHA-256-Fingerabdruck hinterlegt, und nur genau dieses Zertifikat wird akzeptiert. Das spart einen weiteren Let's-Encrypt-Namen für einen Endpunkt, der ohnehin nur von einer IP erreichbar ist. Fingerabdruck ermitteln:

openssl x509 -in zertifikat.pem -noout -fingerprint -sha256

4. Anbindung in ASP.NET Core

Für MIKE-Projekte gibt es das Paket Mike.Status.HealthEndpoint. Damit ist der Anschluss drei Zeilen:

builder.Services.AddMikeStatus(o =>
{
    o.Dienst = "technikerportal";
    o.Port   = 9443;                       // eigener Listener
    o.Token  = builder.Configuration["STATUS_TOKEN"]!;
});

builder.Services.AddMikeCheck<DatenbankPruefung>("db",   "Datenbank");
builder.Services.AddMikeCheck<MailPruefung>     ("mail", "Mail-Relay");

app.MapMikeStatus();

Eine Einzelprüfung ist eine kleine Klasse:

public sealed class DatenbankPruefung(NpgsqlDataSource quelle) : IMikeCheck
{
    public async Task<MikeCheckErgebnis> PruefenAsync(CancellationToken ct)
    {
        await using var verbindung = await quelle.OpenConnectionAsync(ct);
        await using var befehl = verbindung.CreateCommand();
        befehl.CommandText = "select 1";
        await befehl.ExecuteScalarAsync(ct);

        return MikeCheckErgebnis.Ok();
    }
}

Für alles, was nicht .NET ist, gilt schlicht der JSON-Vertrag oben — die Umsetzung ist in jeder Sprache eine Handvoll Zeilen.

5. Jobs statt Dienste: Puls senden

Nächtliche Sicherungen, Abgleiche und Aufgaben hinter NAT lassen sich nicht sinnvoll anpingen. Sie melden sich stattdessen selbst. Der Statusdienst legt dafür einen Monitor an und gibt einen Puls-Schlüssel aus, der genau einmal angezeigt wird:

curl -fsS -X POST https:///beat/<schluessel>

Am Ende des Jobs aufrufen. Bleibt der Puls länger als das eingestellte Fenster aus, gilt die Komponente als gestört. In einer crontab steht das so:

30 3 * * *  /opt/backup/lauf.sh && curl -fsS -X POST https:///beat/<schluessel>
Das && ist die halbe Miete: Der Puls geht nur raus, wenn der Job auch erfolgreich war. Ein ; würde auch nach einem Fehlschlag melden, dass alles in Ordnung sei.

6. Freigabe im Backend

Nach dem Anlegen des Monitors zeigt ein Testlauf sofort die Rohantwort — Fehler bei Firewall, Token oder Zertifikat fallen dort auf und nicht erst im Betrieb. Anschließend wird je gefundenem Prüfschlüssel entschieden: verwerfen, verborgen mitlaufen lassen oder als Komponente veröffentlichen.

Nichts wird von selbst öffentlich. Taucht später ein neuer Prüfschlüssel in der Antwort auf, läuft er zunächst verborgen mit und wird im Backend gemeldet. Ein Update Ihres Projekts kann damit niemals ungewollt eine neue Zeile auf der Kundenseite erzeugen.

7. Maschinenlesbarer Status

Der aktuelle Gesamtzustand steht als JSON bereit und lässt sich von anderen Systemen auswerten:

curl -fsS https:///status.json