Ir al contenido

Proyecto independiente de I+D · Colonia

Notas técnicas

Correcciones breves de errores de categoría frecuentes.

No normativo

Versión del Companion
1.0
Corresponde a COADF Core
2.2
Estado
Vigente
Última revisión

Cada nota corrige un error de categoría: dos cosas que se parecen y ofrecen cosas distintas.

OpenTelemetry no es una traza de auditoría

OpenTelemetry registra y propaga contexto de ejecución: qué llamadas hizo una petición, cuánto tardaron, dónde fallaron. Está diseñado para muestrearse, filtrarse y transformarse en el camino hacia un backend, y una traza que no se muestrea no se exporta; el filter processor del Collector descarta por configuración la telemetría que coincide. Su identidad es una ejecución, transportada en la cabecera W3C traceparent. Una traza de auditoría responde a otra pregunta sobre otra unidad: qué le ocurrió a una transacción de negocio, quién actuó y con qué evidencia, de forma completa y sin ediciones posteriores.

  • No muestrear, filtrar ni encaminar nunca entradas de auditoría a través de una pipeline de telemetría.
  • Correlacionar ambas: registrar el trace_id de auditoría en los spans como atributo. No reutilizar un identificador de traza distribuida como identidad de auditoría.
  • Clasificar aquello con lo que se correlaciona. Un atributo de span sale del almacén de auditoría hacia exportadores, proveedores y una retención propia: una referencia opaca, nunca datos personales ni un secreto.
  • Contar con que una transacción de negocio abarque varias trazas distribuidas: la petición de recepción, un job asíncrono, una decisión tomada días después.

OPA es un motor de políticas, no una autoridad reguladora

Open Policy Agent evalúa reglas que alguien escribió contra una entrada que alguien suministró. Desacopla la decisión de su aplicación, y eso es lo que permite gestionar las reglas como datos. No sabe lo que exige una normativa, y una regla escrita en Rego es exactamente tan correcta como la lectura del texto que codifica. La respuesta del motor es evidencia de que se aplicó una regla, nunca evidencia de que la regla fuera correcta.

  • Toda regla necesita un responsable, una fuente y una revisión, como cualquier otra interpretación de un texto.
  • Registrar la versión con cada decisión, para que una corrección posterior de la regla pueda distinguirse de las decisiones tomadas con la anterior.
  • Una suite de pruebas en verde para una política demuestra que la regla se comporta como pretendía su autor, y nada sobre si el autor leyó bien el texto.

Las políticas de admisión de Kubernetes no sustituyen la validación en la aplicación

El control de admisión intercepta las peticiones al servidor de API de Kubernetes después de la autenticación y la autorización, antes de que el objeto se persista. Ve Deployments, Pods y ConfigMaps, y las peticiones de lectura lo eluden por completo. Nunca ve las peticiones HTTP que atiende un servicio, los mensajes que consume ni las respuestas que devuelve un modelo. Juzga las peticiones a medida que llegan, algo que Kubernetes explica de forma expresa para un plugin de admisión: cuando se añade un LimitRange, los pods que ya existen siguen sin cambios.

  • Usar la admisión para propiedades de las cargas de trabajo: imágenes fijadas por digest, versiones nombradas, credenciales ausentes donde tienen que estar ausentes.
  • Mantener la validación de frontera en la aplicación, en cada punto de entrada que tenga.
  • Auditar por separado los objetos existentes, como hace la auditoría de Gatekeeper; la admisión solo ve cambios.

El event sourcing no es necesario para una evidencia de solo inserción

El event sourcing convierte un log de eventos de solo inserción en el sistema de registro y deriva el estado de él. Eso da una historia completa por construcción, a un precio considerable: cada modelo de lectura es una proyección, y cada cambio en la forma de un evento es una migración de la historia. Una traza de auditoría de solo inserción junto a un estado ordinario da lo que pide COADF P-4 (una historia a la que se añade y que nunca se reescribe, reconstruible en una consulta) sin cambiar cómo guarda su estado el resto del sistema. Los privilegios por operación y los triggers de rechazo bastan para construirla en PostgreSQL.

  • Elegir el event sourcing por razones propias del dominio, no para obtener una traza de auditoría.
  • Una tabla de solo inserción con un rol que solo puede insertar, triggers de rechazo y escrituras idempotentes realiza una evidencia de solo inserción sin event sourcing, dentro de la propia frontera de confianza de la base de datos.
  • En ambos casos, la entrada se escribe en la misma transacción que el cambio que registra.

Los microservicios no son necesarios para el aislamiento probabilístico

La frontera probabilística es una propiedad de los caminos de código: ningún camino permite que la salida de un modelo se convierta en un objeto autorizado sin un paso explícito y registrado. Una frontera de módulo que el build hace cumplir mantiene esa propiedad dentro de un solo proceso, con contratos de importación en Python o reglas de arquitectura como pruebas unitarias en Java. Una frontera de red añade una aplicación a nivel de infraestructura y, con ella, versionado de contratos, fallos parciales, reintentos y propagación de contexto entre saltos, que son lugares nuevos donde la propiedad puede perderse.

  • Desplegar el componente probabilístico por separado cuando lo pidan el escalado, el aislamiento de una biblioteca de un proveedor o las entregas independientes, no porque lo pida un principio.
  • Hacer cumplir la frontera de módulo con una prueba de arquitectura en cualquier caso.
  • Cuando la frontera es una red, validar de nuevo en el lado receptor.

El tipado estático no sustituye la validación en tiempo de ejecución en las fronteras externas

Un sistema de tipos comprueba el código contra sí mismo. En una frontera externa, los datos vienen de fuera del código: un modelo, un cliente, una cola. Las anotaciones de tipo de TypeScript se borran antes de que el programa se ejecute y JSON.parse está tipado como si devolviera any; el runtime de Python no hace cumplir las anotaciones de tipo; y un tipo de Java describe lo que se le pidió producir a un deserializador, no lo que envió el emisor. El tipo es una promesa que la frontera tiene que cumplir, en tiempo de ejecución, con un esquema.

  • Derivar el tipo estático del esquema de tiempo de ejecución siempre que el lenguaje lo permita.
  • Validar en cada lado receptor, no solo en el punto de entrada web.
  • Mantener los casts fuera del código de frontera: un cast es donde el sistema de tipos deja de comprobar.

Una pipeline de CI en verde no demuestra que un control sea suficiente para la arquitectura

Una pipeline en verde demuestra que pasaron las comprobaciones que ejecutó. No dice nada de las comprobaciones que se omitieron y se notificaron como exitosas, de las selecciones que no correspondieron a ninguna prueba, de los fences colocados en el camino equivocado ni de las propiedades para las que nadie escribió una comprobación. El modelo de informe de controles de COADF enuncia la misma regla desde el otro lado: un control se informa como impuesto solo cuando su evidencia se ejecutó en la ejecución identificada y pasó.

  • Registrar, en cada ejecución, qué comprobaciones se ejecutaron y cuántas aserciones se evaluaron.
  • Demostrar los dientes de cada fence en su camino real, y volver a demostrarlos cuando el camino cambia.
  • Revisar lo que no se comprueba con la misma seriedad que lo que sí.

COADF Engineering Companion 1.0 · no normativo · corresponde a COADF Core 2.2

Derechos de publicación reservados. Por ahora no se concede ninguna licencia pública para el COADF Engineering Companion 1.0 ni para sus ejemplos de referencia.

Estado de propiedad intelectual y de publicación