No primeiro post desta série, descrevemos várias abordagens para aumentar a segurança das suas chaves privadas SSL. O post terminou com uma demonstração de um ponto remoto de distribuição de senhas (PDP), usado para compartilhar com segurança senhas de criptografia com instâncias do NGINX.
Sistemas de gerenciamento de segredos como o HashiCorp Vault funcionam de maneira semelhante ao PDP usado como exemplo:
- Eles usam um serviço centralizado de gerenciamento de segredos (ou altamente disponível e distribuído), acessado por HTTPS ou outra API
- Os clientes são autenticados por tokens de autenticação ou outros meios
- Os tokens podem ser revogados conforme necessário para controlar o acesso ao segredo
Neste post, mostramos como configurar o HashiCorp Vault para distribuir senhas SSL. Para aumentar ainda mais a segurança, você pode configurar um módulo de segurança de hardware externo (HSM).
Para eliminar completamente o armazenamento em disco de pares de certificado e chave SSL, consulte o terceiro artigo desta série, Como usar o armazenamento de chave-valor do NGINX Plus para proteger chaves SSL efêmeras do HashiCorp Vault. Ele explica como gerar chaves SSL efêmeras a partir do HashiCorp Vault e armazená-las na memória, no armazenamento de chave-valor do NGINX Plus.
Esta publicação se aplica tanto ao NGINX Open Source quanto ao NGINX Plus. Para facilitar a leitura, usaremos NGINX ao longo do texto.
Como usar o HashiCorp Vault para proteger chaves privadas SSL
As instruções desta seção configuram um servidor PDP central usando o Vault para distribuir senhas SSL. Elas se baseiam nas instruções da DigitalOcean; adapte-as conforme necessário para cumprir suas próprias políticas do Vault.
Em nosso exemplo, cada servidor web remoto tem um token de autenticação exclusivo. Esses tokens podem ser usados para acessar segredos no caminho secret/webservers/ do Vault, e armazenamos as senhas SSL em secret/webservers/ssl_passwords.
Veremos como proteger os tokens e como revogar tokens de autenticação individuais quando necessário.
Baixe, instale e inicialize o HashiCorp Vault no servidor PDP
- Siga as instruções da DigitalOcean para baixar e extrair o Vault no seu servidor PDP. Estamos usando o seguinte arquivo de exemplo /etc/vault.hcl para permitir o acesso remoto ao Vault e desabilitar o TLS (para facilitar os testes):
backend "file" { path = "/var/lib/vault"
}
listener "tcp" {
address = "0.0.0.0:8200"
tls_disable = 1
}- Inicie o Vault usando os scripts de inicialização (caso você os tenha criado) ou manualmente:
user@pdp:~$ sudo /usr/local/bin/vault server -config=/etc/vault.hcl- Inicialize o Vault e obtenha o token raiz inicial:
user@pdp:~$ export VAULT_ADDR=http://localhost:8200
user@pdp:~$ vault init -key-shares=3 -key-threshold=2
user@pdp:~$ vault operator unseal
Initial Root Token: 86c5c2a4-8ab2-24dd-1816-48449c83114e- Precisamos fornecer o Token Raiz Inicial em muitos dos comandos a seguir. Por conveniência, nós o atribuímos à variável de shell
root_token:
user@pdp:~$ root_token=86c5c2a4-8ab2-24dd-1816-48449c83114eArmazene os segredos
- Ainda no servidor PDP, crie um arquivo temporário chamado /tmp/ssl_passwords.txt contendo as senhas.
- Armazene este arquivo como um segredo no Vault e verifique se é possível recuperá-lo:
user@pdp:~$ VAULT_TOKEN=$root_token vault kv put secret/webservers/ssl_passwords value=@/tmp/ssl_passwords.txt
user@pdp:~$ VAULT_TOKEN=$root_token vault kv get -field=value secret/webservers/ssl_passwords
password1
password2
...- Por segurança, exclua /tmp/ssl_passwords.txt.
- Crie uma especificação de política em um arquivo chamado web.hcl com o seguinte conteúdo:
path "secret/webservers/*" {
capabilities = ["read"]
}- Carregue a política no Vault, nomeando-a como
web:
user@pdp:~$ VAULT_TOKEN=$root_token vault policy write web web.hcl- Crie um novo token de autenticação, associe-o à política
webe, opcionalmente, inclua o parâmetrodisplay-namepara atribuir a ele um nome fácil de identificar. Anote os valores detokenetoken_accessor; você os usará nos comandos seguintes:
user@pdp:~$ VAULT_TOKEN=$root_token vault token create -policy=web -display-name=webserver1
Key Value
--- -----
token dcf75ffd-a245-860f-6960-dc9e834d3385
token_accessor 0c1d6181-7adf-7b42-27be-b70cfa264048- O servidor web NGINX usa esse token para recuperar as senhas SSL. A política
webimpede que o servidor web recupere segredos fora do caminho secret/webservers/*.
Verifique se o servidor web consegue recuperar o token
- No servidor web NGINX, instale o binário do Vault.
- Declare a localização do servidor Vault remoto (neste caso, http://pdp:8200), e verifique se a máquina do servidor web consegue recuperar as senhas SSL usando o token:
user@web1:~$ export VAULT_ADDR=http://pdp:8200user@web1:~$ VAULT_TOKEN=dcf75ffd-a245-860f-6960-dc9e834d3385 vault kv get -field=value secret/webservers/ssl_passwords
password1
password2
...Configure o NGINX Vault Connector no servidor web
- Como parte da configuração do PDP de exemplo no primeiro post, criamos um script de shell chamado connector.sh no host do NGINX (máquina do servidor web). Aqui, vamos modificá-lo para usar o Vault:
#!/bin/sh
# Usage: connector_v.sh
CONNECTOR=$1
CREDS=$2
[ -e $CONNECTOR ] && /bin/rm -f $CONNECTOR
mkfifo $CONNECTOR; chmod 600 $CONNECTOR
export VAULT_ADDR=http://pdp:8200
export VAULT_TOKEN=$CREDS
while true; do
vault kv get -field=value secret/webservers/ssl_passwords > $CONNECTOR
sleep 0.1 # race condition, ensures EOF
done- Execute o script como um processo em segundo plano, da seguinte forma:
root@web1:~# ./connector_v.sh /var/run/nginx/ssl_passwords \dcf75ffd-a245-860f-6960-dc9e834d3385 &- Teste o conector fazendo a leitura a partir do caminho do conector:
root@web1:~$ cat /var/run/nginx/ssl_passwordspassword1
password2
...- Configure o NGINX para ler o arquivo ssl_passwords na inicialização e usar seu conteúdo como senhas para descriptografar chaves privadas criptografadas. Você pode incluir a diretiva
ssl_password_fileem um blocoserver(como o criado para a configuração padrão no primeiro post) ou no contextohttppara aplicá-la a vários servidores virtuais:
ssl_password_file /var/run/nginx/ssl_passwords;- Verifique se o NGINX consegue ler a senha e descriptografar as chaves SSL:
root@web1:~# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successfulRevogando o token de autenticação de um servidor web
Você pode revogar o acesso facilmente caso o servidor web seja comprometido ou desativado. Para isso, basta revogar diretamente o token de autenticação usado pelo servidor web:
user@pdp:~$ VAULT_TOKEN=$root_token vault token revoke dcf75ffd-a245-860f-6960-dc9e834d3385Os tokens do Vault são dados confidenciais, e muitos fluxos de trabalho do Vault não armazenam cópias dos tokens emitidos para um cliente autenticado. Se a cópia de um token vazar, um invasor poderá se passar pelo cliente.
Em vez disso, é comum gerenciar um token ativo usando seu acessador, que concede direitos limitados sobre o token e não pode ser usado para recuperar o valor do token. Em vez de armazenar os tokens quando eles são emitidos, armazene o acessador correspondente.
Se você precisar determinar o accessor do token de autenticação de um servidor web, execute o comando vault list para obter a lista de accessors e execute o comando vault token lookup em cada accessor para encontrar aquele com o nome de exibição e a política relevantes:
user@pdp:~$ VAULT_TOKEN=$root_token vault list /auth/token/accessors
Keys
----
83be5a73-9025-1221-cb70-4b0e8a3ba8df
0c1d6181-7adf-7b42-27be-b70cfa264048
f043b145-7a63-01db-ea85-9f22f413c55e
user@pdp:~$ VAULT_TOKEN=$root_token vault token lookup -accessor 0c1d6181-7adf-7b42-27be-b70cfa264048
Key Value
--- -----
...
display-name webserver1
...
policy web
...Em seguida, você pode revogar o token usando o accessor dele:
user@pdp:~$ VAULT_TOKEN=$root_token vault token revoke -accessor 0c1d6181-7adf-7b42-27be-b70cfa264048Implicações de segurança
O uso do Vault apresenta um perfil de segurança semelhante ao do PDP de exemplo descrito no primeiro post. As chaves privadas SSL só podem ser obtidas se a senha correspondente for obtida e, para isso, um invasor precisa conhecer o valor de um token de autenticação válido.
O principal benefício de usar o Vault é automatizar e dimensionar o armazenamento de segredos.
Como usar um HSM externo para gerenciar chaves privadas
Nenhuma das soluções que abordamos até agora nesta série protege a chave privada quando um invasor obtém acesso de root ao servidor NGINX. Se um invasor conseguir acessar a memória de execução do NGINX ou gerar um despejo de memória, existem técnicas bem conhecidas para examinar a memória do processo e localizar os dados da chave privada.
Os módulos de segurança de hardware (HSMs) externos resolvem esse problema armazenando as chaves privadas SSL em hardware externo inviolável. Eles oferecem a descriptografia como serviço, que o NGINX acessa sempre que precisa realizar uma operação SSL que exige a chave.
O servidor NGINX nunca tem acesso aos dados da chave privada SSL. Um invasor que obtenha acesso root ao servidor não poderá obter a chave privada SSL, mas poderá descriptografar dados sob demanda acessando o serviço de descriptografia do HSM com as credenciais do NGINX.
Como configurar o NGINX para acessar um HSM
O NGINX delega todas as operações de chave privada SSL a uma biblioteca criptográfica chamada OpenSSL. Dispositivos HSM de terceiros podem ser disponibilizados ao NGINX por meio do mecanismo OpenSSL fornecido pelo fabricante do HSM.
A configuração do NGINX é específica para o HSM de cada fornecedor, mas geralmente segue um processo simples:
- Configure o NGINX para usar o mecanismo OpenSSL do fornecedor em vez do mecanismo de software padrão:
ssl_certificate_key engine:vendor-hsm-engine:...;- Em vez de usar a chave privada real, configure o NGINX para usar a chave “falsa” fornecida pelo fabricante. Essa chave contém um identificador que aponta para a chave real no dispositivo HSM:
ssl_certificate_key ssl/vendor.private.key;- A chave também pode conter as credenciais para acessar o dispositivo HSM, ou as credenciais podem ser fornecidas por meio de configurações adicionais específicas do fornecedor.
- (Opcional) Aplique os ajustes desejados, como aumentar o número de processos de trabalho do NGINX, para maximizar o desempenho do NGINX e do HSM.
Para ver um exemplo de configuração de HSM, consulte a documentação do CloudHSM da Amazon.
Implicações de segurança
HSMs externos são um método altamente seguro para armazenar chaves privadas SSL. Um invasor com acesso root ao servidor NGINX pode usar as credenciais do NGINX para descriptografar dados arbitrários por meio do HSM, mas não consegue obter a chave privada não criptografada. Um HSM torna significativamente mais difícil para um invasor se passar por um site ou descriptografar dados arbitrários offline.
Conclusão
É essencial garantir que dados confidenciais, como a chave privada SSL, estejam totalmente protegidos, pois as consequências de sua divulgação são muito graves.
Para muitas organizações que contam com processos de segurança adequados, basta armazenar a chave privada nos balanceadores de carga de frontend e, em seguida, restringir e auditar todo o acesso a esses servidores (a configuração padrão descrita no primeiro post).
Para organizações que precisam implantar configurações do NGINX com frequência, as medidas descritas nesta publicação e na primeira podem ser usadas para limitar os usuários ou as entidades que podem visualizar os dados da chave privada.
No terceiro post desta série, Como usar o armazenamento de chave-valor do NGINX Plus para proteger chaves SSL efêmeras do HashiCorp Vault, explicamos como automatizar o provisionamento de chaves e certificados do Vault para o armazenamento de chave-valor do NGINX Plus, usando a API do NGINX Plus.
Observe novamente que nenhum desses métodos reduz a necessidade de proteger totalmente as instâncias do NGINX em execução contra acesso remoto ou manipulação da configuração.
Experimente o NGINX Plus – comece hoje mesmo sua avaliação gratuita de 30 dias ou entre em contato conosco para conversar sobre seus casos de uso.
Sobre o autor

Publicações relacionadas no blog

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
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
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
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
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
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.