Segurança em Micro Serviços: Boas Práticas e Estratégias

Marcelo M. Gonçalves
11 min readFeb 26, 2023

--

Constantemente observamos movimentos de adoção massiva para arquiteturas cada vez mais distribuídas. O objetivo seria adquirir agilidade e alavancar seus negócios com a maior velocidade possível. Neste contexto, a tração não dependerá apenas de resultados positivos aos desafios impostos pelos sistemas distribuídos, mas também da aderência aos novos desafios de segurança a serem endereçados e incorporados ao ciclo de desenvolvimento.

Mais serviços = mais complexidade = maiores riscos + vulnerabilidades de segurança.

Micro serviços não são uma tendência passageira e nem a única forma de estruturarmos nossos componentes. Sistemas distribuídos são naturalmente complexos tanto em arquitetura quanto em infraestrutura, portanto os trade-offs devem ser cuidadosamente avaliados evitando ganharmos agilidade ao custo de maior manutenção decorrente da granularidade implicitamente adotada. Desta forma, evitar excessos durante a captura do nível de distribuição correto dos serviços fará a diferença no processo.

O desenvolvimento seguro sugere acrescentarmos segurança ao ciclo de desenvolvimento de nossos projetos e serviços. O sucesso com micro serviços dependerá dos cuidados dedicados em cada etapa do Software Development Life Cycle (SDLC): Design; Build; Deploy; Maintain; Manage.

Arquiteturas distribuídas acrescentam, exponencialmente, potenciais riscos e vulnerabilidade de segurança aos serviços. Na medida em que crescem, essas aplicações expõem dezenas de centenas de novos pontos de atenção a serem contemplados, de forma a seguir possibilitando aos serviços operarem integralmente sem comprometer sua integridade.

Precisamos que os times compreendam os conceitos de segurança atribuídos ao processo, possibilitando agregarmos padrões e tendências de segurança e consequentemente elegendo determinadas soluções comuns a uma camada mais corporativa dentro da organização, podendo ser reaproveitadas em diversos locais.

Embora não haja uma definição precisa ao que se refere o estilo de arquitetura para sistemas distribuídos, no contexto dos micro serviços, Martin Fowler e James Lewis propoem uma lista de características comuns entre estes componentes: gestão descentralizada; smart endpoints e pipelines inteligentes; manutenção de dados; automação de infraestrutura e camadas de service mesh. Estes elementos adicionam aos nossos serviços um novo conjunto de riscos de segurança em potencial. Em todas as camadas, abordagens de desenvolvimento e arquitetura precisam estar interconectados com o ecossistema de segurança.

Todo o serviço deve estar alinhado às necessidades de negócio, para isso, os times especializados em devops / infra e desenvolvimento devem estar devidamente sincronizados.

Integrando Segurança aos Padrões de Arquitetura

O sucesso genuíno das nossas aplicações depende da segurança bem estabelecida. Desta forma, independente do estilo ou padrão de arquitetura adotado para nossos serviços / componentes, práticas de segurança da informação, cyber security e segurança de redes precisam estar alinhadas e serem seguidas.

Arquiteturas com sistemas distribuídos são considerados até quatro vezes mais vulneráveis do que arquiteturas monolíticas tradicionais ou monólitos modulares (macro serviços). Micro serviços, ao serem distribuídos, expõem diversos pontos de falhas em diversas camadas do espectro, confeccionando uma superfície de ataque mais larga e vulnerável.

O contexto de execução adjacente para a execução dos micro serviços são infinitamente mais complexos, e substancialmente distintos, se comparados às aplicações monolíticas.

Desacoplar segurança dos serviços em camadas de Service mesh (istio, cilium, linkerd) facilita a centralização e gerenciamento de elementos relacionados à segurança da informação. Anteceder a resolução de vulnerabilidades antes que ocorram seria o desejado, porém a ineficiência operacional e falta de integração a stacks de segurança impossibilita avanços significativos nesta área.

Para as empresas, o tema segurança sempre estará entre os principais e constantes desafios. Sendo necessários investimentos e uma boa estratégia para garantir a sustentabilidade do negócio. Todo o esforço despendido em estratégias e boas práticas, descritas ao longo deste artigo, não serão suficientes caso não haja conscientização e mudança para um novo mindset. Será essencial que esteja, enraizado nas fundações e cultura da empresa, que os elementos da segurança da informação sejam posicionados no centro.

Estratégia: Defense in Depth

