Módulo 6: Runtime Security Admission Control And Image Scanning

1. Introducción al módulo: el portero antes de `etcd`

Descripción

Los Módulos 1-5 construyeron un clúster completo: Pods, Deployments, Services, ConfigMaps, Secrets, probes, autoscaling, Ingress, NetworkPolicy, y GitOps pull-based con ArgoCD sincronizando andes-cargo-status-api desde un repositorio Git real. En ningún momento, sin embargo, se le preguntó a ningún objeto —antes de crearlo— si tenía permitido existir. Cualquier Pod bien formado, con cualquier imagen, con cualquier cantidad de CPU o memoria (o ninguna), llegó a etcd sin que nadie lo detuviera. Este módulo cierra esa puerta: instala dos motores de políticas distintos que se paran, literalmente, en el único punto de entrada al clúster (kube-apiserver, Módulo 1, lección 6) y deciden, objeto por objeto, si tiene permitido pasar — antes de que exista.

Este no es un tema nuevo del ecosistema Andes Cargo. Es un tema que otra guía ya nombró, con precisión, y dejó explícitamente para esta.

Conexión con el módulo

cloud-security-and-guardrails-guide construyó ocho módulos completos de seguridad preventiva y detectiva sobre la infraestructura Terraform/AWS de Andes Cargo —OIDC, secretos, conftest/Rego contra un terraform plan, escaneo de HCL con Trivy y Checkov, SBOM y firma con cosign—. En su Módulo 7, esa guía nombró explícitamente el par de conceptos que este módulo construye (preventivo/detectivo), y en su frontera de alcance dejó esta cita exacta, sin ambigüedad, señalando hacia aquí.


La cita textual completa

cloud-security-and-guardrails-guide/DISENO.md, en la sección "NO entra en (frontera con guías hermanas)", dice, palabra por palabra:

"EKS y runtime de contenedores (admission controllers en clúster — OPA Gatekeeper, Kyverno —, escaneo de imágenes Docker, NetworkPolicy) → kubernetes-and-eks-in-production-guide. Andes Cargo no tiene contenedores en este ecosistema (el handler Lambda se empaqueta en .zip, no en imagen); el escaneo y la firma de esta guía son de artefacto de despliegue y de IaC, no de imagen de contenedor."

Vale la pena leer esa cita dos veces, porque nombra tres cosas que delega, no una:

  1. Admission controllers en clúster — OPA Gatekeeper y Kyverno, nombrados por su nombre propio, sin construirse ahí.
  2. Escaneo de imágenes Docker — distinto, la propia cita lo aclara, del escaneo que esa guía sí hace (trivy config sobre HCL, en su Módulo 5).
  3. NetworkPolicy — que, en realidad, ya construiste tú, en el Módulo 4 de esta misma guía, antes de llegar aquí. Se nombra en la cita porque, al momento de escribir esa frontera, cloud-security-and-guardrails-guide no sabía todavía en qué orden ibas a leer las guías del ecosistema — la cita es una promesa de cobertura, no un anuncio de que faltaba construirla.

Y hay una frase, dentro de esa misma cita, que merece su propio párrafo: "Andes Cargo no tiene contenedores en este ecosistema". Esa era la foto exacta hasta el punto en que cloud-security-and-guardrails-guide se escribió — el caso Andes Cargo, en su origen (aws-core-services-guide), es un handler Lambda empaquetado en .zip, sin Docker de por medio. Tú, sin embargo, empezaste este módulo habiendo ya construido cinco módulos completos sobre un clúster de Kubernetes real, con una imagen Docker real (andes-cargo-status-api:latest) corriendo en Pods reales. La premisa "Andes Cargo no tiene contenedores" dejó de ser cierta en el momento exacto en que terminaste el Módulo 1 de esta guía — este módulo es, entre otras cosas, el que hereda esa corrección de continuidad y la usa como terreno de trabajo real, no hipotético.


Qué NO cubre cloud-security-and-guardrails-guide, y qué sí cubre este módulo

La tabla siguiente no es un resumen genérico — es la traducción literal, punto por punto, de la cita anterior a lo que vas a construir en las próximas siete lecciones:

Lo que cloud-security-and-guardrails-guide sí construyóEl artefacto exactoLo que este módulo construye en su lugar
Policy-as-code con conftest/OPA (Módulo 4)Rego evaluando un terraform plan en JSON, fuera del clúster, como un archivo estáticoRego (Gatekeeper) y YAML (Kyverno) evaluando objetos en vivo, dentro del clúster, en el instante de cada kubectl apply
Escaneo de infraestructura con Trivy (Módulo 5)trivy config sobre archivos .tf (HCL) — busca configuración insegura declarada, nunca ejecutadatrivy image sobre andes-cargo-status-api:latest — busca vulnerabilidades reales, ya instaladas, en las capas de un artefacto que sí corre
Preventivo vs. detectivo, nombrado (Módulo 7)CloudTrail como el ejemplo central de "detectivo": queda registro, después del hechoAdmission control como el ejemplo central de "preventivo": decide antes de que el objeto exista — el mismo vocabulario, aplicado a una capa distinta
Supply chain, SBOM y firma con cosign (Módulo 6)Verifica que un artefacto de despliegue (el .zip de Lambda) no fue alterado, antes de que apply.yml lo subaFuera de alcance de este módulo — firmar y verificar una imagen de contenedor (cosign sobre OCI) seguiría el mismo patrón conceptual, pero no se construye aquí; queda nombrado como el paso natural que seguiría a este módulo si el ecosistema lo necesitara

La fila que de verdad importa retener, antes de seguir: el mismo problema —"¿esta configuración es segura antes de que corra?"— tiene una solución distinta según en qué capa vive el objeto que evalúas. Un terraform plan es un documento JSON que existe antes de que AWS cree nada; conftest lo evalúa como archivo, sin tocar ninguna API en vivo. Un Pod de Kubernetes, en cambio, nace en el momento exacto en que kube-apiserver lo recibe — no hay un "plan" separado que evaluar de antemano, así que el motor de políticas tiene que interceptar la solicitud misma, en vivo, dentro del clúster. Esa diferencia de arquitectura —archivo estático fuera vs. objeto en vivo dentro— es el hilo que atraviesa las ocho lecciones de este módulo, y vas a verlo con nombre explícito en la lección 3.


Analogía: el portero que revisa la lista antes de dejarte entrar

Imagina un edificio de oficinas con dos sistemas de seguridad. El primero es una cámara en el vestíbulo: graba todo lo que pasa, y si alguien entra sin autorización, hay una grabación que lo prueba — después del hecho, cuando ya está adentro. El segundo es un portero, parado en la única puerta del edificio, con una lista en la mano: revisa esa lista antes de que cualquier persona cruce el umbral, y si el nombre no está, esa persona nunca entra — no hay nada que grabar, porque el evento que la cámara habría capturado simplemente nunca ocurrió.

Un admission controller es ese portero, aplicado a kube-apiserver. No es la cámara que revisa después (eso, en el vocabulario que cloud-security-and-guardrails-guide ya usó en su Módulo 7, es "detectivo" — CloudTrail, los logs de auditoría de Kubernetes, que este módulo no construye). Es el portero que se para exactamente en el único punto de entrada al clúster —el mismo kube-apiserver que la lección 6 del Módulo 1 te mostró como "la única puerta de entrada"— y decide, objeto por objeto, antes de que etcd lo guarde, si tiene permitido existir. Vas a ver el punto exacto del ciclo de vida de un request donde este portero se para en la lección 2.


El mapa de este módulo: las 8 lecciones

   MÓDULO 6 — SEGURIDAD DE RUNTIME: ADMISSION CONTROL Y ESCANEO DE IMAGEN

   M6.1  Introducción (esta)                          la cita, la frontera, el portero
   M6.2  Qué es un admission controller                el punto exacto del ciclo de vida
   M6.3  OPA Gatekeeper: ConstraintTemplate/Constraint  Rego dentro de un CRD de K8s
   M6.4  Manos a la obra: Gatekeeper + primera política EJECUTADO — v3.23.0, rechazo real
   M6.5  Kyverno: la alternativa YAML-nativa            Rego vs. YAML, sin ganador
   M6.6  Manos a la obra: la misma política, en Kyverno EJECUTADO — v1.18.2, rechazo real
   M6.7  Manos a la obra: trivy image                   EJECUTADO — hallazgos reales
   M6.8  Proyecto: los guardrails de runtime             EJECUTADO — ambos motores + trivy
