Cómo acceder a secretos de Vault dentro de Kubernetes mediante el operador de secretos externos (ESO)

El autor seleccionó el Fondo de Diversidad en Tecnología para recibir una donación como parte del programa Write for DOnations .

En Kubernetes, puedes usar secretos en pods para evitar mantener cadenas de conexión y otros datos confidenciales en el control de origen o para evitar que tu aplicación acceda a datos confidenciales directamente. Almacenar secretos en un almacén de secretos como HashiCorp Vault es una forma segura de permitir el acceso a las herramientas necesarias. Los almacenes de secretos suelen proporcionar funciones como API HTTP para interactuar con ellos de forma segura. Las herramientas como Vault también suelen proporcionar formas de integración con Kubernetes, como mediante el uso de sidecars . Sin embargo, una desventaja de este enfoque y otras formas en que estas herramientas se integran con Kubernetes es que suelen ser específicas de la aplicación y crean un acoplamiento estrecho con la herramienta, lo que es posible que desees evitar para poder cambiar fácilmente el proveedor de secretos si es necesario.

External Secrets Operator (ESO) es un operador de Kubernetes que agrega varias definiciones de recursos personalizados (CRD) y le permite consumir el recurso de secretos nativos de Kubernetes. Para ello, crea secretos de Kubernetes y los mantiene sincronizados con un secreto específico ubicado en un proveedor de secretos, ya sea HashiCorp Vault, AWS Secrets Manager, GCP Secrets Manager o cualquier otro proveedor compatible. El principal beneficio de este sistema es que, al hacer referencia a secretos nativos de Kubernetes, cualquier servicio que consuma secretos en Kubernetes se desvincula de estas herramientas. Esta separación le permite cambiar más fácilmente el proveedor de respaldo sin necesidad de cambiar nada más.

En este tutorial, instalará el operador de secretos externos en un clúster de Kubernetes administrado por DigitalOcean y configurará un SecretStorey un ExternalSecretspara obtener valores de una instancia de HashiCorp Vault.

Al final, tendrás una configuración funcional en la que podrás obtener secretos de cualquier proveedor compatible con el operador de secretos externos para usarlos dentro de un clúster de Kubernetes.

Al igual que con cualquier servicio que administre información confidencial, debe considerar leer documentación adicional sobre las mejores prácticas de implementación de Vault antes de usarlo en un entorno similar al de producción. Por ejemplo, la guía de fortalecimiento de la producción de Vault cubre temas como políticas, tokens raíz y auditoría.

Si está buscando un servicio de alojamiento de Kubernetes administrado, consulte nuestro servicio de Kubernetes simple y administrado diseñado para el crecimiento .

Prerrequisitos

Para completar este tutorial, necesitarás:

  • Una cuenta de DigitalOcean. Si no tiene una, regístrese para obtener una nueva cuenta .

  • Un clúster de Kubernetes configurado con el panel de control de DigitalOcean. Para comenzar, consulte la guía de Kubernetes de DigitalOcean para crear clústeres .

    • Otros métodos para configurar clústeres, como el tutorial Cómo crear un clúster de Kubernetes usando Kubeadm en Ubuntu 20.04 , también funcionan, pero este tutorial utiliza el método del Panel de control.
  • Doctl instalado, lo cual puedes hacer siguiendo nuestra guía sobre Cómo instalar y configurar doctl .

  • La kubectlherramienta de línea de comandos instalada en su máquina local y configurada para conectarse a su clúster. Puede leer más sobre la instalación kubectl en la documentación oficial .

  • Helm instalado. Para la instalación, consulte el paso 1 de nuestro tutorial, Cómo instalar software en clústeres de Kubernetes con el administrador de paquetes Helm 3 .

  • Vault instalado en su equipo, con un secreto que haya creado. Para instalar Vault y crear un secreto de forma segura, siga nuestro tutorial Cómo administrar secretos de forma segura con HashiCorp Vault en Ubuntu 20.04 . Guarde los tokens de acceso creados en este tutorial para usarlos en un paso posterior.

    • Puede utilizar cualquier otro proveedor compatible con el operador de secretos externos, pero en este tutorial se utilizará HashiCorp Vault. Puede encontrar una lista de proveedores en la documentación del producto Vault .

Paso 1: Instalación del operador de secretos externos (ESO)

