Suscríbete para recibir notificaciones de nuevas publicaciones:

Kubectl con Cloudflare Zero Trust

2022-06-24

3 min de lectura
Esta publicación también está disponible en English, 日本語, 한국어 y 简体中文.

Cloudflare utiliza con regularidad Kubernetes para las cargas de trabajo de ingeniería. Lo usa para activar el backend de nuestras API y para gestionar el procesamiento por lotes, como la agregación de análisis y la detección de bots, así como para las herramientas de ingeniería, como nuestros canales CI/CD. Sin embargo, entre los equilibradores de carga, los servidores de la API, etcd, los ingresos y los pods, la superficie que expone Kubernetes puede ser bastante grande.

Kubectl with Cloudflare Zero Trust

En esta publicación, comentaremos cómo nuestro equipo de ingeniería prueba primero Cloudflare Zero Trust a nivel interno para proteger Kubernetes, y activa kubectl sin proxies.

Nuestro enfoque general para la seguridad de Kubernetes

Como parte de nuestras medidas de seguridad, limitamos considerablemente lo que puede acceder a nuestros clústeres a través de la red. Cuando se expone un servicio de red, añadimos protecciones adicionales, como exigir la autenticación de Cloudflare Access o TLS mutuo (o ambos) para acceder a los recursos de ingreso.

Estas restricciones de red incluyen el acceso al servidor de la API del clúster. Sin este acceso, los ingenieros de Cloudflare no podrían utilizar herramientas como kubectl para examinar los recursos de su equipo. Aunque creemos que las Implementaciones continuas y GitOps son buenas prácticas, permitir que los desarrolladores usen la API de Kubernetes ayuda en la solución de problemas y a aumentar la velocidad de los desarrolladores. No tener acceso hubiera sido un problema.

Usamos Cloudflare Zero Trust para satisfacer nuestros requisitos de seguridad, y queríamos contar cómo lo estamos utilizando, y el proceso que nos ha llevado hasta aquí.

Antes de Zero Trust

En el entorno anterior a Zero Trust, los ingenieros podían acceder a la API de Kubernetes conectándose a un dispositivo VPN. Aunque es algo habitual en el sector, y permite el acceso a la API, también dejaba a los ingenieros como clientes en la red interna: tenían mucho más acceso a la red del necesario.

No nos gustaba esta situación, pero ese fue el statu quo durante varios años. A principios de 2020 retiramos nuestra VPN, y entonces el equipo de Kubernetes tuvo que encontrar otra solución.

Kubernetes con Cloudflare Tunnels

En ese momento trabajamos estrechamente con el equipo que desarrolla Cloudflare Tunnels para que fuera posible gestionar las conexiones kubectl utilizando Access y los túneles cloudflared.

Aunque esto funcionaba para nuestros usuarios de ingeniería, era un obstáculo importante para la incorporación de nuevos empleados. Cada clúster de Kubernetes necesitaba su propia conexión de túnel desde el dispositivo del ingeniero, lo que hacía que el cambio entre clústeres fuera incómodo. Aunque kubectl permitía la conexión mediante proxies SOCKS, esta compatibilidad no era válida para todas las herramientas del ecosistema Kubernetes.

Seguimos usando esta solución a nivel interno mientras buscábamos una solución mejor.

Kubernetes con Zero Trust

Desde el lanzamiento de Cloudflare One, hemos estado probando primero a nivel interno el agente Zero Trust en distintas configuraciones. Al principio, lo habíamos utilizado para implementar un DNS seguro con 1.1.1.1. Con el paso del tiempo, empezamos a utilizarlo para probar primero a nivel interno funciones adicionales de Zero Trust.

Ahora estamos aprovechando el enrutamiento de la red privada en Cloudflare Zero Trust para permitir que los ingenieros accedan a las API de Kubernetes sin que haya que configurar túneles cloudflared, o configurar kubectl y otras herramientas del ecosistema Kubernetes para usar túneles. Esto no es algo específico de Cloudflare, ¡puedes hacerlo hoy mismo para tu equipo!

Configurar Zero Trust

Para habilitar la infraestructura como código, utilizamos una herramienta de gestión de la configuración para nuestra configuración Zero Trust, que hemos adaptado a continuación. Sin embargo, es posible conseguir la misma configuración mediante el panel de control de Cloudflare Zero Trust.

