Escritura de código de función de conexión de CloudFront para la validación de TLS mutua (espectador) - Amazon CloudFront

Escritura de código de función de conexión de CloudFront para la validación de TLS mutua (espectador)

Las funciones de conexión de CloudFront permiten escribir funciones de JavaScript sencillas para la validación de certificados de mTLS y la lógica de autenticación personalizada. El código de la función de conexión puede validar los certificados de los clientes, implementar reglas de autenticación específicas del dispositivo, gestionar escenarios de revocación de certificados y tomar decisiones de permitir o denegar las conexiones TLS en las ubicaciones periféricas de CloudFront de todo el mundo.

Las funciones de conexión proporcionan una forma eficaz de ampliar la validación de certificados integrada en CloudFront con su propia lógica empresarial. A diferencia de las funciones de solicitud y respuesta del espectador que procesan datos HTTP, las funciones de conexión funcionan en la capa de TLS y tienen acceso a la información del certificado, a las direcciones IP del cliente y a los detalles de la conexión de TLS. Esto las hace ideales para implementar modelos de seguridad de confianza cero, sistemas de autenticación de dispositivos y políticas de validación de certificados personalizadas que van más allá de la validación estándar de PKI.

El código de la función de conexión se ejecuta en un entorno seguro y aislado con tiempos de inicio de submilisegundos y se puede escalar para gestionar millones de conexiones por segundo. El tiempo de ejecución está optimizado para las cargas de trabajo de validación de certificados y proporciona una integración integrada con CloudFront KeyValueStore para operaciones de búsqueda de datos en tiempo real, lo que permite escenarios de autenticación sofisticados, como la comprobación de la lista de revocación de certificados y la validación de la lista de dispositivos permitidos.

Como ayuda para escribir código de la función de conexión eficaz, consulte los siguientes temas. Para ver ejemplos de código completos y tutoriales paso a paso, consulte las secciones de tutoriales de esta guía y explore los ejemplos de funciones de conexión disponibles en la consola de CloudFront.

Casos de uso y finalidades de la función de conexión de CloudFront

Antes de escribir la función de conexión de CloudFront, determine cuidadosamente qué tipo de lógica de autenticación o validación de certificados debe implementar. Las funciones de conexión están diseñadas para casos de uso específicos que requieren una validación personalizada más allá de la comprobación estándar de los certificados de PKI. La comprensión del caso de uso lo ayuda a diseñar un código eficiente que cumpla con los requisitos de seguridad y, al mismo tiempo, mantenga un rendimiento óptimo.

Los casos de uso comunes de la función de conexión incluyen:

  • Gestión de la revocación de certificados: implemente políticas personalizadas para gestionar los certificados revocados, incluidos los periodos de gracia para la rotación de los certificados, las excepciones de redes de confianza para los dispositivos internos o los escenarios de acceso de emergencia en los que los certificados revocados podrían necesitar un acceso temporal.

  • Compatibilidad con mTLS opcional: gestione las conexiones de mTLS y las que no lo son con políticas de autenticación diferentes, lo que permite ofrecer una mayor seguridad a los clientes que admiten certificados y, al mismo tiempo, mantener la compatibilidad con los clientes antiguos.

  • Autenticación basada en IP: combine la validación de los certificados con las comprobaciones de las direcciones IP de los clientes para mejorar la seguridad, por ejemplo, restringiendo el acceso desde regiones geográficas específicas, redes corporativas o rangos de IP maliciosos conocidos.

  • Validación de certificados multiusuario: implemente reglas de validación específicas para cada inquilino en las que se apliquen diferentes autoridades de certificación o criterios de validación en función del emisor del certificado del cliente o de los atributos del sujeto.

  • Control de acceso basado en el tiempo: aplique restricciones basadas en el tiempo para que los certificados solo sean válidos durante horas, periodos de mantenimiento o periodos laborables específicos, incluso si el certificado en sí no ha caducado.

Las funciones de conexión se ejecutan después de que CloudFront lleve a cabo la validación estándar del certificado (verificación de la cadena de confianza, comprobaciones de caducidad y validación de firmas), pero antes de que se establezca la conexión de TLS. Este tiempo brinda la flexibilidad de agregar criterios de validación personalizados y, al mismo tiempo, beneficiarse de la validación de certificados integrada de CloudFront. La función recibe los resultados de la validación estándar y puede tomar decisiones fundamentadas sobre si permitir o denegar la conexión en función de criterios estándar y personalizados.

Al diseñar la función de conexión, tenga en cuenta las implicaciones de rendimiento de la lógica de validación. Las funciones tienen un límite de ejecución de 5 milisegundos, por lo que las operaciones complejas deben optimizarse para aumentar su velocidad. Utilice KeyValueStore para realizar búsquedas rápidas de datos en lugar de realizar cálculos complejos y estructure su lógica de validación para que los certificados no válidos respondan rápido a los errores.

