Rotação de certificados SSL/TLS sem reinicializações no NGINX Open Source

NGINX | 26 de setembro de 2023

No universo dos servidores web de alto desempenho, o NGINX é uma escolha popular porque sua arquitetura leve e eficiente permite lidar com grandes volumes de tráfego. Com a introdução da função de dicionário compartilhado como parte do módulo JavaScript do NGINX (njs), os recursos de desempenho do NGINX alcançam um novo patamar.

Nesta publicação do blog, exploramos a funcionalidade e os benefícios do dicionário compartilhado do njs e mostramos como configurar o NGINX Open Source sem precisar reiniciá-lo ao renovar certificados SSL/TLS.

Noções básicas e benefícios do dicionário compartilhado

A nova diretiva js_shared_dict_zone permite que os usuários do NGINX Open Source habilitem zonas de memória compartilhada para a troca eficiente de dados entre processos de trabalho. Essas zonas de memória compartilhada funcionam como dicionários de chave-valor, armazenando configurações dinâmicas que podem ser acessadas e modificadas em tempo real.

Os principais benefícios do dicionário compartilhado incluem:

  • Sobrecarga mínima e facilidade de uso – Integrado diretamente ao njs, é fácil de provisionar e usar, com uma API intuitiva e uma implementação simples. Ele também ajuda a simplificar o processo de gerenciamento e compartilhamento de dados entre processos de trabalho.
  • Leve e eficiente – Integra-se perfeitamente ao NGINX, aproveitando seu modelo de E/S não bloqueante e orientado a eventos. Essa abordagem reduz o uso de memória e melhora a simultaneidade, permitindo que o NGINX processe com eficiência muitas conexões simultâneas.
  • Escalabilidade – Aproveita a capacidade do NGINX de escalar horizontalmente entre vários processos de trabalho, permitindo compartilhar e sincronizar dados entre esses processos sem a necessidade de mecanismos complexos de comunicação entre processos. A configuração de tempo de vida (TTL) permite gerenciar registros nas entradas do dicionário compartilhado, removendo-os da zona devido à inatividade. O parâmetro evict remove o par chave-valor mais antigo para liberar espaço para novas entradas.

Rotação de SSL com o dicionário compartilhado

Um dos casos de uso mais relevantes do dicionário compartilhado é a rotação de SSL/TLS. Ao usar js_shared_dict_zone, não é necessário reiniciar o NGINX quando um certificado ou uma chave SSL/TLS é atualizado. Além disso, ele oferece uma API semelhante a REST para gerenciar certificados no NGINX.

Abaixo está um exemplo do arquivo de configuração do NGINX que configura o servidor HTTPS com as diretivas js_set e ssl_certificate. Os manipuladores JavaScript usam js_set para ler o certificado SSL/TLS ou a chave de um arquivo.

Este trecho de configuração usa o dicionário compartilhado para armazenar certificados e chaves na memória compartilhada como um cache. Se a chave não estiver presente, ele lerá o certificado ou a chave do disco e os colocará no cache.

Você também pode expor um local que limpe o cache. Depois que os arquivos no disco forem atualizados (por exemplo, quando os certificados e as chaves forem renovados), o dicionário compartilhado força a leitura a partir do disco. Esse ajuste permite alternar certificados/chaves sem precisar reiniciar o processo do NGINX.

