Como usar o NGINX Plus e o NGINX para autenticar usuários de aplicações com LDAP

NGINX | 22 de junho de 2015

Os clientes frequentemente nos perguntam como podem usar o NGINX Plus e o NGINX para proteger recursos ou aplicações por meio da autenticação dos usuários que solicitam acesso a eles. Hoje, anunciamos uma implementação de referência desse tipo de sistema de autenticação e a disponibilizamos no repositório da NGINX, Inc. no GitHub. Neste post, descrevemos como a implementação funciona, como instalá-la e como usá-la como modelo para seu próprio sistema de autenticação.

A solução utiliza o módulo ngx_http_auth_request_module do NGINX Plus e do NGINX, que encaminha as solicitações de autenticação para um serviço externo. Na implementação de referência, esse serviço é um daemon que chamamos de ldap‑auth. Ele foi escrito em Python e se comunica com um servidor de autenticação Lightweight Directory Access Protocol (LDAP) — por padrão, o OpenLDAP, mas também testamos o daemon ldap‑auth com as configurações padrão do Microsoft® Windows® Server Active Directory (nas versões 2003 e 2012).

O daemon ldap‑auth serve como modelo para seu próprio aplicativo “conector”, que você pode desenvolver em outras linguagens, implantar com diferentes sistemas de autenticação ou ambos. A equipe de Serviços Profissionais da NGINX está disponível para ajudar com essas adaptações.

Observações:

  • A implementação de referência não se destina ao uso em produção, mas apenas a servir de modelo para suas próprias implementações.
  • Para facilitar a leitura, o restante deste artigo se refere ao NGINX Plus, mas a implementação de referência também funciona com o NGINX Open Source. O módulo http_auth_request, que é um pré-requisito, está incluído tanto nos pacotes do NGINX Plus quanto nos binários pré-compilados do NGINX.

Como a autenticação funciona na implementação de referência

Para realizar a autenticação, o módulo http_auth_request faz uma subsolicitação HTTP ao daemon ldap‑auth, que atua como intermediário e interpreta a subsolicitação para o servidor LDAP – ele usa HTTP para se comunicar com o NGINX Plus e a API apropriada para se comunicar com o servidor LDAP.

Partimos do pressuposto de que, se você tem interesse na implementação de referência, já possui uma aplicação ou outros recursos que deseja proteger exigindo autenticação. No entanto, para facilitar os testes da implementação de referência, fornecemos um daemon de backend de exemplo, também escrito em Python, que escuta na porta 9000. Durante os testes, ele pode substituir uma aplicação HTTP real, solicitando as credenciais do usuário e criando um cookie com base nelas.

A implementação de referência do NGINX Plus para autenticação LDAP inclui o daemon ldap-auth e um daemon de backend de exemplo

