
Secrets são essenciais para a operação 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 secrets diferentes para funcionar corretamente. E aí surge um novo desafio: como distribuir, gerenciar, monitorar e rotacionar os secrets das aplicações sem gerar exposição acidental?
Kubernetes Secrets
O Kubernetes oferece um objeto chamado Secret, que você pode usar para armazenar dados sensíveis das aplicações, como senhas, chaves SSH, chaves de API, tokens, entre outros. Um Kubernetes Secret pode ser injetado em um container de Pod como variável de ambiente ou montado como arquivo. Usar Kubernetes Secrets permite abstrair dados sensíveis e configurações do deployment da aplicação.
Por exemplo, um secret do Kubernetes pode ser criado com o comando kubectl create secret:
https://gist.github.com/02c582490747681776f1f480ec2f4165
ou um arquivo db-credentials.yaml do Kubernetes, que descreve o mesmo secret:
Vale lembrar: armazenar dados sensíveis em um Kubernetes Secret não os torna seguros. Por padrão, todos os dados nos Kubernetes Secrets ficam armazenados em texto puro codificado em base64.
A partir da versão 1.13, o Kubernetes oferece suporte à criptografia de dados de Secrets em repouso, usando o objeto EncryptionConfiguration com um provedor de criptografia interno ou externo.
Lista de provedores de criptografia atualmente suportados:
Provedores internos: aescbc, aesgsm, secretbox
Mesmo assim, a criptografia de Secrets em repouso não é aplicada por padrão. E, mesmo quando habilitada, não é suficiente nem pode ser considerada uma solução completa de gerenciamento de secrets.
Uma solução completa de gerenciamento de secrets também precisa contemplar: distribuição de secrets, rotação, controle de acesso granular, log de auditoria, monitoramento de uso, versionamento, armazenamento com criptografia robusta, uma API prática e SDK(s) para clientes — além de outros recursos úteis.
Gerenciamento de secrets na nuvem
Vários provedores de nuvem oferecem serviços de gerenciamento de secrets como parte de sua plataforma, ajudando você a proteger os secrets necessários para acessar aplicações, serviços e APIs. Usar esses serviços elimina a necessidade de fazer hardcode de informações sensíveis em texto puro e de criar um ciclo de vida caseiro para gerenciar secrets. Os serviços de gerenciamento de secrets permitem controlar o acesso aos secrets das aplicações por meio de permissões granulares e auditoria.
Integrando o Kubernetes com serviços de gerenciamento de secrets
De modo geral, qualquer aplicação pode usar o SDK/API específico do provedor para acessar secrets armazenados em um serviço de gerenciamento de secrets. Normalmente, isso exige alterar o código da aplicação ou usar algum tipo de script de bootstrap ou Init containers, com ferramentas de CLI do cliente ou APIs web.
Facilite tudo com a ferramenta secrets-init
Hoje estamos lançando o doitintl/secrets-init — uma ferramenta open source (Apache License 2.0) que simplifica a integração de serviços de gerenciamento de secrets nativos da nuvem com workloads em containers rodando em clusters Kubernetes gerenciados pela nuvem ou autogerenciados.
Em essência, o secrets-init é um sistema init minimalista, projetado para rodar como PID 1 dentro de um ambiente de container, de forma parecida com o dumb-init, e oferece integração fluida com diversos serviços de gerenciamento de secrets nativos da nuvem, como:
Por que você precisa de um sistema init em um container Docker?
Vale a pena ler a explicação no repositório do dumb-init da Yelp
Em resumo:
- Encaminhamento adequado de sinais
- Coleta de processos zumbis órfãos
O que o secrets-init faz
O secrets-init roda como PID 1, atuando como um sistema init simples que serve de ENTRYPOINT ou primeiro comando do container, com a responsabilidade de iniciar um processo filho e repassar todos os sinais do sistema para uma sessão enraizada nesse processo filho. É essa a essência de um processo init. Por outro lado, o secrets-init também repassa quase todas as variáveis de ambiente sem alterações, substituindo variáveis especiais de secrets pelos valores obtidos dos serviços de gerenciamento de secrets.
Integração com o Docker
O secrets-init é um binário compilado estaticamente (sem dependências externas) e pode ser facilmente embutido em qualquer imagem Docker. Baixe o binário do secrets-init e use-o como ENTRYPOINT do container Docker.
Por exemplo:
https://gist.github.com/7efe25155c034ee1b978a2477b3224e4
Integração com o Kubernetes
Para usar o secrets-init com objetos do Kubernetes (Pod/Deployment/Job/etc) sem alterar a imagem Docker, considere injetar o secrets-init no Pod de destino por meio de um initContainer. Você pode usar a imagem Docker doitint/secrets-init ou criar a sua. Copie o binário do secrets-init do init container para um volume compartilhado e altere o command do Pod para executar o secrets-init como primeiro comando.
Integração com o AWS Secrets Manager
Para começar a usar o secrets-init com o AWS Secrets Manager, basta definir o ARN do secret da AWS como valor de uma variável de ambiente. O secrets-init vai resolver qualquer valor de ambiente, usando o ARN especificado, para o valor do secret referenciado.
Exemplo, usando o secrets-init com um Job do Kubernetes:
https://gist.github.com/6ae6d57ed08b26c64f534f87fc1872df
Integração com o AWS Systems Manager Parameter Store
Dá para usar o AWS Systems Manager Parameter Store para armazenar parâmetros da aplicação em texto puro ou criptografados (uma espécie de secrets).
Como no exemplo anterior, basta definir o ARN do AWS Parameter Store como valor de uma variável de ambiente. O secrets-init vai resolver qualquer valor de ambiente, usando o ARN especificado, para o valor do parâmetro referenciado.
Exemplo de formato do AWS Systems Manager Parameter Store:
https://gist.github.com/9a7a83ec1659c391412557e5af340f42
Para resolver secrets do AWS Secrets Manager e do Parameter Store, o secrets-init precisa rodar com uma IAM role que tenha permissão para acessar os secrets desejados.
Isso pode ser feito atribuindo uma IAM Role a um Pod do Kubernetes ou a uma Task do ECS. Veja o post no blog do EKS Introducing fine-grained IAM roles for service accounts.
Também é possível atribuir uma IAM Role à instância EC2 onde o container está rodando, mas essa opção é bem menos segura e não é recomendada.
Integração com o Google Secret Manager
O Google Cloud lançou recentemente um novo serviço para gerenciar secrets na nuvem: Google Secret Manager
Você pode definir o nome do secret do Google, usando o prefixo reconhecido pelo secrets-init (gcp:secretmanager:), seguido do nome do secret (projects/{PROJECT_ID}/secrets/{SECRET_NAME} ou projects/{PROJECT_ID}/secrets/{SECRET_NAME}/versions/{VERSION}) como valor da variável de ambiente. O secrets-init vai resolver qualquer valor de ambiente, usando o nome especificado, para o valor do secret referenciado.
https://gist.github.com/65d46eb2b1fe44417a9d91828c94712d
Para resolver secrets do Google a partir do Google Secret Manager, o secrets-init precisa rodar com uma IAM role que tenha permissão para acessar os secrets desejados.
Isso pode ser feito atribuindo uma IAM Role a um Pod do Kubernetes com Workload Identity. Também é possível atribuir uma IAM Role à instância GCE onde o container está rodando, mas essa opção é menos segura.
(15/03/2020) Atualização: Kubernetes Admission Webhook
O projeto kube-secrets-init implementa um admission webhook do Kubernetes que injeta um initContainer em qualquer Pod com referências explícitas (variável de ambiente) ou implícitas (Secrets e ConfigMaps do Kubernetes) a secrets na nuvem.
Links úteis
- Kubernetes GKE Workload Identity — post no blog da DoiT
- doitintl/secrets-init — repositório no GitHub
- kube-secrets-init — repositório do admission webhook do Kubernetes no GitHub
Resumo
Espero que este post seja útil. Fico no aguardo de seus comentários e perguntas.
Quer mais conteúdos? Confira nosso blog ou siga o Alexei no Twitter.