Asegurar sistemas distribuídos representa um desafio complexo devido à diversidade e escala dos componentes envolvidos. Com vários serviços interagindo através de redes potencialmente não seguras, o risco de acesso não autorizado e brechas de dados aumenta significativamente. Este artigo explora uma abordagem prática para asegurar sistemas distribuídos usando um projeto de código aberto. O projeto demonstra como integrar vários mecanismos de segurança e tecnologias para lidar com desafios de segurança comuns, como autenticação, autorização e comunicação segura.
Compreensão de Desafios de Segurança em Sistemas Distribuídos
Sistemas distribuídos envolvem vários serviços ou microserviços que devem se comunicar de forma segura através de uma rede. Principais desafios de segurança em tais arquiteturas incluem:
- Comunicação segura: Garantir que dados transmitidos entre serviços estejam encriptados e protegidos de interceptação ou adulteração
- Autenticação: Verificar as identidades de usuários e serviços para prevenir acesso não autorizado
- Autorização: Controlar o que os usuários e serviços autenticados são permitidos fazer, com base em seus papéis e permissões
- Aplicação de Política: Implementar controles de acesso finos e políticas que governam as interações de serviço-para-serviço e de usuário.
- Gestão de certificados: Gerenciamento de certificados digitais para criptografar dados e estabelecer confiança entre serviços
Este projeto de código aberto aborda estes desafios usando várias tecnologias e soluções integradas.
Configuração e Inicialização do Projeto
O projeto começa com a configuração de um ambiente seguro usando scripts de shell e Docker. A configuração envolve fornecer certificados digitais e iniciar os serviços necessários para garantir que todos os componentes estejam prontos para comunicação segura.
Passos para Configurar o Ambiente
1. Fornecimento de Certificados
O projeto usa um script de shell (provisioning.sh
) para simular uma Autoridade Certificadora (CA) e gerar os certificados necessários para os serviços.
./provisioning.sh
2. Iniciando Serviços
Docker Compose é usado para iniciar todos os serviços definidos no projeto, garantindo que eles estejam configurados corretamente para operação segura.
docker-compose up
3. Testando Comunicação de Serviço para Serviço
Para validar a comunicação de serviço para serviço usando certificados e tokens JWT, o script test_services.sh
é fornecido. Este script demonstra como diferentes serviços interagem de forma segura usando seus certificados atribuídos.
Resolvendo Desafios de Segurança em Sistemas Distribuídos
O projeto integra várias tecnologias-chave para abordar os desafios de segurança primários mencionados anteriormente. Aqui está como cada desafio é abordado:
1. Comunicação Segura com Mutual TLS (mTLS)
Desafio
Em um sistema distribuído, os serviços devem se comunicar de forma segura para evitar acesso não autorizado e brechas de dados.
Solução
O projeto usa Mutual TLS (mTLS) para segurar a comunicação entre serviços. O mTLS garante que ambos o cliente e o servidor autentiquem um ao outro usando seus respectivos certificados. Esta autenticação mutua evita que serviços não autorizados comunique com serviços legítimos.
Implementação
O Nginx está configurado como um proxy reverso para lidar com mTLS. Ele exige que ambos os certificados de cliente e servidor sejam usados para estabelecer uma conexão segura, garantindo que os dados transmitidos entre serviços permaneçam confidenciais e imune a manipulação.
2. Autenticação com Keycloak
Desafio
A autenticação adequada de usuários e serviços é crítica para evitar acesso não autorizado.
Solução
O projeto usaKeycloak, uma solução de gerenciamento de identidade e acesso de código aberto, para gerenciar a autenticação. Keycloak suporta múltiplos métodos de autenticação, incluindo OpenID Connect e credenciais do cliente, tornando-o adequado para ambas as autenticações de usuários e serviços.
- Autenticação de Usuários:
Os usuários são autenticados usando OpenID Connect. Keycloak é configurado com um cliente (appTest-login-client
) que gerencia os fluxos de autenticação de usuários, incluindo o login, a emissão de tokens e o tratamento de callback. - Autenticação de Serviços:
Para a autenticação de serviço a serviço, o projeto usa um cliente Keycloak (client_credentials-test
) configurado para o tipo de garantia de credenciais do cliente. Este método é ideal para autenticar serviços sem intervenção do usuário.
Fluxo de Autenticação de Exemplo
- Os usuários navegam até a página de login.
- Após o login bem-sucedido, o Keycloak redireciona o usuário para uma página de callback com um código de autorização.
- O código de autorização é então trocado por um token JWT, que é usado para as solicitações subsequentes. O arquivo
authn.js
no diretórionginx/njs
fornece uma implementação detalhada deste fluxo.
Exemplo de Autenticação de Serviço Usando Credenciais do Cliente
curl -X POST "http://localhost:9000/realms/tenantA/protocol/openid-connect/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=client_credentials-test" \
-d "client_secret=your-client-secret-here"
3. Autorização do Usuário com Open Policy Agent (OPA) e JWT
Desafio
Aplicar controles de acesso fino-granular para garantir que usuários e serviços autenticados tenham acesso apenas a recursos autorizados
Solução
O projeto usa uma combinação de Open Policy Agent (OPA) e tokens JWT para aplicar as políticas de autorização. O projeto demonstra três estratégias diferentes de validação de JWT para garantir uma robusta segurança:
- Recuperando certificados do Keycloak: Faz a recuperação dinâmica de certificados do Keycloak para validar o token.
- Usando x5t (Impressão Digital): Usa a impressão digital embutida no token para recuperar a chave pública de um armazenamento de confiança local.
- Validação de certificado embutida: Valida o token usando um certificado embutido, garantindo que o certificado é validado contra uma Autoridade de Certificação (CA) confiável.
Consulte o arquivo nginx/njs/token.js para a implementação detalhada destas estratégias.
4. Aplicação de Políticas com Open Policy Agent (OPA)
Desafio
Implementar políticas de controle de acesso dinâmicas e flexíveis para ambos os serviços e usuários
Solução
OPA é usado para aplicar políticas de acesso com granularidade fina. As políticas são escritas em uma linguagem declarativa (Rego) e armazenadas no diretório opa/. Essas políticas definem as condições sob as quais os serviços podem se comunicar e os usuários podem acessar recursos, garantindo que os controles de acesso são aplicados de forma consistente em todo o sistema.
5. Gerenciamento de Certificados
Desafio
Gerenciar certificados digitais para serviços para estabelecer confiança e garantir comunicações seguras.
Solução:
O projeto inclui um robusto sistema de gerenciamento de certificados. Um script de shell (provisioning.sh
) é usado para simular uma Autoridade de Certificação (CA) e gerar certificados para cada serviço. Essa abordagem simplifica o gerenciamento de certificados e garante que todos os serviços tenham as credenciais necessárias para a comunicação segura.
Nós também adicionamos um ponto final para atualizar o certificado de serviço sem a necessidade de reiniciar o nginx.
curl --insecure https://localhost/certs --cert certificates/gen/serviceA/client.crt --key certificates/gen/serviceA/client.key -F cert=@certificates/gen/serviceA/client.crt -F key=@certificates/gen/serviceA/client.key
Conclusão
Construir um sistema distribuído seguro requer uma consideração cuidadosa de vários aspectos de segurança, incluindo comunicação segura, autenticação, autorização, aplicação de políticas e gerenciamento de certificados. Este projeto de código aberto fornece um exemplo abrangente de como integrar vários mecanismos de segurança para abordar esses desafios eficazmente.
Ao seguir as configurações e o setup demonstrados neste projeto, os desenvolvedores podem aproveitar o TLS mutual, Keycloak, Open Policy Agent e Nginx para construir uma arquitetura de segurança robusta. Essas tecnologias, quando combinadas, fornecem uma forte base para proteger sistemas distribuídos contra uma ampla gama de ameaças, garantindo tanto a proteção de dados quanto o controle de acesso seguro.
Source:
https://dzone.com/articles/designing-a-secure-architecture-for-distributed-systems