Hardening del Clúster
CIS Benchmarks (kube-bench)
El CIS (Center for Internet Security) es una organización reconocida mundialmente que publica guías de mejores prácticas para asegurar sistemas informáticos.
En el ecosistema de Kubernetes, el CIS Kubernetes Benchmark es un documento exhaustivo que detalla cómo configurar de forma segura cada componente del clúster. Se divide en varias secciones, evaluando principalmente:
-
Control Plane (Master): Configuración segura del
kube-apiserver,kube-controller-manager,kube-scheduleryetcd. -
Worker Nodes: Configuración segura del
kubelety el motor de contenedores. -
Políticas y RBAC: Uso de roles, service accounts y políticas de red.
¿Qué es kube-bench?
Leer el documento PDF del CIS de cientos de páginas y revisar cada flag a mano es inviable. Aquí entra kube-bench.
Es una herramienta de código abierto desarrollada por Aqua Security (escrita en Go) que automatiza la evaluación de tu clúster contra las reglas del CIS Kubernetes Benchmark.
Básicamente, escanea tu nodo y te dice qué configuraciones son inseguras y, lo más importante, cómo arreglarlas.
Estados de Evaluación (Interpretando la salida)
Cuando ejecutas kube-bench, evalúa cientos de reglas y categoriza el resultado de cada una en 4 estados:
-
✅ [PASS]: El componente está configurado de forma segura según el CIS. ¡Todo bien!
-
❌ [FAIL]: Hay una configuración insegura que viola directamente el benchmark.
-
⚠️ [WARN]: Una configuración que podría ser un riesgo o requiere revisión manual, pero no es un fallo crítico automático.
-
ℹ️ [INFO]: Información general que no requiere acción inmediata.
Uso de kube-bench
¿Cómo se ejecuta?
En un entorno de producción, kube-bench suele ejecutarse como un binario directamente en el nodo o mediante un Job/Pod de Kubernetes.
# kube-bench
# Evaluar todos los componentes en el nodo actual
kube-bench
# Evaluar SOLO los componentes del Control Plane (Master)
kube-bench run --targets master
# Evaluar SOLO la configuración del Worker Node (kubelet, etc.)
kube-bench run --targets node
# Evaluar otros componentes
kube-bench run --targets etcd
kube-bench run --targets controlplane
kube-bench run --targets policies
# Ejecutar una evaluación específica
kube-bench run --check 1.1.12
# Para hacer debug de kube-bench
kube-bench run --check 1.1.7 -v 5
# End kube-bench
El Flujo de Trabajo (Troubleshooting y Remediación)
El mayor superpoder de kube-bench no es solo decirte qué está mal, sino darte la solución exacta. Al final de la salida, siempre hay una sección de Remediations (Remediaciones).
Ejemplo de un escenario tipo examen:
-
El Fallo: Ejecutas el escaneo y ves:
[FAIL] 1.2.1 Ensure that the --anonymous-auth argument is set to false -
La Remediación: Bajas al final del reporte y
kube-benchte dirá algo como:
"Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml on the master node and set the below parameter: --anonymous-auth=false"
-
Tu Acción:
-
Abres el manifiesto estático: vim /etc/kubernetes/manifests/kube-apiserver.yaml
- Añades el flag bajo la sección de comandos del contenedor.
-
Guardas y esperas a que el kubelet reinicie el Pod del apiserver.
-
Verificación: Vuelves a correr
kube-benchy verificas que el test 1.2.1 ahora marca[PASS].
# kube-apiserver
# Ver configuración
cat /etc/kubernetes/manifests/kube-apiserver.yaml
# Flags importantes
--advertise-address=<IP>
--anonymous-auth=false
--allow-privileged=true
--authorization-mode=Node,RBAC
--etcd-servers=https://127.0.0.1:2379
--service-cluster-ip-range=10.96.0.0/12
--profiling=false
# End kube-apiserver
# Remediación
# Control Plane Files
chmod 600 /etc/kubernetes/manifests/kube-apiserver.yaml
chmod 600 /etc/kubernetes/manifests/kube-controller-manager.yaml
chmod 600 /etc/kubernetes/manifests/kube-scheduler.yaml
chmod 600 /etc/kubernetes/manifests/etcd.yaml
# PKI Files
chmod 600 /etc/kubernetes/pki/*.key
chmod 644 /etc/kubernetes/pki/*.crt
# etcd
# Tener en cuenta que kubeadm levanta el servicio de etcd como un Pod.
# En la forma tradicional, etcd se levanta con un servicio del Sistema Operativo.
# Ejecutar en caso no exista el usuario (despliegue con kubeadm)
useradd -r -M -s /sbin/nologin etcd
chown etcd:etcd /var/lib/etcd
chmod 700 /var/lib/etcd
# End Remediación
Tips Clave para Certificaciones (CKS)
-
Conoce los archivos críticos: Saber dónde están los manifiestos de los Pods Estáticos (
/etc/kubernetes/manifests/) y la configuración del kubelet (/var/lib/kubelet/config.yaml) es obligatorio, ya que el 90% de las fallas del CIS Benchmark se corrigen editando estos archivos. -
Cuidado con romper el clúster: Algunos flags de seguridad recomendados por CIS pueden romper tu clúster si no sabes lo que haces (por ejemplo, deshabilitar puertos necesarios). En el examen, limítate a corregir exactamente lo que te piden.
-
Comprende la justificación: No solo copies y pegues. Entiende por qué estás agregando --profiling=false o --authorization-mode=Node,RBAC.
Restricción de acceso a la API
Restringir el acceso a la API se basa en un concepto de "Defensa en Profundidad" (múltiples capas de seguridad). Todas estas configuraciones de endurecimiento (hardening) se aplican modificando el Pod Estático del master: /etc/kubernetes/manifests/kube-apiserver.yaml.
- Capa 1: Bloquear a los "Desconocidos" (Autenticación)
Por defecto, Kubernetes es sorprendentemente amigable y permite que ciertas peticiones pasen sin credenciales para facilitar el descubrimiento del clúster. En producción, esto es un riesgo enorme.
-
La vulnerabilidad: Peticiones sin certificado ni token pueden consultar endpoints públicos o descubrir versiones del servidor.
-
La Solución (Flag):
--anonymous-auth=false -
Efecto: Cualquier petición que no presente credenciales válidas recibe inmediatamente un rechazo HTTP 401 (Unauthorized). Ni siquiera llega a evaluarse qué quería hacer.
-
Capa 2: Cerrar Puertas Traseras (Puertos Inseguros)
En versiones muy antiguas de Kubernetes, el API Server servía tráfico sin cifrar (HTTP puro) en el puerto 8080 para facilitar el debugging local, saltándose los controles de seguridad.
-
La vulnerabilidad: Alguien con acceso local al nodo Master podría enviar comandos por el puerto inseguro y obtener privilegios de administrador.
-
La Solución (Flag):
--insecure-port=0 -
Efecto: Apaga por completo el puerto HTTP no cifrado. Obliga a que absolutamente todo el tráfico viaje por HTTPS (puerto 6443 por defecto) y pase por los filtros de autenticación. (Nota: Kubeadm moderno ya lo trae en 0 por defecto, pero CIS Benchmark exige verificarlo).
-
Capa 3: Modo de Autorización Estricto (AuthZ)
Una vez que el API sabe quién eres (estás autenticado), debe decidir qué puedes hacer. Kubernetes soporta varios modos de autorización, pero hay una combinación ganadora para seguridad.
-
La vulnerabilidad: Usar modos permisivos como
AlwaysAllowo no aislar los permisos internos de los nodos. -
La Solución (Flag):
--authorization-mode=Node,RBAC -
Efecto:
- Node: Es un autorizador especial que asegura que un kubelet (Worker Node) solo pueda modificar sus propios Pods y leer Secretos asignados exclusivamente a él, impidiendo que un nodo comprometido robe datos de otro nodo.
- RBAC (Role-Based Access Control): Obliga a que humanos y ServiceAccounts deban tener Roles explícitos asignados para poder ejecutar cualquier verbo (
get,list,create,delete) sobre los recursos.
-
Capa 4: Cifrado en la Comunicación (Criptografía Fuerte)
No basta con exigir HTTPS; hay que exigir un HTTPS moderno y seguro. El CIS Benchmark audita que no estés usando algoritmos de cifrado obsoletos.
-
La vulnerabilidad: Algoritmos vulnerables que podrían permitir ataques de intermediario (Man-in-the-Middle).
-
La Solución (Flags):
-
--tls-cipher-suites=...(Se especifica una lista de cifrados fuertes recomendados por seguridad). -
--profiling=false(Apaga los endpoints de debugging de rendimiento que exponen detalles internos del sistema operativo).
-
Auditoría de Logs
Es el registro cronológico y detallado de cada llamada que se hace a la API de Kubernetes. Responde a las preguntas fundamentales de seguridad: ¿Quién hizo qué, cuándo, cómo y con qué resultado?
Como el kube-apiserver es el único punto de entrada, configurar la auditoría allí nos garantiza visibilidad absoluta, ya sea que la petición venga de un usuario con kubectl, un Service Account desde un Pod, o un componente interno del Control Plane.
Los 2 Conceptos Clave: Fases y Niveles
Para configurar la auditoría, debes entender en qué momento de la petición se registra el evento y con qué nivel de detalle.
Fases (Stages)
Es el "cuándo" se registra el evento dentro del ciclo de vida de la petición:
-
RequestReceived: Apenas la petición llega al API Server (antes de delegarla a otro componente).
-
ResponseStarted: Se envían las cabeceras de respuesta, pero el cuerpo (data) aún se está procesando (útil para peticiones largas como un watch).
-
ResponseComplete: La petición terminó y el API Server ha respondido por completo. Es la fase más común para registrar.
-
Panic: Ocurrió un error crítico interno en el servidor.
Niveles (Levels)
Es la "cantidad de información" que vas a guardar en el log:
-
None: No se registra nada. Útil para ignorar ruido (ej. peticiones constantes de lectura de los kubelets).
-
Metadata: Guarda la información básica: usuario, fecha, recurso solicitado y verbo (get, list, create), pero NO el cuerpo del manifiesto YAML. Es el equilibrio perfecto.
-
Request: Guarda la Metadata + el cuerpo de la petición.
-
RequestResponse: Guarda la Metadata + el cuerpo de la petición + la respuesta completa del API Server.
[!WARNING]
RequestResponseconsume mucho disco.
Configuración: La Regla de los 3 Pasos
Para encender la auditoría en tu clúster, necesitas sincronizar tres piezas. Si fallas en una, el API Server no arrancará.
- Crear la Política de Auditoría (Audit Policy)
Necesitas un archivo YAML en el nodo Master (ej. en /etc/kubernetes/audit-policy.yaml) que le diga al API Server qué nivel aplicar a qué recursos.
apiVersion: audit.k8s.io/v1
kind: Policy
# Evitar que el log se llene (Drop)
omitStages:
- "RequestReceived"
rules:
# No registrar lecturas del kube-proxy (ruido)
- level: None
users: ["system:kube-proxy"]
# Registrar todo lo que tenga que ver con Secretos a nivel Metadata
- level: Metadata
resources:
- group: "" # Core API group
resources: ["secrets"]
# Atrapa todo lo demás a nivel básico
- level: Metadata
- Configurar los Flags del kube-apiserver
Debes editar el manifiesto estático del API Server (/etc/kubernetes/manifests/kube-apiserver.yaml) para pasarle la política y decirle dónde guardar el archivo de texto:
--audit-policy-file=/etc/kubernetes/audit-policy.yaml(Ruta al archivo que creaste).--audit-log-path=/var/log/kubernetes/audit/audit.log(Dónde guardar el archivo final).--audit-log-maxage=30(Días a retener el log - Opcional pero buena práctica).-
--audit-log-maxbackup=10(Cantidad de archivos rotados a conservar - Opcional). -
Mapear los Volúmenes (El error más común en el examen)
¡No lo olvides! El kube-apiserver corre en un contenedor. Si le dices que lea la política en /etc/kubernetes/ y guarde el log en /var/log/kubernetes/, el contenedor buscará esas carpetas dentro de sí mismo y no las encontrará (o las borrará al reiniciarse).
Debes usar volumeMounts y volumes de tipo HostPath en el manifiesto YAML para mapear esas carpetas desde tu nodo Master hacia el contenedor del API Server.