Skip to content

Commit f1f65bd

Browse files
committed
docs: document C5 optimized pipeline execution
1 parent ce728e7 commit f1f65bd

1 file changed

Lines changed: 398 additions & 0 deletions

File tree

docs/09-c5-optimized-pipeline.md

Lines changed: 398 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,398 @@
1+
# Etapa 9 — C5: Pipeline Otimizado
2+
3+
<!-- Observação interna: revisar prints e atualizar caminhos das evidências antes de abrir o PR. -->
4+
5+
> **TCC:** Avaliação Experimental do Impacto de Práticas DevSecOps no Lead Time de Pipelines CI/CD
6+
> **Repositório:** [r2WillDev/tcc-devsecops-pipeline](https://github.com/r2WillDev/tcc-devsecops-pipeline)
7+
> **Branch:** `feature/c5-optimized-pipeline`
8+
> **Status:** :white_check_mark: Concluída — aguardando PR
9+
10+
---
11+
12+
## Sumário
13+
14+
- [Objetivo da Etapa](#objetivo-da-etapa)
15+
- [Contexto Experimental](#contexto-experimental)
16+
- [Arquivos Criados e Modificados](#arquivos-criados-e-modificados)
17+
- [Otimizações Aplicadas](#otimizações-aplicadas)
18+
- [Problemas Encontrados e Solução](#problemas-encontrados-e-solução)
19+
- [Resultados das 5 Execuções Oficiais](#resultados-das-5-execuções-oficiais)
20+
- [Estatísticas Consolidadas](#estatísticas-consolidadas)
21+
- [Comparação C4 vs C5](#comparação-c4-vs-c5)
22+
- [Resultados de Segurança](#resultados-de-segurança)
23+
- [Observações Metodológicas](#observações-metodológicas)
24+
25+
---
26+
27+
## Objetivo da Etapa
28+
29+
A Etapa 9 tem como objetivo criar, executar e documentar o cenário **C5 — Pipeline Otimizado**, uma versão aperfeiçoada do cenário C4 que **preserva integralmente as práticas DevSecOps** (SAST, SCA e DAST), mas aplica otimizações controladas para **reduzir o overhead operacional** e melhorar o lead time do pipeline CI/CD.
30+
31+
> [!IMPORTANT]
32+
> O C5 **não remove** nenhuma ferramenta de segurança. O SonarQube SAST, o Trivy SCA e o OWASP ZAP DAST **continuaram ativos** em todas as execuções oficiais. As otimizações foram aplicadas na camada de infraestrutura e orquestração do pipeline, não na cobertura de segurança.
33+
34+
A métrica principal de lead time neste experimento é o `workflow_total`, que representa o tempo total de execução do pipeline do início ao fim. As demais etapas são métricas operacionais individuais e **não** devem ser somadas ao `workflow_total` para evitar dupla contagem.
35+
36+
---
37+
38+
## Contexto Experimental
39+
40+
O experimento é estruturado em cinco cenários progressivos de pipeline CI/CD:
41+
42+
| Cenário | Descrição | Ferramentas de Segurança |
43+
| ------- | --------- | ------------------------ |
44+
| **C1** | Pipeline Baseline | Nenhuma |
45+
| **C2** | Pipeline com SAST | SonarQube |
46+
| **C3** | Pipeline com SAST + SCA | SonarQube + Trivy |
47+
| **C4** | Pipeline com SAST + SCA + DAST | SonarQube + Trivy + OWASP ZAP |
48+
| **C5** | Pipeline Otimizado | SonarQube + Trivy + OWASP ZAP *(com otimizações)* |
49+
50+
O **C5** é comparado **principalmente com o C4**, pois ambos possuem a mesma cobertura de segurança. O objetivo da comparação é quantificar o impacto das otimizações no lead time sem comprometer a postura de segurança do pipeline.
51+
52+
O ambiente de execução utilizou:
53+
54+
- Runner **self-hosted** (`tcc-wsl-runner`)
55+
- **WSL 2** com Ubuntu 24.04
56+
- **Docker Desktop** com integração WSL ativa
57+
- **kind** para cluster Kubernetes local
58+
- **SonarQube** Community Edition em container Docker
59+
- **OWASP ZAP** em execução automatizada
60+
61+
---
62+
63+
## Arquivos Criados e Modificados
64+
65+
| Arquivo | Ação | Finalidade |
66+
| ------- | ---- | ---------- |
67+
| [`.github/workflows/c5-optimized.yml`](../.github/workflows/c5-optimized.yml) | Criado | Workflow do cenário C5 com otimizações |
68+
| [`analysis/raw/c5_optimized.csv`](../analysis/raw/c5_optimized.csv) | Criado | Armazenamento das métricas brutas das execuções C5 |
69+
| [`docs/09-c5-optimized-pipeline.md`](../docs/09-c5-optimized-pipeline.md) | Criado | Documentação desta etapa |
70+
71+
> [!NOTE]
72+
> O script `ci/scripts/measure_step.sh` **não foi modificado**. O comportamento de medição, registro de status e fail-fast herdado das etapas anteriores foi reaproveitado sem alteração.
73+
74+
### Commits realizados
75+
76+
| Hash | Mensagem |
77+
| ---- | -------- |
78+
| `18e1e93` | `analysis: add C5 results CSV header` |
79+
| `ce7f225` | `ci: add initial C5 optimized workflow` |
80+
| `4e1ab5d` | `ci: add Python dependency cache to C5 workflow` |
81+
| `e935bab` | `ci: add Trivy cache to optimized pipeline` |
82+
| `5fb08dc` | `ci: add conditional DAST execution to C5 workflow` |
83+
84+
Adicionalmente, foi realizado um ajuste posterior:
85+
86+
```text
87+
ci: force JavaScript actions to Node 24 in C5 workflow
88+
```
89+
90+
Esse commit adicionou a variável de ambiente `FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true` ao workflow. Com isso, o aviso sobre Node.js 20 passou a ser apenas informativo — as actions JavaScript foram forçadas a executar com Node.js 24, garantindo compatibilidade futura com a plataforma GitHub Actions.
91+
92+
---
93+
94+
## Otimizações Aplicadas
95+
96+
| Otimização | Implementação | Impacto esperado | Evidência |
97+
| ---------- | ------------- | ---------------- | --------- |
98+
| Cache de dependências Python | `actions/setup-python@v6` com `cache: "pip"` | Elimina o download repetido de pacotes PyPI entre execuções | `Cache restored successfully` nos logs |
99+
| Cache do banco de dados Trivy | `actions/cache@v4` em `~/.cache/trivy` | Evita download repetido do banco de vulnerabilidades | `Cache hit occurred on the primary key Linux-trivy-v0.71.0-...` |
100+
| Execução condicional do OWASP ZAP | Input `run_zap` com padrão `"true"` | Permite execuções manuais econômicas sem comprometer dados oficiais | Parâmetro `run_zap` visível no `workflow_dispatch` |
101+
| Fail-fast herdado | Comportamento do `measure_step.sh` | Encerra o pipeline imediatamente quando uma etapa crítica falha, evitando execução de etapas pesadas desnecessárias | Comportamento observado em tentativas com falha |
102+
| Compatibilidade futura Node.js 24 | `FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true` | Prepara o workflow para a descontinuação do Node.js 20 nas actions | Warning informativo nos logs de execução |
103+
104+
### Detalhamento das otimizações
105+
106+
#### 1. Cache de dependências Python
107+
108+
O cache foi configurado usando `actions/setup-python@v6` com os parâmetros:
109+
110+
```yaml
111+
- name: Setup Python with pip cache
112+
uses: actions/setup-python@v6
113+
with:
114+
python-version: "3.12"
115+
cache: "pip"
116+
cache-dependency-path: "app/requirements.txt"
117+
```
118+
119+
Evidência de cache hit nos logs:
120+
121+
```text
122+
Cache hit for: setup-python-Linux-x64-24.04-Ubuntu-python-3.12.13-pip-...
123+
Cache restored successfully
124+
```
125+
126+
#### 2. Cache do Trivy
127+
128+
O banco de dados de vulnerabilidades do Trivy foi cacheado usando `actions/cache@v4`:
129+
130+
```yaml
131+
- name: Cache Trivy vulnerability database
132+
uses: actions/cache@v4
133+
with:
134+
path: ~/.cache/trivy
135+
key: ${{ runner.os }}-trivy-${{ env.TRIVY_VERSION }}-${{ hashFiles('ci/config/trivy.yaml') }}
136+
restore-keys: |
137+
${{ runner.os }}-trivy-${{ env.TRIVY_VERSION }}-
138+
```
139+
140+
Evidência de cache hit nos logs:
141+
142+
```text
143+
Cache hit occurred on the primary key Linux-trivy-v0.71.0-...
144+
```
145+
146+
#### 3. Execução condicional do OWASP ZAP
147+
148+
O input `run_zap` foi adicionado ao `workflow_dispatch`, com valor padrão `"true"`:
149+
150+
```yaml
151+
on:
152+
workflow_dispatch:
153+
inputs:
154+
run_zap:
155+
description: "Run OWASP ZAP DAST scan"
156+
required: true
157+
default: "true"
158+
type: choice
159+
options:
160+
- "true"
161+
- "false"
162+
```
163+
164+
> [!WARNING]
165+
> A execução condicional do ZAP **não foi usada para reduzir artificialmente o tempo** das execuções oficiais. Nas 5 execuções coletadas para o experimento, o `run_zap` manteve o valor padrão `"true"` e o DAST foi executado normalmente. A condicional existe apenas para facilitar execuções de teste manual sem custo de tempo, sem impactar os dados experimentais.
166+
167+
Quando `run_zap=false`, as etapas de DAST registram métricas com status `skipped`, preservando a comparabilidade estrutural do CSV.
168+
169+
#### 4. Fail-fast herdado
170+
171+
O script `ci/scripts/measure_step.sh` registra o status de cada etapa e, em caso de falha, encerra com `exit 1`. Esse comportamento evita que etapas pesadas como o ZAP sejam executadas após uma falha crítica anterior, reduzindo o desperdício de tempo em runs com erro.
172+
173+
#### 5. Compatibilidade futura com Node.js 24
174+
175+
```yaml
176+
env:
177+
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
178+
```
179+
180+
O warning sobre Node.js 20 permaneceu nos logs apenas como aviso informativo. Com essa variável ativa, as actions que ainda usavam o runtime Node.js 20 passaram a ser executadas com Node.js 24, preparando o workflow para a descontinuação futura do Node.js 20 na plataforma GitHub Actions.
181+
182+
183+
184+
## Problemas Encontrados e Solução
185+
186+
### Falha na etapa `Run SonarQube SAST analysis`
187+
188+
<details>
189+
<summary>:warning: Expandir detalhes do problema e solução</summary>
190+
191+
#### Erro observado
192+
193+
```text
194+
failed to connect to the docker API at unix:///var/run/docker.sock
195+
```
196+
197+
#### Causa raiz
198+
199+
O runner `tcc-wsl-runner` estava em execução dentro do WSL, mas o **Docker Desktop** não estava ativo ou a integração com a distro `Ubuntu-24.04` havia sido desativada. Como consequência:
200+
201+
- O socket `/var/run/docker.sock` não estava disponível no WSL
202+
- O SonarQube Scanner não conseguia se comunicar com o daemon Docker
203+
- A etapa de SAST falhou antes de completar a análise
204+
205+
#### Solução aplicada
206+
207+
1. Reiniciar o Docker Desktop no Windows
208+
2. Aguardar inicialização completa do daemon Docker
209+
3. Verificar e ativar a integração Docker Desktop → WSL2 → `Ubuntu-24.04`
210+
4. Confirmar a presença do socket no WSL:
211+
212+
```bash
213+
ls -l /var/run/docker.sock
214+
```
215+
216+
5. Subir novamente o container do SonarQube:
217+
218+
```powershell
219+
docker compose -f .\infra\sonarqube\docker-compose.yml up -d
220+
```
221+
222+
6. Aguardar o SonarQube ficar `UP`:
223+
224+
```powershell
225+
Invoke-RestMethod http://localhost:9000/api/system/status
226+
```
227+
228+
7. Reiniciar o runner no WSL:
229+
230+
```bash
231+
cd ~/actions-runner-tcc
232+
./run.sh
233+
```
234+
235+
#### Resultado
236+
237+
- Runner voltou a ouvir e processar jobs
238+
- Docker ficou acessível no WSL via socket
239+
- SonarQube retornou ao status `UP`
240+
- O workflow C5 executou com sucesso nas execuções subsequentes
241+
242+
</details>
243+
244+
---
245+
246+
## Resultados das 5 Execuções Oficiais
247+
248+
249+
Os dados abaixo foram extraídos dos artifacts gerados pelo GitHub Actions, especialmente do arquivo `analysis/raw/c5_optimized_run.csv`, produzido em cada execução oficial do workflow C5. O arquivo versionado `analysis/raw/c5_optimized.csv` contém apenas o cabeçalho base para padronização dos dados.
250+
251+
| Run | `workflow_total` | `dast_zap_baseline` | `kubernetes_deploy` | `sonarqube_sast` | Status |
252+
| --: | ---------------: | ------------------: | ------------------: | ---------------: | ------ |
253+
| 1 | 172 | 44 | 39 | 16 | :white_check_mark: success |
254+
| 2 | 240 | 79 | 37 | 12 | :white_check_mark: success |
255+
| 3 | 180 | 44 | 29 | 20 | :white_check_mark: success |
256+
| 4 | 178 | 37 | 34 | 13 | :white_check_mark: success |
257+
| 5 | 189 | 36 | 38 | 18 | :white_check_mark: success |
258+
259+
### Dados brutos completos (CSV)
260+
261+
<details>
262+
<summary>Expandir CSV completo</summary>
263+
264+
```csv
265+
run,install_dependencies,unit_tests,sonarqube_sast,docker_build,sca_fs,sca_image,sca_total,kubernetes_deploy,kubernetes_smoke_test,dast_health_check,dast_zap_baseline,workflow_total
266+
1,0,2,16,5,0,1,1,39,5,0,44,172
267+
2,1,1,12,2,1,0,1,37,6,0,79,240
268+
3,1,1,20,2,0,3,3,29,5,0,44,180
269+
4,0,1,13,2,0,2,2,34,5,0,37,178
270+
5,0,2,18,2,0,2,2,38,5,0,36,189
271+
```
272+
273+
</details>
274+
275+
---
276+
277+
## Estatísticas Consolidadas
278+
279+
> [!NOTE]
280+
> O `workflow_total` é a **métrica principal de lead time** do experimento e **não** é incluído no ranking de etapas operacionais. As médias abaixo são calculadas sobre as 5 execuções oficiais.
281+
282+
| Métrica | Resultado |
283+
| ------- | --------: |
284+
| `workflow_total` médio | **191,80 s** |
285+
| `workflow_total` mínimo | 172,00 s |
286+
| `workflow_total` máximo | 240,00 s |
287+
| Variação (`max - min`) | 68,00 s |
288+
| Desvio padrão amostral | 27,63 s |
289+
| Etapa operacional mais lenta | `dast_zap_baseline` — 48,00 s |
290+
| Segunda etapa mais lenta | `kubernetes_deploy` — 35,40 s |
291+
292+
### Ranking das etapas operacionais por média (s)
293+
294+
> `workflow_total` **excluído** do ranking por ser a métrica agregada de lead time.
295+
296+
| Posição | Etapa | Média (s) |
297+
| ------: | ----- | --------: |
298+
| 1 | `dast_zap_baseline` | **48,00** |
299+
| 2 | `kubernetes_deploy` | **35,40** |
300+
| 3 | `sonarqube_sast` | 15,80 |
301+
| 4 | `kubernetes_smoke_test` | 5,20 |
302+
| 5 | `docker_build` | 2,60 |
303+
| 6 | `sca_total` | 1,80 |
304+
| 7 | `sca_image` | 1,60 |
305+
| 8 | `unit_tests` | 1,40 |
306+
| 9 | `install_dependencies` | 0,40 |
307+
| 10 | `sca_fs` | 0,20 |
308+
| 11 | `dast_health_check` | 0,00 |
309+
310+
---
311+
312+
## Comparação C4 vs C5
313+
314+
<a id="comparacao-c4-c5"></a>
315+
316+
> [!IMPORTANT]
317+
> A comparação entre C4 e C5 é o principal indicador do impacto das otimizações aplicadas, **mantendo a mesma cobertura de segurança** (SAST + SCA + DAST).
318+
319+
| Métrica | C4 (referência) | C5 (médio) | Redução absoluta | Redução percentual |
320+
| ------- | --------------: | ---------: | ---------------: | -----------------: |
321+
| `workflow_total` | 309 s | 191,80 s | **117,20 s** | **37,93%** |
322+
| `dast_zap_baseline` | 197 s | 48,00 s | **149,00 s** | **75,63%** |
323+
324+
### Análise da redução
325+
326+
A redução de **~37,93%** no `workflow_total` do C5 em relação ao C4 de referência não deve ser atribuída exclusivamente ao cache. Os fatores que contribuíram para a melhora incluem:
327+
328+
- :rocket: **Cache de dependências Python** — eliminou o download repetido de pacotes PyPI
329+
- :rocket: **Cache do banco de dados Trivy** — eliminou o download repetido do banco de CVEs
330+
- :rocket: **Ambiente aquecido** — o runner self-hosted manteve dados de camadas Docker e artefatos locais entre execuções
331+
- :rocket: **Variações naturais do runner local** — o ambiente WSL + Docker Desktop apresenta variabilidade inerente
332+
- :rocket: **Menor overhead operacional** — a soma das otimizações reduziu o tempo de preparação de cada etapa
333+
334+
A redução expressiva do `dast_zap_baseline` pode estar relacionada ao aquecimento do ambiente local, reaproveitamento de camadas/imagens Docker, menor overhead do runner self-hosted e variações naturais da execução do ZAP em ambiente WSL + Docker Desktop.
335+
336+
337+
---
338+
339+
## Resultados de Segurança
340+
341+
O C5 manteve plena cobertura de segurança. Os resultados abaixo confirmam que as ferramentas continuaram operacionais e reportando achados.
342+
343+
### Trivy SCA
344+
345+
| Alvo | Low | Medium | High | Critical | Total |
346+
| ---- | --: | -----: | ---: | -------: | ----: |
347+
| Filesystem | — | 1 | — | — | 1 |
348+
| Image | 63 | 33 | 8 | 2 | **106** |
349+
| **Total** | **63** | **34** | **8** | **2** | **107** |
350+
351+
> [!NOTE]
352+
> O total agregado soma os achados por alvo de análise (`filesystem` e `image`) e não representa necessariamente vulnerabilidades únicas deduplicadas entre os dois scans.
353+
354+
355+
> [!NOTE]
356+
> As vulnerabilidades reportadas pelo Trivy são consistentes com os resultados dos cenários anteriores (C3 e C4), confirmando que o C5 não alterou o escopo de análise de dependências.
357+
358+
### OWASP ZAP DAST
359+
360+
| Info | Low | Medium | High | Total |
361+
| ---: | --: | -----: | ---: | ----: |
362+
| 1 | 2 | 0 | 0 | **3** |
363+
364+
365+
> [!NOTE]
366+
> Nenhuma vulnerabilidade de severidade **Medium** ou **High** foi identificada pelo ZAP. O resultado está alinhado com os cenários anteriores, confirmando que a aplicação FastAPI de teste mantém o mesmo perfil de exposição.
367+
368+
369+
370+
## Observações Metodológicas
371+
372+
1. **`workflow_total` como métrica de lead time:** o `workflow_total` representa o tempo total decorrido desde o início do workflow até sua conclusão. É a métrica que mais se aproxima do conceito de *lead time* em CI/CD. As demais métricas são etapas operacionais individuais e servem para diagnóstico, não para ranking de lead time.
373+
374+
2. **Não atribuir todo o ganho ao cache:** as otimizações de cache são uma parte do ganho, mas o ambiente aquecido (runner self-hosted que mantém estado entre runs), as variações naturais do WSL e do Docker Desktop, e a menor sobrecarga operacional agregada também contribuíram para a redução observada.
375+
376+
3. **Comparabilidade dos dados:** as 5 execuções oficiais do C5 foram realizadas com `run_zap=true` (valor padrão), garantindo que o DAST esteve ativo em todas as medições. Execuções de teste manual com `run_zap=false` não foram incluídas nos dados experimentais.
377+
378+
4. **Variabilidade esperada:** o desvio padrão amostral de 27,63 s (sobre uma média de 191,80 s) é esperado em ambientes self-hosted locais. A run 2 apresentou o maior `workflow_total` (240 s), puxado pelo `dast_zap_baseline` de 79 s, o que é consistente com a variabilidade do ZAP em ambientes locais.
379+
380+
5. **Preservação das práticas DevSecOps:** o C5 demonstra que é possível **reduzir o lead time de um pipeline DevSecOps sem abrir mão das verificações de segurança**. Esse é o ponto central da contribuição do cenário C5 para o experimento.
381+
382+
> O C5 preservou SAST, SCA e DAST, aplicando otimizações controladas para reduzir overhead operacional e melhorar o lead time sem eliminar práticas de segurança.
383+
384+
385+
386+
### Notas de rodapé
387+
388+
O `workflow_total` é calculado pelo script `measure_step.sh` como a diferença entre o timestamp de início do job e o timestamp de conclusão da última etapa medida.[^1]
389+
390+
O desvio padrão amostral foi calculado com `n-1` no denominador (fórmula de Bessel), adequado para amostras pequenas.[^2]
391+
[^1]: O script `ci/scripts/measure_step.sh` registra timestamps em epoch Unix e calcula a duração em segundos inteiros por diferença simples.
392+
393+
[^2]: Fórmula: s = √(Σ(xᵢ − x̄)² / (n − 1)), onde n = 5 execuções e x̄ = 191,80 s.
394+
O uso de n-1 é recomendado quando a amostra é pequena e o objetivo é estimar o desvio padrão populacional a partir de uma amostra.
395+
396+
---
397+
398+
*Documento gerado para o TCC — Avaliação Experimental do Impacto de Práticas DevSecOps no Lead Time de Pipelines CI/CD.*<br>

0 commit comments

Comments
 (0)