From db15f5582359410a1ba08b2cffa71416df3cee47 Mon Sep 17 00:00:00 2001 From: Joel Alvarez Date: Mon, 27 Jul 2026 13:44:56 -0700 Subject: [PATCH] docs: add API security material --- diagrams/09-seguridad-de-apis.mmd | 7 ++++ docs/09-seguridad-de-apis.md | 65 +++++++++++++++++++++++++++++-- examples/09-seguridad-de-apis.rs | 14 +++++++ 3 files changed, 83 insertions(+), 3 deletions(-) create mode 100644 diagrams/09-seguridad-de-apis.mmd create mode 100644 examples/09-seguridad-de-apis.rs diff --git a/diagrams/09-seguridad-de-apis.mmd b/diagrams/09-seguridad-de-apis.mmd new file mode 100644 index 0000000..e535b7e --- /dev/null +++ b/diagrams/09-seguridad-de-apis.mmd @@ -0,0 +1,7 @@ +flowchart LR + I[Entrada no confiable] --> V{Forma y tamaño válidos} + V -->|No| S[Mensaje seguro de rechazo] + V -->|Sí| A{Acción y recurso autorizados} + A -->|No| D[Denegación sin datos ajenos] + A -->|Sí| E[Ejecutar capacidad] + E --> L[Registrar señal sin secreto] diff --git a/docs/09-seguridad-de-apis.md b/docs/09-seguridad-de-apis.md index b1ada5f..476603c 100644 --- a/docs/09-seguridad-de-apis.md +++ b/docs/09-seguridad-de-apis.md @@ -66,11 +66,70 @@ curso adopta la tercera alternativa. 4. ¿Qué señal diferenciaría uso legítimo de abuso automatizado? 5. ¿Qué evidencia permite investigar un incidente sin registrar un secreto? +## De la entrada a la frontera + +Una frontera segura valida antes de ejecutar y decide qué error puede conocer +el consumidor. Los detalles internos ayudan a depurar al proveedor, pero no +deben viajar junto con datos sensibles ni convertirse en una pista para abuso. + +```mermaid +flowchart LR + I[Entrada no confiable] --> V{Forma y tamaño válidos} + V -->|No| S[Mensaje seguro de rechazo] + V -->|Sí| A{Acción y recurso autorizados} + A -->|No| D[Denegación sin datos ajenos] + A -->|Sí| E[Ejecutar capacidad] + E --> L[Registrar señal sin secreto] +``` + +El archivo fuente está en +[`diagrams/09-seguridad-de-apis.mmd`](../diagrams/09-seguridad-de-apis.mmd). +El rechazo es parte del contrato: evita ejecutar datos inválidos y evita usar +un mensaje interno como respuesta para el consumidor. + +## Implementación + +El módulo [`security_boundary`](../src/security_boundary.rs) representa una +frontera por sensibilidad de entrada y exposición de error. Rechaza valores +vacíos o extensos y prohíbe configurar detalles internos para una entrada +sensible. + +No cifra datos ni identifica ataques por sí solo. Hace verificable una regla +previa: una frontera de información sensible solo puede entregar mensajes +seguros a quien consume la API. + +## Ejemplo: rechazar sin filtrar + +```rust +use rust_api_design::security_boundary::{ + DataSensitivity, ErrorExposure, SecurityBoundary, +}; + +let boundary = SecurityBoundary::new( + "importe", + DataSensitivity::Sensitive, + ErrorExposure::SafeMessage, +)?; + +assert!(boundary.rejects("")); +# Ok::<(), rust_api_design::security_boundary::SecurityError>(()) +``` + +El ejemplo ejecutable está en +[`examples/09-seguridad-de-apis.rs`](../examples/09-seguridad-de-apis.rs). +La entrada se rechaza sin incluir consultas, rutas internas o secretos en la +respuesta. + +## Pruebas + +Las pruebas aceptan una frontera sensible con mensaje seguro, rechazan detalles +internos y rechazan entradas extensas. No sustituyen un análisis de amenazas; +protegen la condición mínima que evita exponer una frontera interna. + ## Siguiente paso -El modelo Rust del capítulo representará una frontera de API por entrada, -sensibilidad y exposición de error. No implementará criptografía ni un WAF; -hace visible qué combinación de datos y respuesta debe rechazarse. +El siguiente bloque añadirá práctica, solución ejecutable y una decisión de +benchmark. Después el curso cerrará con estrategia de APIs para sistemas reales. ## Decisiones registradas diff --git a/examples/09-seguridad-de-apis.rs b/examples/09-seguridad-de-apis.rs new file mode 100644 index 0000000..40b29e3 --- /dev/null +++ b/examples/09-seguridad-de-apis.rs @@ -0,0 +1,14 @@ +//! Ejemplo ejecutable del capítulo 9: validar sin filtrar detalles internos. + +use rust_api_design::security_boundary::{DataSensitivity, ErrorExposure, SecurityBoundary}; + +fn main() -> Result<(), Box> { + let boundary = SecurityBoundary::new( + "importe", + DataSensitivity::Sensitive, + ErrorExposure::SafeMessage, + )?; + + println!("¿La entrada vacía se rechaza? {}", boundary.rejects("")); + Ok(()) +}