En este paso, instalará el operador External Secrets a través de Helm en su clúster de Kubernetes. Dado que usará Helm para instalar el operador External Secrets, deberá asegurarse de que su contexto de Kubernetes esté configurado correctamente.

Para configurarlo, comience descargando el archivo Kubeconfig desde el Panel de control de DigitalOcean Cloud de su clúster de Kubernetes. En la pestaña Descripción general , busque la sección Configuración y seleccione el botón Descargar archivo de configuración . El archivo se llama clustername-kubeconfig.yaml. Puede colocar este archivo en cualquier lugar, pero la ubicación sugerida es la ~/.kubecarpeta. Luego, configure su variable de entorno KUBECONFIGigual a la ruta del archivo mediante uno de los siguientes comandos.

En Linux o Mac, puedes ejecutar el comando:

  1. export KUBECONFIG=/home/sammy/.kube/clustername-kubeconfig.yaml

En Windows desde Powershell, puedes usar el comando:

  1. $env:KUBECONFIG = "C:Userssammy.kubeclustername-kubeconfig.yaml"

A continuación, confirme su contexto actual ejecutando el siguiente comando:

  1. kubectl config current-context

El resultado será similar al siguiente:

Producción

my-k8s-cluster

Una vez configurado el contexto actual, puedes agregar el external-secretsrepositorio a Helm:

  1. helm repo add external-secrets https://charts.external-secrets.io

El resultado será similar al siguiente:

Producción

"external-secrets" has been added to your repositories

A continuación, asegúrese de tener el repositorio más actualizado:

  1. helm repo update

El resultado será similar al siguiente:

Producción

...Successfully got an update from the "external-secrets" chart repository

Una vez que se haya agregado el repositorio, puede usar Helm para instalar lo external-secrets repositoryque agregó:

  1. helm install external-secrets
  2. external-secrets/external-secrets
  3. -n external-secrets
  4. --create-namespace
  5. --set installCRDs=true

Con la -n external-secretsopción , se especifica que se external-secrets repositorydebe instalar en el external-secretsespacio de nombres. Con --create-namespace, se creará el espacio de nombres si no existe. Por último, se configura --set installCRDSpara trueasegurarse de que las definiciones de recursos personalizados para el operador de secretos externos se instalen con él.

El resultado será similar al siguiente:

Producción

NAME: external-secretsLAST DEPLOYED: {Date goes here}NAMESPACE: external-secretsSTATUS: deployedREVISION: 1TEST SUITE: NoneNOTES:external-secrets has been deployed successfully!In order to begin using ExternalSecrets, you will need to set up a SecretStoreor ClusterSecretStore resource (for example, by creating a 'vault' SecretStore).More information on the different types of SecretStores and how to configure themcan be found in our Github: https://github.com/external-secrets/external-secrets

En este paso, instalaste el operador External Secrets a través de Helm en tu clúster de Kubernetes, lo que te permitirá crear un SecretStorey un ExternalSecret. En el siguiente paso, crearás un SecretStore.

Paso 2: creación de una tienda secreta

En este paso, creará un SecretStore, que es lo que el operador de secretos externos utiliza para almacenar información sobre cómo comunicarse con el proveedor de secretos determinado. Pero antes de trabajar con el operador de secretos externos, deberá agregar su token de Vault dentro de Kubernetes para que el operador de secretos externos pueda comunicarse con el proveedor de secretos.

Como parte de los requisitos previos, es posible que haya seguido el tutorial Cómo administrar secretos de forma segura con HashiCorp Vault en Ubuntu 20.04 , que generó un token de Vault para usar en la autenticación. En este paso, puede usar el token raíz que obtuvo al abrir su Vault (no se recomienda para producción) o el token del Paso 5 de ese tutorial, que trata sobre la creación de una Política de autorización en Vault.

Advertencia: Para los fines de este tutorial, puede utilizar el token proporcionado al inicializar Vault, pero no se recomienda para producción. La mejor práctica es configurar algo más seguro para el uso real con el operador de secretos externos. Puede leer sobre los diferentes métodos de autenticación que se admiten en la documentación del producto Vault .

Colocarás este token dentro de Kubernetes como un secreto para que External Secrets Operator pueda usarlo para comunicarse con Vault. Puedes hacerlo ejecutando el siguiente comando y reemplazando la parte resaltada con tu token de Vault:

  1. kubectl create secret generic vault-token --from-literal=token=YOUR_VAULT_TOKEN

