Então, você acha que seu ambiente de CI/CD é seguro?
Anita Buehrle
21 de fevereiro de 2019
0 minutos de leituraEste artigo, escrito em coautoria pela Weaveworks e pela Snyk, explica como combinar um pipeline de integração contínua (CI) e entrega contínua (CD) baseado em GitOps com boas práticas de segurança para reforçar a segurança geral do fluxo de desenvolvimento para Kubernetes.
O pipeline de CI/CD típico
Seu pipeline de CI/CD pode ser muito parecido com o modelo simplificado abaixo. O fluxo começa bem à esquerda, quando o código está na máquina do desenvolvedor e é enviado para um repositório de código, como o GitHub. Em seguida, uma ferramenta de CI obtém o código, executa testes e cria um artefato, como uma imagem de contêiner. A imagem é enviada ao repositório de imagens e implantada em um orquestrador de código aberto, como o Kubernetes, ou em um sistema semelhante.

Mas muitas vezes as pessoas não se perguntam se o modelo típico de envio do pipeline de CI/CD é seguro. Pense nestas duas perguntas:
Seu ambiente de CI tem acesso direto ao repositório de imagens de contêiner?
Seu ambiente de CI tem acesso direto ao cluster de produção?
Vamos analisar o pipeline novamente, mas desta vez vamos nos concentrar em quais etapas têm acesso umas às outras. Na imagem abaixo, usamos RW para acesso de leitura e gravação e RO para acesso somente leitura. Provavelmente há muito mais linhas vermelhas do que você esperava! Esse pipeline simples viola alguns dos princípios de segurança do Open Web Application Security Project (OWASP), incluindo o Princípio do Menor Privilégio e a Separação de Funções. Por exemplo, o desenvolvedor tem acesso de leitura e gravação ao repositório de código e ao cluster.
Ao remover o acesso direto dos desenvolvedores ao repositório de imagens e ao cluster, você reduz a superfície de ataque e o acesso privilegiado, além de separar as funções.

Chega o GitOps
GitOps é uma forma de fazer entrega contínua para aplicações nativas da nuvem. Ele usa o Git como fonte da verdade para infraestrutura e aplicações declarativas. Os pipelines de entrega implantam automaticamente as alterações na infraestrutura quando há mudanças no Git. Mas a ideia vai além: também são usadas ferramentas para observar o estado real da produção e avisar quando a fonte não corresponde à realidade.
O método GitOps resolve as falhas de segurança do pipeline ao executar um operador de reconciliação dentro do próprio cluster. Ele atua em um repositório Git de configuração, usando credenciais separadas. O operador compara e reconcilia o estado desejado, definido nos arquivos de manifesto armazenados no repositório Git, com o estado real do cluster.

Isso significa que não há vazamento de credenciais entre os limites. O sistema de CI pode operar em uma “zona” de segurança diferente, em vez de atuar no cluster de destino. Cada componente do pipeline precisa de apenas uma credencial RW. Como as credenciais do cluster nunca saem do próprio cluster, você pode “manter seus segredos por perto”.
Ainda preciso me preocupar com segurança?
Ao adotar essa abordagem, você reduz os riscos de segurança ao eliminar problemas relacionados ao Princípio do Menor Privilégio e à Separação de Funções, entre outros. É claro que isso não resolve todas as suas preocupações com segurança. Na verdade, reforça ainda mais a importância de proteger bem o repositório de código.
Chega o GitSecOps
Tudo bem, já temos jargões demais no nosso setor, então não vamos inventar mais um. Dito isso, a maioria das ideias de James Governor, também conhecido como @monkchips, acaba se tornando realidade mais cedo ou mais tarde. Obrigado pela ideia, James. Esperamos que você goste do artigo!
Confira algumas dicas para proteger melhor seu repositório de código.
Adicione testes de segurança às suas PRs
Os principais repositórios de código oferecem frameworks avançados de hooks orientados a eventos, que permitem enviar solicitações HTTP POST para um serviço à sua escolha quando determinados eventos ocorrem. Há muitos eventos que você pode usar, mas um dos mais úteis para testar alterações incrementais no código é o evento pull_request.
Muitas ferramentas de análise estática de código são compatíveis com hooks. Assim, quando uma PR é criada, uma solicitação HTTP POST é enviada para iniciar os testes das atualizações mais recentes. Esse também é um ótimo momento para verificar se as alterações no código e na configuração estão de acordo com suas expectativas de segurança.
Faça uma análise estática do seu repositório com a Snyk
A Snyk analisa estaticamente seu repositório para encontrar dependências vulneráveis que você possa estar usando e ajudar a corrigi-las. Além de testar seus repositórios na interface da Snyk para encontrar problemas, você também pode impedir que usuários adicionem novas bibliotecas vulneráveis: basta testar as pull requests e reprovar o teste se uma nova vulnerabilidade for introduzida.

