Ir al contenido principal
Laravel, shipping fast.

Te fías de lo que te envía un tercero más de lo que te fiarías de un usuario.

Aquí: Statamic es, para esta API, una entrada. Sus respuestas son datos de fuera, y acaban en tus respuestas.

Qué lo impide: el Capítulo 3 trató al proveedor como no fiable desde la primera línea. License::fromProvider() valida cada carga y lanza MalformedProviderResponse, que el Capítulo 7 renderiza como un 502. El driver rechaza una respuesta cuyo data no sea una lista, así que una página de error en HTML no puede pasar por «ninguna licencia». El Resource decide qué campos se reenvían, así que un campo nuevo en el proveedor no se convierte en un campo nuevo de tu API. Cada llamada tiene un timeout, y ningún mensaje del proveedor se le repite jamás a un consumidor.

Cómo lo sabes: el test del Capítulo 12 en el que el proveedor omite un campo. Añade a sus primos: un campo del tipo equivocado, HTML donde se esperaba JSON, un 200 con el cuerpo vacío. La API debería responder a cada uno con un 502 y un código, nunca con un 500 y nunca con un 200.

Lo que la lista no cubre

Cuatro cosas quedan fuera de esa lista y corresponden a toda revisión.

Dependencias. Tu aplicación es en su mayor parte código de otras personas. composer audit contrasta cada paquete instalado con las vulnerabilidades conocidas, y el Capítulo 14 lo ejecuta en cada build.

Secretos. Conoce cada secreto que guarda la aplicación, dónde vive y cómo lo reemplazarías. La clave de aplicación merece una mirada especial: cifra los settings de cada consumidor, y el Capítulo 20 explica cómo rotarla sin perderlos.

Las señales de un ataque. Una ráfaga de 401 desde una dirección es alguien tanteando. Una ráfaga de 403 desde un token es alguien sondeando lo que puede hacer una credencial robada. Una ráfaga de 404 en una ruta es alguien recorriendo tus registros. Laravel no los reporta como errores, con razón. El log de peticiones del Capítulo 6 tiene el estado, la dirección y el ID del token en cada fila, así que cada una de esas señales es una consulta. Cuéntalas, y alerta cuando el recuento de un llamante se salga de lo normal.

Un registro de quién hizo qué. El log de peticiones muestra que alguien llamó a POST /consumers/7/tokens. No muestra qué habilidades se concedieron. Para las pocas acciones privilegiadas (emitir un token, revocar uno, borrar un consumidor), escribe una entrada de auditoría que diga quién, a quién y qué:

// app/Http/Controllers/TokenController.php, en store()
Log::channel('audit')->info('token.issued', [
    'by' => $request->user()->id,
    'for' => $consumer->id,
    'abilities' => $request->validated('abilities'),
]);

audit es un canal propio en config/logging.php, que se conserva más tiempo que el log de la aplicación y se envía a algún sitio donde la aplicación no pueda reescribirlo.

Una revisión que se repite

Una revisión hecha una sola vez describe una API que un mes después ya no existe. La forma útil es lo bastante pequeña para pasarla por cada endpoint nuevo, como parte del pull request:

  1. ¿Quién puede llamar a esto? ¿Qué habilidad o Policy, y está declarada en el controlador? ¿Tiene una fila en el test del llamante equivocado?
  2. ¿Qué registros puede tocar? ¿Hay una Policy, y un test con el llamante equivocado?
  3. ¿Qué campos puede leer y escribir? ¿Todo campo del Resource está pensado para salir, y toda regla del request para que este llamante pueda fijarla?
  4. ¿Qué es lo más grande que puede pedir? ¿Tiene un límite cada entrada?
  5. ¿Hace una petición, o guarda una URL? ¿De dónde sale la dirección?

Cinco preguntas, respondidas en el pull request que añade el endpoint.

Resumen del capítulo 19

  • Revisa el conjunto, sobre el papel, contra una lista de cómo se rompen de verdad las APIs. Los fallos de autorización encabezan esa lista.
  • Para cada ID de una URL, ten claro quién puede poner qué valor ahí, y prueba al llamante equivocado. Los bindings con ámbito no son autorización.
  • Todo controlador declara quién puede llamarlo. Lleva una tabla de rutas y llamantes rechazados, como un test.
  • El aislamiento de inquilinos mediante credenciales se sostiene solo si nada recurre a una cuenta compartida.
  • Controla los campos en las dos direcciones: un Resource a la salida, atributos validados y asignables a la entrada.
  • Dale un límite a cada entrada, cabeceras incluidas.
  • Quien llama solo puede conceder lo que tiene.
  • Protege las operaciones de negocio caras con límites de negocio, no solo con límites de peticiones.
  • Trata como hostil cualquier URL que aporte quien llama: solo HTTPS, todas las direcciones resueltas públicas, sin redirecciones, y ten claro qué deja eso todavía abierto.
  • Fija la configuración de producción a propósito, y lee tus respuestas de error como lo haría un atacante.
  • Borra lo que ya no necesites: versiones, tokens, endpoints.
  • Trata la respuesta de un proveedor como una entrada.
  • Cuenta los 401, los 403 y los 404, y audita las acciones privilegiadas.
  • Hazle las cinco preguntas a cada endpoint nuevo.

No se pudo cargar el audio. Inténtalo de nuevo en un momento.