Skip to main content

Como configurar SSL/TLS para o Ingress do Kubernetes

Escrito por

Peter De Tender

17 de novembro de 2022

0 minutos de leitura

Hoje, aplicativos web e móveis e endpoints de microsserviços baseados em API estão se tornando o padrão. Esses aplicativos são acessíveis pelo protocolo web HTTP. A criptografia oferecida pelo Secure Sockets Layer ou Transport Layer Security (SSL/TLS) é indispensável para proteger a comunicação entre cliente e servidor e entre back-ends de API.

SSL/TLS são mecanismos de criptografia baseados em certificados. O SSL é o padrão há mais de 20 anos. O TLS é uma evolução mais segura do SSL: segue o mesmo conceito, mas usa mecanismos de criptografia mais rigorosos.

Os certificados TLS podem ser autoassinados pela autoridade de certificação interna de uma organização ou assinados por uma das muitas autoridades de certificação públicas disponíveis, como GoDaddy, DigiCert, Symantec, GlobalSign e Let’s Encrypt. Quando a comunicação baseada em IP é criptografada, o tráfego fica protegido contra invasores que tentam inspecionar os pacotes de dados.

Em um ambiente Kubernetes, os contêineres de workloads são executados dentro da rede do Kubernetes. Normalmente, eles são expostos ao mundo externo (online) por meio de um controlador Ingress baseado em HTTP — um serviço baseado em API que encaminha o tráfego para os PODs. Para garantir a segurança nesse cenário, devemos adicionar ao cluster Kubernetes uma configuração baseada em criptografia SSL/TLS.

Qualquer situação comum que envolva troca de dados — por exemplo, enviar um nome de usuário e uma senha para autenticação ou acessar dados confidenciais, como chaves de acesso a endpoints de aplicativos e armazenamento, strings de conexão de bancos de dados e outros — sempre se beneficia da proteção por criptografia.

Este artigo mostra como configurar certificados TLS/SSL com o controlador Ingress no Kubernetes. Vamos configurar um controlador NGINX Ingress, criar um certificado SSL/TLS autoassinado, definir as regras necessárias para vincular o certificado ao controlador e conectá-lo a um serviço de aplicativo de exemplo do Kubernetes.

Como configurar certificados TLS/SSL

Antes de começar, verifique se você tem um ambiente Kubernetes em execução na sua máquina local (por exemplo, Docker com Kubernetes ou MiniKube) ou em um ambiente de nuvem hospedado, como Azure (AKS), AWS (EKS), GCP (GKS) ou Ocean (DOKS), com o Helm instalado.

Esta demonstração usa uma implantação padrão do Azure Kubernetes Service, conforme mostrado neste artigo do Microsoft Learn, com uma assinatura gratuita do Azure. No entanto, a maioria das etapas é específica do Kubernetes, e não da nuvem, então você pode acompanhar independentemente do ambiente em que hospeda o Kubernetes.

Como criar o controlador Ingress

Vamos começar aplicando a configuração do controlador Ingress ao cluster Kubernetes. Há várias opções disponíveis, incluindo NGINX, Google Cloud Load Balancer, Traefik e Contour. Este artigo usa o NGINX, um controlador Ingress conhecido e relativamente simples de configurar. Ele é disponibilizado pela comunidade Kubernetes ingress-nginx no GitHub.  

Além da variedade de controladores Ingress, também há várias maneiras de configurá-los, como com Helm ou kubectl. Nesta demonstração, usaremos o Helm, pois ele funciona com qualquer arquitetura Kubernetes.

A implantação envolve as seguintes etapas:

  • Especificar o nome de um novo namespace do Kubernetes, que será usado pelo controlador Ingress. É para isso que serve a variável NAMESPACE.

  • Baixar o pacote do controlador ingress-nginx usando o comando helm repo add.

  • Gravar a configuração a ser atualizada usando helm repo update.

  • Instalar o pacote usando o comando helm install.

Como este exemplo usa o Azure e o Azure Load Balancer, o comando helm install é ampliado para definir a integração com as sondas de integridade do Azure Load Balancer. Essa configuração varia de acordo com o seu ambiente Kubernetes (local, Azure, AWS, GCP e assim por diante).

Na linha de comando, execute:

NAMESPACE=ingress-nginx

helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update

helm install ingress-nginx ingress-nginx/ingress-nginx \
  --create-namespace \
  --namespace $NAMESPACE \
  --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-health-probe-request-path"=/healthz

A imagem abaixo mostra o comando helm completo:

Terminal exibindo comandos do Helm para adicionar e atualizar o repositório ingress-nginx e instalar o chart ingress-nginx.

O resultado da criação do controlador NGINX será semelhante ao mostrado na imagem abaixo:

A saída do terminal confirma que o controlador ingress-nginx foi instalado e implantado no namespace ingress-nginx.

Em seguida, valide a instalação do controlador Ingress com o comando abaixo:

kubectl --namespace ingress-nginx get services -o wide -w ingress-nginx-controller

A imagem abaixo mostra a resposta ao comando anterior.

Saída do terminal mostrando o kubectl listando o serviço LoadBalancer ingress-nginx-controller com portas HTTP e HTTPS.

No navegador, acesse o EXTERNAL-IP listado para o ingress-nginxcontroller. Ainda não especificamos regras de Ingress, pois não estamos encaminhando o tráfego para um serviço de aplicativo real. Isso resultará em um erro HTTP 404. Mesmo assim, você verá que o controlador NGINX está respondendo.

Em um Mac, o IP externo pode aparecer como localhost em vez de um número IP.

Janela do navegador exibindo uma página de erro “404 Not Found” do nginx, com a barra de endereço indicando “Não seguro”.

Ao clicar na mensagem Não seguro, você verá que nenhum certificado está sendo usado:

Aviso do navegador indicando “Não seguro” para 168.62.208.113 porque o site não tem um certificado.

Agora, tente se conectar novamente ao mesmo endereço IP, desta vez usando HTTPS. O navegador exibirá um aviso de que não é seguro continuar, como mostrado abaixo:

Página de aviso do navegador exibindo “Sua conexão não é particular” para 20.245.164.52, com um erro de autoridade certificadora inválida.

Clique no botão Avançado e, em seguida, em Continuar para .

Aviso de segurança do navegador informando que o servidor em 20.245.164.52 tem um certificado de segurança não confiável, com um link para continuar mesmo assim

Na mesma aba Não seguro, clique no ícone do certificado, destacado abaixo:

Aviso do navegador mostrando “Não seguro” e uma mensagem de certificado inválido para https://20.245.164.52.

Isso exibe os detalhes do certificado falso integrado do controlador Ingress, como mostrado abaixo. Vamos substituir esse certificado.

Visualizador de certificados mostrando a guia Geral de um certificado fictício do controlador de Ingress do Kubernetes, emitido para e por Acme Co.

Como escolher um certificado SSL/TLS

Há várias maneiras de obter certificados SSL/TLS:

  • Autoassinado: esse tipo de certificado costuma ser usado para fins internos e depende da autoridade de certificação (CA) da sua própria infraestrutura de chaves públicas (PKI).

  • Obtido de uma autoridade de certificação pública:Usado normalmente em aplicativos acessíveis pela internet pública. As organizações compram um certificado SSL/TLS de uma autoridade de certificação pública, como GlobalSign, Symantec, DigiCert ou GoDaddy. A principal vantagem de uma CA pública é que os certificados raiz, que validam todos os certificados emitidos, são confiáveis para os navegadores modernos. Em geral, os certificados são válidos por um a cinco anos.

  • Let’s Encrypt: Let’s Encrypt é um projeto sem fins lucrativos. A principal diferença entre as CAs públicas e o Let’s Encrypt é que você não precisa pagar pelos certificados SSL/TLS. Além disso, os certificados do Let’s Encrypt são válidos por apenas três meses.

Além do tipo de certificado SSL/TLS, precisamos considerar tarefas de manutenção, como a rotação de certificados e chaves. Para o caso de uso de Kubernetes e controlador Ingress deste artigo, é possível executar tarefas agendadas para criar um novo certificado SSL/TLS e cron jobs no cluster Kubernetes para criar novos Secrets. Também é importante escolher a validade adequada para os certificados de uma CA pública ou do Let’s Encrypt.

Outro aspecto da criptografia e da segurança SSL/TLS é decidir se você quer implementá-la no nível do controlador Ingress, do Pod ou do aplicativo, ou em ambos. Cada cenário tem vantagens e desvantagens. No nível do Ingress, é possível especificar um vínculo direto entre todas as solicitações recebidas pelo Ingress e os serviços de back-end do Kubernetes.

Armazenar certificados SSL/TLS dentro do Pod ou aplicativo em execução aumenta a complexidade do Pod ou aplicativo. No entanto, pode haver motivos de negócio para garantir a criptografia do tráfego entre o controlador Ingress e o Pod ou aplicativo, além da criptografia do tráfego público definida na configuração do controlador. Nesta demonstração, criaremos um certificado autoassinado. As etapas são semelhantes para as outras duas opções.

