
Armazene chaves de API, senhas, certificados e outros dados sensíveis em serviços de gestão de secrets nativos da nuvem e acesse-os a partir de clusters K8s.
Introdução
Os secrets são essenciais para o funcionamento de muitos sistemas em produção. A exposição acidental de secrets é um dos maiores riscos e precisa ser tratada com cuidado. Os desenvolvedores devem fazer o possível para proteger os secrets das aplicações.
O problema fica ainda mais complicado quando uma empresa migra para uma arquitetura de microsserviços e vários serviços precisam acessar diferentes secrets para funcionar corretamente. Isso traz novos desafios: como distribuir, gerenciar, monitorar e rotacionar os secrets das aplicações sem expô-los acidentalmente?
No post anterior ( Parte I), mostrei uma forma de integrar os serviços de gestão de secrets da AWS e do Google Cloud ( AWS Secrets Manager, AWS SSM Parameter Store e Google Cloud Secret Manager) com o Kubernetes, usando o initContainer doitintl/secrets-init adicionado manualmente a um Pod de destino.
Neste post, vou apresentar uma abordagem nativa do Kubernetes para integrar os serviços de gestão de secrets na nuvem mencionados acima.
Injeção automática de secrets na nuvem
Embora dê para alterar manualmente os arquivos YAML de Deployment do Kubernetes para usar o secret-init como sistema init do container, seria muito melhor se alguém fizesse isso por você — e somente para os Pods do Kubernetes que referenciam secrets na nuvem. Felizmente, o Kubernetes permite inspecionar e alterar qualquer Pod antes da criação do container, por meio de um mecanismo conhecido como mutating admission webhook.
O doitintl/kube-secrets-init é um projeto open source da DoiT International que implementa um mutating admission webhook do Kubernetes para injeção de secrets na nuvem, com suporte tanto a secrets gerenciados pela AWS quanto pelo Google Cloud.
O kube-secrets-init monitora clusters Kubernetes em busca de Pods recém-criados ou atualizados e adiciona um initContainer com o utilitário doitintl/secrets-init aos Pods que referenciam secrets na nuvem, seja diretamente (via variáveis de ambiente) ou indiretamente (via Secret e ConfigMap do Kubernetes).

Integração com o AWS Secrets Manager
Você pode usar uma referência ARN de um secret da AWS como valor de uma variável de ambiente. O secrets-init resolve esse valor, com base no ARN informado, para o valor do secret referenciado.
https://gist.github.com/930c9ea733557f9715f976df042bf361
Integração com o AWS Systems Manager Parameter Store
Você pode usar o AWS Systems Manager Parameter Store para armazenar parâmetros e secrets de aplicações.
Basta informar uma referência ARN do AWS Parameter Store como variável de ambiente. O secrets-init resolve esse valor, com base no ARN informado, para o valor do parâmetro referenciado.
https://gist.github.com/f7d9a81d5e239cdd734989a689d46f82
Integração com o Google Secret Manager
Você pode informar o nome de um Google Secret (com o prefixo gcp:secretmanager:) como valor de uma variável de ambiente. O secrets-init resolve esse valor, com base no nome informado, para o valor do secret referenciado. O nome do secret pode incluir uma versão, caso queira referenciar uma versão específica.
https://gist.github.com/d121cce3a9d4664a876deb95f18493d7
Pré-requisitos
AWS
Para resolver secrets da AWS no AWS Secrets Manager e no Parameter Store, a aplicação secrets-init precisa ser executada sob uma IAM Role da AWS com uma das IAM policies abaixo anexadas.
Para o AWS Secrets Manager:
https://gist.github.com/7348301b4882a564cbd9644d6697c3eb
Para o AWS Systems Manager Parameter Store:
https://gist.github.com/3f3dd3d015a4c000341491c18ac2c4b7
Em um cluster EKS, o recomendado é usar AWS IAM Roles for Service Account. Também dá para atribuir uma IAM Role à instância EC2 onde o container está rodando, mas essa opção é considerada menos segura.
Google Cloud
Para resolver secrets do Google no Google Secret Manager, a aplicação secrets-init precisa ser executada sob uma IAM role com permissões suficientes para acessar os secrets desejados. Por exemplo, dá para atribuir as duas IAM roles predefinidas do Google a seguir a uma Google Service Account: Secret Manager Viewer e Secret Manager Secret Accessor.
No cluster GKE, dá para atribuir uma IAM Role a um Pod do Kubernetes via Workload Identity. Também é possível atribuir uma IAM Role à instância GCE onde o container está rodando, mas essa opção é considerada menos segura.
Descomente a flag --provider=google no arquivo deployment.yaml.
O deployment do webhook
- Para subir o servidor de webhook do
kube-secrets-init, precisamos criar um service de webhook e um deployment no nosso cluster Kubernetes. É bem direto, com exceção de um detalhe: a configuração TLS do servidor. Se você abrir o arquivo deployment.yaml, vai notar que o certificado e o respectivo arquivo de chave privada são lidos a partir de argumentos de linha de comando, e que o caminho desses arquivos vem de um volume mount apontando para um secret do Kubernetes:
https://gist.github.com/b861984a2be2f2f63596f089f417cefc
O ponto mais importante é lembrar de definir o certificado CA correspondente mais adiante na configuração do webhook, para que o apiserver saiba que ele deve ser aceito. Por enquanto, vamos reaproveitar o script originalmente escrito pela equipe do Istio para gerar uma solicitação de assinatura de certificado. Em seguida, enviamos a solicitação para a API do Kubernetes, buscamos o certificado e criamos o secret necessário a partir do resultado.
Primeiro, execute o script webhook-create-signed-cert.sh e verifique se o secret com o certificado e a chave foi criado:
https://gist.github.com/43135c6af29328bcd74a37b0df5188f8
Depois que o secret for criado, podemos criar o deployment e o service. São recursos padrão de deployment e service do Kubernetes. Até aqui, geramos apenas um servidor HTTP que aceita requisições pelo service na porta 443:
https://gist.github.com/3971cf1f46f5a57d11d922ed84b0543f
Configurar o Mutating Admission Webhook
Agora que nosso servidor de webhook está no ar, ele já consegue aceitar requisições do apiserver. Mas, antes, precisamos criar alguns recursos de configuração no Kubernetes. Vamos começar pelo validating webhook e configurar o mutating webhook depois. Se você der uma olhada na configuração do webhook, vai notar que ela contém um placeholder para CA_BUNDLE:
https://gist.github.com/fcafa7ed3b3c3b951b7fad3c0d5fbdb6
Existe um pequeno script que substitui o placeholder CA_BUNDLE na configuração por essa CA. Execute este comando antes de criar a configuração do validating webhook:
https://gist.github.com/6d5bb7724cef04e9e6a2af12da917a21
Crie uma configuração de mutating webhook:
https://gist.github.com/f946d6046cc1a76a21526c346ca403c1
Configurar o RBAC do secrets-init-webhook
Crie uma Service Account do Kubernetes para ser usada com o secrets-init-webhook:
https://gist.github.com/0cda887b586609cbdbb700f7412e70ad
Defina as permissões RBAC para a service account do webhook:
https://gist.github.com/1205f1a5d2f449cc3340a404ea474b77
Resumo
Espero que este post seja útil. Fico no aguardo dos seus comentários e dúvidas.
Você também está convidado a contribuir (Issues, Features, PRs) com o projeto no GitHub doitintl/kube-secrets-init.
Quer mais conteúdos do Alexei? Confira o nosso blog ou siga o Alexei no Twitter.