Lo primero que tenemos que hacer es crear un nuevo túnel. Se usará este túnel para conectar la red perimetral de Cloudflare a la API de Kubernetes. Ejecutamos los puntos de conexión del túnel en Kubernetes, utilizando la configuración que mostramos más adelante en esta publicación.

El secreto "tunnel_secret" debe ser un número aleatorio de 32 bytes, que debes guardar de forma temporal, ya que lo volveremos a usar más tarde para la configuración de Kubernetes.

resource "cloudflare_argo_tunnel" "k8s_zero_trust_tunnel" {
  account_id = var.account_id
  name       = "k8s_zero_trust_tunnel"
  secret     = var.tunnel_secret
}

Después de haber creado el túnel, tenemos que crear las rutas para que la red de Cloudflare sepa qué tráfico debe enviar por el túnel.

Ofrecemos compatibilidad con el acceso a la API de Kubernetes mediante direcciones IPv4 e IPv6, así que configuramos rutas para ambas. Si te conectas a tu servidor de la API mediante un nombre de host, estas direcciones IP deben coincidir con lo que se devuelve a través de una búsqueda de DNS.

resource "cloudflare_tunnel_route" "k8s_zero_trust_tunnel_ipv4" {
  account_id = var.account_id
  tunnel_id  = cloudflare_argo_tunnel.k8s_zero_trust_tunnel.id
  network    = "198.51.100.101/32"
  comment    = "Kubernetes API Server (IPv4)"
}
 
resource "cloudflare_tunnel_route" "k8s_zero_trust_tunnel_ipv6" {
  account_id = var.account_id
  tunnel_id  = cloudflare_argo_tunnel.k8s_zero_trust_tunnel.id
  network    = "2001:DB8::101/128"
  comment    = "Kubernetes API Server (IPv6)"
}

A continuación, configuraremos los parámetros de Cloudflare Gateway para que sea compatible con los servidores y clientes de la API.

Como utilizamos TLS mutuo entre los clientes y el servidor de la API, y no todo el tráfico entre kubectl y los servidores de la API es HTTP, hemos desactivado la inspección de HTTP para estas conexiones.

resource "cloudflare_teams_list" "k8s_apiserver_ips" {
  account_id = var.account_id
  name       = "Kubernetes API IPs"
  type       = "IP"
  items      = ["198.51.100.101/32", "2001:DB8::101/128"]
}
 
resource "cloudflare_teams_rule" "k8s_apiserver_zero_trust_http" {
  account_id  = var.account_id
  name        = "Don't inspect Kubernetes API"
  description = "Allow connections from kubectl to API"
  precedence  = 10000
  action      = "off"
  enabled     = true
  filters     = ["http"]
  traffic     = format("any(http.conn.dst_ip[*] in $%s)", replace(cloudflare_teams_list.k8s_apiserver_ips.id, "-", ""))
}

Para personalizar aún más tu seguridad, puedes emparejar estas reglas con otras de Zero Trust, como confirmación de dispositivos, duración de la sesión y políticas de acceso de usuarios y grupos.

Implementar túneles

Una vez que hayas creado y configurado tus túneles, puedes implementar sus puntos de conexión en tu red. Hemos optado por implementar los túneles como pods, ya que esto nos permite utilizar las estrategias de implementación de Kubernetes para desplegar las actualizaciones y gestionar los fallos de nodos.

Esto crea un ConfigMap de Kubernetes con una configuración básica, que permite el enrutamiento WARP para el ID del túnel especificado. Puedes obtener este ID de túnel desde tu sistema de gestión de configuración, desde el panel de control de Cloudflare Zero Trust, o ejecutando el siguiente comando desde otro dispositivo conectado a la misma cuenta.

apiVersion: v1
kind: ConfigMap
metadata:
  name: tunnel-zt
  namespace: example
  labels:
    tunnel: api-zt
data:
  config.yaml: |
    tunnel: 8e343b13-a087-48ea-825f-9783931ff2a5
    credentials-file: /opt/zt/creds/creds.json
    metrics: 0.0.0.0:8081
    warp-routing:
        enabled: true

cloudflared tunnel list