El resultado será similar al siguiente:

Producción

secret/vault-token created

Puede verificar esto ejecutando el siguiente comando, que obtiene todos los secretos en el defaultespacio de nombres (que es donde estará el suyo a menos que haya agregado un espacio de nombres al comando anterior):

  1. kubectl get secrets

El resultado será algo como lo siguiente:

NAME                  TYPE                                  DATA      AGEvault-token           Opaque                                1         2m

Una vez creado este secreto, puede comenzar a trabajar con el operador de secretos externos. El primer paso es configurar un SecretStore, que contiene la información para comunicarse con un proveedor de secretos e identifica qué proveedor utilizar. Cualquier secreto externo en el mismo espacio de nombres puede acceder a los almacenes de secretos, por lo que debe asegurarse de segmentar sus espacios de nombres según sea necesario. En este tutorial, colocará todo en el defaultespacio de nombres, pero esto no se recomienda para un clúster de producción.

Con nanosu editor de texto favorito, cree un secret-store.yamlarchivo y pegue en él el siguiente contenido. Asegúrese de completar los datos específicos de su configuración, como el servercampo que es el punto final desde el que se puede acceder a su servidor Vault:

tienda secreta.yaml

apiVersion: external-secrets.io/v1beta1kind: SecretStoremetadata:  name: vault-backendspec:  provider:    vault:      server: "https://your-domain:8200"      path: "kv"      version: "v1"      auth:        tokenSecretRef:          name: "vault-token"          key: "token"

En el providercampo, especifica vaultel proveedor y dónde acceder a él mediante el servercampo. También especifica la ruta kv, que es la ruta raíz donde se encuentran tus secretos. Si seguiste el tutorial de requisitos previos de Vault pero le asignaste SecretStoreun nombre distinto a kv, asegúrate de cambiar ese campo en consecuencia.

v1La versión del motor KV debe estar habilitada de forma predeterminada. Si cambió la versión del kvmotor en Vault al habilitarlo, también puede especificar la versión como v2.

El campo final es la authsección donde especifica el secreto que creó anteriormente proporcionando el nombre del secreto y la clave dentro del secreto en la que se encuentra el token. Para obtener más información sobre otros métodos de autenticación para Vault, consulte la documentación del producto .

Si está interesado en obtener más información sobre otras opciones de configuración disponibles para SecretStores, puede encontrar la especificación CRD en la documentación del producto External Secrets , que contiene todos los campos que se pueden proporcionar y algunos otros campos agregados por Kubernetes que se pueden obtener después de que se agregan.

Guarde y cierre el archivo.

Crea el archivo SecretStoreejecutando el siguiente comando:

  1. kubectl apply -f ./secret-store.yaml

Este comando aplica este CRD a su clúster y crea el objeto. Puede ver el objeto ejecutando el siguiente comando, que le mostrará toda la información sobre el objeto dentro de Kubernetes:

  1. kubectl get SecretStore vault-backend -o yaml

El resultado será similar al siguiente:

Producción

apiVersion: external-secrets.io/v1alpha1kind: SecretStoremetadata:  annotations:    # Some kubernetes annotations  creationTimestamp: # Timestamp of the creation time  generation: 1  name: vault-backend  namespace: default  resourceVersion: "12345"  uid: # a UID for the resourcespec:  provider:    vault:      auth:        tokenSecretRef:          key: token          name: vault-token          namespace: default      path: kv      server: https://your-domain:8200      version: v1status:  conditions:    - type: Ready      status: "False"      reason: "ConfigError"      message: "SecretStore validation failed"      lastTransitionTime: "0000-00-00T00:00:00Z"

Si creó el SecretStorecorrectamente, no verá el statuscampo, pero si ve un type: Readyy un status: "False", entonces los campos reasony messagele brindarán más información sobre lo que está mal. Un problema muy común es could not create client. Esto generalmente significa que el método de autenticación para su cliente ha fallado, ya que SecretStoreintentará crear un cliente para su proveedor para verificar que todo esté funcionando. Con el método de autenticación de token para este tutorial, asegúrese de verificar que su SecretStorerecurso tenga el espacio de nombres correcto para su secreto y que el nombre y la clave coincidan exactamente con lo que creó.