Estructura de eventos y formato de respuesta de la función de conexión de CloudFront

Las funciones de conexión de CloudFront reciben una estructura de eventos diferente a la de las funciones de solicitud y respuesta del espectador. En lugar de datos de solicitud/respuesta HTTP, las funciones de conexión reciben información sobre certificados y conexiones que puede utilizar para tomar decisiones de autenticación.

Estructura de eventos para las funciones de conexión

Las funciones de conexión reciben un objeto de eventos que contiene el certificado y la información de conexión. La estructura de eventos de la función se muestra a continuación:

{ "clientCertificate": { "certificates": { "leaf": { "serialNumber": "string", "issuer": "string", "subject": "string", "validity": { "notBefore": "string", "notAfter": "string", }, "sha256Fingerprint": "string" } } }, "clientIp": "string", "endpoint": "string", "distributionId": "string", "connectionId": "string" }

A continuación, se muestra un ejemplo de la estructura del objeto de eventos:

{ "clientCertificate": { "certificates": { "leaf": { "serialNumber": "00:9e:2a:af:16:56:e5:47:25:7d:2e:38:c3:f9:9d:57:fa", "issuer": "C=US, O=Ram, OU=Edge, ST=WA, CN=mTLS-CA, L=Snoqualmie", "subject": "C=US, O=Ram, OU=Edge, ST=WA, CN=mTLS-CA, L=Snoqualmie", "validity": { "notBefore": "2025-09-10T23:43:10Z", "notAfter": "2055-09-11T00:43:02Z" }, "sha256Fingerprint": "_w6bJ7aOAlGOj7NUhJxTfsfee-ONg_xop3_PTgTJpqs=" } } }, "clientIp": "127.0.0.1", "endpoint": "d3lch071jze0cb.cloudfront.net", "distributionId": "E1NXS4MQZH501R", "connectionId": "NpvTe1925xfj24a67sPQr7ae42BIq03FGhJJKfrQYWZcWZFp96SIIg==" }

Formato de respuesta de funciones de conexión

La función de conexión debe devolver un objeto de respuesta que indique si se va a permitir o denegar la conexión. Utilice los métodos auxiliares para tomar decisiones de conexión:

function connectionHandler(connection) { // Helper methods to allow or deny connections if (/* some logic to determine if function should allow connection */) { connection.allow(); } else { connection.deny(); } }

A diferencia de las funciones de solicitud y respuesta del espectador, las funciones de conexión no pueden modificar las solicitudes o respuestas HTTP. Solo pueden permitir o denegar la conexión de TLS.

Características del tiempo de ejecución de JavaScript de funciones de conexión de CloudFront

Las funciones de conexión de CloudFront utilizan el tiempo de ejecución de JavaScript 2.0 de CloudFront Functions, que proporciona un entorno seguro y de alto rendimiento optimizado específicamente para las cargas de trabajo de validación de certificados. El tiempo de ejecución está diseñado para comenzar en submilisegundos y gestionar millones de ejecuciones simultáneas en la red de periferia global de CloudFront.

El entorno de tiempo de ejecución incluye una amplia compatibilidad con el lenguaje de JavaScript:

  • Compatibilidad con ECMAScript 2020 (ES11): características modernas de JavaScript que incluyen el encadenamiento opcional (?.), la fusión de NULL (??), y BigInt para gestionar números de serie de certificados de gran tamaño.

  • Objetos integrados: objetos de JavaScript estándar como Object, Array, JSON, Math y Date.

  • Registro de consola: utilice console.log() para depurar y supervisar las decisiones de validación de certificados. Los registros están disponibles en tiempo real durante las pruebas y pueden ayudar a solucionar los problemas de la lógica de validación durante el desarrollo.

  • Integración con KeyValueStore: acceso nativo a CloudFront KeyValueStore para operaciones de búsqueda de datos ultrarrápidas, lo que permite comprobar la revocación de certificados en tiempo real, validar las listas de dispositivos permitidos y recuperar la configuración específica del inquilino.

Las funciones de conexión están optimizadas para ofrecer un alto rendimiento en los escenarios de validación de certificados. El tiempo de ejecución gestiona automáticamente la administración de la memoria, la recopilación de elementos no utilizados y la limpieza de recursos para garantizar un rendimiento coherente en millones de conexiones simultáneas. Todas las operaciones están diseñadas para ser deterministas y rápidas, y las búsquedas de KeyValueStore suelen completarse en microsegundos.

El entorno de tiempo de ejecución está completamente aislado entre las ejecuciones de las funciones, lo que garantiza que no se filtren datos entre las diferentes conexiones de los clientes. La ejecución de cada función comienza con un estado limpio y no tiene acceso a los resultados de la ejecución anterior ni a los datos del cliente desde otras conexiones.

API y métodos auxiliares de la función de conexión de CloudFront

Las funciones de conexión de CloudFront proporcionan métodos auxiliares especializados diseñados para simplificar las decisiones de validación de certificados y mejorar la observabilidad. Estos métodos están optimizados para el flujo de trabajo de validación de conexiones y se integran perfectamente con los sistemas de registro y supervisión de conexiones de CloudFront.

  • connection.allow(): permita que continúe la conexión de TLS. Este método indica a CloudFront que complete el establecimiento de comunicación de TLS y permita al cliente establecer la conexión. Úselo cuando se apruebe la validación del certificado y se cumpla cualquier lógica de autenticación personalizada.

  • connection.deny(): deniegue la conexión de TLS y finalice el establecimiento de comunicación. Este método cierra inmediatamente la conexión e impide que fluya el tráfico HTTP. El cliente recibirá un error de conexión de TLS. Úselo para los certificados no válidos, los errores de autenticación o las infracciones de las políticas.

  • connection.logCustomData(): agregue datos personalizados a los registros de conexión (hasta 800 bytes de texto UTF-8). Este método permite incluir los resultados de la validación, los detalles del certificado o el fundamento de la decisión en los registros de conexión de CloudFront para la supervisión de la seguridad, la auditoría de conformidad y la solución de problemas.

Estos métodos proporcionan una interfaz clara y declarativa para tomar decisiones de conexión y registrar la información relevante para la supervisión y la depuración. El patrón de permitir/denegar garantiza que la intención de la función sea clara y que CloudFront pueda optimizar la gestión de la conexión en función de la decisión. Los datos de registro personalizados están disponibles inmediatamente en los registros de conexión de CloudFront y se pueden utilizar con herramientas de análisis de registros para supervisar la seguridad y obtener información operativa.

Llame siempre a connection.allow() o connection.deny() antes de que finalice la función. Si no se llama a ninguno de los dos métodos, CloudFront denegará la conexión de forma predeterminada como medida de seguridad.

Integración de KeyValueStore con la función de conexión de CloudFront

Las funciones de conexión de CloudFront pueden usar KeyValueStore de CloudFront para realizar búsquedas de datos ultrarrápidas para escenarios de validación de certificados. KeyValueStore es especialmente eficaz para las funciones de conexión, ya que proporciona un acceso a los datos global y, en última instancia, coherente con tiempos de búsqueda de microsegundos en todas las ubicaciones periféricas de CloudFront. Esto lo hace ideal para mantener listas de revocación de certificados, listas de dispositivos permitidos, configuraciones de inquilinos y otros datos de validación a los que es necesario acceder durante los establecimientos de comunicación de TLS.

La integración de KeyValueStore está diseñada específicamente para flujos de trabajo de validación de conexiones de alto rendimiento:

  • kvsHandle.exists(clave): compruebe si existe una clave en el KeyValueStore sin recuperar el valor. Este es el método más eficaz para los escenarios de validación binaria, como la comprobación de la revocación de certificados, en los que solo necesita saber si el número de serie de un certificado está en una lista de revocaciones.

  • kvsHandle.get(clave): recupere un valor del KeyValueStore para escenarios de validación más complejos. Úselo cuando necesite acceder a los datos de configuración, las reglas de validación o los metadatos asociados a un certificado o identificador de dispositivo.

Las operaciones de KeyValueStore son asíncronas y deben usarse con la sintaxis async/await. El KeyValueStore tiene un límite de tamaño total de 10 MB y admite hasta 10 millones de pares clave-valor. Con el tiempo, los datos de KeyValueStore son coherentes en todas las ubicaciones periféricas y, por lo general, las actualizaciones se propagan en cuestión de segundos.

Para obtener un rendimiento óptimo, estructure las claves de KeyValueStore para minimizar las operaciones de búsqueda. Utilice los números de serie de los certificados como claves para comprobar las revocaciones de forma sencilla o cree claves compuestas que combinen el hash del emisor y el número de serie para entornos con varias autoridades de certificación. Tenga en cuenta las ventajas y desventajas entre la complejidad de las claves y la capacidad de KeyValueStore al diseñar la estructura de datos.

Uso de async y await

Las funciones de conexión admiten operaciones asíncronas mediante la sintaxis de async/await, que es esencial cuando se trabaja con operaciones de KeyValueStore u otras tareas asincrónicas. El patrón async/await garantiza que la función espere a que se completen las búsquedas en KeyValueStore antes de tomar decisiones de conexión, a la vez que mantiene las características de alto rendimiento necesarias para el procesamiento del establecimiento de comunicación de TLS.

El uso adecuado de la función async/await es fundamental para las funciones de conexión, ya que las operaciones de KeyValueStore, si bien son muy rápidas, siguen siendo operaciones de red que requieren la coordinación de toda la infraestructura distribuida de CloudFront. El tiempo de ejecución gestiona automáticamente la resolución prometida y garantiza que la función se complete dentro del límite de ejecución de 5 milisegundos.

ejemplo : función de conexión asíncrona con KeyValueStore
import cf from 'cloudfront'; async function connectionHandler(connection) { const kvsHandle = cf.kvs(); // Async operation to check KeyValueStore for certificate revocation const isRevoked = await kvsHandle.exists(connection.clientCertificate.certificates.leaf.serialNumber); if (isRevoked) { // Log the revocation decision with certificate details connection.logCustomData(`REVOKED_CERT:${connection.clientCertificate.certificates.leaf.serialNumber}:${connection.clientCertificate.certificates.leaf.issuer}`); console.log(`Denying connection for revoked certificate: ${connection.clientCertificate.certificates.leaf.serialNumber}`); return connection.deny(); } // Log successful validation for monitoring connection.logCustomData(`VALID_CERT:${connection.clientCertificate.certificates.leaf.serialNumber}`); console.log(`Allowing connection for valid certificate: ${connection.clientCertificate.certificates.leaf.serialNumber}`); return connection.allow(); }

Utilice siempre async/await al llamar a los métodos de KeyValueStore u otras operaciones asincrónicas. El tiempo de ejecución de la función de conexión gestiona automáticamente la resolución de las promesas y garantiza un flujo de ejecución adecuado dentro de las estrictas restricciones temporales del procesamiento de establecimiento de comunicación de TLS. Evite utilizar los patrones .then() o callback, ya que async/await permite gestionar los errores de forma más limpia y ofrece un mejor rendimiento en el entorno de la función de conexión.

Al diseñar funciones de conexión asíncronas, estructure el código para minimizar el número de operaciones de KeyValueStore y realícelas lo antes posible en su lógica de validación. Esto garantiza el máximo rendimiento y reduce el riesgo de problemas de tiempo de espera durante los periodos de tráfico alto. Considere agrupar las comprobaciones de validación relacionadas con los lotes y utilizar el método KeyValueStore más eficiente (exists() frente a get()) para el caso de uso.

Ejemplos de código de función de conexión

Los siguientes ejemplos muestran patrones de funciones de conexión comunes para diferentes escenarios comunes. Utilice estos ejemplos como puntos de partida para las propias implementaciones de funciones de conexión.

ejemplo : validación de certificados de dispositivo

Este ejemplo valida los números de serie de los dispositivos y los campos de asunto de los certificados para dispositivos IoT, consolas de juegos y otros escenarios de autenticación de clientes:

async function connectionHandler(connection) { // Custom validation: check device serial number format const serialNumber = connection.clientCertificate.certificates.leaf.serialNumber; if (!serialNumber.startsWith("DEV")) { connection.logCustomData(`INVALID_SERIAL:${serialNumber}`); return connection.deny(); } // Validate certificate subject contains required organizational unit const subject = connection.clientCertificate.certificates.leaf.subject; if (!subject.includes("OU=AuthorizedDevices")) { connection.logCustomData(`INVALID_OU:${subject}`); return connection.deny(); } // Allow connection for valid devices connection.logCustomData(`VALID_DEVICE:${serialNumber}`); return connection.allow(); }

Esta función realiza varias comprobaciones de validación además de la validación estándar del certificado, como el formato del número de serie del dispositivo y la verificación de la unidad organizativa.

ejemplo : mTLS opcionales con autenticación mixta

Este ejemplo gestiona las conexiones de mTLS y las que no lo son con políticas de autenticación diferentes:

async function connectionHandler(connection) { if (connection.clientCertificate) { // mTLS connection - enhanced validation for certificate holders const subject = connection.clientCertificate.certificates.leaf.subject; connection.logCustomData(`MTLS_SUCCESS:${subject}:${connection.clientIp}`); console.log(`mTLS connection from: ${subject}`); return connection.allow(); } else { // Non-mTLS connection - apply IP-based restrictions const clientIp = connection.clientIp; // Only allow non-mTLS from specific IP ranges if (clientIp.startsWith("203.0.113.") || clientIp.startsWith("198.51.100.")) { connection.logCustomData(`NON_MTLS_ALLOWED:${clientIp}`); console.log(`Non-mTLS connection allowed from: ${clientIp}`); return connection.allow(); } connection.logCustomData(`NON_MTLS_DENIED:${clientIp}`); return connection.deny(); } }

Esta función proporciona una seguridad mejorada para los clientes con certificados y, al mismo tiempo, mantiene la compatibilidad con los clientes antiguos de rangos de IP fiables.