#LecciónQué construye
1Introducción (esta)La cita textual completa, la frontera exacta, el portero como analogía central
2Qué es un admission controllerAutenticación → autorización → admissionetcd; preventivo, no detectivo
3OPA Gatekeeper: ConstraintTemplate/ConstraintRego dentro de un CRD; contraste explícito con conftest (fuera del clúster)
4Manos a la obra: instalando GatekeeperEjecutado: v3.23.0, política de límites de recursos, Pod rechazado y Pod admitido
5Kyverno: la alternativa YAML-nativaRego vs. YAML declarativo; cuándo un equipo elige cada uno, sin declarar ganador
6Manos a la obra: la misma política, en KyvernoEjecutado: v1.18.2, misma prueba, comparación lado a lado
7Manos a la obra: trivy imageEjecutado: hallazgos reales de andes-cargo-status-api:latest, por severidad
8Proyecto: los guardrails de runtime de Andes CargoEjecutado: ambos motores activos a la vez + trivy image como gate antes de cargar una imagen

Al cerrar este módulo, andes-cargo-cluster va a tener, por primera vez desde el Módulo 1, un portero real parado en kube-apiserver — y vas a saber, con evidencia literal, qué mensaje exacto muestra cuando rechaza algo.


Errores comunes

Pensar que este módulo repite el Módulo 4 de cloud-security-and-guardrails-guide con otro nombre (de solapamiento aparente). Qué pasa: alguien, al ver "políticas" y "Rego" mencionados en ambas guías, asume que este módulo es una copia del módulo de conftest. Cómo detectarlo: si tu resumen mental es "ya vi esto, es lo mismo con otro logo". Cómo corregirlo: el lenguaje (Rego) puede coincidir en Gatekeeper, pero el momento y el objeto que evalúa son completamente distintos — conftest lee un archivo JSON estático, generado por terraform plan, en una máquina que no tiene ninguna conexión con AWS en el instante de la evaluación. Gatekeeper corre dentro del clúster, como un Deployment real, y responde a cada solicitud HTTP que kube-apiserver le reenvía, en el instante exacto en que ocurre. La lección 3 de este módulo dedica una sección completa a esta distinción.

Asumir que "Andes Cargo no tiene contenedores" sigue siendo cierto (de continuidad desactualizada). Qué pasa: alguien lee la cita de cloud-security-and-guardrails-guide en esta lección y concluye que el ecosistema completo de Andes Cargo sigue sin Docker. Cómo detectarlo: si tu modelo mental de Andes Cargo, después de leer esta lección, sigue siendo "cuatro servicios serverless, un .zip de Lambda, nada de contenedores". Cómo corregirlo: esa premisa era cierta cuando cloud-security-and-guardrails-guide se escribió; dejó de serlo en el Módulo 1 de esta guía, cuando cargaste andes-cargo-status-api:latest en andes-cargo-cluster por primera vez. El Módulo 8 de esta guía (lección 6) documenta esa corrección de continuidad de forma explícita, para que ningún alumno del ecosistema se quede con la foto vieja.

Esperar que este módulo firme imágenes con cosign, porque cloud-security-and-guardrails-guide lo hizo con el .zip de Lambda (de expectativa de paridad). Qué pasa: alguien, viendo que la guía hermana firmó su artefacto de despliegue, espera que este módulo firme andes-cargo-status-api:latest de la misma forma. Cómo detectarlo: si buscas un paso de cosign sign/cosign verify en las lecciones 4, 6 o 8. Cómo corregirlo: firmar imágenes OCI es, conceptualmente, la misma idea aplicada a un artefacto distinto — pero está fuera del alcance declarado de este módulo, que se concentra en admission control y escaneo de vulnerabilidades. Esta lección lo nombra en la tabla de arriba, explícitamente, como el paso natural que no se construye aquí — no por descuido, sino porque el alcance de este módulo ya lo dice la cita: "admission controllers en clúster... escaneo de imágenes Docker", no "firma de imágenes".


Ejercicios

Ejercicio 1 — Reescribe la cita de memoria, sin copiarla. Sin volver a mirar la sección "La cita textual completa" de esta lección, escribe en tus propias palabras las tres cosas exactas que cloud-security-and-guardrails-guide delega hacia esta guía.

Ver solución

