Escrever o código da função de conexão do CloudFront para validação de TLS mútua (visualizador)
As funções de conexão do CloudFront possibilitam escrever funções leves em JavaScript para validação de certificados mTLS e lógica de autenticação personalizada. O código da função de conexão pode validar certificados de cliente, implementar regras de autenticação específicas do dispositivo, lidar com cenários de revogação de certificados e tomar decisões para permitir/negar conexões TLS nos locais da borda do CloudFront ao redor do mundo.
As funções de conexão oferecem um método eficaz para estender a validação integrada de certificados do CloudFront com sua própria lógica de negócios. Diferentemente das funções de solicitação de visualizador e resposta ao visualizador que processam dados HTTP, as funções de conexão operam na camada de TLS e têm acesso a informações do certificado, ao endereço IP do cliente e a detalhes da conexão TLS. Isso as torna ideais para implementar modelos de segurança de confiança zero, sistemas de autenticação de dispositivos e políticas personalizadas de validação de certificados que vão além da validação padrão de PKI.
O código da função de conexão é executado em um ambiente seguro e isolado com tempos de inicialização de menos de 1 milissegundo e pode ser escalado para lidar com milhões de conexões por segundo. O runtime é otimizado para workloads de validação de certificados e oferece integração incorporada com o KeyValueStore do CloudFront para operações de pesquisa de dados em tempo real, permitindo cenários de autenticação sofisticados, como verificação da lista de revogação de certificados e validação da lista de permissões de dispositivos.
Para escrever um código de função de conexão eficaz, consulte os tópicos a seguir para obter ajuda. Para ver exemplos completos de código e tutoriais detalhados, consulte as seções do tutorial neste guia e explore os exemplos de função de conexão disponíveis no console do CloudFront.
Tópicos
Casos de uso e propósitos das funções de conexão do CloudFront
Estrutura de eventos e formato de resposta da função de conexão do CloudFront
Recursos do runtime do JavaScript para funções de conexão do CloudFront
Métodos auxiliares e APIs de função de conexão do CloudFront
Integração entre o KeyValueStore e a função de integração do CloudFront
Casos de uso e propósitos das funções de conexão do CloudFront
Antes de escrever uma função de conexão do CloudFront, determine cuidadosamente que tipo de validação de certificados ou lógica de autenticação é necessário implementar. As funções de conexão são projetadas para casos de uso específicos que exigem validação personalizada além da verificação padrão de certificados PKI. Entender seu caso de uso ajuda a criar um código eficiente que atenda aos seus requisitos de segurança e, ao mesmo tempo, mantenha o desempenho ideal.
Entre os casos de uso comuns de função de conexão estão:
-
Tratamento de revogação de certificados: implemente políticas personalizadas para lidar com certificados revogados, como períodos de carência para alternância de certificados, exceções de rede confiável para dispositivos internos ou cenários de acesso de emergência em que certificados revogados possam precisar de acesso temporário.
-
Suporte opcional à mTLS: gerencie conexões mTLS e não mTLS com políticas de autenticação diferentes para oferecer segurança aprimorada a clientes que usam certificados e, ao mesmo tempo, manter a compatibilidade com clientes legados.
-
Autenticação baseada em IP: combine a validação de certificados com as verificações de endereço IP de clientes para aumentar a segurança restringindo, por exemplo, o acesso de regiões geográficas específicas, redes empresariais ou intervalos de IP mal-intencionados conhecidos.
-
Validação de certificado multilocatário: implemente regras de validação específicas de locatário, nas quais diferentes autoridades de certificação ou critérios de validação se aplicam com base no emissor do certificado do cliente ou nos atributos do assunto.
-
Controle de acesso baseado em tempo: aplique restrições com base no tempo em situações em que os certificados são válidos somente durante horários, janelas de manutenção ou períodos comerciais específicos, mesmo que o certificado em si não tenha expirado.
As funções de conexão são executadas depois que o CloudFront realiza a validação padrão de certificados (verificação da cadeia de confiança, verificações de expiração e validação de assinatura), mas antes do estabelecimento da conexão TLS. Com essa regulação de tempo, você tem flexibilidade para adicionar critérios de validação personalizados e, ao mesmo tempo, se beneficiar da validação de certificados integrada do CloudFront. A função recebe os resultados da validação padrão e pode tomar decisões respaldadas sobre se deve permitir ou negar a conexão com base em critérios padrão e personalizados.
Ao projetar sua função de conexão, considere as implicações de desempenho da lógica de validação. Como as funções têm um limite de execução de 5 milissegundos, as e necessário otimizar operações complexas para ganhar velocidade. Use o KeyValueStore para pesquisas rápidas de dados em vez de cálculos complexos e estruture a lógica de validação para antecipar-se à falha no caso de certificados inválidos.
Estrutura de eventos e formato de resposta da função de conexão do CloudFront
As funções de conexão do CloudFront recebem uma estrutura de eventos diferente das funções de solicitação de visualizador e de resposta ao visualizador. Em vez de dados de solicitação/resposta HTTP, as funções de conexão recebem informações de certificado e conexão que podem ser usadas para tomar decisões de autenticação.
Estrutura de eventos para funções de conexão
As funções de conexão recebem um objeto de evento que contém informações de certificado e conexão. A estrutura de eventos da função é mostrada abaixo:
{ "clientCertificate": { "certificates": { "leaf": { "serialNumber": "string", "issuer": "string", "subject": "string", "validity": { "notBefore": "string", "notAfter": "string", }, "sha256Fingerprint": "string" } } }, "clientIp": "string", "endpoint": "string", "distributionId": "string", "connectionId": "string" }
Abaixo é apresentado um exemplo da estrutura do objeto de evento:
{ "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 resposta da função de conexão
A função de conexão deve exibir um objeto de resposta que indique se a conexão deve ser permitida ou negada. Use os métodos auxiliares para tomar decisões sobre conexão:
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(); } }
Diferentemente das funções de solicitação de visualizador e resposta ao visualizador, as funções de conexão não podem modificar solicitações ou respostas HTTP. Elas só podem permitir ou negar a conexão TLS.
Recursos do runtime do JavaScript para funções de conexão do CloudFront
As funções de conexão do CloudFront usam o Runtime 2.0 do JavaScript para o CloudFront Functions, que oferece um ambiente seguro e de alto desempenho especificamente otimizado para workloads de validação de certificados. O runtime foi projetado para ser iniciado em menos de 1 milissegundo e processar milhões de execuções simultâneas na rede de borda global do CloudFront.
O ambiente de runtime inclui suporte abrangente à linguagem JavaScript:
-
Suporte ao ECMAScript 2020 (ES11): Recursos modernos de JavaScript, como encadeamento opcional (?.), coalescência nula (??) e BigInt, para processar números de série extensos de certificado.
-
Objetos integrados: objetos JavaScript padrão, como Object, Array, JSON, Math e Date.
-
Registro em log do console: use console.log() para depurar e monitorar decisões de validação de certificados. Os logs são disponibilizados em tempo real durante o teste e podem ajudar a solucionar problemas de lógica de validação no desenvolvimento.
-
Integração com o KeyValueStore: acesso nativo ao KeyValueStore do CloudFront para operações de pesquisa de dados ultrarrápidas, o que permite a verificação de revogação de certificados em tempo real, a validação da lista de permissões de dispositivos e a recuperação da configuração específica do locatário.
As funções de conexão são otimizadas para oferecer alto desempenho em cenários de validação de certificados. O runtime gerencia automaticamente o gerenciamento de memória, a coleta de resíduos e a limpeza de recursos para garantir um desempenho consistente em milhões de conexões simultâneas. Todas as operações são projetadas para serem determinísticas e rápidas. Prova disso são as pesquisas no KeyValueStore, que normalmente são concluídas em questão de microssegundos.
O ambiente de runtime é completamente isolado entre as execuções de função, garantindo que não haja vazamento de dados entre diferentes conexões de cliente. Cada execução de função começa com um estado limpo e não tem acesso aos resultados da execução anterior ou aos dados do cliente de outras conexões.
Métodos auxiliares e APIs de função de conexão do CloudFront
As funções de conexão do CloudFront oferecem métodos auxiliares especializados projetados para simplificar as decisões de validação de certificados e aprimorar a observabilidade. Esses métodos são otimizados para o fluxo de trabalho de validação de conexão e se integram perfeitamente aos sistemas de monitoramento e registro em log de conexões do CloudFront.
-
connection.allow(): permite que a conexão TLS continue. Esse método sinaliza ao CloudFront para concluir o handshake do TLS e permitir que o cliente estabeleça a conexão. Use-o quando a validação do certificado for aprovada e qualquer lógica de autenticação personalizada for satisfeita.
-
connection.deny(): nega a conexão TLS e encerra o handshake. Esse método encerra imediatamente a conexão e impede que qualquer tráfego HTTP flua. O cliente receberá um erro de conexão TLS. Use-o para certificados inválidos, falha na autenticação ou violações de política.
-
connection.logCustomData (): adiciona dados personalizados aos logs de conexão (até 800 bytes de texto UTF-8). Esse método permite incluir resultados de validação, detalhes do certificado ou justificação de decisão nos logs de conexão do CloudFront para monitoramento de segurança, auditoria de conformidade e solução de problemas.
Esses métodos oferecem uma interface limpa e declarativa para tomar decisões de conexão e registrar em log informações relevantes para monitoramento e depuração. O padrão de permitir/negar garante que a intenção da função seja clara e que o CloudFront possa otimizar o tratamento de conexões com base em sua decisão. Os dados de registro em log personalizado estão imediatamente disponíveis nos logs de conexão do CloudFront e podem ser usados com ferramentas de análise de log para monitoramento de segurança e insights operacionais.
Sempre chame connection.allow() ou connection.deny() antes que sua função seja concluída. Se nenhum método for chamado, o CloudFront negará a conexão por padrão como medida de segurança.
Integração entre o KeyValueStore e a função de integração do CloudFront
As funções de conexão do CloudFront podem usar o KeyValueStore do CloudFront para realizar pesquisas de dados ultrarrápidas em cenários de validação de certificados. O KeyValueStore é particularmente eficaz para funções de conexão porque oferece acesso global e com consistência final aos dados com tempos de pesquisa de microssegundos em todos os locais da borda do CloudFront. Isso o torna ideal para manter listas de revogação de certificados, listas de permissões de dispositivos, configurações de locatários e outros dados de validação que precisam estar acessíveis durante o handshake do TLS.
A integração do KeyValueStore foi projetada especificamente para fluxos de trabalho de validação de conexão de alto desempenho:
-
KVSHandle.exists (key): verifica se existe uma chave no KeyValueStore sem recuperar o valor. Esse é o método mais eficiente para cenários de validação binária, como verificação de revogação de certificados, em que somente é necessário saber se o número de série do certificado está em uma lista de revogação.
-
KVSHandle.get(key): recupera um valor do KeyValueStore para cenários de validação mais complexos. Use-o quando precisar acessar dados de configuração, regras de validação ou metadados associados a um certificado ou identificador de dispositivo.
As operações do KeyValueStore são assíncronas e devem ser usadas com a sintaxe async/await. O KeyValueStore tem um limite de tamanho total de 10 MB e comporta até 10 milhões de pares de chave-valor. Os dados do KeyValueStore têm consistência final em todos os locais da borda e as atualizações normalmente se propagam em questão de segundos.
Para ter um desempenho ideal, estruture as chaves do KeyValueStore para minimizar as operações de pesquisa. Use o número de série dos certificados como chave para simplificar a verificação de revogação ou crie chaves compostas combinando o hash do emissor e o número de série para ambientes com várias CAs. Considere as vantagens e desvantagens entre a complexidade das chaves e a capacidade do KeyValueStore ao projetar sua estrutura de dados.
Utilizar async e await
As funções de conexão permitem operações assíncronas usando a sintaxe async/await, que é essencial ao trabalhar com operações do KeyValueStore ou outras tarefas assíncronas. O padrão async/await garante que a função aguarde a conclusão das pesquisas do KeyValueStore antes de tomar decisões de conexão, mantendo as características de alto desempenho necessárias para o processamento de handshake do TLS.
O uso adequado de async/await é fundamental para as funções de conexão porque as operações do KeyValueStore, embora muito rápidas, ainda são operações de rede que exigem coordenação em toda a infraestrutura distribuída do CloudFront. O runtime processa automaticamente a resolução de promises e garante que a função seja concluída dentro do limite de execução de 5 milissegundos.
exemplo : função de conexão async com o 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(); }
Sempre use async/await ao chamar métodos do KeyValueStore ou outras operações assíncronas. O runtime da função de conexão processa a resolução de promises automaticamente e garante o fluxo de execução adequado, de acordo com as rígidas restrições de tempo de processamento de handshake do TLS. Evite usar .then() ou padrões de retorno de chamada, pois async/await oferece um tratamento de erros mais claro e melhor desempenho no ambiente da função de conexão.
Ao criar funções de conexão assíncronas, estruture o código para minimizar o número de operações do KeyValueStore e execute-as o mais cedo possível em sua lógica de validação. Isso garante máximo desempenho e reduz o risco de problemas de tempo limite durante períodos de tráfego intenso. Considere a possibilidade de agrupar verificações de validação relacionadas em lote e usar o método do KeyValueStore [exists() versus get()] mais eficiente para seu caso de uso.
Exemplo de código de função de conexão
Os exemplos a seguir demonstram padrões de função de conexão comuns para diferentes cenários de validação. Use esses exemplos como pontos de partida para suas próprias implementações de função de conexão.
exemplo : validação de certificado de dispositivo
Este exemplo valida números de série de dispositivo e campos de assunto de certificado para dispositivos de IoT, consoles de jogos e outros cenários de autenticação 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(); }
Essa função executa várias verificações de validação, além da validação padrão de certificados, como o formato do número de série do dispositivo e a verificação da unidade organizacional.
exemplo : mTLS opcional com autenticação mista
Este exemplo lida com conexões mTLS e não mTLS com políticas de autenticação 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(); } }
Essa função oferece segurança aprimorada para clientes com certificados, mantendo a compatibilidade com clientes legados de intervalos de IP confiáveis.