Skip to main content

Como usar ConfigMaps com segurança

Escrito por

Kuria Macharia

feature kubernetes polp

9 de setembro de 2022

0 minutos de leitura

ConfigMaps é um objeto de API usado no Kubernetes para armazenar dados em pares de chave e valor. Na prática, é um dicionário com configurações. Alguns exemplos de informações que você pode encontrar em um ConfigMap são nomes de host, credenciais públicas, strings de conexão e URLs.

Um ConfigMap desvincula o código de um aplicativo das configurações, permitindo alterá-las sem afetar o aplicativo. Por exemplo, você pode definir configurações diferentes para os ambientes de desenvolvimento, teste e produção.

No entanto, é importante lembrar que o uso de ConfigMaps pode trazer desafios de segurança, pois eles não criptografam os dados armazenados. Por isso, precisamos entender quando é melhor usar ConfigMaps e quando eles não oferecem segurança suficiente.

Este artigo explica como os ConfigMaps funcionam, como usá-los com segurança e em quais casos devemos recorrer a outras opções de armazenamento de dados mais seguras.

ConfigMaps no Kubernetes

Antes de ver como usar ConfigMaps, vamos explorar os detalhes técnicos do seu funcionamento e o papel que desempenham no Kubernetes.

Como os ConfigMaps funcionam

Os ConfigMaps armazenam pares de chave e valor como dados de texto simples ou binários, diferentemente de outros objetos do Kubernetes que usam campos spec. Eles podem armazenar dados binários como strings codificadas em base64 e dados de texto simples como sequências de bytes UTF-8.

O cluster pode acessar ConfigMaps das seguintes maneiras:

  • Montando-os como um volume de dados.

  • Acessando-os remotamente por Pods no mesmo namespace do Kubernetes.

  • Mantendo-os separados dos Pods para que outros componentes do cluster Kubernetes possam usá-los.

Os Pods podem usar ConfigMaps como arquivos de configuração, variáveis de ambiente ou argumentos de linha de comando.

Ao trabalhar com ConfigMaps, é essencial considerar seu tamanho limitado: 1 MB. Se tivermos conjuntos de dados maiores, devemos considerar outras opções de armazenamento, como bancos de dados, montagens de arquivos separadas ou serviços de arquivos.

O papel dos ConfigMaps

O papel mais importante dos ConfigMaps é tornar os aplicativos portáteis, separando o código do aplicativo das configurações. Essa separação facilita a migração do ambiente de desenvolvimento para o ambiente de teste e, por fim, para o de produção.

Vamos ver um exemplo de como um ConfigMap pode ajudar no trabalho com Kubernetes. Para esta demonstração, imagine que estamos desenvolvendo um aplicativo localmente e pretendemos implantá-lo com provedores de serviços gerenciados do Kubernetes.

Para acessar o banco de dados localmente, precisamos definir a variável de ambiente DATABASE_HOST como localhost ou 127.0.0.1. Ao migrar para um ambiente de produção, precisamos alterar o valor dessa variável para um que exponha o componente do banco de dados.

Como usar ConfigMaps com segurança

Antes de começar, veja os pré-requisitos para criar um ConfigMap em um cluster Kubernetes local:

Nesta demonstração, vamos criar um ConfigMap em YAML e montá-lo como um volume. Esse método permite criá-lo da mesma forma que criamos um recurso do Kubernetes.

Crie um arquivo chamado mongo-config.yaml e adicione o código a seguir:

kind: ConfigMap
apiVersion: v1
metadata:
  name: test-configmap
data:
  # Setting the configuration as key-value properties
  database: mongodb
  database_uri: mongodb://localhost:8080
keys: |
  image.public.key=554
  rsa.public.key=36

Em seguida, crie um ConfigMap a partir do arquivo acima usando o comando a seguir:

kubectl apply -f mongo-config.yaml

Agora, vamos ver como usar o ConfigMap. Nesta demonstração, usaremos o ConfigMap criado acima com variáveis de ambiente. Para usar o ConfigMap, adicione uma propriedade envFrom ao YAML do Pod, como mostra o código a seguir:

kind: Pod
apiVersion: v1
metadata:
  name: pod-variables-env
spec:
  containers:
    - name: configmap-var
      image: nginx:1.7.9
      envFrom:
        - configMapRef:
          name: test-configmap

No trecho de código acima, usamos envFrom para acessar as informações do ConfigMap a partir de um contêiner.

A última etapa é anexá-lo aos Pods, que criamos executando o comando a seguir:

kubectl exec -it pod-variables-env sh

Isso disponibiliza o ConfigMap para os contêineres como uma variável de ambiente.

Secrets no Kubernetes

Os Secrets costumam ser apresentados como alternativas seguras aos ConfigMaps, pois têm alguns pontos em comum:

  • Usam pares de chave e valor para armazenar dados.

  • Os Pods podem usar ambos como arquivos em um volume.

  • Eles podem ser usados como variáveis de ambiente (embora isso não seja recomendado).

  • São tipos de objeto acessados por meio de um servidor de API.

  • Ambos têm um limite de 1 MB e, portanto, não são adequados para grandes volumes de dados.

Secrets são objetos projetados para criptografar e armazenar dados confidenciais no Kubernetes. Alguns dados que devemos armazenar em Secrets incluem senhas, chaves de API, tokens, strings de conexão com bancos de dados e outros. Eles permitem separar os dados confidenciais do código do aplicativo. Essa separação reduz o risco de exposição de dados confidenciais que podem colocar o cluster e o aplicativo em risco. Uma coisa para a qual você não deve usar Secrets são variáveis de ambiente. Como dizem Liz Rice e Michael Hausenblasbokk no livro Kubernetes Security:

  • variáveis de ambiente costumam ser registradas em logs em caso de falhas/erros

  • kubectl describe pod exibe os valores das variáveis de ambiente em texto simples

  • docker inspect exibe os valores das variáveis de ambiente em texto simples

