DEV Community

Kelly Lima
Kelly Lima

Posted on

Pipeline Prowler

Antes de tudo, gostaria de dizer o que me motivou a criar esse artigo/tutorial, bom, sou nova na área de segurança e percebi que tenho muita dificuldade em encontrar artigos/tutoriais em português, em específico de Cloud, vejo muito o básico da teoria sendo explicado, mas vejo pouca prática, então decidi unir o útil ao agradável, passar os conhecimentos que tenho (são poucos e talvez não tão bem definidos) mas espero que possa ajudar alguém e também me ajudar, pois escrevendo para outras pessoas preciso conhecer melhor ainda o assunto o que me faz estudar mais ainda. 💙


Mas o que é o Prowler?

Prowler é uma ferramenta open-source de segurança, neste caso, voltado para segurança Cloud, em específico AWS. Ele funciona como um scan, scanea o seu ambiente baseado em diversos padrões de controle, um exemplo seria o CIS. Dei um resumo do resumo sobre, você pode ver melhor sobre ele aqui.

No desenvolvimento dessa pipeline eu quebrei muito a cabeça, primeiro por não conhecer Jenkins (quem dirá Jenkinsfile) e entender o conceito do Prowler mas não ter visto em prática, no final ela ficou bem mais simples, mas acredite, para alguém que só conhecia e mexia com Angular, foi um desafio legal.

Agora vamos lá, de forma resumida nós iremos criar um Jenkinsfile e trabalhar com imagem Docker do Prowler dentro. O Prowler já possui uma imagem feita e já possui diversos parâmetros que podemos passar, o que facilita bastante o desenvolvimento, de forma resumida nós teremos duas grandes etapas:

  • Dar pull na imagem Docker do Prowler;
  • Executar o scan.

OBS: Fiz esse tutorial para pessoas que conheçam o básico de Jenkinsfile/estrutura, assim como de AWS (Access Keys).


Vamos lá, primeiro que iremos subir essa pipeline através de um arquivo Jenkinsfile e ele no final ficará assim:

Imagem do código da pipeline

Simples, não? Bom, agora vou explicar um pouquinho cada stage que temos:

  1. Primeiro stage chamado: Pipeline Info é apenas visual, eu gosto de ter um primeiro stage apenas para retornar que está inicializando, para mim deixa a usabilidade melhor, mas caso você não queira, pode ignorar.

  2. Segundo stage chamado: Setting up Prowler container é onde fazemos um docker pull da imagem do Prowler, como comentei, Prowler já possui uma imagem própria configurada dentro do Docker Hub, pode ver melhor aqui.

  3. Terceiro stage chamado Setting up envs AWS and run Prowler, é onde a magia toda acontece e tenho alguns pontos para colocar sobre, primeiro:

  • Nos steps nós temos um comando withAWS, mas o que é isso? Bom, withAWS é um comando que vem do plugin Pipeline: AWS Steps, você pode ver melhor sobre aqui, bom esse comando em específico é para setar uma "autorização" para os próximos passos, ou seja, uma credencial diretamente, uma role, um profile. No exemplo acima nós estamos passando uma role, e as permissões que essa role precisa ter, você pode encontrar aqui no Github do projeto.

  • Após passarmos as credenciais que serão usadas, nós iremos passar um script, com alguns pontos que vamos abordar por partes, primeiro, vamos imaginar que iremos passar o comando docker run sem estar dentro de um script, ele irá ficar assim:

Imagem do código da pipeline

  • Vamos falar um pouco sobre cada parâmetro que estamos passando:
--rm        | para remover nosso _container_ após a execução
--name      | é onde passamos o nome do nosso container
--env       | são variáveis de ambiente para pegar os valores das nossas credenciais da AWS para poder executar o scan
Enter fullscreen mode Exit fullscreen mode
  • Esses são os parâmetros mínimos que precisam ser passados para executar o Prowler, e você pode ver melhor sobre na documentação aqui.

  • Agora vamos falar dos outros:

-f        | para filtrarmos por uma região específica
-M        | caso queiramos salvar o resultado do nosso scan, é com esse parâmetro que escolhemos o formato do resultado, pode ser HTML, Json e outros, no exemplo estamos selecionando HTML 
-B        | para salvar o nosso resultado em um Bucket S3 nós podemos passar esse parâmetro com nome do mesmo
Enter fullscreen mode Exit fullscreen mode
  • Algumas observações, o output no formato HTML é muito útil, similar a um dashboard e podemos filtrar por serviço, controle, o que deu falha ou sucesso, sem contar que conta com outras informações como um score que você pode utilizar para ter uma base da saúde do seu ambiente.

  • Uma outra observação, estamos sempre utilizando a última versão da imagem lançada e não uma fixa, está desse jeito para fins didáticos, mas eu recomendo que em um ambiente produtivo seja definido uma versão específica para evitar problemas de compatibilidade no futuro.


Vamos voltar para o nosso código completo? No nosso código completo o último stage fica:

Imagem do código da pipeline

  • Por que executamos desse jeito com o nosso comando docker run em volta de um script e não diretamente igual no exemplo acima que usamos para explicar os comandos? Na verdade, nós podemos executar igual está acima, sem ter um script em volta e ele irá executar todo o comando, mas teremos um problema no retorno do Jenkins. Nossa pipeline irá retornar como Failure mesmo tendo executado tudo da forma correta, pois o Jenkins irá retornar exit code 3, como mostro abaixo:

Imagem do erro na pipeline

Aparentemente quando se executa um Shell Script no Jenkins, tudo que for diferente de 0 (que é sucesso) ele irá lançar um erro de exceção e "quebrar" a pipeline, então nós devemos tratar esse retorno, nós tratamos exatamente na parte que colocamos o returnStatus: true, podemos ver melhor aqui na documentação do Jenkins sobre esse parâmetro para Shell Scripts.

Admito que levei algumas horas de pesquisa e ainda não compreendi a fundo o porque de ele retornar exit code 3, mas descobri que não é algo incomum o Jenkins retornar erros e as pessoas tratarem dessa forma por se tratar de um falso positivo. Também dá para tratar erros específicos utilizando if/else.

Peguei essa dica aqui.

Uma observação, para fins didáticos nós deixamos para ele sempre retornar sucesso, por sabermos que se trata de um falso positivo, mas em um cenário produtivo eu recomendo tratar o erro em específico (exitCode == 3) e pensando em outros erros para retornar algum aviso/ação.


Bom, é isso pessoal! Espero que esse tutorial ajude alguém 💙

Top comments (0)