Functions no Firewall
Consulte o evento, os métodos e os metadados de requisição que uma função em um firewall usa para permitir, negar, descartar ou responder a uma requisição.
Uma função em um firewall é código JavaScript que o firewall executa em uma requisição quando uma das suas regras a chama. O código recebe a requisição como um evento firewall. Os métodos desse evento decidem o que acontece com a requisição: adicionam headers e a deixam seguir, a negam, a descartam ou a respondem. Para acompanhar uma requisição da regra até a função e de volta, consulte Como Firewall funciona.
Uma função em um firewall é executada antes da aplicação, então o código dela decide se uma requisição chega ou não à aplicação. O código que participa de servir uma requisição que o firewall permitiu roda em uma aplicação, a partir de uma função cujo ambiente de execução é application. Para a instância que coloca essa função em uma aplicação, consulte Instâncias de função.
Ambiente de execução
Toda função carrega um ambiente de execução, e um firewall executa somente uma função cujo ambiente é firewall. Você define o ambiente ao criar a função em Functions:
| Interface | Configuração | Valor para uma função de firewall |
|---|---|---|
| API | execution_environment, um campo da função | firewall |
| Azion CLI | --execution-environment, uma flag de azion create function | firewall |
O campo da API recebe application ou firewall, e o padrão é application. Uma função criada sem o campo é uma função de aplicação, e a API recusa uma instância dela em um firewall. A ajuda da CLI diz Either 'edge_application' or 'edge_firewall' para a flag. Nenhum dos dois valores está no enum da API, e a API recusa ambos. azion describe function --function-id <function-id> --format json imprime o campo de uma função existente, como "execution_environment": "application".
No Azion Console, o campo Function de uma instância de função lista somente as funções cujo ambiente é firewall.
Uma função com o ambiente firewall ainda não é executada em nenhuma requisição até que outros dois objetos apontem para ela. Uma instância de função coloca a função em um firewall, e uma regra cujo comportamento Run Function nomeia essa instância a chama. Para escrever essa regra, consulte Run Function.
O firewall também precisa ter Functions habilitado. Até que tenha, Azion Console oculta a aba Functions Instances do firewall e lista o comportamento como Run Function - required Functions, que não pode ser selecionado. O switch Functions fica na seção Modules da aba Main Settings do firewall. Um firewall criado pela API, pela CLI ou pela página de criação do Azion Console começa com Functions habilitado. O drawer de criação do Azion Console começa com ele desativado.
O evento firewall
Uma função em um firewall registra um listener para o evento firewall com addEventListener. O listener recebe o evento, que carrega a requisição em event.request e os métodos que decidem o que acontece com ela.
Para ler um header que a requisição já carrega, chame event.request.headers.get(<name>). O exemplo Functions em um firewall lê vários headers da requisição dessa forma para escolher o que o seu handler faz.
Toda função em um firewall precisa terminar com um resultado final, como event.continue(), event.deny() ou event.drop(). Para escrever condicionais que sempre chegam a um resultado, consulte Boas práticas de Firewall.
Métodos do evento
A tabela lista os métodos que uma função em um firewall chama no evento firewall, em ordem alfabética.
| Método | Argumentos | O que faz |
|---|---|---|
event.addRequestHeader() | Um nome de header e o seu valor | Adiciona o header à requisição que segue para a origem |
event.addResponseHeader() | Um nome de header e o seu valor | Adiciona o header à resposta que o usuário recebe |
event.args() | O nome de um argumento, como 'arg_name' | Lê esse argumento dos Arguments da instância de função |
event.continue() | Nenhum | Encerra a função com um resultado final. O firewall retoma o processamento a partir do comportamento Run Function que chamou a função |
event.deny() | Nenhum | Finaliza a requisição com HTTP 403 Forbidden. O status, o corpo e o motivo são fixos |
event.drop() | Nenhum | Finaliza a requisição sem resposta ao cliente |
event.respondWith() | Um objeto Response | Intercepta a requisição e a responde com uma resposta personalizada, cujo status, headers e conteúdo o objeto define |
event.waitUntil() | Uma promise, como a que um handler async retorna | Executa um handler async a partir do listener síncrono. Sem ele, a promise pode terminar em exceções inesperadas |
event.addRequestHeader
event.addRequestHeader() adiciona um header à requisição que segue para a origem. Ele recebe dois argumentos, o nome do header e o seu valor. Este listener adiciona dois headers e deixa a requisição seguir:
event.addResponseHeader
event.addResponseHeader() adiciona um header à resposta que o usuário recebe. Ele recebe os mesmos dois argumentos, o nome do header e o seu valor. Este listener adiciona dois headers de resposta e deixa a requisição seguir:
event.deny
event.deny() finaliza a requisição com HTTP 403 Forbidden. Ele não recebe argumentos, então a função não pode alterar o status, o corpo nem o motivo dessa resposta. Para uma resposta que a função controla, o método a chamar é event.respondWith(). Este listener nega toda requisição que recebe:
event.drop
event.drop() finaliza a requisição sem resposta ao cliente e não recebe argumentos. Este listener descarta toda requisição que recebe:
event.respondWith
event.respondWith() intercepta a requisição e a responde com uma resposta personalizada. Ele recebe um objeto Response, que define o status, os headers e o conteúdo da resposta. A chamada desta seção é executada dentro de um listener firewall e responde com um corpo JSON, o status 599 e um content-type igual a application/json:
Metadados
Uma função em um firewall lê metadados da requisição para filtrar o acesso à aplicação e aplicar lógicas diferentes por cenário. Quatro grupos desses metadados descrevem de onde uma requisição vem e como ela chega. A referência API de metadados lista os campos de cada grupo.
| Grupo | O que contém | Campos |
|---|---|---|
| GeoIP | De onde a requisição vem. Use-o para negar o acesso à aplicação a partir de certos lugares | Metadados de GeoIP |
| Remote | O endereço IP e a porta TCP que o cliente usa | Metadados de Remote |
| Server | O protocolo que a requisição usa | Metadados de Server |
| TLS | Detalhes disponíveis quando a requisição chega por uma conexão TLS segura | Metadados de TLS |
Limites
Uma função em um firewall é executada dentro de dois conjuntos de limites. Os limites da própria função, como tamanho do código, memória, tempo de CPU e sub-requisições, estão em Limites de Functions. Os limites do firewall e das suas instâncias de função estão em Limites de Firewall.
Os argumentos de uma instância de função, que a função lê com event.args(), comportam no máximo 100.000 bytes. Um payload maior é recusado com Value size (in bytes) is too big. Maximum size allowed is 100000 bytes.
Erros
Duas recusas vêm do ambiente de execução de uma função. Azion CLI imprime cada mensagem entre colchetes, depois de Error: Failed to create function: ou de Error: failed to create the Firewall Function Instance:. azion create function encerra a mensagem com Check your settings and try again. If the error persists, contact Azion support.
| Mensagem | Comando | O que causa | O que fazer |
|---|---|---|---|
"edge_firewall" is not a valid choice. | azion create function | --execution-environment edge_firewall, um valor que a ajuda da CLI lista e a API não aceita | Use --execution-environment firewall |
Invalid edge function runtime. You should use a function designed for Edge Firewall. | azion create firewall-instance | O ambiente de execução da função é application | Instancie uma função cujo ambiente de execução é firewall |