Há vários tipos de Secrets disponíveis, dependendo do tipo de dado que queremos manter privado. O tipo mais usado é Opaque, que permite armazenar dados arbitrários definidos pelo usuário. Para autenticação básica, usamos o tipo basic-auth.

Por padrão, os Secrets não são criptografados e ficam armazenados no etcd, o armazenamento do servidor de API. Qualquer pessoa com acesso à API pode acessar e alterar secrets. Para limitar esse acesso, é preciso:

  • Ativar a criptografia dos dados dos secrets em repouso (muitos, se não todos, os provedores gerenciados de Kubernetes oferecem essa opção durante a criação do cluster).

  • Ativar e configurar regras de RBAC para limitar a leitura e a edição.

  • Limitar, com RBAC, quem pode criar Secrets.

ConfigMaps e Secrets

Embora ConfigMaps e Secrets tenham semelhanças, eles não são iguais — e cada um atende melhor a determinados casos de uso, definidos pelas nossas necessidades de segurança.

A principal diferença entre ConfigMaps e Secrets é a confidencialidade dos dados que contêm. Secrets ofuscam os dados usando codificação base64, enquanto os dados nos ConfigMaps ficam em texto simples. Vale lembrar que também podemos armazenar texto simples em ConfigMaps como strings codificadas em base64.

Outra diferença é que há vários tipos de Secrets no Kubernetes. Podemos escolher o tipo de Secret com base nos dados confidenciais que queremos proteger.

Quando usar ConfigMaps

ConfigMaps são muito eficazes para separar os dados do aplicativo do código de configuração. Por exemplo, imagine que temos um contêiner de aplicativo com dados de funcionários, conectado a um banco de dados MySQL. Se codificarmos diretamente no contêiner a configuração da conexão com o banco de dados, a migração do ambiente de desenvolvimento para o de produção ficará complicada. Isso porque não podemos usar o banco de dados de desenvolvimento em produção.

Um ConfigMap facilita a migração do aplicativo ao armazenar os dados de configuração em um arquivo separado, fora do contêiner. Para mudar de ambiente, basta alterar a referência ao banco de dados.

Você pode exibir facilmente os dados contidos nos ConfigMaps executando kubectl describe configmaps <name>. Também é fácil editar esses dados, pois eles aparecem em texto simples. Embora isso facilite a alteração das configurações conforme o ambiente (desenvolvimento, teste ou produção), ConfigMaps não são adequados para lidar com dados confidenciais. Dados confidenciais devem ser armazenados em Kubernetes Secrets para que possam ser criptografados e ter o acesso limitado.

Quando usar Secrets

Assim como os ConfigMaps, os Secrets separam os dados do código do aplicativo. Isso ajuda a impedir a exposição de dados confidenciais durante a criação ou modificação de Pods.

Agora, vamos voltar ao exemplo dos dados de funcionários. Nesse caso, o aplicativo precisa do host do servidor, da porta, do nome do banco de dados, do nome de usuário e da senha para se conectar ao banco de dados.

Vamos comparar dois trechos de código. O primeiro mostra como um ConfigMap lida com os dados; o segundo, como um Secret faz isso.

Veja como fica um ConfigMap:

db-configmap.yaml

apiVersion: v1
kind: ConfigMap
# ConfigMap data
metadata:
  name: employee-database-conf
  namespace: default
# Database configurations
data:
  server.host: "10.07.11.653"
  server.port: "3030"
  db.name: employees_data

O arquivo YAML do ConfigMap acima contém os detalhes não confidenciais da conexão com o banco de dados: host do servidor, porta do servidor e nome do banco de dados.

Veja como ficaria um arquivo de Secret:

db-secret.yaml

apiVersion: v1
kind: Secret
# Secret Data
metadata:
  name: employee-database-auth
  namespace: default
# The type of Secret 
type: kubernetes.io/basic-auth
# Secret data
stringData:
  username: dGhlYWRtaW4= //theadmin
  password: YWRtaW5wYXNz //adminpass

No arquivo YAML do Secret acima, o tipo é especificado como basic-auth, que lida com credenciais de autenticação básica. O stringData contém os dados que devem ser mantidos privados. Neste caso, o nome de usuário e a senha.

No exemplo hipotético acima, os Secrets nos ajudaram a manter privados o nome de usuário e a senha do banco de dados. Também garantem que essas informações não sejam expostas durante a criação ou modificação do Pod.

Segurança de configurações no Kubernetes

Um ConfigMap é um objeto de API no Kubernetes usado para armazenar dados de configuração não confidenciais em pares de chave e valor. Por padrão, ele armazena dados em texto simples e permite separar o código do aplicativo das configurações. Secrets também são objetos de API do Kubernetes, usados para criptografar e armazenar dados de configuração confidenciais em pares de chave e valor. No entanto, eles reduzem o risco de exposição de dados confidenciais que podem colocar o cluster e o aplicativo em risco.

Para criar um cluster Kubernetes seguro que mantenha o código do aplicativo separado das configurações, armazene os dados confidenciais em Secrets e as configurações não confidenciais em ConfigMaps. Também é fundamental ativar o RBAC para restringir o acesso aos ConfigMaps e Secrets. Isso reduz o risco de acesso ou alteração não autorizados das configuraçõ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.