docs(devsecops): agregar página resumen con diagrama del pipeline
docs/devsecops/index.md documenta el pipeline completo (job gitleaks + job build) con un diagrama Mermaid del orden real de ejecución, tabla de qué bloquea vs qué solo informa, y qué pasa si cada herramienta falla. Nav actualizado: "Resumen" como landing page de la sección DevSecOps. Con esto quedan las 5 herramientas de la Fase 2 (Gitleaks, Trivy, Semgrep, Syft, Cosign) integradas y documentadas para workloads/ecommerce, listas para replicar a commerce-backend y docs-portal en una próxima vuelta.
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
# DevSecOps
|
||||
|
||||
Fase 2 del lab: integrar tooling de seguridad al pipeline de Gitea
|
||||
Actions, empezando por un solo repo de referencia — el frontend de ARI
|
||||
Shopping (`workloads/ecommerce`, `.gitea/workflows/build.yaml`) — antes
|
||||
de replicarlo a `commerce-backend` y `docs-portal`.
|
||||
|
||||
Cinco herramientas, cada una respondiendo una pregunta distinta:
|
||||
|
||||
| Herramienta | Pregunta que responde | Modo |
|
||||
|---|---|---|
|
||||
| [Gitleaks](gitleaks.md) | ¿Hay un secreto commiteado? | **Bloquea** |
|
||||
| [Trivy — imagen](trivy.md) | ¿La imagen tiene una CVE conocida? | CRITICAL **bloquea**, HIGH informa |
|
||||
| [Trivy — IaC](trivy.md) | ¿El manifiesto de Kubernetes es inseguro? | Informa |
|
||||
| [Semgrep (SAST)](sast.md) | ¿El código tiene un patrón inseguro conocido? | Informa (auditoría) |
|
||||
| [Syft (SBOM)](sbom.md) | ¿Qué paquetes exactos quedaron en la imagen? | Informa (inventario) |
|
||||
| [Cosign](cosign.md) | ¿Esta imagen es exactamente la que armó el pipeline? | **Bloquea** (smoke test) |
|
||||
|
||||
## El pipeline completo
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
subgraph J1["job: gitleaks (push + pull_request)"]
|
||||
A1[checkout] --> A2["gitleaks detect --no-git"]
|
||||
end
|
||||
|
||||
A2 -- "secreto encontrado" --> XA["❌ pipeline detenido<br/>build nunca arranca"]
|
||||
A2 -- "limpio" --> B0
|
||||
|
||||
subgraph J2["job: build (solo push a main, needs: gitleaks)"]
|
||||
B0[checkout + validaciones de código] --> B1["Trivy IaC<br/>(frontend.yaml)"]
|
||||
B1 -.informa.-> B2["Semgrep SAST<br/>(audit mode)"]
|
||||
B2 -.informa.-> B3[login registry]
|
||||
B3 --> B4["docker build<br/>(push: false, load: true)"]
|
||||
B4 --> B5["Trivy imagen<br/>CRITICAL"]
|
||||
B5 -- "CRITICAL con fix" --> XB["❌ detenido<br/>no se sube la imagen"]
|
||||
B5 -- "sin CRITICAL" --> B6["Trivy imagen<br/>HIGH (informa)"]
|
||||
B6 --> B7["Syft → SBOM<br/>(CycloneDX + SPDX)"]
|
||||
B7 --> B8["docker push"]
|
||||
B8 --> B9["cosign sign"]
|
||||
B9 --> B10["cosign verify<br/>(smoke test)"]
|
||||
B10 -- "firma inválida" --> XC["❌ detenido"]
|
||||
B10 -- "firma válida" --> B11["actualizar frontend.yaml<br/>(GitOps, Argo CD sincroniza)"]
|
||||
end
|
||||
```
|
||||
|
||||
## Por qué este orden
|
||||
|
||||
- **Gitleaks corre en un job aparte, antes que todo lo demás** — incluso
|
||||
antes que el checkout completo del job de build. Si hay un secreto,
|
||||
no tiene sentido gastar minutos de build en un commit que hay que
|
||||
rechazar igual. Es el único check que corre también en `pull_request`,
|
||||
no solo en push a `main`.
|
||||
- **Trivy IaC y Semgrep corren antes del build de Docker.** Ninguno de
|
||||
los dos necesita la imagen construida — analizan manifiestos y código
|
||||
fuente respectivamente — así que si algo llamativo apareciera ahí, se
|
||||
sabe temprano, sin esperar el build (que es el paso más lento del
|
||||
pipeline).
|
||||
- **Trivy imagen corre después del build pero antes del push.** Por eso
|
||||
el build usa `push: false, load: true`: la imagen queda en el daemon
|
||||
local del runner, escaneable, pero no sale hacia el registry hasta
|
||||
pasar el gate de CRITICAL.
|
||||
- **Syft (SBOM) corre sobre la imagen ya validada**, antes del push —
|
||||
documenta exactamente lo que se está por publicar.
|
||||
- **Cosign firma después del push exitoso** (no tiene sentido firmar
|
||||
algo que no llegó al registry) y se verifica en el mismo pipeline como
|
||||
smoke test.
|
||||
|
||||
## Qué pasa si cada uno falla
|
||||
|
||||
| Si falla... | El pipeline... |
|
||||
|---|---|
|
||||
| Gitleaks | Se detiene ahí mismo. El job `build` nunca arranca (`needs: gitleaks`). Nada se construye. |
|
||||
| Trivy IaC | No se detiene — el hallazgo queda en el log, informativo. |
|
||||
| Semgrep | No se detiene — mismo criterio: primera vuelta en modo auditoría. |
|
||||
| Trivy imagen (CRITICAL) | Se detiene después del build, antes del push. La imagen con la CVE nunca llega al registry. |
|
||||
| Trivy imagen (HIGH) | No se detiene — se reporta para revisar en conjunto. |
|
||||
| Syft | Si el propio comando falla (no si "encuentra algo" — un SBOM no tiene hallazgos que bloqueen), el pipeline se detiene por error real de la herramienta. |
|
||||
| Cosign sign/verify | Se detiene. Si la imagen se firmó pero no verifica, algo está mal con las llaves o con la imagen — no se continúa con la promoción GitOps. |
|
||||
|
||||
## Qué falta después de esta primera vuelta
|
||||
|
||||
- Revisar en conjunto los hallazgos de Trivy IaC y Semgrep (hoy
|
||||
informativos) y decidir cuáles pasan a bloquear.
|
||||
- Decidir si Trivy imagen sube el umbral de bloqueo a HIGH una vez que
|
||||
el backlog de CVEs conocidas esté bajo control.
|
||||
- Admission controller en el cluster que verifique la firma de Cosign
|
||||
antes de dejar correr un Pod (ver [cosign.md](cosign.md)) — hoy la
|
||||
verificación es solo un smoke test dentro del propio pipeline.
|
||||
- Replicar este mismo patrón a `commerce-backend` (Medusa) y
|
||||
`docs-portal`, adaptando lo que corresponda a cada stack.
|
||||
Reference in New Issue
Block a user