Pipeline Prowler
Tags: aws, opensource, devops, tutorial
Published: 2023-02-19 02:38:46

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](https://github.com/prowler-cloud/prowler).

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/10k3m4ygzu9ulj2ykqsz.png)

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](https://plugins.jenkins.io/pipeline-aws/), 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](https://github.com/prowler-cloud/prowler#aws-managed-iam-policies) 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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/drwfzsjpc1wgsdc0mzc9.png)

- 
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
```

- 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](https://github.com/prowler-cloud/prowler).


- 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
```

- 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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kk63esm4v1q1z1czcy1u.png)

- 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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jai53f6auhhh1uhk6b8j.png)

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](https://www.jenkins.io/doc/pipeline/steps/workflow-durable-task-step/#sh-shell-script) 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](https://stackoverflow.com/questions/69571607/jenkins-treats-any-non-zero-exit-code-as-error).

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 💙