Reforce a segurança do Amazon EKS com RBAC, IMDS seguro e logs de auditoria
Kamil Potrec
7 de julho de 2021
0 minutos de leituraConfigurações incorretas em infraestrutura como código (IaC) podem ser tão perigosas quanto vulnerabilidades no código. Pequenos erros de configuração podem deixar dados confidenciais acessíveis pela internet ou tornar endpoints privados e painéis acessíveis a usuários anônimos, que podem usá-los como ponto de partida para um comprometimento. Pesquisas recentes em segurança apontam para o aumento de malware direcionado à plataforma Kubernetes, o que reforça a necessidade de configurações seguras.
Nesta série de posts, vamos analisar as configurações padrão usadas nas implantações do Amazon Elastic Kubernetes Service (EKS). Em seguida, mostraremos como pequenas configurações incorretas ou efeitos colaterais indesejados podem expor nossos clusters a problemas de segurança no EKS.
O que é o Amazon Elastic Kubernetes Service?
O Amazon Elastic Kubernetes Service é um serviço gerenciado do Kubernetes. A AWS é responsável por gerenciar os componentes do plano de controle do cluster, enquanto o cliente gerencia os nós de trabalho e os recursos do cluster.
Além de oferecer alta disponibilidade e escalabilidade do plano de controle, o Amazon EKS se integra ao Identity and Access Management para gerenciar controles de acesso baseados em funções, associar contas de serviço do Kubernetes a funções do IAM, usar grupos de nós gerenciados para escalar automaticamente a capacidade dos nós de trabalho conforme a demanda, centralizar logs e muito mais. Confira a documentação oficial do Amazon EKS para ver a lista completa de recursos.
Além dos custos adicionais, algumas desvantagens de usar um serviço gerenciado são a perda de controle granular sobre as configurações do plano de controle e a necessidade de manter os dados armazenados no banco de dados do plano de controle em contas pertencentes à AWS.
Implante o EKS rapidamente
O Amazon EKS pode ser implantado de várias maneiras, incluindo pelo console web, pela ferramenta de linha de comando do Amazon EKS ou com ferramentas de IaC, como CloudFormation ou Terraform.
Vamos usar o Terraform para implantar um cluster com os valores padrão. Você encontra os arquivos de configuração do Terraform desta demonstração neste repositório. Vamos usar o Terraform Cloud para executar os comandos do Terraform e persistir as alterações no estado.
O cluster EKS precisa ser executado em uma VPC. Você pode implantar uma VPC com o Terraform usando este módulo.
No ambiente de demonstração, vamos implantar três sub-redes privadas e três públicas. As sub-redes privadas não têm uma rota padrão vinculada ao gateway da internet. Um gateway NAT fornecerá acesso à internet às sub-redes privadas. Observação: para fins de demonstração, vamos implantar apenas um gateway NAT. A arquitetura de rede de alto nível do nosso ambiente de demonstração está ilustrada abaixo.

O cluster EKS precisa do ID de uma VPC existente e dos IDs das sub-redes que serão usadas para se comunicar com os pools de nós e provisionar balanceadores de carga para serviços e controladores de ingresso. Como parte do ambiente de demonstração, vamos implantar um grupo de nós autogerenciado com três instâncias.
O Terraform Cloud permite executar planos pela interface do usuário ou por meio de operações remotas. Para iniciar ações pela interface, é necessário fazer commit do código no sistema de controle de versão. As operações remotas permitem receber rapidamente informações sobre o estado dos arquivos de configuração locais. Nos bastidores, o Terraform envia um arquivo compactado com a configuração local para um servidor remoto, executa o comando remotamente e transmite os resultados de volta ao terminal. Para usar um arquivo de estado gerenciado pelo Terraform Cloud, precisamos adicionar uma configuração de backend com o workspace e a organização corretos.
Isso também exige acesso à API do Terraform Cloud. Para saber como configurá-lo, consulte a documentação oficial do Terraform Cloud.
O plano inicial mostra que nossos arquivos de configuração criarão 44 novos recursos.
Agora podemos usar a interface do Terraform Cloud para implantar o ambiente. Quando a implantação for concluída, poderemos ver informações de saída sobre o novo cluster na página de visão geral.

