Skip to main content

Cómo usar ConfigMaps de Kubernetes de forma segura

Escrito por

Kuria Macharia

feature kubernetes polp

9 de septiembre de 2022

0 minutos de lectura

ConfigMaps es un objeto de API que se usa en Kubernetes para almacenar datos en pares clave-valor. Es, básicamente, un diccionario que contiene ajustes de configuración. Algunos datos que podrías esperar encontrar en un ConfigMap incluyen nombres de host, credenciales públicas, cadenas de conexión y URL.

Un ConfigMap desacopla el código de una aplicación de sus configuraciones, lo que permite modificarlas sin afectar la aplicación. Por ejemplo, te permite establecer distintas configuraciones para los entornos de desarrollo, pruebas y producción.

Sin embargo, es importante tener en cuenta que el uso de ConfigMaps puede plantear desafíos de seguridad, ya que no cifran los datos que contienen. Por eso, debemos entender cuándo conviene usar ConfigMaps y cuándo no son lo suficientemente seguros.

Este artículo explora cómo funcionan los ConfigMaps, cómo usarlos de forma segura y algunos casos en los que debemos recurrir a otras opciones de almacenamiento de datos más seguras.

ConfigMaps en Kubernetes

Antes de ver cómo usar ConfigMaps, exploremos los detalles técnicos de su funcionamiento y el papel que desempeñan en Kubernetes.

Cómo funcionan los ConfigMaps

Los ConfigMaps almacenan pares clave-valor como datos de texto sin formato y datos binarios, a diferencia de otros objetos de Kubernetes que usan campos spec. Los ConfigMaps pueden almacenar datos binarios como cadenas codificadas en base64 y datos de texto sin formato como secuencias de bytes UTF-8.

El clúster puede acceder a los ConfigMaps de las siguientes maneras:

  • Montándolos como un volumen de datos.

  • Mediante el acceso remoto de Pods en el mismo espacio de nombres de Kubernetes.

  • Separándolos de los Pods y permitiendo que otros componentes del clúster de Kubernetes los usen.

Los Pods pueden usar ConfigMaps como archivos de configuración, variables de entorno o argumentos de línea de comandos.

Al trabajar con ConfigMaps, es fundamental tener en cuenta que su tamaño está limitado a 1 MB. Si tenemos conjuntos de datos más grandes, debemos considerar otras opciones de almacenamiento, como bases de datos, montajes de archivos independientes o servicios de archivos.

El papel de los ConfigMaps

El papel más importante de los ConfigMaps es hacer que las aplicaciones sean portátiles al separar el código de la aplicación de los ajustes de configuración. Esta separación permite migrar fácilmente de un entorno de desarrollo a uno de pruebas y, finalmente, a uno de producción.

Veamos un ejemplo de cómo un ConfigMap puede ayudarnos al trabajar con Kubernetes. Para esta demostración, supongamos que estamos desarrollando una aplicación localmente y que pensamos implementarla con proveedores de servicios de Kubernetes administrados.

Para acceder a la base de datos localmente, debemos establecer la variable de entorno DATABASE_HOST en localhost o 127.0.0.1. Al migrar a un entorno de producción, debemos cambiar el valor de esa variable por uno que exponga el componente de la base de datos.

Cómo usar ConfigMaps de forma segura

Antes de empezar, estos son los requisitos previos para crear un ConfigMap en un clúster local de Kubernetes:

En esta demostración, veremos cómo crear un ConfigMap en YAML y montarlo como volumen. Este método nos permite crearlo de la misma manera que creamos un recurso de Kubernetes.

Crea un archivo llamado mongo-config.yaml y agrega el siguiente código:

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

Luego, crea un ConfigMap a partir del archivo anterior con el siguiente comando:

kubectl apply -f mongo-config.yaml

Ahora, veamos cómo consumir el ConfigMap. En esta demostración, usaremos el ConfigMap que creamos anteriormente con variables de entorno. Para consumirlo, agrega una propiedad envFrom al YAML del Pod, como se muestra en el siguiente código:

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

En el fragmento de código anterior, usamos envFrom para acceder a la información del ConfigMap desde un contenedor.

El último paso es asociarlo a los Pods, que creamos ejecutando el siguiente comando:

kubectl exec -it pod-variables-env sh

Esto permite que los contenedores accedan al ConfigMap como una variable de entorno.

Secrets en Kubernetes

A menudo, se presentan los Secrets como alternativas seguras a los ConfigMaps, ya que tienen algunas características en común:

  • Usan pares clave-valor para almacenar datos.

  • Los Pods pueden usar ambos como archivos en un volumen.

  • Se pueden consumir como variables de entorno (aunque no es recomendable).

  • Son tipos de objetos a los que se accede mediante un servidor de API.

  • Ambos tienen un límite de 1 MB, por lo que no son adecuados para grandes volúmenes de datos.

Los Secrets son objetos diseñados para cifrar y almacenar datos confidenciales en Kubernetes. Algunos datos que debemos guardar en Secrets incluyen contraseñas, claves de API, tokens, cadenas de conexión a bases de datos, entre otros. Permiten separar los datos confidenciales del código de la aplicación. Esta separación reduce el riesgo de exposición de datos confidenciales que podrían poner en riesgo el clúster y la aplicación. No debes usar Secrets para almacenar variables de entorno. Como dicen Liz Rice y Michael Hausenblasbokk en su libro Kubernetes Security:

  • las variables de entorno suelen volcarse en los registros cuando se producen fallas o errores

  • kubectl describe pod muestra los valores de las variables de entorno como texto sin formato

  • docker inspect muestra los valores de las variables de entorno como texto sin formato

