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.
4.7 KiB
4.7 KiB
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 | ¿Hay un secreto commiteado? | Bloquea |
| Trivy — imagen | ¿La imagen tiene una CVE conocida? | CRITICAL bloquea, HIGH informa |
| Trivy — IaC | ¿El manifiesto de Kubernetes es inseguro? | Informa |
| Semgrep (SAST) | ¿El código tiene un patrón inseguro conocido? | Informa (auditoría) |
| Syft (SBOM) | ¿Qué paquetes exactos quedaron en la imagen? | Informa (inventario) |
| Cosign | ¿Esta imagen es exactamente la que armó el pipeline? | Bloquea (smoke test) |
El pipeline completo
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 amain. - 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) — hoy la verificación es solo un smoke test dentro del propio pipeline.
- Replicar este mismo patrón a
commerce-backend(Medusa) ydocs-portal, adaptando lo que corresponda a cada stack.