A partir da versão 1.23, o Kubernetes já não suporta a validação da identidade do servidor através do campo Nome comum (CN) X.509 nos certificados. Em alternativa, o Kubernetes baseia-se apenas nas informações nos campos de nome alternativo do assunto (SAN) X.509.
Para evitar o impacto nos seus clusters, tem de substituir os certificados incompatíveis sem SANs para back-ends de webhooks e servidores de API agregados antes de atualizar os seus clusters para a versão 1.23 do Kubernetes.
Por que motivo o Kubernetes já não suporta certificados de back-end sem SANs
O GKE opera o Kubernetes de código aberto, que usa o componente kube-apiserver para contactar os back-ends do servidor de API agregado e webhook através do Transport Layer Security (TLS). O componente kube-apiserver é escrito na linguagem de programação Go.
Antes do Go 1.15, os clientes TLS validavam a identidade dos servidores aos quais se ligavam através de um processo de dois passos:
- Verifique se o nome DNS (ou o endereço IP) do servidor está presente como um dos SANs no certificado do servidor.
- Como alternativa, verifique se o nome DNS (ou o endereço IP) do servidor é igual ao CN no certificado do servidor.
A RFC 6125 descontinuou totalmente a validação da identidade do servidor com base no campo CN em 2011. Os navegadores e outras aplicações críticas para a segurança já não usam o campo.
Para se alinhar com o ecossistema TLS mais amplo,
o Go 1.15 removeu o passo 2
do respetivo processo de validação, mas deixou um comutador de depuração (x509ignoreCN=0
) para
ativar o comportamento antigo para facilitar o processo de migração. A versão
1.19 do Kubernetes foi a primeira versão criada com o Go 1.15. Os clusters do GKE nas versões 1.19 a 1.22 ativaram o interruptor de depuração por predefinição para dar aos clientes mais tempo para substituir os certificados do webhook afetado e dos back-ends do servidor da API agregada.
O Kubernetes versão 1.23 é criado com o Go 1.17, que remove o interruptor de depuração. Assim que o GKE atualizar os seus clusters para a versão 1.23, as chamadas não vão conseguir estabelecer ligação do plano de controlo do seu cluster a webhooks ou serviços de API agregados que não forneçam um certificado X.509 válido com SAN adequado.
Identificar clusters afetados
Para clusters que executam versões de patch, pelo menos, 1.21.9 ou 1.22.3
Para clusters nas versões de patch 1.21.9 e 1.22.3 ou posteriores com o Cloud Logging ativado, o GKE fornece um registo de registos de auditoria da nuvem para identificar chamadas para back-ends afetados a partir do seu cluster. Pode usar o seguinte filtro para pesquisar os registos:
logName =~ "projects/.*/logs/cloudaudit.googleapis.com%2Factivity"
resource.type = "k8s_cluster"
operation.producer = "k8s.io"
"invalid-cert.webhook.gke.io"
Se os seus clusters não tiverem chamado back-ends com certificados afetados, não vê registos. Se vir um registo de auditoria deste tipo, este vai incluir o nome do anfitrião do back-end afetado.
Segue-se um exemplo da entrada do registo para um back-end de webhook alojado por um serviço denominado example-webhook no espaço de nomes 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",
...
},
...
}
Os nomes de anfitrião dos serviços afetados (por exemplo, example-webhook.default.svc
) são incluídos como sufixos nos nomes das etiquetas que começam por invalid-cert.webhook.gke.io/
. Também pode obter o nome do cluster que fez a chamada a partir da etiqueta resource.labels.cluster_name
, que tem o valor example-cluster
neste exemplo.
Estatísticas de descontinuação
Pode saber que clusters usam certificados incompatíveis nas estatísticas de descontinuação. As estatísticas estão disponíveis para clusters com a versão 1.22.6-gke.1000 ou posterior.
Outras versões do cluster
Se tiver um cluster numa versão de patch anterior a 1.22.3 na versão secundária 1.22 ou numa versão de patch anterior a 1.21.9, tem duas opções para determinar se o seu cluster é afetado por esta descontinuação:
Opção 1 (recomendada): Atualize o seu cluster para uma versão de patch que suporte a identificação de certificados afetados com registos. Certifique-se de que o Cloud Logging está ativado para o seu cluster. Após a atualização do cluster, os registos de identificação do Cloud Audit Logs são produzidos sempre que o cluster tenta chamar um serviço que não faculta um certificado com um SAN adequado. Como os registos só são gerados numa tentativa de chamada, recomendamos que aguarde 30 dias após uma atualização para dar tempo suficiente para que todos os caminhos de chamadas sejam invocados.
Recomendamos a utilização de registos para identificar os serviços afetados, uma vez que esta abordagem minimiza o esforço manual através da produção automática de registos para mostrar os serviços afetados.
Opção 2: inspecione os certificados usados pelos webhooks ou pelos servidores da API agregada nos seus clusters para determinar se são afetados por não terem SANs:
- Obtenha a lista de webhooks e servidores de API agregados no seu cluster e identifique os respetivos backends (serviços ou URLs).
- Inspeção dos certificados usados pelos serviços de back-end.
Dado o esforço manual necessário para inspecionar todos os certificados desta forma, este método só deve ser seguido se precisar de avaliar o impacto das descontinuações na versão 1.23 do Kubernetes antes de atualizar o cluster para a versão 1.21. Se puder atualizar o cluster para a versão 1.21, deve atualizá-lo primeiro e, em seguida, seguir as instruções na Opção 1 para evitar o esforço manual.
Identificar serviços de back-end a inspecionar
Para identificar os back-ends que podem ser afetados pela descontinuação, obtenha a lista de Webhooks e serviços de API agregados, bem como os respetivos back-ends associados no cluster.
Para apresentar uma lista de todos os webhooks relevantes no cluster, use os seguintes kubectl
comandos:
kubectl get mutatingwebhookconfigurations -A # mutating admission webhooks
kubectl get validatingwebhookconfigurations -A # validating admission webhooks
Pode obter um serviço ou um URL de back-end associado para um determinado webhook examinando o campo clientConfig.service
ou o campo webhooks.clientConfig.url
na configuração do webhook:
kubectl get mutatingwebhookconfigurations example-webhook -o yaml
O resultado deste comando é semelhante ao seguinte:
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
webhooks:
- admissionReviewVersions:
clientConfig:
service:
name: example-service
namespace: default
port: 443
Tenha em atenção que clientConfig pode especificar o respetivo back-end como um serviço Kubernetes (clientConfig.service
) ou como um URL (clientConfig.url
).
Para apresentar uma lista de todos os serviços de API agregados relevantes no cluster, use o seguinte comando
kubectl
:
kubectl get apiservices -A |grep -v Local # aggregated API services
O resultado deste comando é semelhante ao seguinte:
NAME SERVICE AVAILABLE AGE
v1beta1.metrics.k8s.io kube-system/metrics-server True 237d
Este exemplo devolve metric-server
Service do espaço de nomes kube-system
.
Pode obter um serviço associado para uma determinada API agregada examinando o campo spec.service
:
kubectl get apiservices v1beta1.metrics.k8s.io -o yaml
O resultado deste comando é semelhante ao seguinte:
...
apiVersion: apiregistration.k8s.io/v1
kind: APIService
spec:
service:
name: metrics-server
namespace: kube-system
port: 443
Inspeção do certificado de um serviço
Depois de identificar os serviços de back-end relevantes para inspecionar, pode inspecionar o certificado de cada serviço específico, como example-service
:
Encontre o seletor e a porta de destino do serviço:
kubectl describe service example-service
O resultado deste comando é semelhante ao seguinte:
Name: example-service Namespace: default Labels: run=nginx Selector: run=nginx Type: ClusterIP IP: 172.21.xxx.xxx Port: 443 TargetPort: 444
Neste exemplo,
example-service
tem o seletorrun=nginx
e a porta de destino444
.Encontre um pod correspondente ao seletor:
kubectl get pods --selector=run=nginx
O resultado do comando é semelhante ao seguinte:
NAME READY STATUS RESTARTS AGE example-pod 1/1 Running 0 21m
Configure um encaminhamento de porta
do seu
kubectl
localhost para o pod.kubectl port-forward pods/example-pod LOCALHOST_PORT:TARGET_PORT # port forwarding in background
Substitua o seguinte no comando:
LOCALHOST_PORT
: o endereço a ouvir.TARGET_PORT
oTargetPort
do passo 1.
Use
openssl
para imprimir o certificado usado pelo Serviço:openssl s_client -connect localhost:LOCALHOST_PORT </dev/null | openssl x509 -noout -text
Este exemplo de saída mostra um certificado válido (com entradas SAN):
Subject: CN = example-service.default.svc X509v3 extensions: X509v3 Subject Alternative Name: DNS:example-service.default.svc
Este exemplo de saída mostra um certificado com um SAN em falta:
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
Remova o encaminhamento de portas da execução em segundo plano com os seguintes comandos:
$ jobs [1]+ Running kubectl port-forward pods/example-pod 8888:444 & $ kill %1 [1]+ Terminated kubectl port-forward pods/example 8888:444
Inspeção do certificado de um back-end de URL
Se o webhook usar um url
backend,
ligue-se diretamente ao nome de anfitrião especificado no URL. Por exemplo, se o URL for https://example.com:123/foo/bar
, use o seguinte comando openssl
para imprimir o certificado usado pelo back-end:
openssl s_client -connect example.com:123 </dev/null | openssl x509 -noout -text
Mitigar o risco da atualização para a versão 1.23
Depois de identificar os clusters afetados e os respetivos serviços de back-end que usam certificados sem SANs, tem de atualizar os back-ends dos webhooks e do servidor de API agregado para usar certificados com SANs adequados antes de atualizar os clusters para a versão 1.23.
O GKE não atualiza automaticamente os clusters nas versões 1.22.6-gke.1000 ou posteriores com back-ends que usam certificados incompatíveis até que substitua os certificados ou até que a versão 1.22 atinja o fim do suporte padrão.
Se o seu cluster estiver numa versão do GKE anterior a 1.22.6-gke.1000, pode impedir temporariamente as atualizações automáticas configurando uma exclusão de manutenção para impedir atualizações secundárias.
Recursos
Consulte os seguintes recursos para ver informações adicionais sobre esta alteração:
- Notas de lançamento do Kubernetes 1.23
- O Kubernetes é criado com o Go 1.17. Esta versão do Go remove a capacidade de usar uma definição do ambiente
GODEBUG=x509ignoreCN=0
para reativar o comportamento antigo descontinuado de tratar o CN dos certificados de serviço X.509 como um nome de anfitrião.
- O Kubernetes é criado com o Go 1.17. Esta versão do Go remove a capacidade de usar uma definição do ambiente
- Notas de lançamento do Kubernetes 1.19
e
Kubernetes 1.20
- O comportamento antigo descontinuado de tratar o campo CN nos certificados de serviço X.509 como um nome de anfitrião quando não existem SANs está agora desativado por predefinição.
- Notas de lançamento do Go 1.17
- A indicação temporária
GODEBUG=x509ignoreCN=0
foi removida.
- A indicação temporária
- Notas de lançamento do Go 1.15
- O comportamento antigo e descontinuado de tratar o campo CN em certificados X.509 como um anfitrião quando não existem SANs está agora desativado por predefinição.
- RFC 6125
(página 46)
- Embora a utilização do valor CN seja uma prática existente, está descontinuada e as autoridades de certificação são incentivadas a fornecer valores
subjectAltName
.
- Embora a utilização do valor CN seja uma prática existente, está descontinuada e as autoridades de certificação são incentivadas a fornecer valores
- Webhooks de admissão