Depois que o ambiente for implantado, podemos seguir a documentação oficial da AWS para acessar o cluster de demonstração.
Este cluster será nossa referência para a avaliação. Vamos começar observando como foi fácil conectar ao cluster.
Restrinja o acesso à API do Kubernetes
O serviço EKS dá acesso à API do Kubernetes por meio de endpoints de serviço. Por padrão, o endpoint do cluster é acessível publicamente. Isso significa que qualquer pessoa na internet pode tentar acessá-lo. Por padrão, a API do Kubernetes aceita solicitações anônimas, mas os autorizadores ABAC e RBAC exigem autorização explícita para usuários anônimos/não autenticados. Os clusters EKS têm RBAC ativado por padrão, o que podemos verificar consultando os parâmetros do servidor da API.
Os logs também mostram que o EKS implementa um método de autenticação por token via webhook. Isso significa que os usuários do Kubernetes precisam obter o token de autenticação pela API da AWS, que é separada do endpoint da API do Kubernetes do cluster. O Amazon EKS não interfere nas decisões de autorização do cluster.
Para aumentar ainda mais a confiança, podemos tentar nos conectar ao cluster sem credenciais autenticadas. Para simular usuários anônimos, precisamos enviar uma solicitação à API sem um cabeçalho de autorização. O kubectl tem uma opção de depuração muito útil que exibe todas as solicitações como comandos CURL, que podemos reutilizar.
Se enviarmos a mesma solicitação sem o cabeçalho de autorização correto, veremos que ela não foi autorizada.
Agora que verificamos que, por padrão, o acesso aos nossos recursos é um pouco restrito, é hora de falar sobre defesa em profundidade. Esse conceito se refere à aplicação de várias camadas de controles de segurança para evitar umúnico ponto de falha no nosso sistema de segurança. Na implantação atual, as permissões de RBAC são nosso único controle contra o acesso ao cluster por qualquer pessoa na internet.
Este arquivo de configuração mostra como alguém poderia habilitar o acesso anônimo:
Depois de aplicar essa configuração, podemos ver que a solicitação anônima é aceita:
Os desenvolvedores do Kubernetes introduziram algumas medidas de segurança para garantir que esse tipo de configuração seja explícito. O usuário system:anonymous e o grupo system:unauthenticated precisam ser listados explicitamente no atributo subjects. O uso de caracteres curinga, como *, não concede acesso a esses dois sujeitos. Você pode testar isso alterando o name do sujeito no nosso exemplo para o caractere *.
O acesso público ao servidor da API do Kubernetes também aumenta o impacto de qualquer vazamento de credenciais. Com uma API acessível publicamente, as credenciais vazadas podem ser usadas de qualquer lugar do mundo. A descoberta de uma vulnerabilidade de dia zero no fluxo de autorização é outro motivo importante para limitar quem pode enviar pacotes ao servidor da API. Vulnerabilidades desse tipo já foram relatadas, por exemplo, CVE-2019-11253 e CVE-2020-8559.
Podemos reduzir o impacto de endpoints públicos limitando os endereços IP que têm acesso. No Terraform, isso pode ser feito adicionando o atributo cluster_endpoint_public_access_cidrs à definição do módulo.
A segunda opção é desativar completamente o endpoint público e habilitar um endpoint privado da VPC. Isso pode ser feito no módulo do Terraform com os atributos cluster_endpoint_private_access e cluster_endpoint_public_access. Assim, somente usuários com acesso à rede da VPC poderão acessar o cluster.
No entanto, ambas as opções têm um grande impacto nos custos operacionais. A ausência de um endpoint público pode causar problemas ao usar um sistema público de implantação contínua, como o Terraform Cloud. No nosso ambiente de demonstração, desativar o endpoint público fez a implantação falhar com o seguinte erro de acesso negado.