Serviços contendo dados sensíveis precisam de camadas adicionais de defesa, evitando que invasores apropriem-se de serviços adicionais ao elemento comprometido. Com o objetivo de proteger o núcleo destes serviços, práticas como a Defesa em profundidade (Defense in Depth) sugerem uma estratégia composta por diversos níveis de segurança, exigindo múltiplas camadas de proteção desde físicas / rede até aplicação / código.

A depender de sua natureza, nem todos os tipos de serviços necessitam de camadas extras de segurança. Ao nos referimos a serviços não críticos e menos granulares (aplicações monolíticas ou monólitos modulares), a proteção oferecida através de firewalls individuais é suficiente. Ao mesmo tempo, existem casos onde não devemos confiar exclusivamente em firewalls e desta forma, outros mecanismos e estratégias de segurança, juntamente com boas práticas mais avançadas são indicadas para serviços transacionais.

Mecanismos: Autorização e controle de acesso; autenticação baseada em tokens para usuários e serviços; criptografia no tráfego dos dados; proteção de senhas / secrets e monitoramento das aplicações para detecção de ações suspeitas.

DevSecOps

DevOps são descritos como um conjunto de práticas e ferramentas que facilitam a entrega contínua de conteúdos, automatizando processos e tarefas através da criação de pipelines de execução, os quais efetivamente agilizam as entregas. Equipes de engenheiros DevOps habilitam colaboração eficiente e um workflow de integração contínuo dentro de uma organização. Ao mesmo tempo, problemas envolvendo vulnerabilidade e riscos em potencial à segurança levaram à necessidade de colaboração entre desenvolvimento, segurança e operações: DevSecOps.

Em resumo, a filosofia / cultura DevSecOps sugere adicionarmos uma camada adicional de segurança às práticas DevOps. Ao longo do ciclo e trajetória, a ciência sobre as boas práticas e padrões seguros devem estar presentes.

Conceitualmente, a diferença entre ambas as modalidades seria a adição de práticas de segurança da informação a serem considerados ao nos referirmos ao DevSecOps. Na prática, DevOps e DevSecOps seguem os princípios CI/CD. Quando as recomendações de segurança não são levadas em consideração nos ambientes de execução dos pipelines, o conceito de Continuous Risk Management deve ser introduzido com objetivo de identificar os motivos para a não aderência.

APIs e serviços expostos como micro serviços necessitam de práticas e abordagens DevSecOps. Não existem margens para a segurança não ser considerada e para isso, ferramentas para design e testes de pipelines DevOps devem ser adotadas, melhorando a imagem geral da filosofia DevOps, transformando-a em DevSecOps.

Segmentação e Isolamento

O desacoplamento dos componentes que compõem uma aplicação permite eliminarmos co-dependências desnecessárias entre os micro serviços. Todos os canais de comunicação inter-serviços estabelecidos, em diferentes camadas de uma aplicação, necessitam evitar a exposição de interfaces para camadas inadequadas ou não autorizadas, respeitando o isolamento imposto visando reduzir vulnerabilidades de segurança.

Sistemas distribuídos, e consequentemente arquiteturas de micro serviços tratam o isolamento como um dos princípios chave da sua estratégia. O isolamento proporciona autonomia em seus processos de deploy e manutenção sem afetar os demais serviços convivendo em um mesmo ecossistema.

O deploy dos micro serviços em containers distintos produz uma camada de abstração, reduzindo a ocorrência de conflitos entre Linguagens, Libs e Frameworks.

Containers promovem o isolamento necessário para favorecer a segurança em situações onde temos micro serviços implantados em diferentes linguagens (Heterogenous technical stack). Ao mesmo tempo, o isolamento / segmentação apresenta um alto preço a ser pago e na medida em que distribuímos, diversas categorias de vulnerabilidades são acrescentadas ao processo: novas vulnerabilidades a serem exploradas; malwares; riscos na comunicação irrestrita entre containers; gestão insegura dos dados; configurações adicionais necessárias.

Segurança com API Gateways

APIs são vulneráveis e suscetíveis a ataques, e em conjunto com sua exposição via mini/micro serviços impõem aos APIs Gateways a missão crítica de realizar o gerenciamento de acesso e roteamento das APIs para os serviços de backend com segurança. Gateways atuam como um ponto único de entrada, controlando e mapeando requisições, ajudando a bloquear acesso indevido de clientes externos e consequentemente prevenindo ataques em potencial e atividades maliciosas.

Serviços de backend são implementações das APIs. Servindo como ponto de entrada para as funcionalidades com origem em UIs (user interfaces), estas APIs são comumente expostas através de BFFs (Backend For Frontend).