A continuación, tendremos que crear un secreto para nuestras credenciales del túnel. Aunque deberías utilizar un sistema de gestión de secretos, para simplificar crearemos uno directamente aquí.

Esto crea un nuevo secreto "tunnel-creds" en el espacio de nombres "example" con el archivo de credenciales que espera el túnel.

jq -cn --arg accountTag $CF_ACCOUNT_TAG \
       --arg tunnelID $CF_TUNNEL_ID \
       --arg tunnelName $CF_TUNNEL_NAME \
       --arg tunnelSecret $CF_TUNNEL_SECRET \
   '{AccountTag: $accountTag, TunnelID: $tunnelID, TunnelName: $tunnelName, TunnelSecret: $tunnelSecret}' | \
kubectl create secret generic -n example tunnel-creds --from-file=creds.json=/dev/stdin

Ahora podemos implementar los túneles. Implementamos varias réplicas para garantizar que algunas estén siempre disponibles, incluso mientras se vacían los nodos.

Uso de Kubectl con Cloudflare Zero Trust

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    tunnel: api-zt
  name: tunnel-api-zt
  namespace: example
spec:
  replicas: 3
  selector:
    matchLabels:
      tunnel: api-zt
  strategy:
    rollingUpdate:
      maxSurge: 0
      maxUnavailable: 1
  template:
    metadata:
      labels:
        tunnel: api-zt
    spec:
      containers:
        - args:
            - tunnel
            - --config
            - /opt/zt/config/config.yaml
            - run
          env:
            - name: GOMAXPROCS
              value: "2"
            - name: TZ
              value: UTC
          image: cloudflare/cloudflared:2022.5.3
          livenessProbe:
            failureThreshold: 1
            httpGet:
              path: /ready
              port: 8081
            initialDelaySeconds: 10
            periodSeconds: 10
          name: tunnel
          ports:
            - containerPort: 8081
              name: http-metrics
          resources:
            limits:
              cpu: "1"
              memory: 100Mi
          volumeMounts:
            - mountPath: /opt/zt/config
              name: config
              readOnly: true
            - mountPath: /opt/zt/creds
              name: creds
              readOnly: true
      volumes:
        - secret:
            name: tunnel-creds
          name: creds
        - configMap:
            name: tunnel-api-zt
          name: config

Después de implementar el agente Cloudflare Zero Trust, los miembros de tu equipo podrán acceder a la API de Kubernetes sin tener que configurar ningún túnel SOCKS especial.

Screenshot of the Cloudflare WARP app showing it connected to Teams

¿Y ahora qué?

kubectl version --short
Client Version: v1.24.1
Server Version: v1.24.1

Si lo pruebas, envíanos tus comentarios. Seguimos mejorando Zero Trust para los flujos de trabajo que no usen HTTP.

Protegemos redes corporativas completas, ayudamos a los clientes a desarrollar aplicaciones web de forma eficiente, aceleramos cualquier sitio o aplicación web, prevenimos contra los ataques DDoS, mantenemos a raya a los hackers, y podemos ayudarte en tu recorrido hacia la seguridad Zero Trust.

Visita 1.1.1.1 desde cualquier dispositivo para empezar a usar nuestra aplicación gratuita y beneficiarte de una navegación más rápida y segura.

Para saber más sobre nuestra misión para ayudar a mejorar Internet, empieza aquí. Si estás buscando un nuevo rumbo profesional, consulta nuestras ofertas de empleo.
Cloudflare One WeekSeguridadZero TrustKubernetes

Síguenos en X

Terin Stock|@terinjokes
Cloudflare|@cloudflare

Publicaciones relacionadas

23 de octubre de 2024, 13:00

Fearless SSH: short-lived certificates bring Zero Trust to infrastructure

Access for Infrastructure, BastionZero’s integration into Cloudflare One, will enable organizations to apply Zero Trust controls to their servers, databases, Kubernetes clusters, and more. Today we’re announcing short-lived SSH access as the first available feature of this integration. ...

08 de octubre de 2024, 13:00

Cloudflare acquires Kivera to add simple, preventive cloud security to Cloudflare One

The acquisition and integration of Kivera broadens the scope of Cloudflare’s SASE platform beyond just apps, incorporating increased cloud security through proactive configuration management of cloud services. ...