Em uma máquina Mac ou Linux, ou no shell de uma plataforma de nuvem (aqui, o Cloud Shell), execute o seguinte comando openssl:

mkdir certs

openssl req -x509 -nodes -days 9999 -newkey rsa:2048 -keyout certs/ingress-tls.key -out certs/ingress-tls.crt

A imagem abaixo mostra o resultado do comando anterior.

Terminal exibindo um comando OpenSSL que gera uma chave privada RSA de 2.048 bits e inicia os detalhes da solicitação de assinatura de certificado.

Informe os dados da organização que serão incluídos na solicitação do certificado, como nome da organização, código do país, localização e endereço de e-mail. Nesta demonstração, usamos www.ingress-tls.com como o nome de domínio totalmente qualificado (FQDN) do certificado.

Isso cria o arquivo do certificado (CRT-extension) e o arquivo da chave privada do certificado (KEY-extension) na pasta \certs.

Como criar o Secret do Kubernetes

Em seguida, precisamos vincular o certificado e a chave a um Secret do Kubernetes. Para isso, execute o seguinte comando:

kubectl create secret tls ingress-cert --namespace dev --key=certs/ingress-tls.key --cert=certs/ingress-tls.crt -o yaml
Terminal exibindo um comando kubectl que cria um segredo TLS chamado ingress-cert a partir de arquivos de chave e certificado, seguido de dados YAML codificados.

Para consultar o Secret, use kubectl get secret. O resultado será semelhante ao mostrado na imagem abaixo:

Terminal exibindo o comando kubectl get secret e os secrets do Kubernetes, incluindo um token de conta de serviço e um certificado TLS

Como publicar um novo aplicativo de exemplo no namespace do Ingress

Em seguida, crie um novo arquivo sample-app.yaml com a sintaxe a seguir (preste atenção à indentação do YAML):

apiVersion: apps/v1
kind: Deployment
metadata:
  name: sample-app
  namespace: default
spec:
  selector:
    matchLabels:
      app: sample
  replicas: 2
  template:
    metadata:
      labels:
        app: sample
    spec:
      containers:
      - name: sample
        image: "gcr.io/google-samples/hello-app:2.0"

---

apiVersion: v1
kind: Service
metadata:
  name: sample-app-service
  namespace: default
  labels:
    app: sample
spec:
  type: ClusterIP
  selector:
    app: sample
  ports:
  - port: 80
    targetPort: 8080
    protocol: TCP

Isso cria um novo serviço e um aplicativo de exemplo (usando a imagem de contêiner de exemplo hello-app do Google) no namespace ingress-nginx, que já existe. Observe que o código aloca o Secret SSL/TLS a esse namespace, portanto, você só pode usá-lo em aplicativos e serviços executados nele.

Em seguida, aplique a configuração ao cluster Kubernetes executando o seguinte comando:

kubectl apply -f sample-app.yaml:
Saída do terminal mostrando o kubectl apply criando o deployment e o serviço sample-app

Como integrar o SSL/TLS entre o controlador Ingress e o aplicativo de exemplo

Por fim, crie outro arquivo chamado sample-ingress.yaml e declare o recurso Ingress com os parâmetros de configuração SSL/TLS a seguir:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: sample-app-ingress
  namespace: default
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - www.ingress-tls.com
    secretName: ingress-cert
  rules:
  - host: "www.ingress-tls.com"
    http:
      paths:
        - pathType: Prefix
          path: "/"
          backend:
            service:
              name: sample-app-service
              port:
                number: 80

No exemplo acima, estes são os parâmetros específicos que aplicam o SSL/TLS e o associam ao Secret:

tls:
  - hosts:
    - www.ingress-tls.com
    secretName: ingress-cert
  rules:
  - host: "www.ingress-tls.com"

A seção de caminhos no final do arquivo indica que todas as solicitações recebidas para o host devem ser encaminhadas ao sample-app-service criado na etapa anterior (o aplicativo de contêiner hello-app do Google).

Execute novamente o comando kubectl para aplicar essa configuração ao cluster Kubernetes:

kubectl apply -f sample-app-ingress.yaml

Para testar a conectividade com o FQDN, atualize o arquivo de hosts DNS na sua máquina local (normalmente /etc/hosts em uma máquina Mac ou Linux ou C:\Windows\System32\Drivers\Etc\Hosts no Windows), para que o endereço IP do controlador Ingress seja associado ao FQDN usado.

