Introducción

Confidential Containers (CoCo) refuerza la seguridad de los workloads en entornos no confiables asumiendo que el plano de control de Kubernetes no es confiable. Esto exige validaciones estrictas en el runtime y configuraciones adicionales en los pods, lo que puede complicar la experiencia de los desarrolladores y aumentar la fricción operativa. Kyverno actúa como un Policy as Code engine dentro del mismo plano de control, permitiendo automatizar la inyección de configuraciones CoCo y validar manifiestos antes de que los pods sean admitidos. Así, los equipos de plataforma estandarizan los requisitos de CoCo sin delegar decisiones de seguridad al plano de control, preservando el modelo de confianza cero.

Qué es y para qué sirve

Confidential Containers (CoCo) es una iniciativa de la CNCF que protege workloads en entornos donde partes de la infraestructura (ej: kube-apiserver, kubelet) no son de confianza. Su enfoque central es:
  • Verificar todo: Cada especificación de pod enviada al runtime debe ser validada mediante remote attestation.
  • Runtime seguro: El runtime (ej: Kata Containers con CoCo) verifica la integridad del pod antes de ejecutarlo.

Esto introduce desafíos prácticos para los equipos:

  1. Configuración manual repetitiva: Inyectar annotations, labels, y securityContext correctos en cada manifiesto.
  2. Validación temprana: Rechazar configuraciones inválidas antes de que el pod sea creado (ej: falta el campo runAsNonRoot: true en un pod CoCo).
  3. Consistencia operativa: Garantizar que todas las aplicaciones cumplan con los requisitos de CoCo, incluso en clusters grandes.
Kyverno resuelve estos problemas con:
  • Mutación automática: Inyecta configuraciones CoCo en los manifiestos (ej: añadir seccompProfile: RuntimeDefault).
  • Validación en tiempo de admisión: Rechaza pods con configuraciones inválidas (ej: privileged: true en un pod CoCo).
  • Políticas como código: Definir reglas en YAML que se apliquen de forma declarativa en todo el cluster.

> Importante: Kyverno no sustituye a la remote attestation. Su rol es automatizar la infraestructura para que los equipos se enfoquen en el código, no en los detalles de configuración. La seguridad final sigue siendo responsabilidad del runtime y el proceso de attestación.

Prerequisitos

Para seguir esta guía, necesitás:

ComponenteVersión mínimaNotas
Kubernetes1.28+Cluster con *RuntimeClass* configurado para CoCo (ej: BLOCK32 con CoCo).
Kyverno1.11.0+Instalado en modo *admission controller*.
Kata Containers3.1.0+Con soporte para CoCo (ver [Kata CoCo docs](https://github.com/kata-containers/kata-containers/blob/main/docs/confidential-containers/README.md)).
Helm3.12.0+Para instalar Kyverno y sus políticas.
PermisosBLOCK33Para instalar Kyverno y crear políticas globales.
Imagen CoCoBLOCK34Ejemplo de imagen para probar (reemplazá con tu registry interna).
GitCualquier versiónPara clonar repositorios de políticas (opcional, pero recomendado).
> Verificá el runtime CoCo:

>

> kubectl get runtimeclass
> 

> Deberías ver una entrada como:

>

> name: kata-qemu-sev
> handler: kata-qemu-sev
> 

> Si no existe, configuralo según la documentación de Kata CoCo.

Guía paso a paso

Paso 1: Instalar Kyverno en el cluster

Instalá Kyverno usando Helm con la configuración recomendada para políticas de mutación/validación:

helm repo add kyverno https://kyverno.github.io/kyverno/
helm repo update
helm install kyverno kyverno/kyverno -n kyverno --create-namespace --version 3.1.0

> Resultado esperado:

>

> kubectl get pods -n kyverno
> NAME                        READY   STATUS    RESTARTS   AGE
> kyverno-7c6b8d4f5-abc12   1/1     Running   0          30s
> 

Verificá que el admission controller esté activo:

kubectl get validatingwebhookconfigurations
kubectl get mutatingwebhookconfigurations

Deberías ver entradas como kyverno-policy-validating-webhook y kyverno-resource-mutating-webhook.

Paso 2: Crear políticas para inyectar configuraciones CoCo

Kyverno usa ClusterPolicy para definir reglas globales. Creá un archivo coco-policies.yaml con las siguientes políticas:

Política 1: Inyectar runAsNonRoot y seccompProfile en todos los pods

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: inject-coco-security-context
  annotations:
    policies.kyverno.io/title: "Inyectar contexto de seguridad CoCo"
    policies.kyverno.io/severity: "high"
spec:
  validationFailureAction: enforce
  background: true
  rules:
    - name: require-non-root-and-seccomp
      match:
        resources:
          kinds:
            - Pod
      mutate:
        patchesJson6902: |-
          - op: add
            path: "/spec/securityContext/runAsNonRoot"
            value: true
          - op: add
            path: "/spec/securityContext/seccompProfile/type"
            value: "RuntimeDefault"

Aplicá la política:

kubectl apply -f coco-policies.yaml

> Resultado esperado:

> – Los pods nuevos deben incluir runAsNonRoot: true y seccompProfile: RuntimeDefault.

> – Si un pod no cumple, Kyverno lo rechazará con un error como:

>

> Error from server (failed to create pod: admission webhook "validate.kyverno.svc-fail" denied the request: resource Pod/default/mi-pod was blocked due to the following policies
> require-non-root-and-seccomp: validation error: Se requiere runAsNonRoot=true y seccompProfile: RuntimeDefault. rule require-non-root-and-seccomp failed at path /spec/securityContext/)
> 

Política 2: Validar que los pods usen un RuntimeClass CoCo

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-coco-runtimeclass
  annotations:
    policies.kyverno.io/title: "Validar RuntimeClass CoCo"
    policies.kyverno.io/severity: "critical"
spec:
  validationFailureAction: enforce
  background: true
  rules:
    - name: validate-runtimeclass
      match:
        resources:
          kinds:
            - Pod
      validate:
        message: "El pod debe usar un RuntimeClass de CoCo (ej: kata-qemu-sev)."
        pattern:
          spec:
            runtimeClassName: "kata-*"

Aplicá la política:

kubectl apply -f coco-policies.yaml

> Resultado esperado:

> – Los pods deben especificar un runtimeClassName que empiece con kata- (ej: kata-qemu-sev).

> – Si no lo incluyen, Kyverno rechazará el pod:

>

> Error from server (failed to create pod: admission webhook "validate.kyverno.svc-fail" denied the request: resource Pod/default/mi-pod was blocked due to the following policies
> require-coco-runtimeclass: validation error: El pod debe usar un RuntimeClass de CoCo. rule validate-runtimeclass failed at path /spec/runtimeClassName)
> 

Política 3: Rechazar pods con privileged: true (incompatible con CoCo)

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: reject-privileged-pods
  annotations:
    policies.kyverno.io/title: "Rechazar pods privilegiados en CoCo"
    policies.kyverno.io/severity: "critical"
spec:
  validationFailureAction: enforce
  background: true
  rules:
    - name: no-privileged-containers
      match:
        resources:
          kinds:
            - Pod
      validate:
        message: "Los pods en CoCo no pueden tener containers privilegiados."
        pattern:
          spec:
            containers:
            - securityContext:
                privileged: false
            initContainers:
            - securityContext:
                privileged: false

> Resultado esperado:

> – Cualquier pod con privileged: true será rechazado por Kyverno.

Paso 3: Probar las políticas con un manifiesto de ejemplo

Creá un archivo test-coco-pod.yaml con un pod válido para CoCo:

apiVersion: v1
kind: Pod
metadata:
  name: coco-test-pod
spec:
  runtimeClassName: kata-qemu-sev
  containers:
  - name: nginx
    image: nginx:latest
    securityContext:
      runAsNonRoot: true
      allowPrivilegeEscalation: false
      capabilities:
        drop: ["ALL"]
  securityContext:
    runAsNonRoot: true
    seccompProfile:
      type: RuntimeDefault

Aplicá el pod:

kubectl apply -f test-coco-pod.yaml

> Resultado esperado:

> – El pod se crea exitosamente.

> – Verificá que el runtime sea CoCo:

>

> kubectl get pod coco-test-pod -o jsonpath='{.spec.runtimeClassName}'
> # Debería devolver: kata-qemu-sev
> 

Paso 4: Probar un pod inválido (para verificar que Kyverno funciona)

Creá un archivo invalid-coco-pod.yaml:

apiVersion: v1
kind: Pod
metadata:
  name: invalid-coco-pod
spec:
  containers:
  - name: nginx
    image: nginx:latest
    securityContext:
      privileged: true  # Inválido para CoCo

Aplicá el pod:

kubectl apply -f invalid-coco-pod.yaml

> Resultado esperado:

> – Kyverno rechazará el pod con un error similar a:

>

> Error from server (failed to create pod: admission webhook "validate.kyverno.svc-fail" denied the request: resource Pod/default/invalid-coco-pod was blocked due to the following policies
> no-privileged-containers: validation error: Los pods en CoCo no pueden tener containers privilegiados. rule no-privileged-containers failed at path /spec/containers/0/securityContext/privileged)
> 

Paso 5: Inyectar configuraciones automáticamente en deployments

Para automatizar aún más el proceso, creá una política que muté los Deployments para inyectar el runtimeClassName y el contexto de seguridad:

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: mutate-deployments-for-coco
  annotations:
    policies.kyverno.io/title: "Mutar Deployments para CoCo"
    policies.kyverno.io/severity: "medium"
spec:
  validationFailureAction: enforce
  background: true
  rules:
    - name: mutate-deployment-spec
      match:
        resources:
          kinds:
            - Deployment
      mutate:
        patchesJson6902: |-
          - op: add
            path: "/spec/template/spec/runtimeClassName"
            value: "kata-qemu-sev"
          - op: add
            path: "/spec/template/spec/securityContext/runAsNonRoot"
            value: true
          - op: add
            path: "/spec/template/spec/securityContext/seccompProfile/type"
            value: "RuntimeDefault"

Aplicá la política:

kubectl apply -f coco-policies.yaml

> Resultado esperado:

> – Un Deployment nuevo se creará con las configuraciones CoCo inyectadas automáticamente.

> – Verificá con:

>

> kubectl get deployment mi-deployment -o yaml | grep -A5 "spec:"
> 

Consideraciones y buenas prácticas

Limitaciones conocidas

  1. Kyverno en el plano de control no confiable:
– Kyverno no es parte del modelo de confianza de CoCo. Su rol es automatizar la infraestructura, pero la seguridad final depende de:

– La remote attestation del runtime (ej: Kata Containers).

– La configuración correcta del RuntimeClass (ver Kata CoCo docs).

Solución: No uses Kyverno para decisiones de seguridad críticas. Úsalo solo para simplificar la experiencia del desarrollador.

  1. Rendimiento:
– Kyverno añade latencia en el admission controller (típicamente <100ms por validación). En clusters grandes, esto puede afectar la escalabilidad.

Solución: Usá políticas optimizadas (ej: validationFailureAction: audit para reglas que no sean críticas) y solo valida lo necesario.

  1. Compatibilidad con herramientas externas:
– Algunas herramientas (ej: Istio, Linkerd) pueden modificar los pods después de que Kyverno los valide.

Solución: Ordená los admission controllers con mutating webhooks para que Kyverno actúe antes que otras herramientas.

Alternativas y extensiones

HerramientaUso recomendadoLimitaciones
**OPA (Open Policy Agent)**Para políticas complejas fuera de Kubernetes (ej: validar imágenes en CI/CD).Requiere un *admission controller* adicional.
**Gatekeeper**Para políticas basadas en OPA, con mejor soporte para *deny-all*.Menos flexible para mutaciones.
**Kustomize + Kyverno**Para generar manifiestos con configuraciones CoCo pre-definidas.Requiere que los equipos usen Kustomize.
### Monitoreo y debugging
  1. Ver logs de Kyverno:
   kubectl logs -n kyverno deploy/kyverno
   

Buscá errores como:

   failed to process policy: failed to apply policy: ...
   
  1. Ver eventos de rechazo:
   kubectl get events --sort-by='.lastTimestamp' | grep "admission webhook"
   
  1. Políticas de ejemplo:
Kyverno Policy Library (filtro «Confidential Computing»)

CoCo Community Demo (el segmento de demo empieza en 18:00).

Seguridad adicional

  • Rotar certificados de Kyverno:
Kyverno usa certificados para el admission controller. Rotalos periódicamente:
  kubectl delete secret kyverno-svc.kyverno.svc.tls -n kyverno
  kubectl rollout restart deployment -n kyverno kyverno
  
  • Limitar permisos de Kyverno:
Kyverno necesita permisos mínimos. Usá un ServiceAccount dedicado:
  apiVersion: rbac.authorization.k8s.io/v1
  kind: ClusterRole
  metadata:
    name: kyverno:policy:admin
  rules:
  - apiGroups: ["kyverno.io"]
    resources: ["clusterpolicies"]
    verbs: ["create", "update", "delete", "get", "list"]
  ---
  apiVersion: rbac.authorization.k8s.io/v1
  kind: ClusterRoleBinding
  metadata:
    name: kyverno:policy:admin
  subjects:
  - kind: ServiceAccount
    name: kyverno
    namespace: kyverno
  roleRef:
    kind: ClusterRole
    name: kyverno:policy:admin
    apiGroup: rbac.authorization.k8s.io
  

Conclusión

Automatizar la infraestructura de Confidential Containers (CoCo) con Kyverno permite:

  1. Reducir errores manuales: Inyección automática de configuraciones como runAsNonRoot, seccompProfile, y runtimeClassName.
  2. Validar temprano: Rechazar pods inválidos antes de que sean creados.
  3. Escalar con seguridad: Estandarizar requisitos de CoCo en todo el cluster sin sacrificar productividad.

El enfoque correcto es:

  • Kyverno para automatizar la infraestructura.
  • Runtime CoCo (ej: Kata) para la seguridad final.
  • Remote attestation para verificar la integridad del pod.

Con esta configuración, los equipos de desarrollo pueden enfocarse en el código, mientras que la plataforma garantiza que todos los workloads cumplan con el modelo de confianza cero de CoCo.

Fuentes

Deja una respuesta

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