A partire dalla versione 1.23, Kubernetes non supporta più la convalida dell'identità del server utilizzando il campo Common Name (CN) X.509 nei certificati. Al contrario, Kubernetes si baserà solo sulle informazioni nei campi Subject Alternative Name (SAN) X.509.
Per evitare ripercussioni sui tuoi cluster, devi sostituire i certificati incompatibili senza SAN per i backend di webhook e server API aggregati prima di eseguire l'upgrade dei cluster alla versione 1.23 di Kubernetes.
Perché Kubernetes non supporta più i certificati di backend senza SAN
GKE gestisce Kubernetes open source, che utilizza il componente kube-apiserver per contattare il tuo webhook e i backend del server API aggregati utilizzando Transport Layer Security (TLS). Il componente kube-apiserver è scritto nel linguaggio di programmazione Go.
Prima di Go 1.15, i client TLS convalidavano l'identità dei server a cui si connettevano utilizzando una procedura in due passaggi:
- Controlla se il nome DNS (o l'indirizzo IP) del server è presente come uno dei valori SAN nel certificato del server.
- Come soluzione alternativa, controlla se il nome DNS (o l'indirizzo IP) del server è uguale al CN sul certificato del server.
Nel 2011, lo standard RFC 6125 ha ritirato completamente la convalida dell'identità del server in base al campo CN. I browser e altre applicazioni di importanza critica per la sicurezza non utilizzano più il campo.
Per allinearsi all'ecosistema TLS più ampio,
Go 1.15 ha rimosso il passaggio 2
dalla procedura di convalida, ma ha lasciato un'opzione di debug (x509ignoreCN=0
) per attivare il vecchio comportamento e semplificare la procedura di migrazione. La versione 1.19 di Kubernetes è stata la prima versione creata utilizzando Go 1.15. Per impostazione predefinita, i cluster GKE nelle versioni da 1.19 a 1.22 hanno attivato l'opzione di debug per offrire ai clienti più tempo per sostituire i certificati per il webhook interessato e i backend del server API aggregati.
Kubernetes versione 1.23 è creato con Go 1.17, che rimuove l'opzione di debug. Una volta che GKE esegue l'upgrade dei tuoi cluster alla versione 1.23, le chiamate non riusciranno a connettersi dal piano di controllo del cluster a webhook o servizi API aggregati che non forniscono un certificato X.509 valido con SAN appropriati.
Identificazione dei cluster interessati
Per i cluster con versioni patch almeno 1.21.9 o 1.22.3
Per i cluster con versioni patch 1.21.9 e 1.22.3 o successive con logging Cloud abilitato, GKE fornisce un log degli audit log di Cloud per identificare le chiamate ai backend interessati dal tuo cluster. Puoi utilizzare il seguente filtro per cercare i log:
logName =~ "projects/.*/logs/cloudaudit.googleapis.com%2Factivity"
resource.type = "k8s_cluster"
operation.producer = "k8s.io"
"invalid-cert.webhook.gke.io"
Se i tuoi cluster non hanno chiamato i backend con i certificati interessati, non vedrai alcun log. Se vedi un log di controllo di questo tipo, includerà il nome host del backend interessato.
Di seguito è riportato un esempio di voce di log per un backend webhook ospitato da un servizio denominato example-webhook nello spazio dei nomi default:
{
...
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",
...
},
...
}
I nomi host dei servizi interessati (ad es. example-webhook.default.svc
) sono inclusi come suffissi nei nomi delle etichette che iniziano con invalid-cert.webhook.gke.io/
. Puoi anche ottenere il nome del cluster che ha effettuato la chiamata dall'etichetta resource.labels.cluster_name
, che in questo esempio ha il valore example-cluster
.
Approfondimenti sul ritiro
Puoi scoprire quali cluster utilizzano certificati incompatibili dagli approfondimenti sul ritiro. Gli approfondimenti sono disponibili per i cluster che eseguono la versione 1.22.6-gke.1000 o successive.
Altre versioni del cluster
Se hai un cluster su una versione con patch precedente alla 1.22.3 nella versione minore 1.22 o su una versione con patch precedente alla 1.21.9, hai due opzioni per determinare se il tuo cluster è interessato da questa ritiro:
Opzione 1 (consigliata): esegui l'upgrade del cluster a una versione con patch che supporta l'identificazione dei certificati interessati con i log. Assicurati che Cloud Logging sia abilitato per il cluster. Dopo l'upgrade del cluster, gli audit log di Cloud Audit Logs che lo identificano verranno generati ogni volta che il cluster tenta di chiamare un servizio che non fornisce un certificato con un SAN appropriato. Poiché i log verranno prodotti solo al tentativo di chiamata, ti consigliamo di attendere 30 giorni dopo un upgrade per lasciare tempo sufficiente per l'attivazione di tutti i percorsi di chiamata.
Ti consigliamo di utilizzare i log per identificare i servizi interessati perché questo approccio minimizza l'intervento manuale producendo automaticamente i log per mostrare i servizi interessati.
Opzione 2: controlla i certificati utilizzati dai webhook o dai server API aggregati nei tuoi cluster per determinare se sono interessati dalla mancata presenza di SAN:
- Ottieni l'elenco di webhook e server API aggregati nel tuo cluster e identifica i relativi backend (servizi o URL).
- Esamina i certificati utilizzati dai servizi di backend.
Dato l'impegno manuale richiesto per ispezionare tutti i certificati in questo modo, questo metodo deve essere seguito solo se devi valutare l'impatto del ritiro nella versione 1.23 di Kubernetes prima di eseguire l'upgrade del cluster alla versione 1.21. Se puoi eseguire l'upgrade del cluster alla versione 1.21, devi prima eseguire l'upgrade e poi seguire le istruzioni dell'opzione 1 per evitare l'intervento manuale.
Identificazione dei servizi di backend da ispezionare
Per identificare i backend che potrebbero essere interessati dal ritiro, ottieni l'elenco di webhook e servizi API aggregati e dei relativi backend associati nel cluster.
Per elencare tutti gli webhook pertinenti nel cluster, utilizza i seguenti comandi kubectl
:
kubectl get mutatingwebhookconfigurations -A # mutating admission webhooks
kubectl get validatingwebhookconfigurations -A # validating admission webhooks
Puoi ottenere un servizio o un URL di backend associato per un determinato webhook esaminando il clientConfig.service
campo
o il webhooks.clientConfig.url
campo
nella configurazione dell'webhook:
kubectl get mutatingwebhookconfigurations example-webhook -o yaml
L'output di questo comando è simile al seguente:
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
webhooks:
- admissionReviewVersions:
clientConfig:
service:
name: example-service
namespace: default
port: 443
Tieni presente che clientConfig può specificare il proprio backend come servizio Kubernetes
(clientConfig.service
) o come URL (clientConfig.url
).
Per elencare tutti i servizi API aggregati pertinenti nel cluster, utilizza il seguente
kubectl
comando:
kubectl get apiservices -A |grep -v Local # aggregated API services
L'output di questo comando è simile al seguente:
NAME SERVICE AVAILABLE AGE
v1beta1.metrics.k8s.io kube-system/metrics-server True 237d
Questo esempio restituisce il servizio metric-server
dallo spazio dei nomi kube-system
.
Puoi ottenere un servizio associato per una determinata API aggregata esaminando il campo spec.service
:
kubectl get apiservices v1beta1.metrics.k8s.io -o yaml
L'output di questo comando è simile al seguente:
...
apiVersion: apiregistration.k8s.io/v1
kind: APIService
spec:
service:
name: metrics-server
namespace: kube-system
port: 443
Ispezione del certificato di un servizio
Dopo aver identificato i servizi di backend pertinenti da ispezionare, puoi controllare il certificato di ogni servizio specifico, ad esempio example-service
:
Individua il selettore e la porta di destinazione del servizio:
kubectl describe service example-service
L'output di questo comando è simile al seguente:
Name: example-service Namespace: default Labels: run=nginx Selector: run=nginx Type: ClusterIP IP: 172.21.xxx.xxx Port: 443 TargetPort: 444
In questo esempio,
example-service
ha il selettorerun=nginx
e la porta di destinazione444
.Trova un pod corrispondente al selettore:
kubectl get pods --selector=run=nginx
L'output del comando è simile al seguente:
NAME READY STATUS RESTARTS AGE example-pod 1/1 Running 0 21m
Configurare un port forwarding
dal tuo
kubectl
localhost al pod.kubectl port-forward pods/example-pod LOCALHOST_PORT:TARGET_PORT # port forwarding in background
Sostituisci quanto segue nel comando:
LOCALHOST_PORT
: l'indirizzo su cui ascoltare.TARGET_PORT
ilTargetPort
del passaggio 1.
Utilizza
openssl
per stampare il certificato utilizzato dal Servizio:openssl s_client -connect localhost:LOCALHOST_PORT </dev/null | openssl x509 -noout -text
Questo esempio di output mostra un certificato valido (con voci SAN):
Subject: CN = example-service.default.svc X509v3 extensions: X509v3 Subject Alternative Name: DNS:example-service.default.svc
Questo esempio di output mostra un certificato con un SAN mancante:
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
Rimuovi l'inoltro di porta dall'esecuzione in background con i seguenti comandi:
$ jobs [1]+ Running kubectl port-forward pods/example-pod 8888:444 & $ kill %1 [1]+ Terminated kubectl port-forward pods/example 8888:444
Controllo del certificato di un backend URL
Se il webhook utilizza un url
backend,
collega direttamente il nome host specificato nell'URL. Ad esempio, se l'URL è https://example.com:123/foo/bar
, utilizza il seguente comando openssl
per stampare il certificato utilizzato dal backend:
openssl s_client -connect example.com:123 </dev/null | openssl x509 -noout -text
Mitigazione del rischio dell'upgrade a 1.23
Dopo aver identificato i cluster interessati e i relativi servizi di backend che utilizzano certificati senza SAN, devi aggiornare i webhook e i backend del server API aggregati in modo che utilizzino certificati con SAN appropriate prima di eseguire l'upgrade dei cluster alla versione 1.23.
GKE non eseguirà automaticamente l'upgrade dei cluster sulle versioni 1.22.6-gke.1000 o successive con backend che utilizzano certificati incompatibili finché non sostituirai i certificati o fino a quando la versione 1.22 non raggiungerà la fine dell'assistenza standard.
Se il tuo cluster utilizza una versione GKE precedente alla versione 1.22.6-gke.1000, puoi impedire temporaneamente gli upgrade automatici configurando un'esclusione di manutenzione per impedire gli upgrade secondari.
Risorse
Per ulteriori informazioni su questa modifica, consulta le seguenti risorse:
- Note di rilascio di Kubernetes 1.23
- Kubernetes viene creato utilizzando Go 1.17. Questa versione di Go rimuove la possibilità di utilizzare un'impostazione di ambiente
GODEBUG=x509ignoreCN=0
per riattivare il comportamento precedente deprecato di trattare il CN dei certificati di servizio X.509 come nome host.
- Kubernetes viene creato utilizzando Go 1.17. Questa versione di Go rimuove la possibilità di utilizzare un'impostazione di ambiente
- Kubernetes 1.19
e
Kubernetes 1.20
note di rilascio
- Il comportamento precedente deprecato di trattare il campo CN sui certificati X.509 come nome host quando non sono presenti SAN è ora disattivato per impostazione predefinita.
- Note di rilascio di Go 1.17
- Il flag temporaneo
GODEBUG=x509ignoreCN=0
è stato rimosso.
- Il flag temporaneo
- Note di rilascio di Go 1.15
- Il comportamento precedente deprecato che tratta il campo CN dei certificati X.509 come un host quando non sono presenti SAN è ora disattivato per impostazione predefinita.
- RFC 6125
(pagina 46)
- Sebbene l'utilizzo del valore CN sia una prassi esistente, è deprecato
e le autorità di certificazione sono incoraggiate a fornire invece valori
subjectAltName
.
- Sebbene l'utilizzo del valore CN sia una prassi esistente, è deprecato
e le autorità di certificazione sono incoraggiate a fornire invece valori
- Webhook di ammissione