docs(devsecops): documentar 4+1 hallazgos de infraestructura y TODOs de Cosign
5 playbooks nuevos en docs/playbooks/ del portal: - SQLite en modo DELETE causando SQLITE_BUSY, por que WAL lo resuelve. - Anchors YAML no soportados por el parser de Gitea Actions, incluido el diagnostico equivocado inicial (indentacion) que se corrigio despues -- documentado con honestidad como leccion de proceso. - Docker-in-Docker vs sibling containers, y por que Semgrep corre nativo en un venv en vez de como container aparte. - El SNI/realm HTTP del tunel rompiendo especificamente a Cosign (docker push funcionaba, cosign sign no), conectado con el incidente ya documentado del 504 -- misma capa de ingress, dos fallas distintas. - Contencion de recursos entre Gitea y su runner: causa raiz real confirmada en vivo durante esta misma sesion (ambos contenedores reiniciados a mitad de un build, sin limites de CPU/memoria reales), con fix propuesto (ver rama fix/gitea-runner-resource-limits en scripts/) pendiente de aplicacion manual. Se actualiza el playbook del 504 para linkear hacia el nuevo hallazgo de contencion, cerrando el loop que habia quedado abierto ahi. cosign.md: nueva seccion "Limitaciones conocidas y mejoras futuras" con los dos TODO reales -- firma por tag en vez de digest (con el warning real de Cosign visto en los logs) y transparency log de Rekor deshabilitado, explicado en simple. index.md: tabla resumen de los 3 pipelines (imagen + adaptacion de Semgrep por stack), diagrama generalizado para reflejar que es el mismo patron en los 3 workflows, y "que falta" actualizado. Validado con mkdocs build --strict (0 errores, 0 warnings) antes de commitear.
This commit is contained in:
@@ -1,9 +1,22 @@
|
||||
# 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`.
|
||||
Actions. Se empezó por un solo repo de referencia — el frontend de ARI
|
||||
Shopping (`workloads/ecommerce`, `.gitea/workflows/build.yaml`) — y ya
|
||||
está replicado, con evidencia real de corridas en verde, a los tres
|
||||
componentes del monorepo:
|
||||
|
||||
| App | Workflow | Imagen | Adaptación de Semgrep |
|
||||
|---|---|---|---|
|
||||
| Frontend (Next.js) | `build.yaml` | `ecommerce-frontend` | `p/typescript` + `p/react` + `p/nextjs` + `p/security-audit` |
|
||||
| Backend (Medusa v2, API TypeScript) | `build-medusa.yaml` | `ecommerce-medusa` | `p/typescript` + `p/security-audit` + `p/owasp-top-ten` (sin React/Next.js — es una API, no SSR) |
|
||||
| Docs Portal (MkDocs, Python) | `deploy-docs.yaml` | `docs-portal` | `p/python` + `p/security-audit` (sin código de aplicación propio hoy) |
|
||||
|
||||
Cada app tiene su propia llave pública de Cosign commiteada
|
||||
(`cosign.pub` en su propio directorio), pero las tres comparten el
|
||||
mismo par de llaves de firma (mismos secrets `COSIGN_PRIVATE_KEY` /
|
||||
`COSIGN_PASSWORD` a nivel de repo) — una sola identidad de firma para
|
||||
todo el registry de este lab.
|
||||
|
||||
Cinco herramientas, cada una respondiendo una pregunta distinta:
|
||||
|
||||
@@ -18,6 +31,11 @@ Cinco herramientas, cada una respondiendo una pregunta distinta:
|
||||
|
||||
## El pipeline completo
|
||||
|
||||
El mismo patrón corre, con el mismo orden de etapas, en los tres
|
||||
workflows (`build.yaml`, `build-medusa.yaml`, `deploy-docs.yaml`) — lo
|
||||
que cambia entre ellos es el ruleset de Semgrep y qué manifiesto(s)
|
||||
escanea Trivy IaC (ver tabla arriba), no la estructura del pipeline.
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
subgraph J1["job: gitleaks (push + pull_request)"]
|
||||
@@ -28,8 +46,8 @@ flowchart TD
|
||||
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)"]
|
||||
B0[checkout + validaciones de código] --> B1["Trivy IaC<br/>(manifiesto K8s de la app)"]
|
||||
B1 -.informa.-> B2["Semgrep SAST<br/>(ruleset por stack, audit mode)"]
|
||||
B2 -.informa.-> B3[login registry]
|
||||
B3 --> B4["docker build<br/>(push: false, load: true)"]
|
||||
B4 --> B5["Trivy imagen<br/>CRITICAL"]
|
||||
@@ -40,7 +58,7 @@ flowchart TD
|
||||
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)"]
|
||||
B10 -- "firma válida" --> B11["actualizar manifiesto de la app<br/>(GitOps, Argo CD sincroniza)"]
|
||||
end
|
||||
```
|
||||
|
||||
@@ -87,5 +105,15 @@ flowchart TD
|
||||
- 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.
|
||||
- Firmar por digest en vez de por tag, y reevaluar el transparency log
|
||||
de Sigstore — ver
|
||||
[limitaciones conocidas de Cosign](cosign.md#limitaciones-conocidas-y-mejoras-futuras).
|
||||
- `commerce-backend` tiene dos CVE CRITICAL documentados como excepción
|
||||
puntual en `workloads/commerce-backend/.trivyignore` (Go stdlib
|
||||
embebido en el binario de esbuild, sin fix compatible con la versión
|
||||
de Vite que usa el admin-sdk de Medusa hoy) — revisar en cada bump de
|
||||
`@medusajs/*` si ya deja de ser necesaria.
|
||||
- Contención de recursos entre Gitea y su runner bajo carga real —
|
||||
causa raíz confirmada, fix propuesto y documentado, aplicación
|
||||
manual pendiente (ver
|
||||
[playbook de contención de recursos](../playbooks/incidente-contencion-recursos-gitea-runner-2026-08.md)).
|
||||
|
||||
Reference in New Issue
Block a user