Como implementar TLS no Kubernetes
Rubaiat Hossain
31 de julho de 2023
0 minutos de leituraCom a evolução contínua da tecnologia de nuvem, a demanda por Kubernetes está disparando. Como resultado, a segurança se tornou prioridade para desenvolvedores que querem proteger os dados de suas aplicações. É aí que entra o Transport Layer Security (TLS). O TLS é essencial para garantir uma conexão segura entre suas aplicações e a internet.
O TLS usa criptografia assimétrica e simétrica para manter seus dados protegidos durante a transmissão e quando estão armazenados. O certificado TLS usado no Kubernetes costuma ser um certificado de chave pública emitido por uma autoridade certificadora (CA) confiável. Esse certificado contém informações sobre a identidade do servidor, a chave pública usada na criptografia e a assinatura digital da CA que o emitiu.
Este artigo orienta você na implementação de uma conexão TLS para suas aplicações em um cluster Kubernetes, oferecendo uma compreensão abrangente do TLS e de sua importância para proteger suas aplicações e dados.
Como o TLS é implementado para workloads do Kubernetes
Quando as solicitações chegam a uma aplicação em execução em um cluster Kubernetes, elas passam por um componente de rede que funciona como gateway para o tráfego de entrada. Dependendo de como você configura sua aplicação, esse componente pode ser um controlador de Ingress do Kubernetes, um serviço de balanceador de carga, um serviço ClusterIP ou um serviço NodePort.
O Kubernetes não oferece uma implementação padrão de criptografia TLS para a comunicação entre o cliente e o componente de rede. Isso significa que as solicitações são atendidas por HTTP, e não por HTTPS. No entanto, você pode configurar facilmente sua aplicação Kubernetes para usar HTTPS e permitir uma comunicação segura com TLS.
O Kubernetes também oferece recursos como Secrets e ConfigMaps, que podem ser usados para gerenciar com segurança seus certificados TLS e outros dados confidenciais necessários à aplicação.
Historicamente, o TLS (e seu antecessor, o SSL) era implementado entre sistemas e usuários que precisavam de comunicações seguras. Com a expansão dos sistemas distribuídos e a grande redução no custo e no impacto no desempenho da implementação do TLS — sem falar nas preocupações cada vez maiores com a privacidade —, hoje a maioria dos especialistas recomenda criptografar todo o tráfego. Alguns casos de uso comuns para criptografia de rede incluem:
Sistemas de pagamento: Se sua aplicação lida com dados de pagamento, como contas bancárias e cartões de crédito, você precisa implementar o TLS. Esse é um requisito regulatório e é necessário para garantir que os dados dos usuários estejam seguros durante a transmissão. Criptografar os dados de pagamento também transmite confiança aos clientes e garante que eles se sintam seguros ao usar seus serviços.
Criptografia de ponta a ponta com uma malha de serviços: Com um mecanismo de criptografia de ponta a ponta e uma malha de serviços como o Istio, o TLS pode proteger a comunicação entre diferentes microsserviços em um cluster Kubernetes. Essa é uma abordagem popular para arquiteturas modernas de microsserviços distribuídos.
IoT e computação de borda: Aplicações Kubernetes que interagem com dispositivos de IoT ou sistemas de computação de borda devem implementar TLS para proteger a transmissão de dados entre os dispositivos e a nuvem, evitando o acesso não autorizado aos dados gerados pelos dispositivos de IoT.
Redes de distribuição de conteúdo (CDNs): Se suas aplicações usam CDNs para armazenar conteúdo em cache e distribuí-lo, a implementação do TLS pode ajudar a garantir uma transmissão segura e evitar a adulteração de dados ou o acesso não autorizado.
Como configurar o TLS no Kubernetes
Nas próximas seções, você vai implementar o TLS para uma aplicação simples do Kubernetes usando um projeto Node.js que simula uma aplicação de processamento de pagamentos. O código da aplicação e as configurações necessárias do Kubernetes estão disponíveis neste repositório do GitHub.
Pré-requisitos
Para acompanhar este tutorial, você precisa do seguinte:
Um mecanismo de runtime de contêiner: Neste artigo, vamos considerar que o Docker está instalado e configurado na sua estação de trabalho.
Uma distribuição do Kubernetes: Você precisa instalar uma distribuição do Kubernetes para criar o cluster e outros recursos necessários, como deployments e serviços. Este tutorial usa o kind (v0.18.0), mas você pode usar qualquer outra distribuição do Kubernetes, como minikube ou K3s.
kubectl: Esta interface de linha de comando é usada para se comunicar com o cluster Kubernetes e executar comandos. Este tutorial usa a versão 1.26.
mkcert: Essa ferramenta é usada para obter um certificado TLS confiável com um nome de domínio personalizado para sua máquina de desenvolvimento. Você pode instalar o
mkcertna sua máquina de desenvolvimento seguindo as instruções oficiais.Git e Helm: Você precisa ter o Git instalado para usar o projeto de demonstração localmente e o gerenciador de pacotes Helm para Kubernetes. Este guia usa o Helm v3.11.2.
Nas próximas seções, você vai implementar o TLS para uma aplicação de pagamento de demonstração implantada em um cluster Kubernetes local. Primeiro, você implanta a aplicação no cluster kind e verifica se ela usa HTTP em vez de HTTPS. Em seguida, gera um certificado TLS autoassinado e configura a aplicação de pagamento para usá-lo. Por fim, cria um certificado TLS confiável usando mkcert e verifica se sua aplicação Kubernetes pode ser acessada por HTTPS.
Implante a aplicação de pagamento no Kubernetes
Para começar a implementar o TLS na aplicação de exemplo baseada em Kubernetes, clone a aplicação para sua máquina local executando o seguinte comando:
Em seguida, acesse o diretório do projeto com este comando:
Depois de acessar o diretório do projeto, você pode implantar a aplicação no cluster Kubernetes.
Use o seguinte comando para criar seu cluster kind:
Observação: o arquivo config.yaml vincula algumas portas dos nós kind ao localhost. Isso é necessário nas instalações do Docker Desktop, pois os contêineres kind são executados dentro de uma máquina virtual (VM). Se você estiver usando uma estação de trabalho Linux com o Docker instalado nativamente (sem a VM do Docker Desktop), poderá omitir a opção --config.
Em seguida, vamos criar a imagem do contêiner e carregá-la no cluster kind.
Observação: como alternativa, você pode enviar a imagem para um registry em vez de usar kind load. Nesse caso, também será necessário editar o arquivo deployment.yaml (usado abaixo) com as informações do seu registry e atualizar imagePullPolicy para “Always”, para que a imagem seja baixada.
Depois que o cluster for criado, implante a aplicação nele com estes comandos:
Aguarde alguns minutos para que o Kubernetes crie os pods e outros recursos necessários. Você pode verificar o status dos recursos usando estes comandos:
O projeto de demonstração expõe a aplicação de pagamento usando um serviço nodePort na porta 30080. Quando você define um serviço do Kubernetes sem especificar o campo type, o Kubernetes atribui o tipo de serviço padrão: ClusterIP.
No entanto, o endereço IP exposto pelo ClusterIP só pode ser acessado de dentro da rede do cluster. Isso significa que você não pode visualizar a aplicação em execução no cluster usando um cliente externo, como seu navegador. Em produção, talvez você queira usar um serviço LoadBalancer para que seu provedor de nuvem disponibilize um balanceador de carga externo com um endereço IP acessível publicamente.
Use estes comandos para ver os serviços desta aplicação de demonstração:
Dependendo do seu ambiente de runtime, você pode acessar a aplicação de demonstração de uma destas duas maneiras:
Com VM (por exemplo, Docker Desktop):
Para acessar a aplicação de demonstração pelo navegador, use o vínculo de porta do kind configurado no arquivo config.yaml e acesse localhost:30080.
Sem VM (por exemplo, Linux sem Docker Desktop):
Para acessar a aplicação de demonstração pelo navegador, você precisa encontrar o endereço IP exposto pelo nodePort usando o seguinte comando:
O comando deve exibir o INTERNAL-IP do plano de controle do Kubernetes (ou seja, 172.18.0.2). Agora, você pode acessar a aplicação de pagamento da seguinte maneira:
Substitua o endereço IP pelo INTERNAL-IP real do plano de controle do Kubernetes ou por localhost, conforme as instruções acima.
Ao abrir o endereço IP e a porta acima no navegador, você verá a Página de pagamento, onde poderá inserir os dados do cartão. Como esta é uma aplicação simulada, não há processamento real nessa página e os dados não são salvos:

Dependendo do navegador, você verá algum indicador de que a página não é segura perto da barra de endereço. Isso indica que a aplicação está sendo servida por HTTP, e não por HTTPS. Você pode confirmar isso clicando no aviso:

Configure um certificado TLS autoassinado para sua aplicação
Agora, configure o TLS para a aplicação de exemplo no Kubernetes. Crie um certificado autoassinado e uma chave privada:
Em seguida, crie um Secret do Kubernetes com o certificado e a chave privada:
Agora, instale o controlador Nginx Ingress para que ele possa redirecionar as solicitações recebidas para sua aplicação de pagamento usando HTTPS. Como você expôs a aplicação com nodePort, precisa instalar o Ingress usando um arquivo de valores personalizado que defina o tipo de serviço como NodePort.
Crie um arquivo chamado ingress-values.yaml com o seguinte conteúdo:
Em seguida, instale o controlador Nginx Ingress usando o Helm e o arquivo de valores personalizado:
Crie um arquivo ingress.yaml com o seguinte conteúdo:
E aplique este arquivo de manifesto com o seguinte comando:
Atualize o arquivo /etc/hosts com a seguinte entrada:
Se você estiver usando o Docker Desktop, substitua <control_plane_IP> por 127.0.0.1. Caso contrário, use o endereço IP obtido ao executar kubectl get nodes -o wide.
Agora, você pode acessar a aplicação de pagamento por HTTPS: abra https://my-demo-app.local:32443 no navegador. Na primeira vez que visitar a aplicação, o navegador deverá exibir uma página de aviso, permitindo que você aceite o risco e prossiga. Depois disso, você poderá acessar o site por HTTPS:

Seu navegador exibe esse erro porque o certificado TLS é autoassinado. Isso fica evidente porque a parte HTTPS do endereço está riscada.
Configure um certificado TLS confiável para sua aplicação
Para resolver isso, você pode usar mkcert para criar um certificado confiável para seu ambiente de desenvolvimento. Para isso, crie uma CA local e gere um certificado confiável para seu domínio local:
Exclua o Secret anterior e crie um novo para mkcert:
Por fim, reimplante o recurso Ingress executando o seguinte:
Verifique o TLS da aplicação Kubernetes
A esta altura, você deve conseguir acessar sua aplicação de pagamento com um certificado TLS confiável. Reinicie o navegador e acesse https://my-demo-app.local:32443 para que o novo certificado entre em vigor. Desta vez, não deverá aparecer nenhum aviso, e a parte HTTPS do endereço não estará riscada, como acontece em sites protegidos por TLS:

Clique no ícone de cadeado na barra de endereço para confirmar que o certificado TLS é confiável para o navegador e que a conexão é segura:

Você encontra os exemplos de código atualizados na branch solution do nosso repositório do projeto no GitHub.
Conclusão
Ao trabalhar com dados confidenciais, o TLS oferece a segurança necessária. No entanto, implementar o TLS pode ser um desafio quando você não sabe por onde começar.
Neste tutorial, você aprendeu a implementar o TLS para uma aplicação implantada em um cluster Kubernetes local. Você também pode usar esses princípios para implementar TLS em aplicações hospedadas localmente ou em um provedor de nuvem.
Ao implementar TLS em um sistema de produção, considere usar um certificado público de uma autoridade certificadora (CA) confiável, como Let's Encrypt. Embora isso exija que você tenha acesso ao domínio do seu site, é possível implementar configurações adicionais, como usar um serviço de balanceador de carga para expor sua aplicação ou gerenciar vários certificados com um gerenciador de certificados, como o cert-manager. Expor sua aplicação por meio de um balanceador de carga oferece vantagens como maior disponibilidade, escalabilidade e resiliência. Além disso, usar um gerenciador de certificados facilita o provisionamento e o gerenciamento dos certificados do seu cluster no futuro.
Proteja a infraestrutura desde a origem
A Snyk automatiza a segurança e a conformidade de IaC nos fluxos de trabalho e detecta recursos com configurações divergentes ou ausentes.