Funcionalidades como autenticação, registro de transações, aplicação de políticas de runtime e rate-limiting (slow down attackers), presentes em implementações de APIs Gateways (Kong), protegem sua aplicação de acessos não autorizados ou grandes volumes de dados direcionados a ataques por negação de serviço (DDoS). Em muitos casos, dependendo do provedor utilizado, podemos separar a lógica de acesso do código dos serviços, de maneira a monitorar e auditar mais facilmente o fluxo de dados trafegado.

Segurança em APIs Gateways podem ser representadas nas seguintes categorias: Policies (Method, Resource, API level); Policy to Manage the Traffic; Policy to Check JWT.

Secure by Design — Segurança no Ciclo de Desenvolvimento

No contexto de MSA, o significado de “secure by design” refere-se a estarmos cientes dos passos de segurança em todas as etapas de produção do software: design, build e deploy. Para protegermos nossos dados e serviços devemos integrar as diversas camadas de segurança nos artefatos produzidos.

Priorizar a segurança significa testar constantemente nossos códigos e arquitetura, considerando-os embarcados em estágios dos pipelines CI (continuous integration) e CD (continuous delivery) praticando security unit tests, como SAST (Static analysis security testing) e DAST (Dynamic analysis security testing).

Delivery pipelines podem automatizar testes unitários de segurança, minimizando intervenções manuais e repetitivas.

Autenticação de Usuários e Controle de Acesso

Manter a segurança de nossos endpoints e acesso a conteúdo não autorizado trata-se da base para qualquer ambiente dito seguro. Neste contexto, autenticação e controle de acesso (autorização) representam partes críticas para um plano sólido envolvendo implantação de segurança bem sucedida.

O processo de autenticação descreve mecanismos para validação da identidade de determinado usuário para acesso a determinado recurso. Efetivamente, o sucesso durante esse procedimento garante a autenticidade da identidade do usuário. Os processos de autenticação envolvem a solicitação das credenciais do usuário, minimamente exigindo ID / Login e senha de acesso.

Após a autenticação, o usuário precisará interagir com o sistema e para isso, somente estar autenticado não será o suficiente. Neste caso, será necessária a verificação de autorização do usuário para execução das ações necessárias.

O controle de acessos (autorização) é baseado na identidade verificada dos usuários e resume-se a mecanismos capazes de conceder / revogar acesso aos recursos do sistema. Desta forma, o controle de acesso (ACLs — access control list) irá mapear quais ações / operaçẽos estarão disponíveis para execução, pelo usuário, dentro do escopo de uma aplicação: Permissões em arquivos e recursos, aplicações / serviços ou dados.

Alguns exemplos de mecanismos de controle de acesso: mandatory access control (MAC), role-based access control (RBAC) e discretionary access control (DAC).

Para prevenção e deteção de atividades suspeitas em nossas aplicações, OAuth 2.0 e autenticação Multi-factor são recomendados. Nesse caso, para autorização de usuários e prover alertas quando atividades maliciosas são detectadas, respectivamente.

Scan Dependencies

Projetos open-source e bibliotecas de terceiros compõem boa parte dos softwares consumidos e produzidos nos serviços que entregamos para agregarmos valor ao negócio. Quando estes relacionamentos criam grandes cadeias de dependências, acrescentam o risco de possuírem vulnerabilidades de segurança implícitas com difícil rastreio manual da sua integridade.

Esse tipo de pontos de falha podem ser eliminados quando regularmente escaneados repositórios das aplicações, podendo manter rastreabilidades seguras em pipelines de operações DevOps. Conhecer mais a fundo as dependências utilizadas pode assegurar-nos menos riscos, possibilitando habilitar alertas de segurança nos próprios repositórios, automatizando escaneamentos de atualizações originadas de pull requests.

Camadas de segurança Transport Layer Security (TLS, mTLS) em conjunto com protocolos como HTTP protegem os canais de comunicação, entregando criptografia / autenticação para prover confidencialidade e autenticidade aos dados trafegados fortalecendo a segurança.

O escaneamento por dependências desempenha papel fundamental na contribuição para avanços em segurança em libs de terceiros e projetos open-source utilizados. Ao serem detectadas vulnerabilidades em potencial será possível submeter MRs / Patches com correções possibilitando agregarmos valor aos artefatos utilizados pela comunidade.

Segurança em Containers

