TYPO3 auf Kubernetes unter IT-Grundschutz, Teil 5: mTLS auf jeder Strecke
Nach außen ist TLS selbstverständlich. Im Cluster läuft der Verkehr dagegen oft im Klartext, weil „das interne Netz“ als vertrauenswürdig gilt. Bei hohem Schutzbedarf reicht das nicht. Jede Verbindung soll verschlüsselt sein, und beide Seiten sollen sich ausweisen.
Dieser Teil zeigt, wie mTLS auf jeder Strecke funktioniert: mit einer eigenen CA pro Mandant, kurzlebigen Zertifikaten und einem Neuladen, das ohne Neustart auskommt.
Teil 5 von 14 der Serie „TYPO3 auf Kubernetes unter IT-Grundschutz“. Die Übersicht aller Teile steht in Teil 1.
01 — Welche Strecken verschlüsselt werden
Bei einer typischen TYPO3-Installation im Cluster gibt es vier interne Strecken:
- vom Ingress zum Reverse Proxy des Mandanten,
- vom Reverse Proxy zur PHP-Laufzeit, etwa FrankenPHP,
- von der Anwendung zur Datenbank,
- von der Anwendung zum Cache, etwa Valkey.
Das öffentliche Zertifikat endet am Ingress. Ab dort übernimmt ein internes. Bei mTLS weist sich auch der Client mit einem Zertifikat aus. Ein Pod ohne passendes Zertifikat kann eine Verbindung dann nicht aufbauen, selbst wenn das Netz sie erlauben würde.
mTLS ersetzt die NetworkPolicies aus Teil 6 nicht, es ergänzt sie. Die Policy regelt, wer wen erreicht. Das Zertifikat beweist, wer spricht.
02 — Eine eigene CA pro Mandant
cert-manager stellt die Zertifikate aus. Für jeden Mandanten gibt es eine eigene CA, abgebildet als Issuer im Namespace des Mandanten. Ein Zertifikat von Mandant A wird von den Diensten des Mandanten B nicht akzeptiert. Die Trennung reicht damit bis in die Kryptografie.
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: app-mtls
namespace: tenant-a
spec:
secretName: app-mtls
duration: 24h
renewBefore: 8h
privateKey:
algorithm: ECDSA
size: 256
rotationPolicy: Always
usages: [server auth, client auth]
dnsNames:
- app.tenant-a.svc.cluster.local
issuerRef:
name: tenant-a-ca
kind: Issuer
Warum nur 24 Stunden
Ein kurzlebiges Zertifikat verliert seinen Wert schnell, wenn der Schlüssel abhandenkommt. Sperrlisten oder OCSP braucht es dafür nicht. Die Erneuerung nach 16 Stunden lässt acht Stunden Puffer. Und die kurze Laufzeit erzwingt eine funktionierende Automatik. Hängt die Erneuerung an einem manuellen Schritt, fällt das spätestens am nächsten Tag auf.
Mit rotationPolicy: Always entsteht bei jeder Erneuerung auch ein neuer Schlüssel. Mit cert-manager liegen private Schlüssel nur als Secret im Cluster und werden in den Pod eingebunden, nie ins Image gebaut.
Seit Kubernetes 1.37 auch ohne Secret
Kubernetes 1.37 bringt Pod-Zertifikate mit. Dabei erzeugt der kubelet den Schlüssel selbst, holt das Zertifikat bei einem Signer ab und schreibt beides in ein Volume, sodass der Schlüssel nie in einem Secret liegt. Den Signer musst du allerdings selbst stellen, denn cert-manager kann solche Zertifikate noch nicht ausstellen (cert-manager#8378). Ein eigener Signer je Mandant hält die Trennung genauso wie eine CA je Mandant. Wie ich das gebaut und das ganze Netz eines Clusters darauf umgestellt habe, steht in zwei Feldnotizen: Pod-Zertifikate statt geteilter Geheimnisse und Das ganze Netz auf Pod-Zertifikate. Für die meisten Installationen bleibt cert-manager der ausgereifte Standardweg.
03 — Neu laden ohne Neustart
cert-manager erneuert das Secret. Der Prozess, der das Zertifikat nutzt, muss es aber auch neu laden. Genau hier liegt der typische Stolperstein. Die Erneuerung klappt, das Neuladen nicht, und nach 24 Stunden fällt die Verbindung aus.
Jede Komponente hat ihren eigenen Weg:
- Caddy und FrankenPHP laden die Konfiguration über die Admin-API neu. Ein kleiner Sidecar erkennt das neue Zertifikat und stößt das an.
- MariaDB liest die Zertifikate mit
FLUSH SSLneu ein, ohne Verbindungen zu trennen. - Valkey übernimmt neue Zertifikatsdateien, wenn die TLS-Einstellungen per
CONFIG SETneu gesetzt werden. - Wo es keinen solchen Weg gibt, startet ein Werkzeug wie Stakater Reloader die Pods bei geändertem Secret neu, rollierend.
Die Gegenseite prüft das Client-Zertifikat. In Caddy sieht das so aus:
tls /tls/tls.crt /tls/tls.key {
client_auth {
mode require_and_verify
trust_pool file /tls/ca.crt
}
}
Die Datenbank verlangt verschlüsselte Verbindungen mit require_secure_transport=ON, der Anwendungsbenutzer zusätzlich ein Zertifikat mit REQUIRE X509. Valkey lauscht nur auf dem TLS-Port und verlangt mit tls-auth-clients yes ein Client-Zertifikat.
Ablaufzeit überwachen
Das Secret zu überwachen reicht nicht. Entscheidend ist das Zertifikat, das der Dienst tatsächlich ausliefert. Eine Probe, die sich verbindet und die Restlaufzeit misst, schlägt Alarm, bevor der Puffer aufgebraucht ist.
04 — Service Mesh oder explizites mTLS
Ein Service Mesh wie Istio oder Linkerd erledigt mTLS automatisch, über Sidecars oder einen Ambient-Modus. Dazu kommen Richtlinien und Telemetrie. Der Preis ist eine zusätzliche Control Plane, mehr bewegliche Teile und eine schwierigere Fehlersuche.
Explizites mTLS ist die schlankere Variante. Jede Strecke ist sichtbar konfiguriert, und es gibt keine Schicht dazwischen. Dafür braucht jede Komponente ihre eigene Einrichtung. Bei wenigen Diensten pro Mandant, wie bei einer TYPO3-Installation, reicht das explizite Modell in der Regel aus. Ab vielen Diensten mit wechselnden Verbindungen lohnt sich ein Mesh eher.
Bezug zum IT-Grundschutz
Algorithmen, Schlüssellängen und Laufzeiten gehören ins Kryptokonzept nach CON.1. Die Verschlüsselung zwischen den Pods unterstützt die Separierung der Netze (APP.4.4.A7) und die Mikro-Segmentierung für erhöhten Schutzbedarf (APP.4.4.A18). Dass Schlüssel nur als eingebundene Secrets vorliegen und nie im Image, zahlt auf die sichere Speicherung von Zugangsdaten (SYS.1.6.A8) und die Absicherung von Konfigurationsdaten ein (SYS.1.6.A20).
Häufige Fragen
cert-manager oder Pod-Zertifikate?+
cert-manager ist der ausgereifte Standard: Zertifikate liegen als Secret, und ein Reloader startet Pods neu, wenn ein Dienst das erneuerte Zertifikat nicht selbst liest. Pod-Zertifikate kommen ohne Secret aus, und Software, die ihre Dateien neu einliest, braucht keinen Reloader mehr. Dafür brauchst du einen eigenen Signer und etwas Sorgfalt. Eine abgelehnte Anfrage bleibt abgelehnt, deshalb muss die Freigabe beim Signer vor der Umstellung live sein. Und der kubelet schreibt die Dateien mit 0640 für den runAsUser, was PostgreSQL bei einem eigenen Schlüssel ablehnt. Miss also für jede Komponente, was sie mit dem Zertifikat tatsächlich macht.
Warum mTLS, wenn es schon NetworkPolicies gibt?+
NetworkPolicies regeln, welcher Pod welchen erreicht. mTLS prüft die Identität kryptografisch und schützt den Inhalt vor dem Mitlesen. Das sind zwei unabhängige Schichten. Fällt eine aus, hält die andere.
Warum Zertifikate mit nur 24 Stunden Laufzeit?+
Ein gestohlener Schlüssel ist nach spätestens einem Tag wertlos, ganz ohne Sperrlisten. Außerdem erzwingt die kurze Laufzeit eine Automatik, die wirklich funktioniert. Ein Fehler in der Erneuerung fällt am nächsten Tag auf und nicht erst nach einem Jahr.
Brauche ich für mTLS ein Service Mesh?+
Nicht zwingend. Bei wenigen Diensten pro Mandant ist explizites mTLS mit cert-manager überschaubar und gut nachvollziehbar. Ein Mesh lohnt sich eher bei vielen Diensten mit wechselnden Verbindungen, bringt aber eine eigene Control Plane mit.
Was passiert, wenn die Erneuerung ausfällt?+
Die Erneuerung nach 16 Stunden lässt acht Stunden Puffer. Ein Alarm auf die Restlaufzeit des tatsächlich ausgelieferten Zertifikats meldet sich in dieser Zeit. Wer nur das Secret überwacht, sieht ein fehlgeschlagenes Neuladen nicht.
Fazit
mTLS im Cluster ist kein Projekt für ein Service Mesh, sondern für eine saubere Kette: eine CA pro Mandant, kurzlebige Zertifikate, ein zuverlässiges Neuladen in jeder Komponente und eine Überwachung des tatsächlich ausgelieferten Zertifikats. Die kurze Laufzeit ist dabei kein Risiko, sondern ein Prüfstein. Sie zeigt jeden Tag, ob die Automatik funktioniert.
Weiter geht es mit Teil 6: Netz und Mandantentrennung. Zurück zu Teil 4: Keine CVEs über 7.
Ich richte mTLS auf allen Strecken deines Clusters ein. Mit Zertifikaten, die sich selbst erneuern.
Eine CA pro Mandant mit cert-manager, kurzlebige Zertifikate, Neuladen ohne Neustart für Proxy, PHP, Datenbank und Cache sowie eine Überwachung, die vor dem Ablauf warnt.
Plattform-Betrieb statt Beratung auf Papier: Auf Wunsch betreibe ich die Zertifikatskette dauerhaft mit.
Über den Autor

Kai Ole Hartwig
Programmiert seit 2002 – autodidaktisch gelernt, 2012 mit KO-Web selbständig gemacht. Über 100 Projekte, Fokus auf Security, Performance, Automatisierung und Qualität. Heute freiberuflich: DevSecOps-Beratung, Schulungen und Softwareentwicklung.
