De forma geral, podemos entender que o código inicialmente está sendo escrito na máquina do desenvolvedor, finalizado a sua codificação o código é então enviado para um repositório de códigos.
Chegando ao repositório de código, temos o primeiro conceito, que é o de Continuous Integration. Um conjunto de ferramentas e ações que são realizadas no código para garantir a primeira camada de proteção, realizando os primeiros testes de código.
Este código é então enviado para uma segunda etapa, o Continuous Delivery, responsável por “empacotar” o software para que este, por meio de outras ferramentas, seja então colocado para produção.
Claro que temos mais coisas neste processo, o intuito aqui é apenas dar uma visão de um processo de CI/CD e como um pipeline funciona.
Se já entendemos isso, podemos seguir e entender como conseguimos mais segurança para nosso pipeline.
Quando pensamos em segurança de software, temos uma fonte que sempre buscamos consultar, neste caso o OWASP tem um conceito de secure by design, e em seu documento estão listados 10 princípios que devem ser seguidos para entregar um código seguro.
No nosso caso, podemos tomar emprestados estes conceitos e pensar neles como sendo os pontos de partida para tornarmos nosso pipeline mais seguro. Claro que não conseguiremos usar todos, mas podemos tomar alguns destes conceitos para nosso propósito.
Abaixo estão listados os 4 conceitos que vamos tomar emprestados e, no decorrer do artigo, vamos colocar cada um deles para tornar nosso pipeline mais seguro.
Em uma configuração padrão, podemos ver que há inúmeros pontos onde o usuário possui um permissionamento não correto para o processo que queremos proteger. Desta forma, precisamos entender qual o melhor fluxo e como ele pode ser avaliada para entregar a nosso processo o conceito de menor privilégio.
Se pensarmos em reduzir a superfície de ataque e olharmos a imagem de nosso pipeline, podemos perceber que não há razão direta para que o desenvolvedor tenha acesso de escrita dentro do repositório de imagens ou mesmo do cluster. Neste exemplo trabalhamos com containers como resultado final.
Assim, com esta simples mudança, podemos garantir também que todos que terão acesso a este pipeline estarão com uma separação de funções bem definidas (separation of duties). Afinal, isso nos garante um pouco mais de segurança e o que nos entregaria um processo mais como o da imagem abaixo.
Mesmo nosso processo estando bem melhor agora, ainda temos que imaginar que nosso pipeline ainda é um grande alvo, pois nele temos acesso ao código, credenciais e outras informações que são de grande interesse a atacantes.
Nesta segunda imagem podemos ver que houve uma redução considerável no permissionamento. Então, criamos agora, por meio das linhas pontilhadas vermelhas, as fronteiras lógicas entre as separações de funções.
Neste ponto, podemos adotar como ponto de avaliação o uso de um conceito chamado defesa em profundidade, onde vamos criar camadas de segurança que tentam limitar ainda mais o acesso ou mesmo o uso de determinado ativo.
No caso de nosso pipeline, podemos imaginar situações onde o processo de autenticação seja realizado por meio de um mecanismos de segundo fator de autenticação (2fA), onde mesmo tendo sua senha sido digitada, o desenvolvedor deve introduzir um segundo fator, talvez um token, para que o sistema valide seu acesso.
Claro, existem outro conceitos e outras formas que podemos usar para manter e garantir a segurança do pipeline, este é apenas um exemplo de como podemos ir buscar em outras áreas de segurança os conceitos necessários para garantir a segurança de um processo.
A segurança no pipeline é um processo de implementação de boas regras de segurança, mas vamos tentar tratar cada um destas práticas que podemos usar para a segurança do pipeline.
Abaixo vamos colocar os pontos de segurança de acordo com o que é mais usualmente encontrado em um processo de CI/CD, mas podem ter algumas variações de acordo com o seu processo.
Em um primeiro momento, vamos tentar garantir a segurança no extremo inicial do processo. Nosso ponto de avaliação será o desenvolvedor. Lembre-se que aqui não vamos falar de como o desenvolvedor deve logar no sistema ou na máquina – esse assunto já foi tratado anteriormente.
Neste ponto, queremos já começar a tratar da segurança do software, e o desenvolvedor deve ser o primeiro ponto de contato. Para isso, vamos imaginar que a segurança já deve ser pensada diretamente na ferramenta de trabalho. Com isso, podemos imaginar na possibilidade em usar plugins de IDE para que este ao escrever o código já vá passando por um processo de validação.