Imponer una autenticación fuerte para todas las solicitudes del servidor API.
Establecer las banderas de `kube-apiserver`: `--anonymous-auth=false` para rechazar solicitudes no autenticadas, y `--client-ca-file` para imponer la validación de certificados de cliente (mTLS).
Por qué: Estas banderas son controles fundamentales para eliminar el acceso anónimo e imponer una comunicación autenticada y cifrada con el servidor API.
Proteger el almacén de estado etcd del clúster contra acceso no autorizado y robo de datos.
Configurar etcd con mTLS para toda la comunicación de cliente y entre pares (`--cert-file`, `--key-file`, `--peer-cert-file`). Habilitar el cifrado de secretos en reposo a través de la bandera `--encryption-provider-config` del servidor API.
Por qué: etcd contiene todos los secretos del clúster. Cifrar los datos en tránsito (mTLS) y en reposo es fundamental para proteger la información sensible incluso si los nodos etcd son comprometidos.
Rotar las claves de cifrado en reposo de etcd con cero tiempo de inactividad.
1. Añadir la nueva clave como la primera entrada en el archivo `EncryptionConfiguration`. 2. Reiniciar todos los servidores API. 3. Forzar el recifrado de todos los secretos (`kubectl get secrets -A -o json | kubectl replace -f -`). 4. Después de la verificación, eliminar la clave antigua de la configuración y reiniciar los servidores API de nuevo.
Por qué: Cambiar la configuración solo afecta a las nuevas escrituras. Los datos existentes deben reescribirse para ser cifrados con la nueva clave. Eliminar la clave antigua prematuramente bloqueará el acceso a sus datos.
Implementar un modelo de red de confianza cero dentro de un espacio de nombres.
Aplicar una `NetworkPolicy` con un `podSelector: {}` vacío y `policyTypes: [Ingress, Egress]` pero sin reglas de `ingress` o `egress`. Esto selecciona todos los pods y deniega todo el tráfico.
Por qué: Esta política establece una base de "denegar todo", forzando reglas explícitas de "permitir" para toda la comunicación requerida, que es la base de la red de confianza cero.
Las NetworkPolicies de Egreso están bloqueando la resolución DNS para los pods.
Añadir una regla de egreso específica para permitir el tráfico al servicio DNS del clúster. Permitir el egreso al puerto 53 en los protocolos UDP y TCP. Seleccionar los pods kube-dns a través de `namespaceSelector` y `podSelector` si es posible.
Por qué: Las NetworkPolicies son granulares. Una regla de egreso general a un bloque de IP podría no cubrir el protocolo específico (UDP) requerido para DNS, lo que lleva a fallos de resolución.
Asegurar el acceso externo a los servicios expuestos a través de un Ingress.
Configurar el recurso Ingress añadiendo una sección `tls` que referencie un Secret de Kubernetes de tipo `kubernetes.io/tls`. El secret debe contener el certificado TLS y la clave privada.
Por qué: Esto centraliza la terminación TLS en el controlador Ingress, cifrando el tráfico de los clientes hasta el límite del clúster y simplificando la gestión de certificados para los servicios backend.
Fortalecimiento del Clúster
Conceder a los usuarios o aplicaciones solo los permisos mínimos requeridos.
Usar `Roles` y `RoleBindings` con ámbito de espacio de nombres siempre que sea posible. Evitar `cluster-admin` y comodines (`"*"`) en `verbs` o `resources`. Conceder permisos específicos como `["get", "list"]` en `["pods"]`.
Por qué: Esto minimiza el radio de impacto si una cuenta o token es comprometido, previniendo el movimiento lateral y la escalada de privilegios.
Reducir la superficie de ataque para los pods que no necesitan interactuar con la API de Kubernetes.
Deshabilitar el montaje automático de tokens de cuenta de servicio estableciendo `automountServiceAccountToken: false` en el ServiceAccount o en la especificación del Pod.
Por qué: Si un pod es comprometido, un atacante no puede aprovechar un token montado para acceder al servidor API, previniendo ataques a nivel de clúster originados desde el pod comprometido.
Verificar si un usuario o cuenta de servicio específica tiene permiso para realizar una acción.
Por qué: Este comando permite la suplantación para verificar con precisión los permisos efectivos sin necesidad de analizar manualmente todos los Roles y Bindings.
Mantener la seguridad del clúster rotando regularmente los certificados del plano de control y de kubelet.
Para clústeres kubeadm, usar `kubeadm certs renew all`. Para otros, seguir el procedimiento de rotación manual o automatizado documentado. Habilitar la rotación de certificados de cliente/servidor kubelet a través de su configuración.
Por qué: La rotación regular limita la ventana de tiempo en que un atacante puede usar un certificado comprometido. Es una práctica crítica de higiene de seguridad.
Se sospecha que un nodo de trabajo está comprometido y debe ser aislado inmediatamente.
Primero, usar `kubectl cordon <nombre-nodo>` para evitar que se programen nuevos pods. Luego, usar `kubectl drain <nombre-nodo> --ignore-daemonsets --delete-emptydir-data` para desalojar de forma segura las cargas de trabajo en ejecución.
Por qué: El acordonamiento y drenaje es el procedimiento estándar y no destructivo para retirar un nodo de servicio, permitiendo que las cargas de trabajo sean reprogramadas en otro lugar mientras se conserva el nodo comprometido para análisis forense.
Fortalecimiento del Sistema
Restringir las llamadas al sistema que un contenedor puede hacer al kernel del host.
En el `securityContext` del Pod o Contenedor, establecer `seccompProfile.type` en `RuntimeDefault` para una base segura, o `Localhost` con una ruta a un perfil JSON definido a medida para un control más estricto.
Por qué: Seccomp reduce la superficie de ataque del kernel desde dentro de un contenedor, previniendo exploits contra vulnerabilidades del kernel al bloquear syscalls no utilizados o peligrosos.
Confinar los procesos del contenedor restringiendo el acceso a archivos, capacidades de red y otros recursos.
Aplicar un perfil AppArmor a un contenedor a través de la anotación: `container.apparmor.security.beta.kubernetes.io/<nombre_contenedor>: localhost/<nombre_perfil>`. El perfil debe estar precargado en el nodo.
Por qué: AppArmor proporciona Control de Acceso Obligatorio (MAC), añadiendo una capa crucial de defensa en profundidad para contener una aplicación comprometida y evitar que acceda a recursos no autorizados.
Un contenedor necesita una operación privilegiada específica (por ejemplo, enlazar al puerto 80) sin ejecutarse como root.
En `securityContext.capabilities`, `drop: ["ALL"]` y luego `add: ["NET_BIND_SERVICE"]`.
Por qué: Esto sigue el principio de privilegio mínimo al otorgar solo la capacidad específica de Linux requerida, evitando los permisos amplios de ejecutarse como root.
Evitar que un contenedor obtenga acceso completo al sistema host.
Establecer `securityContext.privileged: false` (que es el valor predeterminado). Usar Pod Security Standards o OPA/Kyverno para aplicar esto a todo el clúster.
Por qué: Un contenedor privilegiado tiene casi todas las capacidades del host y acceso a dispositivos, deshabilitando efectivamente el aislamiento del contenedor. Es un vector principal para el escape de contenedores.
Minimizar Vulnerabilidades de Microservicios
Aplicar configuraciones de seguridad de línea base o estrictas para los pods a nivel de espacio de nombres.
Aplicar etiquetas al espacio de nombres, por ejemplo, `pod-security.kubernetes.io/enforce: restricted`. Los modos son `enforce`, `audit` y `warn`.
Por qué: Los Pod Security Standards (PSS) proporcionan una política de seguridad multinivel incorporada que reemplaza a la obsoleta PodSecurityPolicy, facilitando la aplicación de las mejores prácticas de seguridad.
Fortalecer un pod aplicando múltiples controles de seguridad simultáneamente.
Configurar un `securityContext` que combine `runAsNonRoot: true`, `allowPrivilegeEscalation: false` y `readOnlyRootFilesystem: true`.
Por qué: Este enfoque de defensa en profundidad superpone múltiples protecciones: prevención de la ejecución como root, bloqueo de vectores de escalada de privilegios (como setuid) y hacer que el sistema de archivos del contenedor sea inmutable.
Ejecutar cargas de trabajo no confiables o multi-inquilino con un aislamiento más fuerte que los contenedores estándar.
Definir un recurso `RuntimeClass` que apunte a un manejador de tiempo de ejecución en sandbox (por ejemplo, gVisor, Kata Containers). Asignar pods a él usando `spec.runtimeClassName`.
Por qué: Los tiempos de ejecución en sandbox utilizan un kernel en espacio de usuario o máquinas virtuales ligeras para interceptar llamadas al sistema, proporcionando una capa adicional de aislamiento entre el contenedor y el kernel del host.
Aplicar políticas de seguridad complejas y personalizadas que no están cubiertas por los controles estándar de Kubernetes.
Desplegar OPA Gatekeeper. Definir políticas usando `ConstraintTemplate` (la lógica Rego) y aplicarlas con recursos `Constraint`.
Por qué: Gatekeeper actúa como un webhook de admisión de validación, permitiendo imponer reglas arbitrarias, como requerir etiquetas específicas, no permitir rutas de host o aplicar límites de recursos.
Proporcionar secretos a los pods de la manera más segura.
Montar secretos como archivos en un volumen. Para una seguridad aún mayor, usar un controlador CSI de almacén de secretos para montar secretos desde una bóveda externa (por ejemplo, HashiCorp Vault, AWS Secrets Manager) directamente en el pod.
Por qué: Montar como archivos es más seguro que las variables de entorno (que pueden ser registradas o expuestas). Un controlador CSI evita almacenar el secreto en etcd por completo.
Cifrar y autenticar automáticamente todo el tráfico de red de pod a pod.
Desplegar una malla de servicios como Istio o Linkerd. La malla inyecta un proxy sidecar en cada pod para manejar el cifrado mTLS, la autenticación y la aplicación de políticas.
Por qué: Una malla de servicios proporciona redes transparentes de confianza cero sin requerir cambios en el código de la aplicación, asegurando toda la comunicación de servicio interna.
Seguridad de la Cadena de Suministro
Prevenir el despliegue de imágenes de contenedor con vulnerabilidades conocidas (CVEs).
Integrar un escáner como Trivy o Grype en la pipeline CI/CD. Fallar la construcción si las vulnerabilidades exceden un umbral de severidad definido (por ejemplo, HIGH o CRITICAL).
Por qué: Este enfoque de "desplazamiento a la izquierda" detecta las vulnerabilidades tempranamente, antes de que lleguen a producción, reduciendo drásticamente la superficie de ataque de las aplicaciones en ejecución.
Asegurar que solo imágenes de contenedor confiables y no modificadas se desplieguen en el clúster.
Firmar imágenes con `cosign` durante el proceso de construcción de CI. Usar un motor de políticas (Kyverno, OPA Gatekeeper) como controlador de admisión para verificar la firma contra una clave pública antes de permitir la creación de un pod.
Por qué: La firma criptográfica proporciona fuertes garantías de integridad de la imagen (no ha sido manipulada) y autenticidad (proviene de una fuente confiable).
Minimizar la superficie de ataque dentro de la propia imagen del contenedor.
Usar imágenes base mínimas (por ejemplo, distroless, Alpine). Usar un Dockerfile de múltiples etapas para descartar herramientas de construcción. Establecer un usuario no root con la instrucción `USER`. Usar `.dockerignore` para excluir archivos sensibles.
Por qué: Una imagen mínima contiene menos paquetes y herramientas, ofreciendo menos vulnerabilidades potenciales y dificultando que un atacante pivote si el contenedor es comprometido.
Aplicar una política para que todas las imágenes desplegadas deben originarse en el registro privado de la organización.
Usar un controlador de admisión (como OPA Gatekeeper o Kyverno) para crear una política que valide el campo `image` de todas las especificaciones de contenedor contra una lista de nombres de host de registro permitidos.
Por qué: Esto evita que los desarrolladores extraigan imágenes no confiables o no escaneadas de repositorios públicos como Docker Hub, asegurando que todo el código haya pasado por verificaciones de seguridad internas.
Mantener un inventario de todos los componentes de software y dependencias dentro de una imagen de contenedor.
Integrar una herramienta como `Syft` en la pipeline CI/CD para generar una Lista de Materiales de Software (SBOM) en un formato estándar como SPDX o CycloneDX.
Por qué: Un SBOM es esencial para la seguridad de la cadena de suministro, permitiendo la rápida identificación de todos los activos afectados cuando se descubre una nueva vulnerabilidad en una dependencia.
Identificar configuraciones de seguridad erróneas en los manifiestos YAML de Kubernetes antes de que se apliquen.
En la pipeline CI, usar una herramienta como `trivy config` o `kubesec` para escanear archivos de manifiestos de Kubernetes en busca de configuraciones riesgosas, como ejecutarse como root, permitir la escalada de privilegios o montar rutas de host sensibles.
Por qué: Esta verificación proactiva detecta problemas de seguridad en la infraestructura como código antes de que creen vulnerabilidades en el clúster en ejecución.
Monitorización, Registro y Seguridad en Tiempo de Ejecución
Detectar y alertar sobre actividad sospechosa dentro de contenedores en ejecución o en nodos del clúster.
Desplegar Falco como un DaemonSet. Falco usa eBPF o un módulo del kernel para monitorizar llamadas al sistema y alerta sobre comportamientos anómalos basados en su conjunto de reglas (por ejemplo, shell en contenedor, conexiones de red inesperadas).
Por qué: Falco proporciona visibilidad en tiempo real del comportamiento en tiempo de ejecución, permitiendo la detección de amenazas como escapes de contenedores, criptominado o exfiltración de datos que el escaneo estático no puede ver.
Una regla predeterminada de Falco está generando demasiados falsos positivos.
Crear un archivo de reglas de Falco personalizado para anular la regla predeterminada. Añadir excepciones a la `condition` de la regla para excluir comportamientos conocidos como seguros, como procesos específicos o imágenes de contenedor (por ejemplo, `and not container.image.repository contains "debug"`).
Por qué: Ajustar las reglas es fundamental para operacionalizar la seguridad en tiempo de ejecución. Reducir el ruido asegura que los equipos de seguridad puedan centrarse en alertas accionables y de alta prioridad.
Registrar un log cronológico e inmutable de todas las acciones realizadas contra la API de Kubernetes.
Habilitar el registro de auditoría en el `kube-apiserver` proporcionando las banderas `--audit-policy-file` y `--audit-log-path`. Configurar la política para definir qué se registra y a qué nivel.
Por qué: Los logs de auditoría son esenciales para el análisis de seguridad, la investigación de incidentes y el cumplimiento. Proporcionan un registro definitivo de quién hizo qué y cuándo.
Auditar el acceso a recursos sensibles como Secrets sin registrar el contenido del secreto.
Configurar la regla de política de auditoría para Secrets para usar `level: Metadata`. Esto registra el usuario, la marca de tiempo, el recurso y el verbo, pero omite los cuerpos de solicitud y respuesta.
Por qué: Esto proporciona responsabilidad sobre quién accede a los secretos sin crear un nuevo riesgo de seguridad al escribir datos sensibles en los logs de auditoría.
Agrupar logs de todos los componentes del clúster y aplicaciones para un análisis centralizado.
Desplegar un agente de recolección de logs (por ejemplo, Fluentd, Vector) como un DaemonSet para recolectar logs de los nodos y reenviarlos a un SIEM centralizado o sistema de gestión de logs (por ejemplo, Elasticsearch, Splunk).
Por qué: El registro centralizado es crucial para correlacionar eventos en todo el clúster durante una investigación de incidentes y para mantener registros a largo plazo para el cumplimiento.
Reenviar las alertas de seguridad de Falco a un sistema externo para notificación y respuesta.
Desplegar `Falcosidekick` junto con Falco. Configurarlo para recibir alertas de Falco y reenviarlas a salidas como Slack, PagerDuty o un SIEM.
Por qué: Falcosidekick proporciona un mecanismo flexible y robusto para integrar las alertas en tiempo real de Falco en los flujos de trabajo operativos y de seguridad existentes.
Detectar si un contenedor en ejecución ha sido modificado, lo que podría indicar un compromiso.
Aplicar contenedores inmutables con `readOnlyRootFilesystem: true`. Usar una herramienta de seguridad en tiempo de ejecución como Falco para monitorizar y alertar sobre cualquier escritura de archivos en ubicaciones inesperadas.
Por qué: En un modelo inmutable, los contenedores nunca se modifican en tiempo de ejecución; se reemplazan. Cualquier desviación de este patrón es un fuerte indicador de una posible brecha de seguridad.