Solución de problemas

Según cómo se haya configurado Vault, es posible que encuentres algunos errores al crear un archivo SecretStore. Uno de los más comunes es message: unable to validate store. Esto puede deberse a varias cosas, pero hay algunas cosas que puedes verificar, especialmente si usaste el tutorial de requisitos previos para instalar Vault y crear un secreto de forma segura.

Primero, le indicará a Vault que escuche todas las solicitudes entrantes para que pueda acceder a él de forma remota modificando el archivo de configuración de Vault. Si siguió el tutorial de requisitos previos de Vault, deberá modificar el /etc/vault.d/vault.hclarchivo.

Utilizando nanosu editor de texto favorito, abra /etc/vault.d/vault.hclpara editar. Dentro del archivo de configuración en la listener "tcp"sección, verifique la dirección. Si la dirección es 127.0.0.1:8200, cámbiela a 0.0.0.0:8200lo que se muestra a continuación:

/etc/vault.d/vault.hcl

...listener "tcp" {  address       = "0.0.0.0:8200"...}

Este cambio le indica a Vault que escuche conexiones externas para que puedas acceder a él desde el operador de secretos externos. Reinicia Vault (asegúrate de desbloquearlo nuevamente) y ahora debería aceptar conexiones externas.

Un segundo problema podría ser que el firewall bloquee las conexiones en port 8200, lo que se puede solucionar actualizando el firewall:

  1. ufw allow 8200

Advertencia: Esto abrirá Vault a todo el mundo port 8200sin precauciones de seguridad. No se recomienda su uso en producción. Asegúrese de leer sobre el endurecimiento de la producción de Vault para asegurarse de que la instancia de Vault se haya reforzado contra actores maliciosos.

En esta sección, creó un secreto en Kubernetes para almacenar su información sobre cómo autenticarse con su proveedor de secretos. Luego, creó un SecretStorerecurso que le indica al operador de secretos externos cómo comunicarse con su proveedor. En el siguiente paso, creará un archivo ExternalSecret.

Paso 3: creación de un secreto externo

En este paso, creará un ExternalSecret, que es el recurso principal del operador de secretos externos. El ExternalSecretrecurso le indica a ESO que obtenga un secreto específico de un proveedor específico SecretStorey dónde colocar la información. Este recurso es muy importante porque define qué secreto desea obtener del proveedor de secretos externo, dónde colocarlo, qué almacén de secretos usar y con qué frecuencia sincronizar el secreto, entre otras opciones.

Para crear un ExternalSecret, comience creando un archivo llamado external-secret.yamly agregue el siguiente código:

secreto externo.yaml

apiVersion: external-secrets.io/v1alpha1kind: ExternalSecretmetadata:  name: my-cool-secretspec:  refreshInterval: "15s" # How often this secret is synchronized  secretStoreRef:    name: vault-backend    kind: SecretStore  target: # Our target Kubernetes Secret    name: my-cool-new-secret # If not present, then the secretKey field under data will be used    creationPolicy: Owner # This will create the secret if it doesn't exist  data:    - secretKey: my-cool-new-secret-key      remoteRef:        key: message # This is the remote key in the secret provider (might change in meaning based on your provider)        property: value # The property inside of the secret inside your secret provider

Aquí, creas un ExternalSecretque hace referencia a tu secreto SecretStoredel paso anterior. En el targetcampo, le estás indicando al operador de secretos externos la información sobre el secreto de Kubernetes que deseas crear. La datasección es donde se encuentra tu secreto dentro de tu proveedor de secretos (Vault, en este caso) y contiene las siguientes propiedades:

  • secretKey:Esta es la clave dentro del secreto de Kubernetes que desea completar.

  • remoteRef.key:Esta es la clave dentro del proveedor de secretos. Por ejemplo, en Vault, puedes tener secretos ubicados en diferentes rutas. Aquí, puedes usar algo como myfolder/coolsecrets/mysecretcomo valor.

  • remoteRef.property:Esta es la propiedad dentro del secreto en la ruta especificada remoteRef.keyque desea colocar dentro de la clave especificada en secretKey.