Veja uma descrição passo a passo do processo de autenticação na implementação de referência. Os detalhes são determinados pelas configurações no arquivo de configuração nginx-ldap-auth.conf; consulte Configuração da implementação de referência abaixo. O fluxograma após as etapas resume o processo.

  1. Um cliente envia uma solicitação HTTP para um recurso protegido hospedado em um servidor para o qual o NGINX Plus atua como proxy reverso.
  2. O NGINX Plus (especificamente, o módulo http_auth_request) encaminha a solicitação ao daemon ldap‑auth, que responde com o código HTTP 401 porque nenhuma credencial foi fornecida.
  3. O NGINX Plus encaminha a solicitação para http://backend/login, que corresponde ao daemon de backend. Ele grava o URI da solicitação original no cabeçalho X-Target da solicitação encaminhada.
  4. O daemon de backend envia ao cliente um formulário de login (o formulário é definido no código Python do daemon). Conforme configurado pela diretiva error_page, o NGINX define o código HTTP do formulário de login como 200.
  5. O usuário preenche os campos Nome de usuário e Senha no formulário e clica no botão Login. De acordo com o código do formulário, o cliente gera uma solicitação HTTP POST direcionada a /login, que o NGINX Plus encaminha ao daemon de backend.
  6. O daemon de back-end cria uma string no formato username:password, aplica a codificação Base64, gera um cookie chamado nginxauth cujo valor é definido como a string codificada e envia o cookie ao cliente. Ele define o sinalizador httponly para impedir o uso de JavaScript para ler ou manipular o cookie (protegendo contra a vulnerabilidade de cross-site scripting [XSS]).
  7. O cliente retransmite sua solicitação original (da Etapa 1), desta vez incluindo o cookie no campo Cookie do cabeçalho HTTP. O NGINX Plus encaminha a solicitação ao daemon ldap‑auth (como na Etapa 2).
  8. O daemon ldap‑auth decodifica o cookie e envia o nome de usuário e a senha ao servidor LDAP em uma solicitação de autenticação.
  9. A próxima ação depende de o servidor LDAP autenticar o usuário com sucesso:
    • Se a autenticação for bem-sucedida, o daemon ldap‑auth enviará o código HTTP 200 ao NGINX Plus. O NGINX Plus solicitará o recurso ao daemon de backend. Na implementação de referência, o daemon de backend retornará o seguinte texto:
   Hello, world! Requested URL: URL
  • O arquivo nginx-ldap-auth.conf inclui diretivas para armazenar em cache os resultados da tentativa de autenticação; para desabilitar o cache, consulte Cache abaixo.
  • Se a autenticação falhar, o daemon ldap‑auth enviará o código HTTP 401 ao NGINX Plus. O NGINX Plus encaminhará novamente a solicitação ao daemon de backend (como na Etapa 3), e o processo se repetirá.

Na implementação de referência do NGINX Plus para autenticação LDAP, o daemon ldap-auth atua como intermediário entre o NGINX Plus e o servidor LDAP

Instalando os componentes

O arquivo de configuração do NGINX Plus distribuído com a implementação de referência, nginx-ldap-auth.conf, configura todos os componentes, exceto o servidor LDAP (ou seja, o NGINX Plus, o cliente, o daemon ldap‑auth e o daemon de backend), para serem executados no mesmo host, o que é adequado para fins de teste. O servidor LDAP também pode ser executado nesse host durante os testes.

Em uma implantação real, a aplicação de backend e o servidor de autenticação normalmente são executados, cada um, em um host separado, enquanto o NGINX Plus é executado em um terceiro host. Na maioria das situações, o daemon ldap-auth não consome muitos recursos, portanto, ele pode ser executado no host do NGINX Plus ou em outro host de sua escolha.

  1. Crie um clone do repositório do GitHub.
  2. Se o NGINX Plus ainda não estiver em execução, instale-o de acordo com as instruções para o seu sistema operacional.
  3. Se ainda não houver um servidor LDAP em execução, instale e configure um. Por padrão, o daemon ldap‑auth se comunica com o OpenLDAP, mas o Microsoft Windows Active Directory 2003 e 2012 também é compatível. Se você estiver usando o servidor LDAP apenas para testar a implementação de referência, poderá usar a imagem Docker do servidor OpenLDAP disponível no GitHub ou configurar um servidor seguindo instruções como Como instalar e configurar o OpenLDAP e o phpLDAPadmin no Ubuntu 16.04. Anote os valores definidos para o DN base, o DN de associação e a senha de associação. Você os inserirá no arquivo de configuração do NGINX em Configuração da implementação de referência.
  4. No host em que o daemon ldap‑auth será executado, instale os seguintes softwares adicionais. Recomendamos usar as versões distribuídas com o sistema operacional, em vez de baixar os softwares de um repositório de código aberto.
    • Python versão 2. A versão 3 não é compatível.
    • O módulo LDAP para Python, python‑ldap (criado pelo projeto de código aberto python-ldap.org).
  5. Copie os seguintes arquivos do clone do seu repositório para os hosts indicados:
    • nginx-ldap-auth.conf – Arquivo de configuração do NGINX Plus que inclui o conjunto mínimo de diretivas para testar a implementação de referência. Instale-o no host do NGINX Plus (no diretório /etc/nginx/conf.d se estiver usando o esquema de configuração convencional). Para evitar conflitos de configuração, lembre-se de mover ou renomear todos os arquivos de configuração padrão instalados com o NGINX Plus.
    • nginx-ldap-auth-daemon.py – Código Python para o daemon ldap‑auth. Instale-o no host de sua preferência.
    • nginx-ldap-auth-daemon-ctl.sh – Exemplo de script shell para iniciar e interromper o daemon. Instale-o no mesmo host que o daemon ldap‑auth.
    • backend-sample-app.py – Código Python do daemon que, durante os testes, atua como um servidor de aplicações de backend. Instale-o no host de sua preferência.
  6. Modifique o arquivo de configuração do NGINX Plus conforme descrito em Configuração da implementação de referência abaixo. Depois de fazer as alterações, execute o comando nginx -t para verificar se a sintaxe do arquivo é válida.
root# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
  1. Inicie o NGINX Plus. Se o NGINX Plus já estiver em execução, execute o seguinte comando para recarregar o arquivo de configuração:
root# nginx -s reload
  1. Execute os comandos a seguir nos hosts apropriados para iniciar o daemon ldap‑auth e o daemon de backend.
root# nginx-ldap-auth-daemon-ctl.sh start
root# python backend-sample-app.py
  1. Use um navegador da web para acessar http://nginx-server-address:8081. Verifique se o navegador exibe o formulário de autenticação. Depois de preencher e enviar o formulário, verifique se o servidor retorna a resposta esperada para credenciais válidas. Conforme mencionado acima, o daemon de backend retorna o seguinte texto:
   Hello, world! Requested URL: URL

Configurando a implementação de referência

Faça as seguintes alterações no arquivo nginx-ldap-auth.conf. Algumas são obrigatórias e outras opcionais, conforme indicado.

Configurações do servidor LDAP

Conforme implementado em nginx-ldap-auth-daemon.py, o daemon ldap‑auth se comunica com um servidor OpenLDAP, transmitindo parâmetros para especificar qual conta de usuário deve ser autenticada. Para eliminar a necessidade de modificar o código Python, o arquivo nginx-ldap-auth.conf contém diretivas proxy_set_header que definem valores no cabeçalho HTTP, os quais são usados posteriormente para definir os parâmetros. A tabela a seguir mostra a correspondência entre os parâmetros e os cabeçalhos.

Parâmetro LDAP Cabeçalho HTTPbasedn X-Ldap-BaseDNbinddn X-Ldap-BindDNbindpasswd X-Ldap-BindPasscookiename X-CookieNamerealm X-Ldap-Realmtemplate X-Ldap-Templateurl X-Ldap-URL

  • (Obrigatório) Nas diretivas a seguir, substitua os valores em negrito pelos valores corretos para a implantação do seu servidor LDAP. Observe, em especial, que o arquivo nginx-ldap-auth.conf usa a porta padrão do LDAPS, 636. Se você alterar a porta para 389 (a porta padrão do LDAP) ou para outra porta LDAP, lembre-se também de alterar o nome do protocolo de ldaps para ldap.
# URL and port for connecting to the LDAP server
proxy_set_header X-Ldap-URL "ldaps://example.com:636";
 
# Base DN
proxy_set_header X-Ldap-BaseDN "cn=Users,dc=test,dc=local";
 
# Bind DN
proxy_set_header X-Ldap-BindDN "cn=root,dc=test,dc=local";
 
# Bind password
proxy_set_header X-Ldap-BindPass "secret";
  • (Obrigatório se estiver usando o Active Directory em vez do OpenLDAP) Remova o comentário da seguinte diretiva, conforme mostrado:
proxy_set_header X-Ldap-Template "(SAMAccountName=%(username)s)";
  • (Opcional) A implementação de referência usa autenticação baseada em cookies. Se você estiver usando autenticação HTTP básica, comente as seguintes diretivas, conforme mostrado:
#proxy_set_header X-CookieName "nginxauth";
#proxy_set_header Cookie nginxauth=$cookie_nginxauth;
  • (Opcional) Se quiser alterar o valor do parâmetro template que o daemon ldap‑auth passa por padrão ao servidor OpenLDAP, remova o comentário da diretiva a seguir, conforme mostrado, e altere o valor:
proxy_set_header X-Ldap-Template "(cn=%(username)s)";
  • (Opcional) Se quiser alterar o nome do realm do valor padrão (Restricted), remova o comentário e altere a seguinte diretiva:
proxy_set_header X-Ldap-Realm "Restricted";

Endereço IP do daemon de backend

Se o daemon de backend não estiver em execução no mesmo host que o NGINX Plus, altere o endereço IP dele no bloco de configuração upstream:

upstream backend {    server 127.0.0.1:9000;
 }

Endereço IP do daemon ldap‑auth

Se o daemon ldap‑auth não estiver em execução no mesmo host que o NGINX Plus, altere o endereço IP nesta diretiva proxy_pass:

location = /auth-proxy {    proxy_pass http://127.0.0.1:8888;
    # ...
}

Endereço IP e porta em que o NGINX escuta

Se o cliente não estiver sendo executado no mesmo host que o NGINX Plus, altere o endereço IP nesta diretiva listen (ou remova completamente o endereço para aceitar tráfego de qualquer cliente). Se desejar, você também pode alterar a porta na qual o NGINX escuta, atualmente definida como 8081:

server {    listen 127.0.0.1:8081;
    # ...
 }

Cache

O arquivo nginx-ldap-auth.conf permite armazenar em cache tanto os dados quanto as credenciais. Opcionalmente, você pode alterar as seguintes configurações:

  • A diretiva proxy_cache_path no bloco de configuração http cria um diretório no disco local chamado cache e aloca 10 MB na memória compartilhada para uma zona chamada auth_cache, onde os metadados são armazenados.
proxy_cache_path cache/ keys_zone=auth_cache:10m;
  • Se você alterar o nome da zona de memória compartilhada, também deverá alterá-lo na diretiva proxy_cache (no bloco location que direciona o tráfego para o daemon ldap‑auth).
location = /auth-proxy {
    proxy_cache auth_cache;
    # ...
}
  • A diretiva proxy_cache_valid (no mesmo bloco location que proxy_cache) especifica que as respostas armazenadas em cache marcadas com o código HTTP 200 ou 403 são válidas por 10 minutos.
location = /auth-proxy {    proxy_cache_valid 200 403 10m;
    # ...
}

Para desabilitar o cache, comente estas três diretivas, além da diretiva proxy_cache_key.

Personalizando o sistema de autenticação

Como mencionado acima, você pode usar o daemon ldap‑auth como modelo para seu próprio aplicativo que aceite solicitações do módulo http_auth_request. Se estiver desenvolvendo um aplicativo em Python para se comunicar com um tipo diferente de servidor de autenticação (não LDAP), crie uma nova classe de tratamento de autenticação para substituir LDAPAuthHandler no script nginx-ldap-auth-daemon.py.

Uma observação sobre segurança

O daemon de backend usa codificação Base64 no nome de usuário e na senha armazenados no cookie. O Base64 é uma forma muito fraca de ofuscação, o que deixa as credenciais vulneráveis à extração e ao uso indevido. Para que a autenticação tenha alguma utilidade real, é necessário usar uma criptografia mais sofisticada na aplicação de backend.


Compartilhar

Sobre o autor

Owen Garrett
Owen GarrettDiretor Sênior de Gestão de Produtos

Mais publicações de Owen Garrett

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.