Além da integração prática com GitHub, GitLab e Bitbucket, as pull requests são melhores do que “interromper o build”. Na verdade, elas nem precisam bloquear um merge, já que, por padrão, servem apenas para informar. Os testes se concentram somente nas suas alterações, e não no resultado geral, e só falham se você introduzir uma biblioteca vulnerável — não se ela já existia antes da sua alteração.
Nunca armazene credenciais no código ou na configuração
Uma busca rápida no GitHub mostra como é comum armazenar senhas em repositórios. Os 350.000 commits encontrados nessa busca simples não incluem aqueles que não eram tão óbvios pelas mensagens de commit, nem os casos em que alguém tentou ocultar os rastros removendo o histórico.
Você também pode usar ferramentas como o git-secrets para interromper automaticamente os builds quando informações confidenciais forem encontradas no código ou em um arquivo de configuração. Definir regras para toda a equipe que evitem esse tipo de situação é uma ótima maneira de coibir práticas inadequadas no fluxo de trabalho atual dos desenvolvedores.
Há várias maneiras de evitar que credenciais sejam incluídas no repositório desde o início. Tente implementar o maior número possível delas, mas lembre-se: mesmo assim, algumas informações confidenciais podem acabar sendo incluídas. Considere também auditar seus repositórios regularmente e usar ferramentas como GitRob ou truffleHog, que examinam sua base de código em busca de informações confidenciais por meio da correspondência de padrões.
Se você descobrir que armazenou dados confidenciais no repositório de código, precisará tomar algumas medidas para resolver a situação:
Invalide os tokens e as senhas que ficaram expostos.
Quando um segredo é publicado na internet, presuma que os invasores já tiveram acesso a ele e aja de acordo.
Remova todo o histórico que contenha seus segredos para garantir que não reste nenhum vestígio deles no código nem na trilha de auditoria.
Controle o acesso com rigor
Exija que seus colaboradores sigam estas práticas básicas:
Exija autenticação de dois fatores na conta do GitHub de cada colaborador.
Nunca permita que usuários compartilhem contas ou senhas.
Proteja adequadamente todos os laptops e dispositivos que tenham acesso ao seu código-fonte.
As contas costumam ser pessoais e não são desativadas automaticamente quando alguém deixa a empresa. Revogue com rigor o acesso de quem não trabalha mais com você.
Os administradores do repositório devem gerenciar o acesso da equipe aos dados. Dê aos colaboradores acesso somente aos dados necessários para o trabalho.
Adicione um arquivo SECURITY.md
É natural que a maioria dos responsáveis e mantenedores de projetos adicione um arquivo README.md ao repositório. Hoje em dia, aliás, a ausência de um README costuma ser malvista. Da mesma forma, está cada vez mais comum adicionar um arquivo SECURITY.md com informações de segurança do projeto. Além de fornecer aos usuários informações importantes sobre segurança, esse arquivo também leva os mantenedores a pensar em como lidar com divulgações de vulnerabilidades, atualizações e práticas gerais de segurança. Bons exemplos de arquivos SECURITY.md podem ser encontrados nos repositórios do Apache Storm e do TensorFlow.
Resumo
Seu servidor de CI pode coordenar tranquilamente o desenvolvimento, incluindo o merge na branch principal, o build e os testes. No entanto, surgem outras preocupações de segurança quando os servidores de CI começam a realizar operações de entrega contínua. O GitOps usa o Kubernetes ou o cluster para gerenciar internamente as implantações com base nas atualizações da branch principal. Isso também é chamado de “modelo pull de CD”.
O Git é a única fonte da verdade para o código, a configuração e a stack associada. Por isso, ele se torna um foco de segurança muito mais importante. Seguir boas práticas gerais no repositório de código pode ajudar de várias formas: por exemplo, executar automaticamente ferramentas de teste como a Snyk em cada pull request, criar um arquivo SECURITY.MD com procedimentos de segurança em uso e guardar segredos em cofres, em vez de armazená-los no código.
Para adicionar segurança aos seus fluxos de trabalho com Git ou aos seus pipelines de CI/CD, teste a Snyk gratuitamente! Você também pode agendar uma demonstração exclusiva com nossa equipe e ver a Snyk em ação.