Las tres cosas son: (1) admission controllers corriendo dentro del clúster —nombrados explícitamente como OPA Gatekeeper y Kyverno—; (2) escaneo de imágenes Docker —distinto del escaneo de HCL/Terraform que esa guía sí hizo—; y (3) NetworkPolicy —que, en el orden real en que leíste el ecosistema, ya construiste en el Módulo 4 de esta misma guía antes de llegar aquí. Si tu respuesta nombró las tres sin necesitar releer la cita, tienes clara la frontera exacta que gobierna este módulo.

Ejercicio 2 — Explica por qué "Andes Cargo no tiene contenedores" dejó de ser cierto, con una fecha exacta. En una frase, indica el punto exacto —el módulo y la lección— en el que esa premisa se volvió falsa, y por qué.

Ver solución

Se volvió falsa en el Módulo 1, lección 7 de esta guía (kubernetes-and-eks-in-production-guide), el momento en que andes-cargo-status-api:latest se cargó por primera vez en andes-cargo-cluster con kind load docker-image — desde ese instante, Andes Cargo tiene, de verdad, un servicio corriendo como contenedor dentro de un clúster real, no solo un handler Lambda empaquetado en .zip.

Ejercicio 3 — Predice la diferencia entre conftest y Gatekeeper antes de leer la lección 3. Basándote únicamente en la tabla de esta lección, predice: si le muestras el mismo Pod YAML tanto a conftest (con una regla Rego copiada) como a Gatekeeper, ¿cuál de los dos puede rechazarlo antes de que ese Pod exista de verdad en un clúster, y cuál no?

Ver solución

Ninguno de los dos "gana" en ese sentido — los dos son preventivos, cada uno en su propio contexto. conftest puede evaluar ese YAML como archivo estático, en cualquier máquina, sin ningún clúster corriendo — perfecto para un paso de CI antes de que nadie intente aplicar nada. Gatekeeper, en cambio, necesita un clúster real corriendo, con el webhook instalado, para interceptar la solicitud en el momento exacto de kubectl apply — no puede evaluar un archivo sin que alguien lo aplique de verdad contra kube-apiserver. La diferencia no es "quién es más preventivo": es "en qué instante del ciclo de vida de la infraestructura actúa cada uno" — conftest, antes de que exista intención de aplicar nada; Gatekeeper, en el instante exacto en que alguien lo intenta.


Resumen y siguiente paso

Esta lección conectó este módulo, con cita textual completa, con la frontera que cloud-security-and-guardrails-guide dejó explícita en su propio diseño: admission controllers en clúster (OPA Gatekeeper, Kyverno) y escaneo de imágenes Docker, delegados hacia aquí porque esa guía trabaja sobre un .zip de Lambda, no sobre una imagen de contenedor. Viste la tabla completa de qué construye cada guía sobre el mismo problema general —"¿es esto seguro antes de que corra?"— en capas distintas, y la analogía central del módulo: el portero que revisa la lista antes de dejarte entrar, no la cámara que graba después.

Antes de avanzar deberías poder: citar de memoria las tres cosas que la frontera delega; explicar por qué "Andes Cargo no tiene contenedores" dejó de ser cierta, con el módulo y la lección exactos; y distinguir, en una frase, la diferencia de arquitectura entre conftest (archivo estático, fuera del clúster) y un admission controller (objeto en vivo, dentro del clúster).

Siguiente lección: qué es un admission controller, y por qué corre antes de que el objeto exista. Ahí vas a ver el punto exacto del ciclo de vida de un request —autenticación, autorización, admission, etcd— y por qué esto es, con el mismo vocabulario que cloud-security-and-guardrails-guide ya usó en su Módulo 7, estrictamente preventivo.

Recursos

  1. cloud-security-and-guardrails-guide (NIEVA), DISENO.md, sección "NO entra en" — la fuente textual completa de la cita de esta lección.
  2. cloud-security-and-guardrails-guide (NIEVA), Módulo 7, lección 1 — la distinción preventivo/detectivo que este módulo retoma en la lección 2.
  3. kubernetes-and-eks-in-production-guide (NIEVA), Módulo 1, lección 6 — kube-apiserver como la única puerta de entrada al clúster, la base técnica de todo este módulo.
  4. Kubernetes — Admission Controllers Reference — documentación oficial del mecanismo que este módulo construye con dos motores reales.
  5. Open Policy Agent Gatekeeper — el primero de los dos motores, instalado de verdad en la lección 4.
  6. Kyverno — el segundo motor, instalado de verdad en la lección 6.
  7. Trivy — Container Image — el escáner de imagen, ejecutado de verdad en la lección 7.