http {     ...
    js_shared_dict_zone zone=kv:1m;
   
    server {
    …
     # Sets an njs function for the variable. Returns a value of cert/key
      js_set $dynamic_ssl_cert main.js_cert;
      js_set $dynamic_ssl_key main.js_key;
   
      # use variable's data
      ssl_certificate data:$dynamic_ssl_cert;
      ssl_certificate_key data:$dynamic_ssl_key;
     
     # a location to clear cache 
   location = /clear {
      js_content main.clear_cache;
      # allow 127.0.0.1;
      # deny all;
    }
  ...
  }

E aqui está a implementação em JavaScript para a rotação de certificados e chaves SSL/TLS usando js_shared_dict_zone:

function js_cert(r) {  if (r.variables['ssl_server_name']) {
    return read_cert_or_key(r, '.cert.pem');
  } else {
    return '';
  }
}

function js_key(r) {
  if (r.variables['ssl_server_name']) {
    return read_cert_or_key(r, '.key.pem');
  } else {
    return '';
  }
}
/** 
   * Retrieves the key/cert value from Shared memory or fallback to disk
   */
  function read_cert_or_key(r, fileExtension) {
    let data = '';
    let path = '';
    const zone = 'kv';
    let certName = r.variables.ssl_server_name;
    let prefix =  '/etc/nginx/certs/';
    path = prefix + certName + fileExtension;
    r.log('Resolving ${path}');
    const key = ['certs', path].join(':');
    const cache = zone && ngx.shared && ngx.shared[zone];
   
    if (cache) {
    data = cache.get(key) || '';
    if (data) {
      r.log(`Read ${key} from cache`);
      return data;
    }
  }
  try {
    data = fs.readFileSync(path, 'utf8');
    r.log('Read from cache');
  } catch (e) {
    data = '';
    r.log(`Error reading from file:${path}. Error=${e}`);
  }
  if (cache && data) {
    try {
      cache.set(key, data);
      r.log('Persisted in cache');
    } catch (e) {
      const errMsg = `Error writing to shared dict zone: ${zone}. Error=${e}`;
      r.log(errMsg);
    }
  }
  return data
}

Ao enviar a solicitação /clear, o cache é invalidado, e o NGINX carrega o certificado ou a chave SSL/TLS do disco no próximo handshake SSL/TLS. Além disso, você pode implementar um js_content que obtenha um certificado ou uma chave SSL/TLS da solicitação e também os armazene e atualize no cache.

O código completo deste exemplo pode ser encontrado no repositório do njs no GitHub.

Comece hoje mesmo

A função de dicionário compartilhado é uma ferramenta poderosa para a programabilidade da sua aplicação, oferecendo vantagens significativas em termos de simplificação e escalabilidade. Ao aproveitar os recursos de js_shared_dict_zone, você pode criar novas oportunidades de crescimento e lidar com eficiência com o aumento da demanda de tráfego.

Pronto para turbinar sua implantação do NGINX com o js_shared_dict_zone? Você pode atualizar sua implantação do NGINX com o js_shared_dict_zone para viabilizar novos casos de uso e saber mais sobre esse recurso em nossa documentação. Além disso, você pode conferir um exemplo completo de uma função de dicionário compartilhado no recém-lançado projeto njs-acme, que permite que o ambiente de execução do módulo njs funcione com provedores ACME.

Se você tem interesse em começar a usar o NGINX Open Source e está com dúvidas, participe do Slack da comunidade NGINX – apresente-se e conheça esta comunidade de usuários do NGINX!


Compartilhar
Tags: F5 NGINX, Tech

Publicações relacionadas no blog

Como o F5 NGINX One aprimora o gerenciamento e a observabilidade
NGINX | 10/10/2024

Como o F5 NGINX One aprimora o gerenciamento e a observabilidade

Descubra como o F5 NGINX One aprimora o gerenciamento e a observabilidade de ambientes híbridos e multicloud ao oferecer um console web centralizado baseado em SaaS, com insights em tempo real, conformidade automatizada e gerenciamento simplificado de configurações.

Do OpenAPI ao NGINX como gateway de API usando uma API declarativa
NGINX | 17/06/2024

Do OpenAPI ao NGINX como gateway de API usando uma API declarativa

Descubra como transformar uma definição de esquema OpenAPI em uma configuração NGINX totalmente funcional, operando como um API Gateway com a segurança de um Web Application Firewall e um Portal do Desenvolvedor, usando uma abordagem declarativa de API.

Como gerenciar picos repentinos de tráfego e sobrecarga do servidor
NGINX | 14/07/2021

Como gerenciar picos repentinos de tráfego e sobrecarga do servidor

Picos de tráfego e sobrecarga de servidores são preocupações sérias para varejistas online em qualquer época, mas especialmente durante a “Cyber Season” de compras de fim de ano. Detalhamos como você pode aproveitar as soluções de entrega de aplicações de nível de produção da NGINX para se preparar para aumentos repentinos de tráfego.

Distribuição segura de chaves privadas SSL com o NGINX
NGINX | 02/04/2019

Distribuição segura de chaves privadas SSL com o NGINX

Descrevemos três maneiras progressivamente mais seguras de proteger chaves privadas SSL ao configurar o NGINX para processar tráfego HTTPS: permitir acesso de leitura apenas ao usuário root, criptografar as chaves com senhas armazenadas separadamente e distribuir as senhas a partir de um repositório central.

Agrupando solicitações de API em lotes com NGINX Plus e o módulo JavaScript do NGINX
NGINX | 24/05/2018

Agrupando solicitações de API em lotes com NGINX Plus e o módulo JavaScript do NGINX

O módulo JavaScript do NGINX lançado com o NGINX Plus R15 oferece suporte a subsolicitações, possibilitando uma classe totalmente nova de casos de uso para o NGINX Plus. Este exemplo completo também usa a API do NGINX Plus e os módulos de chave-valor para converter solicitações de API dos clientes em solicitações separadas para as APIs dos microsserviços que compõem um aplicativo.

Como superar o esgotamento de portas efêmeras no NGINX e no NGINX Plus
NGINX | 19/04/2016

Como superar o esgotamento de portas efêmeras no NGINX e no NGINX Plus

Confira dicas para evitar o esgotamento de portas efêmeras com ajustes no kernel do Linux, conexões keepalive e conexões vinculadas dinamicamente a endereços IP locais.