Ab Version 1.23 unterstützt Kubernetes nicht mehr die Validierung der Serveridentität mithilfe des X.509-CN-Felds (Common Name) in Zertifikaten. Stattdessen verwendet Kubernetes nur Informationen in den X.509-SAN-Feldern (Subject Alternative Name).
Um Auswirkungen auf Ihre Cluster zu vermeiden, müssen Sie inkompatible Zertifikate ohne SANs für Back-Ends von Webhooks und aggregierten API-Servern ersetzen, bevor Sie ein Upgrade Ihrer Cluster auf Kubernetes Version 1.23 durchführen.
Warum Kubernetes Backend-Zertifikate ohne SANs nicht mehr unterstützt
GKE basiert auf dem Open-Source-Kubernetes-System, das die kube-apiserver-Komponente verwendet, um Ihren Webhook und aggregierte API-Server-Back-Ends über Transport Layer Security (TLS) zu kontaktieren. Die kube-apiserver-Komponente ist in der Programmiersprache Go geschrieben.
In Versionen vor Go 1.15 validierten TLS-Clients die Identität der Server, zu denen sie eine Verbindung herstellten, in zwei Schritten:
- Prüfen, ob der DNS-Name (oder die IP-Adresse) des Servers als einer der SANs auf dem Serverzertifikat vorhanden ist.
- Alternativ prüfen, ob der DNS-Name (oder die IP-Adresse) des Servers mit dem CN im Serverzertifikat übereinstimmt.
RFC 6125 hat die Validierung der Serveridentität gemäß dem CN-Feld 2011 vollständig eingestellt. Browser und andere sicherheitsrelevante Anwendungen verwenden dieses Feld nicht mehr.
Zur Anpassung an die gesamte TLS-Umgebung hat Go 1.15 Schritt 2 aus seinem Validierungsprozess entfernt, jedoch einen Debug-Switch (x509ignoreCN=0
) übrig gelassen, um das alte Verhalten zu aktivieren und den Migrationsprozess zu vereinfachen. Kubernetes Version 1.19 war die erste Version, die mit Go 1.15 erstellt wurde. In GKE-Clustern für Versionen von 1.19 bis 1.22 wurde standardmäßig der Debug-Switch aktiviert, um Kunden mehr Zeit zum Ersetzen der Zertifikate für die betroffenen Webhooks und aggregierten API-Server-Back-Ends zu geben.
Die Kubernetes-Version 1.23 basiert auf Go 1.17, womit der Debugging-Switch entfernt wurde. Nachdem GKE Ihre Cluster auf Version 1.23 aktualisiert hat, können Aufrufe von der Steuerungsebene des Clusters nicht mit Webhooks oder aggregierten API-Diensten verbunden werden, die kein gültiges X.509-Zertifikat mit einem entsprechenden SAN bereitstellen.
Betroffene Cluster bestimmen
Für Cluster mit Patchversionen mindestens 1.21.9 oder 1.22.3
Für Cluster mit Patchversionen 1.21.9 und 1.22.3 oder höher mit Cloud LoggingAktiviert bietet GKE einen Log für Cloud-Audit-Logs, um Aufrufe von betroffenen Back-Ends aus Ihrem Cluster zu identifizieren. Mit dem folgenden Filter können Sie nach den Logs suchen:
logName =~ "projects/.*/logs/cloudaudit.googleapis.com%2Factivity"
resource.type = "k8s_cluster"
operation.producer = "k8s.io"
"invalid-cert.webhook.gke.io"
Wenn Ihre Cluster keine Back-Ends mit betroffenen Zertifikaten aufgerufen haben, werden keine Logs angezeigt. Wenn Sie ein solches Audit-Log sehen, enthält es den Hostnamen des betroffenen Back-Ends.
Das folgende Beispiel zeigt den Logeintrag für ein Webhook-Backend, das von einem Dienst namens example-webhook im Namespace example-webhook gehostet wird:
{
...
resource {
type: "k8s_cluster",
"labels": {
"location": "us-central1-c",
"cluster_name": "example-cluster",
"project_id": "example-project"
}
},
labels: {
invalid-cert.webhook.gke.io/example-webhook.default.svc: "No subjectAltNames returned from example-webhook.default.svc:8443",
...
},
logName: "projects/example-project/logs/cloudaudit.googleapis.com%2Factivity",
operation: {
...
producer: "k8s.io",
...
},
...
}
Die Hostnamen der betroffenen Dienste (z. B. example-webhook.default.svc
) sind als Suffixe in den Labelnamen enthalten, die mit invalid-cert.webhook.gke.io/
beginnen. Sie können auch den Namen des Clusters, der den Aufruf ausgeführt hat, über das Label resource.labels.cluster_name
abrufen, das in diesem Beispiel den Wert example-cluster
hat.
Informationen zur Einstellung
Informationen dazu, welche Cluster inkompatible Zertifikate verwenden, finden Sie in den Informationen zur Einstellung. Informationen sind für Cluster verfügbar, in denen Version 1.22.6-gke.1000 oder höher ausgeführt wird.
Weitere Clusterversionen
Wenn Ihr Cluster in einer Patchversion vor 1.22.3 in der Nebenversion 1.22 oder in einer beliebigen Patchversion vor 1.21.9 ausgeführt wird, haben Sie zwei Möglichkeiten, um festzustellen, ob Ihr Cluster von dieser Einstellung betroffen ist:
Option 1 (empfohlen): Aktualisieren Sie den Cluster auf eine Patchversion, mit der betroffene Zertifikate mit Logs identifiziert werden können. Achten Sie darauf, dass Cloud Logging für Ihren Cluster aktiviert ist. Nach dem Upgrade Ihres Clusters werden die identifizierenden Cloud-Audit-Logs jedes Mal erstellt, wenn der Cluster versucht, einen Dienst aufzurufen, der kein Zertifikat mit einem geeigneten SAN bereitstellt. Da die Logs nur bei einem Aufrufversuch erstellt werden, sollten Sie nach einem Upgrade 30 Tage warten, damit genügend Zeit vorhanden war, um alle Aufrufpfade aufzurufen.
Das Identifizieren von betroffenen Diensten mithilfe von Logs wird empfohlen, da automatisch Logs zu den betroffenen Diensten erstellt werden. Auf diese Weise wird der manuelle Aufwand reduziert.
Option 2: Prüfen Sie alle Zertifikate, die von Webhooks oder aggregierten API-Diensten in Ihren Clustern verwendet werden, um festzustellen, ob sie aufgrund von fehlenden SANs betroffen sind:
- Rufen Sie die Liste der Webhooks und aggregierten API-Server im Cluster ab und identifizieren Sie deren Back-Ends (Dienste oder URLs).
- Prüfen Sie die Zertifikate, die von den Backend-Diensten verwendet werden.
Angesichts des manuellen Aufwands, der mit der Prüfung aller Zertifikate auf diese Weise verbunden ist, sollte diese Methode nur verwendet werden, wenn Sie die Auswirkungen der verworfenen Funktionen in Kubernetes Version 1.23 vor dem Upgrade des Clusters auf Version 1.21 bewerten müssen. Wenn Sie Ihren Cluster auf Version 1.21 aktualisieren können, sollten Sie zuerst ein Upgrade ausführen. Folgen Sie dann der Anleitung in Option 1, um den manuellen Aufwand zu reduzieren.
Zu prüfende Backend-Dienste bestimmen
Um Back-Ends zu bestimmen, die von der Einstellung betroffen sein können, rufen Sie die Liste der Webhooks und aggregierten API-Dienste und ihre zugehörigen Back-Ends im Cluster ab.
Verwenden Sie die folgenden kubectl
-Befehle, um alle relevanten Webhooks im Cluster aufzulisten:
kubectl get mutatingwebhookconfigurations -A # mutating admission webhooks
kubectl get validatingwebhookconfigurations -A # validating admission webhooks
Sie können einen verknüpften Backend-Dienst oder eine zugehörige URL für einen bestimmten Webhook abrufen, indem Sie das Feld clientConfig.service
oder das Feld webhooks.clientConfig.url
in der Konfiguration des Webhooks untersuchen.
kubectl get mutatingwebhookconfigurations example-webhook -o yaml
Die Ausgabe dieses Befehls sieht so aus:
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
webhooks:
- admissionReviewVersions:
clientConfig:
service:
name: example-service
namespace: default
port: 443
Beachten Sie, dass clientConfig sein Backend als Kubernetes-Dienst (clientConfig.service
) oder als URL (clientConfig.url
) angeben kann.
Mit dem folgenden kubectl
-Befehl können Sie alle relevanten aggregierten API-Dienste im Cluster auflisten:
kubectl get apiservices -A |grep -v Local # aggregated API services
Die Ausgabe dieses Befehls sieht so aus:
NAME SERVICE AVAILABLE AGE
v1beta1.metrics.k8s.io kube-system/metrics-server True 237d
In diesem Beispiel wird der metric-server
-Dienst aus dem Namespace kube-system
zurückgegeben.
Anhand des Felds spec.service
können Sie einen verknüpften Dienst für eine bestimmte aggregierte API abrufen:
kubectl get apiservices v1beta1.metrics.k8s.io -o yaml
Die Ausgabe dieses Befehls sieht so aus:
...
apiVersion: apiregistration.k8s.io/v1
kind: APIService
spec:
service:
name: metrics-server
namespace: kube-system
port: 443
Zertifikat eines Dienstes prüfen
Nachdem Sie die entsprechenden Backend-Dienste bestimmt haben, können Sie das Zertifikat jedes einzelnen Dienstes prüfen, z. B. example-service
:
Suchen Sie den Selektor und den Zielport des Dienstes:
kubectl describe service example-service
Die Ausgabe dieses Befehls sieht so aus:
Name: example-service Namespace: default Labels: run=nginx Selector: run=nginx Type: ClusterIP IP: 172.21.xxx.xxx Port: 443 TargetPort: 444
In diesem Beispiel hat
example-service
den Selektorrun=nginx
und den Zielport444
.Suchen Sie einen Pod, der dem Selektor entspricht:
kubectl get pods --selector=run=nginx
Die Ausgabe dieses Befehls sieht in etwa so aus:
NAME READY STATUS RESTARTS AGE example-pod 1/1 Running 0 21m
Richten Sie eine Portweiterleitung ein.
vom
kubectl
-localhost zum Pod.kubectl port-forward pods/example-pod LOCALHOST_PORT:TARGET_PORT # port forwarding in background
Ersetzen Sie im Befehl Folgendes:
LOCALHOST_PORT
: die zu überwachende Adresse.TARGET_PORT
:TargetPort
aus Schritt 1.
Verwenden Sie
openssl
, um das vom Dienst verwendete Zertifikat auszugeben:openssl s_client -connect localhost:LOCALHOST_PORT </dev/null | openssl x509 -noout -text
Diese Beispielausgabe zeigt ein gültiges Zertifikat (mit SAN-Einträgen):
Subject: CN = example-service.default.svc X509v3 extensions: X509v3 Subject Alternative Name: DNS:example-service.default.svc
Diese Beispielausgabe zeigt ein Zertifikat mit einem fehlenden SAN:
Subject: CN = example-service.default.svc X509v3 extensions: X509v3 Key Usage: critical Digital Signature, Key Encipherment X509v3 Extended Key Usage: TLS Web Server Authentication X509v3 Authority Key Identifier: keyid:1A:5F:29:D8:E9:3C:54:3C:35:CC:D8:AB:D1:21:FD:C3:56:25:C0:74
Entfernen Sie die Portweiterleitung mit den folgenden Befehlen, damit sie nicht im Hintergrund ausgeführt wird:
$ jobs [1]+ Running kubectl port-forward pods/example-pod 8888:444 & $ kill %1 [1]+ Terminated kubectl port-forward pods/example 8888:444
Zertifikat eines URL-Back-Ends prüfen
Wenn der Webhook ein url
-Backend verwendet, stellen Sie eine direkte Verbindung zum in der URL angegebenen Hostnamen her. Wenn die URL beispielsweise https://example.com:123/foo/bar
lautet, geben Sie den folgenden openssl
-Befehl aus, um das vom Backend verwendete Zertifikat auszugeben:
openssl s_client -connect example.com:123 </dev/null | openssl x509 -noout -text
Risiko eines 1.23-Upgrades verringern
Wenn Sie die betroffenen Cluster und deren Backend-Dienste mithilfe von Zertifikaten ohne SANs bestimmt haben, müssen Sie die Webhooks und aggregierten API-Server-Backends aktualisieren, um Zertifikate mit entsprechenden SANs vor dem Upgrade der Cluster auf Version 1.23 zu verwenden.
GKE aktualisiert Cluster auf die Version 1.22.6-gke.1000 oder höher nicht automatisch mit Back-Ends, die inkompatible Zertifikate verwenden, bis Sie die Zertifikate ersetzen oder bisVersion 1.22 das Standardsupport-Ende erreicht hat.
Wenn Ihr Cluster eine GKE-Version vor 1.22.6-gke.1000 verwendet, können Sie automatische Upgrades vorübergehend verhindern, indem Sie einen Wartungsausschluss konfigurieren, um geringfügige Upgrades zu verhindern.
Ressourcen
Weitere Informationen zu dieser Änderung finden Sie in den folgenden Ressourcen:
- Versionshinweise zu Kubernetes 1.23
- Kubernetes basiert auf Go 1.17. Mit dieser Version von Go ist es nicht mehr möglich, eine
GODEBUG=x509ignoreCN=0
-Umgebungseinstellung zu verwenden, um das verworfene Legacy-Verhalten für den Umgang mit dem CN-Feld für X.509-Bereitstellungszertifikate als Hostnamen wieder zu aktivieren.
- Kubernetes basiert auf Go 1.17. Mit dieser Version von Go ist es nicht mehr möglich, eine
- Versionshinweise zu Kubernetes 1.19 und Kubernetes 1.20
- Das verworfene Legacy-Verhalten für den Umgang mit dem CN-Feld in X.509-Zertifikaten als Host, wenn keine SANs vorhanden sind, ist jetzt standardmäßig deaktiviert.
- Go 1.17-Versionshinweise
- Das temporäre Flag
GODEBUG=x509ignoreCN=0
wurde entfernt.
- Das temporäre Flag
- Go 1.15-Versionshinweise
- Das verworfene Legacy-Verhalten für den Umgang mit dem CN-Feld in X.509-Zertifikaten als Host, wenn keine SANs vorhanden sind, ist jetzt standardmäßig deaktiviert.
- RFC 6125 (Seite 46)
- Die Verwendung des CN-Werts ist zwar üblich, wurde aber verworfen. Zertifizierungsstellen sollten stattdessen
subjectAltName
-Werte angeben.
- Die Verwendung des CN-Werts ist zwar üblich, wurde aber verworfen. Zertifizierungsstellen sollten stattdessen
- Zulassungs-Webhooks