Hay varios tipos de Secrets para elegir, según el tipo de datos que queramos mantener privados. El tipo más usado es Opaque, que maneja datos arbitrarios definidos por el usuario. Para la autenticación básica, usamos el tipo basic-auth.

De forma predeterminada, los Secrets no se cifran y se almacenan en etcd, el almacenamiento del servidor de API. Cualquier persona con acceso a la API puede acceder a los Secrets y modificarlos. Para limitar el acceso, debes hacer lo siguiente:

  • Habilita el cifrado de los datos de los Secrets en reposo (muchos, si no todos, los proveedores de Kubernetes administrado te ofrecen esta opción al crear el clúster).

  • Habilita y configura reglas de RBAC para limitar la lectura y la edición.

  • Limita quién puede crear Secrets mediante RBAC.

ConfigMaps frente a Secrets

Aunque ConfigMaps y Secrets comparten algunas características, no son iguales y cada uno es más adecuado para ciertos casos de uso, según nuestras necesidades de seguridad.

La principal diferencia entre ConfigMaps y Secrets es la confidencialidad de los datos que contienen. Secrets oculta los datos mediante codificación base64, mientras que los datos de ConfigMaps están en texto sin formato. Ten en cuenta que también podemos almacenar texto sin formato en ConfigMaps como cadenas codificadas en base64.

Otra diferencia es que en Kubernetes hay varios tipos de Secrets. Podemos elegir el tipo de Secret según los datos confidenciales que queramos ocultar.

Cuándo usar ConfigMaps

Los ConfigMaps son muy eficaces para desacoplar los datos de la aplicación del código de configuración. Por ejemplo, supongamos que tenemos un contenedor de aplicación para datos de empleados que se conecta a una base de datos MySQL. Si codificamos directamente la configuración de conexión a la base de datos en el contenedor, habrá confusión al pasar de un entorno de desarrollo a uno de producción, porque no podemos usar la base de datos de desarrollo en producción.

Un ConfigMap facilita el traslado de nuestra aplicación al almacenar los datos de configuración en un archivo independiente, fuera del contenedor. Para cambiar de entorno, solo habría que modificar una referencia a la base de datos.

Puedes mostrar fácilmente los datos de los ConfigMaps ejecutando kubectl describe configmaps <name>. También puedes editarlos con facilidad porque aparecen como texto sin formato. Aunque estas características facilitan cambiar las configuraciones según el entorno (desarrollo, pruebas o producción), los ConfigMaps no son adecuados para manejar datos confidenciales. Los datos confidenciales deben almacenarse en Kubernetes Secrets para poder cifrarlos y limitar el acceso a ellos.

Cuándo usar Secrets

Al igual que los ConfigMaps, los Secrets desacoplan los datos del código de la aplicación. Esto nos permite evitar la exposición de datos confidenciales al crear o modificar Pods.

Ahora volvamos al ejemplo de los datos de empleados. En este caso, la aplicación necesita el host del servidor, el puerto, el nombre de la base de datos, el nombre de usuario y la contraseña para conectarse correctamente a la base de datos.

Comparemos dos fragmentos de código. El primero muestra cómo un ConfigMap maneja los datos y el segundo, cómo lo hace un Secret.

Así se ve un 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

El archivo YAML de configMap anterior contiene los detalles no confidenciales de conexión a la base de datos: el host del servidor, el puerto del servidor y el nombre de la base de datos.

Así se vería un archivo de Secrets:

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

En el archivo YAML de Secret anterior, el tipo de Secret se especifica como basic-auth, que maneja credenciales de autenticación básica. stringData contiene los datos que deben mantenerse privados. En este caso, el nombre de usuario y la contraseña.

En el ejemplo hipotético anterior, Secrets nos ayudó a mantener privados el nombre de usuario y la contraseña de la base de datos. También evita que esta información quede expuesta al crear o modificar el Pod.

Seguridad de la configuración de Kubernetes

Un ConfigMap es un objeto de API de Kubernetes que se usa para almacenar datos de configuración no confidenciales en pares clave-valor. De forma predeterminada, almacena los datos como texto sin formato y permite separar el código de la aplicación de sus configuraciones. Secrets también es un objeto de API de Kubernetes que se usa para cifrar y almacenar datos de configuración confidenciales en pares clave-valor. Sin embargo, reduce el riesgo de exposición de datos confidenciales que podrían poner en riesgo el clúster y la aplicación.

Para crear un clúster de Kubernetes seguro que desacople el código de la aplicación de sus configuraciones, asegúrate de guardar los datos confidenciales en Secrets y las configuraciones no confidenciales en ConfigMaps. También es fundamental habilitar RBAC para restringir el acceso a ConfigMaps y Secrets. Esto reduce el riesgo de que alguien acceda a la configuración sin autorización o la modifique.

Protege la infraestructura desde el origen

Snyk automatiza la seguridad y el cumplimiento de IaC en los flujos de trabajo, y detecta recursos con desviaciones de configuración y recursos faltantes.