Configurando um pipeline básico: Jenkins
Tags: veracode, jenkins, devops, tutorial
Published: 2023-01-04 13:48:56

**Antes de começarmos**
Para fazer uma integração Veracode precisamos ter uma conta e nela obter as credenciais que vamos utilizar para autenticar as ferramentas, você pode saber como obtê-las [aqui](https://dev.to/m3corp/credenciais-da-veracode-340m).

Como padrão para as implementações, vamos seguir um fluxo simples e montar os pipelines em imagens Linux. É perfeitamente possível utilizar imagens Windows, desde que se alterem os comandos para funcionar no Powershell. Como as ferramentas que vamos usar são construídas em Java, precisamos ter ele disponível no sistema.

**Desenho do pipeline**
A ideia é criar um modelo simples de validação de segurança, que consiga fazer uma combinação das soluções da Veracode para conseguir validar o código próprio e de terceiros, ter os resultados no LOG do pipeline e dentro da plataforma, para poder ser integrado com ferramentas de gerenciamento como Azure Boards e Jira. 

Considerando que o fluxo normal de um pipeline seja:
1. Fazer o checkout
2. Compilar e/ou carregar dependências
3. Publicar o artefato

Vamos adicionar as etapas da Veracode, de forma a nesse fluxo conseguirmos validar o código. É possível fazer alguns paralelismos e otimizações, mas a ideia aqui é mostrar uma forma bem simples de implementação. 

As etapas podem ou não serem usadas para quebrar o pipeline, isso vai depender da estratégia de implementação e das políticas aplicadas. Nesse exemplo, apenas a etapa do Pipeline Scan vai ser um definidor de quebra, verificando se existem falhas em código próprio e quebrando o fluxo caso encontre alguma. 

Nosso desenho então vai ficar:
1. Fazer o checkout
2. Compilar e/ou carregar dependências
3. Envia o código para ser analisado em segundo plano na plataforma da Veracode
4. Verifica os componentes de terceiros utilizados
5. Utiliza o Pipeline Scan para validar código próprio e definir quebra
6. Publicar o artefato

Como estamos pensando em uma imagem Linux, vamos utilizar comandos Shell para fazer o download das ferramentas, prepará-las e então utilizadas. A etapa do deploy em si não estará no código de exemplo. 

Para o exemplo, vamos utilizar um projeto Java com falhas conhecidas, chamado [Verademo](https://github.com/IGDEXE/Verademo). É sempre recomendado consultar o [guia de empacotamento](https://docs.veracode.com/r/c_comp_quickref) para saber o que precisa enviar para a Veracode analisar. 

**Construindo nosso Pipeline**
Pensando em Jenkins, temos alguns caminhos para criar um pipeline, aqui vamos fazer de uma forma mais "grosseira", mas recomendo que faça utilizando o recurso "withCredentials" para algo que vá ser utilizado de forma profissional. Esse vai servir para uma POC ou testar alguma ideia. 

Em nossa seção de variáveis, vamos salvar as credenciais e definir as informações como o nome do Projeto e o caminho do pacote que vamos analisar:
```
environment {
        VeracodeID = ''
        VeracodeKey    = ''
        VeracodeProfile = 'Jenkins.Verademo'
        SRCCLR_API_TOKEN = ''
        CaminhoPacote = 'target/verademo.war'
    }
```

Com as nossas variáveis devidamente atualizadas, podemos fazer a criação dos stages conforme nosso desenho. Vou explicar como vamos fazer as etapas da Veracode, mas no final do artigo vai encontrar o script completo incluindo o checkout e o build. 

Nossa primeira etapa Veracode é utilizar o Wrapper para enviar os dados para a nuvem e processar em segundo plano. Vamos fazer isso para conseguirmos verificar os resultados no portal da Veracode e integrar com as ferramentas de bugtracking. Para utilizar o Wrapper, primeiro fazemos o download dele e lodo em seguida o utilizamos passando os parâmetros: 
- vid e vkey -> Credenciais
- action uploadandscan -> É a ação responsável por fazer o SCA e o SAST
- appname -> Identificador do projeto dentro do portal da Veracode
- createprofile -> Utilizamos para configurar se queremos ou não a criação de novos perfis caso não existam
- version -> É o identificador do scan dentro de um projeto/perfil de aplicação
- filepath -> Caminho do arquivo que queremos analisar

Como número de versão, estou utilizando a data para garantir que não tenha um número repetido, mas pode sincronizar com outra informações como o número de build. 
Colocando isso em código, temos:
```
stage('Wrapper') {
            steps {
                sh 'curl -o veracode-wrapper.jar https://repo1.maven.org/maven2/com/veracode/vosp/api/wrappers/vosp-api-wrappers-java/21.2.7.4/vosp-api-wrappers-java-21.2.7.4.jar'
                sh 'java -jar veracode-wrapper.jar -vid ${VeracodeID} -vkey ${VeracodeKey} -action uploadandscan -appname ${VeracodeProfile} -createprofile true  -version $(date +%H%M%s%d%m%y) -filepath ${CaminhoPacote}'
            }
        }
```

Depois do Wrapper, nosso próximo stage vai ser o do SCA. 
Ao contrário do anterior, não precisamos passar diretamente sua credencial, mas ele só vai funcionar caso o valor **SRCCLR_API_TOKEN** esteja como uma variável de ambiente e disponível para o stage. 
A implementação é bem simples, basicamente apenas um Curl para fazer o download de um script do site da Veracode e em seguida utilizamos parâmetros Shell para fazer o scan.
É importante que o SCA rode na mesma pasta onde fica o arquivo com as dependências, então caso tenha dúvidas, consulte a [documentação](https://docs.veracode.com/r/Using_Veracode_SCA_with_Programming_Languages):
```
stage('SCA') {
            steps {
                sh 'curl -sSL https://download.sourceclear.com/ci.sh | bash -s scan --allow-dirty'
            }
        }
```

Nossa última etapa vai utilizar algo para descompactar um ZIP que vamos baixar do site da Veracode. No exemplo eu utilizo o UNZIP para isso, mas fique a vontade para fazer a sua maneira.
O Pipeline Scan vai funcionar de forma similar ao Wrapper, mas precisamos apenas passar as credenciais e o caminho do arquivo. Como o nosso objetivo é usar o LOG com detalhes, passo um parâmetro para trazer não só o que foi encontrado, mas dicas sobre como corrigir:
```
stage('Pipeline Scan') {
            steps {
                sh 'curl -sSO https://downloads.veracode.com/securityscan/pipeline-scan-LATEST.zip'
                sh 'unzip -o pipeline-scan-LATEST.zip'
                sh 'java -jar pipeline-scan.jar -vid ${VeracodeID} -vkey ${VeracodeKey} -f ${CaminhoPacote} --issue_details true'
            }
        }
```
Recomendo a leitura da [documentação](https://docs.veracode.com/r/r_pipeline_scan_commands) para ver quais outros parâmetros podem ser utilizados, como o para configurar quais níveis de falhas são permitidos, por padrão nosso pipeline vai quebrar caso seja encontrada uma falha de qualquer nível.

Nosso script completo vai ficar assim:
```
pipeline {
    agent any
    
    environment {
        VeracodeID = ''
        VeracodeKey    = ''
        VeracodeProfile = 'Jenkins.Java'
        SRCCLR_API_TOKEN = ''
        CaminhoPacote = 'target/verademo.war'
    }

    stages {
        stage('Git Clone') {
            steps {
                git "https://github.com/IGDEXE/Verademo"
            }
        }
        stage('Build') {
            steps {
                sh 'mvn -B -DskipTests clean package'
            }
        }
        stage('SAST Upload') {
            steps {
                sh 'curl -o veracode-wrapper.jar https://repo1.maven.org/maven2/com/veracode/vosp/api/wrappers/vosp-api-wrappers-java/21.2.7.4/vosp-api-wrappers-java-21.2.7.4.jar'
                sh 'java -jar veracode-wrapper.jar -vid ${VeracodeID} -vkey ${VeracodeKey} -action uploadandscan -appname ${VeracodeProfile} -createprofile true  -version $(date +%H%M%s%d%m%y) -filepath ${CaminhoPacote}'
            }
        }
        stage('SCA') {
            steps {
                sh 'curl -sSL https://download.sourceclear.com/ci.sh | bash -s scan --allow-dirty'
            }
        }
        stage('Pipeline Scan') {
            steps {
                sh 'curl -sSO https://downloads.veracode.com/securityscan/pipeline-scan-LATEST.zip'
                sh 'unzip -o pipeline-scan-LATEST.zip'
                sh 'java -jar pipeline-scan.jar -vid ${VeracodeID} -vkey ${VeracodeKey} -f ${CaminhoPacote} --issue_details true'
            }
        }
    }
}
```

**Resultados**
Com esse desenho, a etapa do SCA e do Pipeline Scan vão colocar nos LOGs as informações sobre as falhas encontradas, a exibição vai variar conforme a interface esteja configurada e a ferramenta que esteja utilizando, mas pensando nos resultados, vamos ter para o SCA: 
![Log SCA](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v5xyrk79lx0chrrcfop6.png)

E para o Pipeline Scan:
![Log Pipeline Scan](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tri54o2avkm39ip68hph.png)

Com isso temos um pipeline simples, mas funcional, onde pode verificar a segurança de seu projeto. Recomendo que em conjunto adicione ferramentas de validação de qualidade de código e testes funcionais, para ter um ciclo de desenvolvimento ideal.