Observação: se você não quiser ou não puder atualizar o arquivo hosts local, pode usar um resolvedor DNS https://nip.io. Por exemplo, o nome do nosso controlador Ingress seria resolvido como 20.245.164.52.nip.io. Esse endereço seria resolvido para o endereço IP do controlador20.245.164.52.

Bloco de Notas do Windows exibindo uma entrada no arquivo HOSTS que associa 20.245.164.52 a www.ingress-tls.com, destacada para um controlador de Ingress do Kubernetes.

Abra o navegador e acesse o FQDN usado no certificado (www.ingress-tls.com ou 20.245.164.52.nip.io, no nosso exemplo). Você ainda verá o aviso “Não seguro”, pois o navegador não confia no certificado autoassinado. Clique em Avançado e, em seguida, em Continuar para abrir a URL do aplicativo:

Navegador exibindo um app “Hello, world!” e o visualizador do certificado TLS de www.ingress-tls.com, com informações sobre o emissor e o período de validade do certificado.

Como você pode ver, o aplicativo de exemplo (a saudação “Hello, world!” à esquerda) está funcionando como esperado com o certificado SSL/TLS autoassinado que criamos anteriormente.

Para saber mais, confira a ferramenta CNCF Cert Manager. Ela oferece uma maneira mais avançada de gerenciar certificados e criar Secrets automaticamente.

Comparação entre diferentes provedores de Ingress

Neste passo a passo, usamos o popular controlador NGINX Ingress, mas ele é apenas um entre vários controladores disponíveis. Se você está começando a trabalhar com Kubernetes, o NGINX de código aberto é uma solução simples para distribuir a carga e proteger as workloads do cluster. O NGINX também oferece uma versão voltada para empresas chamada NGINX Plus. Você também pode usar o Kong, outra alternativa comercial que se baseia no mesmo código do NGINX. O Traefik é outra solução comercial, com amplo suporte a protocolos, alta disponibilidade e outros recursos. 

Qualquer solução que escolhermos interage com a API Ingress do Kubernetes. No entanto, no início deste ano, o Kubernetes lançou a versão beta da Gateway API, que pode se tornar uma alternativa interessante à API Ingress atual, especialmente por seus recursos granulares de controle de acesso baseado em funções. Além de oferecer suporte a vários protocolos padrão, como HTTP e TCP/UDP, um dos principais benefícios da Gateway API é que ela também terá suporte integrado a TLS.

Como a Gateway API ainda está nos estágios iniciais de desenvolvimento (atualmente em beta), é cedo demais para saber qual será o futuro da API Ingress em comparação com a Gateway API. É possível que a Gateway API, criada para suceder a API Ingress, ofereça ainda mais funcionalidades do que apenas reproduzir os recursos da API Ingress. Mas, por enquanto, não sabemos como outros fornecedores e extensões vão se adaptar a ela. A boa notícia é que a segurança é uma prioridade, com o TLS usado como padrão para o roteamento.

Conclusão

Sempre que cargas de trabalho e serviços do Kubernetes estão disponíveis em um aplicativo acessível pela internet, os controladores Ingress entram em cena. Além da funcionalidade de proxy reverso, é altamente recomendável integrar certificados SSL/TLS à sua arquitetura Ingress. Isso garante a criptografia do tráfego entre o cliente (navegador) e o servidor (aplicativo do Kubernetes Service). O Kubernetes oferece suporte a diferentes provedores de Ingress e aceita vários certificados SSL/TLS como Secrets. Confira nosso guia de segurança do Kubernetes para conhecer outras práticas recomendadas.

Com comandos administrativos padrão do Kubernetes, como Helm e kubectl, integrar SSL/TLS não deve ser mais complicado do que iniciar qualquer Kubernetes Service. Confira também nosso guia para implementar TLS/SSL em Python.

Proteger as comunicações entre o mundo externo e seus aplicativos com certificados SSL/TLS é apenas uma etapa para executar aplicativos mais seguros: você também precisa proteger cada etapa do ciclo de vida de desenvolvimento de software. Identifique e corrija possíveis vulnerabilidades no código que você escreve e nos projetos de código aberto que utiliza com Snyk Code e Snyk Open Source. Use o Snyk Container para começar com uma imagem-base mais segura e identificar vulnerabilidades adicionais que possam ser introduzidas durante o processo de build. Por fim, verifique com o Snyk IaC se o código implantado não contém brechas de segurança.

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.