El datacampo es una matriz en YAML, por lo que puede especificar varios secretos que le gustaría poner en un solo secreto de Kubernetes. El operador de secretos externos también ofrece cierta lógica de plantilla avanzada que puede usar para crear cosas como cadenas de conexión, sobre las que puede leer más en la sección Plantillas avanzadas de la documentación de producción . También puede leer sobre todos los campos y opciones disponibles ExternalSecretsen los documentos de referencia de secretos externos de la API .

Guarde y cierre su archivo cuando haya terminado.

A continuación, cree este recurso con el siguiente comando:

  1. kubectl apply -f ./external-secret.yaml

Una vez aplicado, puedes asegurarte de que todo esté bien ejecutando el siguiente comando:

  1. kubectl get ExternalSecret my-cool-secret

El resultado será similar al siguiente:

Producción

NAME             STORE           REFRESH INTERVAL   STATUSmy-cool-secret   vault-backend   15s                SecretSynced

La salida confirma la creación exitosa del ExternalSecretrecurso.

Solución de problemas

Si el resultado anterior tiene un Sync Errorvalor inferior STATUS, asegúrese de que su SecretStore esté configurado correctamente. Puede ver el error real ejecutando el siguiente comando:

  1. kubectl get ExternalSecret my-cool-secret -o yaml

El resultado será similar al siguiente, que le brindará más información sobre el error:

Producción

apiVersion: external-secrets.io/v1alpha1kind: ExternalSecretmetadata:  name: my-cool-secretspec:  refreshInterval: "15s"  secretStoreRef:    name: vault-backend    kind: SecretStore  target:    name: my-cool-new-secret    creationPolicy: Owner  data:    - secretKey: my-cool-new-secret-key      remoteRef:        key: test-secret        property: my-coolstatus:  # refreshTime is the time and date the external secret was fetched and  # the target secret updated  refreshTime: "2019-08-12T12:33:02Z"  # Standard condition schema  conditions:    # ExternalSecret ready condition indicates the secret is ready for use.    # This is defined as:    # - The target secret exists    # - The target secret has been refreshed within the last refreshInterval    # - The target secret content is up-to-date based on any target templates    - type: Ready      status: "True" # False if last refresh was not successful      reason: "SecretSynced"      message: "Secret was synced"      lastTransitionTime: "2019-08-12T12:33:02Z"

En esta salida, verás statuscampos y quizás algunas anotaciones adicionales (que puedes ignorar, ya que suelen ser metadatos sobre el recurso). En la statussección, puedes ver información sobre si ExternalSecretse sincronizó correctamente o si algo salió mal.

En este paso, creaste un ExternalSecretrecurso. El recurso ExternalSecret te permite especificar valores en tu proveedor de secretos que deseas recuperar, así como también dónde colocarlos en Kubernetes. Para obtener funciones más avanzadas, puedes consultar la documentación del producto External Secrets .

Conclusión

Ahora que ha configurado correctamente el operador de secretos externos en su clúster de Kubernetes y también ha implementado un SecretStorey ExternalSecret, puede implementar cualquier otro secreto que desee.

External Secrets Operator también tiene muchas otras funciones y recursos personalizados que le permiten configurar su clúster de Kubernetes de la manera que mejor se adapte a sus necesidades. Además, HashiCorp Vault no es el único proveedor y la configuración es similar a la que se describió en este tutorial. Puede obtener más información en la documentación de External Secrets .

Este enfoque de los secretos en Kubernetes es potente y extensible, ya que el operador es de código abierto y le permite utilizar varios proveedores de secretos sin tener que preocuparse por los proveedores específicos en nada que consuma el secreto.

Por último, existen otros recursos para explorar. Uno de ellos es el ClusterExternalSecret, que es nuevo en la versión 0.5.0del operador External Secrets. Este recurso le permite definir un ExternalSecrety luego hacer que el operador cree este ExternalSecreten cada espacio de nombres que coincida con un selector que defina. Puede leer más sobre esta característica en la documentación del producto . Otro recurso es el ClusterSecretStore, que permite que un ExternalSecretdesde cualquier espacio de nombres acceda a él (mientras que un normal SecretStoresolo se puede acceder en el mismo espacio de nombres donde se encuentra).

SUSCRÍBETE A NUESTRO BOLETÍN 
No te pierdas de nuestro contenido ni de ninguna de nuestras guías para que puedas avanzar en los juegos que más te gustan.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Scroll al inicio