Esse erro ocorre porque, internamente, o módulo do Terraform tenta atualizar o mapa de configuração aws-auth, algo que só pode ser feito pela API do Kubernetes. Como você pode ver, o FQDN do servidor da API foi resolvido para um endereço IP privado e o provedor não consegue acessá-lo. Podemos corrigir esse erro desativando o gerenciamento do mapa de configuração no nosso módulo do Terraform. Isso significa que, a partir daí, precisaremos gerenciar o mapa de configuração de autorização por outro método.
Para desativar completamente o endpoint público, você precisará implementar um sistema de implantação contínua que seja executado dentro da VPC, com acesso ao endpoint privado, ou que encaminhe a conexão por um proxy. Este artigo explica muito bem como fazer isso com o AWS CodePipeline, e este módulo do Terraform pode ser usado para executar o Atlantis no serviço AWS Fargate.
O acesso para desenvolvedores também pode ficar mais complicado, pois será necessário implementar um bastion host ou um serviço de VPN para fornecer acesso ao endpoint privado.
Restrinja o acesso ao serviço de metadados da instância
O EKS usa perfis de instância para conceder permissões da AWS a um kubelet em execução em um nó. O kubelet pode acessar essas credenciais pelo serviço de metadados da instância (IMDS). O IMDS pode ser acessado por uma solicitação HTTP a um endereço IP de link local. Por padrão, esse serviço de metadados é acessível a todos os pods no nó. Podemos testar isso executando um pod e obtendo um token STS.
No exemplo acima, podemos usar todas as permissões atribuídas ao nó. Isso é um claro problema de segurança de elevação de privilégios, pois, por padrão, os pods não deveriam precisar de acesso à AWS.
A única forma de mitigar esse problema é limitar o acesso de rede dos pods ao serviço IMDS. O IMDS tem duas versões. A versão 1 usa um método de solicitação e resposta e pode ser consultada por qualquer processo capaz de enviar pacotes ao endereço de link local. A versão 2 usa um método baseado em sessões e permite definir um tempo de vida (TTL) arbitrário para as mensagens de resposta. De acordo com a documentação da AWS, o IMDSv1 continuará disponível junto com o IMDSv2.
Para limitar o impacto desse problema com a configuração nativa da AWS, precisamos desativar completamente o IMDSv1. Para isso, defina o atributo metadata_http_tokens dos nós de trabalho como required. Em seguida, limite o TTL dos pacotes de resposta a 1, que já é o comportamento padrão do serviço. Com o TTL definido como 1, a camada de rede do Kubernetes não consegue encaminhar o pacote para o namespace de rede do pod.
O módulo do Terraform para Amazon EKS usa grupos de escalabilidade automática e modelos de execução para criar nós. Isso significa que, se você atualizar as configurações do serviço de metadados, será necessário atualizar as instâncias.
A limitação dessa solução é que qualquer pod com o atributo hostNetworking definido como true ainda poderá obter as credenciais.
Também é possível usar políticas de rede nativas do Kubernetes para restringir o acesso a endereços IP de link local e, assim, impedir o acesso ao IMDS. A documentação do AWS Calico explica como instalar o plugin CNI do Calico. A política de rede a seguir deve impedir o acesso ao IMDS. O plugin Calico não isola pods com hostNetwork definido como true; portanto, essa solução tem a mesma limitação da solução nativa que desativa o IMDSv1 e define o TTL máximo como 1. No entanto, o uso de políticas de rede não exige a substituição dos nós e pode ser aplicado a pods específicos, caso o IMDS seja realmente necessário dentro do pod.
Ative o registro de logs
Agora que vimos algumas configurações incorretas que podem expor os clusters EKS a ameaças externas e internas, vamos ver se conseguimos auditar esses eventos. O Kubernetes oferece logs de auditoria para que os administradores monitorem as ações realizadas por usuários e serviços do cluster. Infelizmente, esses logs não vêm habilitados por padrão no EKS nem na configuração padrão do módulo do Terraform. Para habilitá-los, precisamos usar o atributo cluster_enabled_log_types e especificar os tipos de log necessários.
O EKS permite habilitar vários tipos de log de forma independente. Do ponto de vista da segurança, temos mais interesse nos logs audit e authenticator.
Os logs de auditoria permitem monitorar as solicitações do Kubernetes e atribuí-las às entidades correspondentes. Vale lembrar que eles geram eventos para cada ação realizada no cluster e, por isso, enviam grandes volumes de dados para o destino configurado, que por padrão é o CloudWatch. Ao limitar os logs a audit e authenticator, podemos reduzir esse volume.
Por exemplo, podemos pesquisar atualizações no mapa aws-config para identificar se alguém o adulterou. Podemos usar o filtro a seguir para obter todos os eventos de patch relacionados a um objeto chamado aws-auth.
O evento de auditoria contém informações muito úteis que podem nos ajudar a identificar quem fez a alteração, de onde essa pessoa se conectou e muito mais.
Esses logs também podem ser muito úteis para detectar tentativas de acesso a recursos por usuários não autorizados. A consulta a seguir pode ser usada para pesquisar solicitações enviadas por usuários anônimos:
Já os logs do authenticator podem nos ajudar a rastrear quem está tentando fazer login no cluster e relacionar essas entidades a grupos e usuários do Kubernetes. No exemplo anterior, sabemos que o usuário com o ID de chave AROAYREY3WYOBFHU7VIRM alterou o configmap, mas não sabemos a qual entidade da AWS esse ID de chave pertence.
A seguir: como reforçar a segurança do Amazon EKS — avançado
Neste artigo, exploramos alguns dos problemas de segurança que podem surgir ao usar o Amazon Elastic Kubernetes Service, incluindo autenticação e autorização, além do acesso ao serviço de metadados da instância. Também vimos como mitigar esses problemas em produção. Na próxima parte desta série, vamos explorar a arquitetura de várias contas como etapa essencial para isolar clusters do Amazon EKS, explicar a importância de usar funções do IAM dedicadas ao criar clusters do Amazon EKS e mostrar como proteger ainda mais os segredos armazenados nos planos de controle do Amazon EKS. Volte para conferir o próximo artigo ou siga @snkysec no Twitter para receber uma notificação quando ele for publicado.
A verificação do Snyk Infrastructure as Code (Snyk IaC) também pode ajudar a mitigar problemas de segurança ao usar o Amazon EKS com Cloud Formation ou Terraform, identificando problemas de segurança no código da implantação antes que ele chegue à produção. Crie uma conta grátis e comece a fazer verificações!
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.



