A partire dalla versione 1.23, Kubernetes non supporta più la convalida dell'identità del server mediante il campo Common Name (CN) X.509 nei certificati. Kubernetes si baserà solo sulle informazioni contenute nei campi SAN (Subject Alternative Name) X.509.
Per evitare l'impatto sui cluster, devi sostituire i certificati incompatibili senza SAN per i backend dei webhook e dei 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 webhook e i backend di server API aggregati mediante TLS (Transport Layer Security). 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 un processo in due passaggi:
- Verifica se il nome DNS (o l'indirizzo IP) del server è presente come uno dei SAN nel certificato del server.
- Come alternativa, verifica se il nome DNS (o l'indirizzo IP) del server corrisponde al CN nel certificato del server.
La convalida dell'identità del server RFC 6125 è stata completamente ritirata in base al campo CN nel 2011. I browser e altre applicazioni critiche per la sicurezza non utilizzano più questo campo.
Per allinearsi al più ampio ecosistema TLS, Go 1.15 ha rimosso il passaggio 2 dal processo di convalida, ma ha lasciato un'opzione di debug (x509ignoreCN=0
) per abilitare il comportamento precedente e semplificare il processo di migrazione. La versione 1.19 di Kubernetes è stata la prima versione creata utilizzando Go 1.15. I cluster GKE sulle versioni da 1.19 a 1.22 hanno abilitato l'opzione di debug per impostazione predefinita per fornire ai clienti più tempo per sostituire i certificati per i backend dei server API e webhook interessati.
La versione 1.23 di Kubernetes è integrata con Go 1.17, che rimuove l'opzione di debug. Dopo che GKE ha eseguito l'upgrade dei cluster alla versione 1.23, le chiamate non si connetteranno dal piano di controllo del cluster a webhook o servizi API aggregati che non forniscono un certificato X.509 valido con la SAN appropriata.
Identificazione dei cluster interessati
Per i cluster che eseguono versioni patch almeno 1.21.9 o 1.22.3
Per i cluster con patch 1.21.9 e 1.22.3 o versioni successive con Cloud Logging abilitato, GKE fornisce un log di audit log di Cloud per identificare le chiamate ai backend interessati dal 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 backend con certificati interessati, non vedrai alcun log. Se invece vedi un audit log di questo tipo, questo includerà il nome host del backend interessato.
Di seguito è riportato un esempio della 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 un valore example-cluster
.
Approfondimenti sul ritiro
Puoi scoprire quali cluster utilizzano certificati incompatibili dagli insight sul ritiro. Gli insight 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 patch precedente alla 1.22.3 nella versione secondaria 1.22 o una versione della patch precedente alla 1.21.9, hai due opzioni per determinare se il tuo cluster è interessato da questo ritiro:
Opzione 1 (consigliata): esegui l'upgrade del cluster a una versione patch che supporti l'identificazione dei certificati interessati con i log. Assicurati che Cloud Logging sia abilitato per il tuo cluster. Dopo l'upgrade del cluster, i log di Cloud Audit Logs di identificazione verranno prodotti ogni volta che il cluster tenta di chiamare un servizio che non fornisce un certificato con una SAN appropriata. Poiché i log vengono generati solo durante un tentativo di chiamata, ti consigliamo di attendere 30 giorni dopo l'upgrade per avere tempo sufficiente per richiamare tutti i percorsi di chiamata.
È consigliabile utilizzare i log per identificare i servizi interessati perché questo approccio riduce al minimo l'impegno manuale generando automaticamente 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 mancanza di SAN:
- Recupera l'elenco di webhook e server API aggregati nel cluster e identifica i rispettivi backend (servizi o URL).
- Ispeziona i certificati utilizzati dai servizi di backend.
Dato lo sforzo manuale necessario per esaminare tutti i certificati in questo modo, è necessario seguire questo metodo solo se è necessario valutare l'impatto dei ritiri 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 eseguirlo, quindi seguire le istruzioni dell'Opzione 1 per evitare lo sforzo manuale.
Identificazione dei servizi di backend da ispezionare
Per identificare i backend che potrebbero essere interessati dal ritiro, recupera l'elenco di webhook e servizi API aggregati e i backend associati nel cluster.
Per elencare tutti i 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 a un determinato webhook esaminando il campo clientConfig.service
o il campo webhooks.clientConfig.url
nella configurazione del 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 un servizio Kubernetes
(clientConfig.service
) o come un URL (clientConfig.url
).
Per elencare tutti i servizi API aggregati pertinenti nel cluster, utilizza il seguente comando kubectl
:
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 a 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 esaminare il certificato di ciascun servizio specifico, ad esempio example-service
:
Trova 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
Configura un port-forward
dal localhost
kubectl
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 rimanere in ascolto.TARGET_PORT
ilTargetPort
del Passaggio 1.
Usa
openssl
per stampare il certificato utilizzato dal Servizio:openssl s_client -connect localhost:LOCALHOST_PORT </dev/null | openssl x509 -noout -text
Questo output di esempio 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 output di esempio mostra un certificato con una 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 il port forwarding 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
Ispezione del certificato del backend di un URL
Se il webhook utilizza un backend url
, connettiti direttamente al nome host specificato nell'URL. Ad esempio, se l'URL è https://example.com:123/foo/bar
, usa il seguente comando openssl
per stampare il certificato utilizzato dal backend:
openssl s_client -connect example.com:123 </dev/null | openssl x509 -noout -text
Mitigare il rischio dell'upgrade a 1,23
Dopo aver identificato i cluster interessati e i relativi servizi di backend utilizzando certificati senza SAN, devi aggiornare i webhook e i backend dei server API aggregati in modo da utilizzare i certificati con le SAN appropriate prima di eseguire l'upgrade dei cluster alla versione 1.23.
GKE non esegue automaticamente l'upgrade dei cluster sulle versioni 1.22.6-gke.1000 o successive con backend che utilizzano certificati incompatibili finché non sostituisci i certificati o fino a quando la versione 1.22 non raggiunge la fine del ciclo di vita.
Se il cluster ha una versione di GKE precedente a 1.22.6-gke.1000, puoi impedire temporaneamente gli upgrade automatici configurando un'esclusione di manutenzione per evitare upgrade di minore entità.
Risorse
Consulta le seguenti risorse per ulteriori informazioni su questo cambiamento:
- Note di rilascio di Kubernetes 1.23
- Kubernetes è stato creato con Go 1.17. Questa versione di Go rimuove la possibilità di utilizzare un'impostazione dell'ambiente
GODEBUG=x509ignoreCN=0
per riattivare il comportamento legacy deprecato di trattare il CN dei certificati di pubblicazione X.509 come nome host.
- Kubernetes è stato creato con Go 1.17. Questa versione di Go rimuove la possibilità di utilizzare un'impostazione dell'ambiente
- Note di rilascio di Kubernetes 1.19
e
Kubernetes 1.20
- Il comportamento precedente deprecato di trattare il campo CN sui certificati di pubblicazione 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 legacy deprecato di trattare il campo CN sui certificati X.509 come host quando non sono presenti SAN è ora disattivato per impostazione predefinita.
- RFC 6125
(pagina 46)
- Sebbene l'uso del valore CN sia già una pratica, è deprecato e le autorità di certificazione sono invitate a fornire invece i valori
subjectAltName
.
- Sebbene l'uso del valore CN sia già una pratica, è deprecato e le autorità di certificazione sono invitate a fornire invece i valori
- Webhook di ammissione