Cloud Intelligence™Cloud Intelligence™

Cloud Intelligence™

Kubernetes e gerenciamento de secrets na nuvem

By Alexei LedenevDec 26, 20195 min read

Esta página também está disponível em English, Deutsch, Español, Français, Italiano e 日本語.

1 yhminsd3pkjvkscqdxvpgq

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:

https://gist.github.com/09d76dd562fb9c5bb6fbaefd9afe377ehttps://gist.github.com/f0de7aa6fa86e29f25a06d78dfeeae5e

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

Provedores KMS:

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

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.