Micro serviços residem na nuvem, rodando em containers e neste contexto, a segurança deve ser um fator chave na comunicação. A segurança deve estar incorporada em todos os estágios do ciclo produtivo (Shift-left Approach), desde o design, passando pelo desenvolvimento até o deploy dos nossos produtos / serviços.

Para que possamos operar com segurança dentro de ambientes in-cloud e assegurar a integridade tanto dos containers em execução quanto de suas imagens base será necessário atenção para medidas como: utilizar imagens assinadas digitalmente; construir registro de imagens interno; realizar escaneamento dos containers em busca de vulnerabilidades; utilização do rootless-mode; controle de acesso com base em papéis.

Times que trabalham no gerenciamento dos próprios clusters na nuvem precisam estar cientes dos 4 C’s (Datacenter, cluster, container e code) para segurança em cloud-native.

Tornar um ambiente seguro não se trata apenas de prevenir intrusos dentro de nossa infraestrutura. Além disso, a detecção e correção de anomalias ao longo do tempo (Time-based security) precisa ser executada regularmente. Geração de eventos de segurança e relatórios de forma periódica previne futuros danos ao negócio, além de serem o primeiro passo em direção a conquista de micro serviços mais seguros.

Devemos evitar a utilização de contas privilegiadas para rodarmos operações em containers. Ao mesmo tempo, limitar acessos e evitar o armazenamento de secrets em disco das imagens / containers, são boas práticas a serem seguidas.

Usando Tokens: Acesso e Identidade

A utilização adequada dos protocolos e ferramentas para entregar segurança, e efetivamente autenticação e autorização entre os micro serviços, dependem da escolha correta de padrões e boas práticas de indústria (OAuth 2.0). O fluxo de execução deve levar em conta toda a cadeia de chamadas envolvidas no processo, desde os backends, passando pela comunicação com a camada de persistência e interfaces de usuário (UI).

Fluxos como Client-credential Flow, possibilitam adicionarmos segurança durante a comunicação server-to-server entre APIs client e API server.

OpenID Connect (OIDC) estendeu OAuth, em 2014, e juntos passaram a oferecer uma especificação padrão quando nos referimos a validação Identify Tokens (JSON web tokens), descoberta de metadados de provedores OpenID, execução de fluxos OAuth, obtenção de tokens JWKS (JSON web key sets) e recebimento de atributos de usuário adicionais atribuídos a access tokens.

Ao utilizarmos o padrão OAuth 2.0, servidores de autorização desempenham um papel chave em tarefas de autenticação de recursos e tokens de acesso, podendo atuar em dois formatos: many-to-one e one-to-one. Tipicamente, contendo prós e contras, encontramos servidores de autorização mantendo relacionamento no estilo many-to-one entre os diversos micro serviços os quais mantém comunicação, centralizando diversas atividades referentes à segurança.

Criptografia: Protegendo os Secrets e Dados

Ao implementarmos serviços que mantém comunicação com servidores de autenticação / autorização, precisamos manter seguros os elementos utilizados para autenticação básica: Chaves de APIs, segredos e credenciais de clientes. Determinados artefatos são sensíveis e devem ser armazenados em locais apropriados, desta forma, a recomendação será armazenar as chaves em variáveis de ambiente (consumidas por containers durante sua execução in-cloud) e os valores em ferramentas como HashiCorp Vault ou Amazon KMS.

Em segurança da informação, a criptografia desempenha papel fundamental para a segurança dos dados e com isso não devemos reinventar a roda escrevendo nossos próprios algoritmos para criptografar / descriptografar. Desta forma, a recomendação será utilizar ferramentas open-source que implementam algoritmos criptográficos confiáveis independente do nível onde estão localizados (camadas de transporte, persistência ou aplicação).

Considerações Finais

Ao agregarmos segurança, no contexto de arquitetura e desenvolvimento de software, devemos encontrar o balanço correto entre cada etapa do ciclo sem comprometer a produtividade durante o processo. O monitoramento constante fornece insumos para tomadas de decisão, ajudando a manter atualizados os artefatos de segurança essenciais para a saúde dos projetos. Afinal, potência e velocidade não são nada sem controle e segurança.

A indústria, em conjunto com as soluções in-cloud, evoluem rapidamente introduzindo novas tendências em software. Estilos de arquitetura distribuídos, como os micro serviços, adicionam agilidade e escalabilidade a um universo em evolução cada vez mais digital. Na medida em que evoluímos e expandimos nossas soluções será crucial não deixarmos a segurança de lado, considerando seus desafios e abraçando as estratégias e boas práticas as quais favorecem a inserção das nossas aplicações em um patamar cada vez mais seguro.

--

--