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.
94 lines
4.3 KiB
Markdown
94 lines
4.3 KiB
Markdown
# Incidente: el ingress del túnel rompió específicamente a Cosign, no al resto del pipeline (2026-08)
|
|
|
|
| | |
|
|
|---|---|
|
|
| **Ventana del incidente** | 2026-08-15, primer intento de firmar una imagen con Cosign en `build.yaml` |
|
|
| **Servicio afectado** | Cadena Cloudflare Tunnel → NPM (Nginx Proxy Manager) → Gitea, específicamente el endpoint del registry de contenedores |
|
|
| **Impacto** | `cosign sign` fallaba siempre, en cada intento — el resto del pipeline (Gitleaks, Trivy, Semgrep, build, push de la imagen) funcionaba normal contra el mismo registry |
|
|
|
|
## Síntoma
|
|
|
|
Todos los pasos anteriores del pipeline pasaban, incluido `docker push`
|
|
de la imagen al registry de Gitea. El paso de Cosign, inmediatamente
|
|
después, fallaba siempre con:
|
|
|
|
```text
|
|
Error: signing [gitea.cruzcloud.net/***/ecommerce-frontend:v1.0.102]:
|
|
accessing entity: invalid realm in www-authenticate: realm scheme
|
|
"http" not allowed for a secure registry; use https
|
|
```
|
|
|
|
Lo llamativo: **`docker push` a ese mismo registry, un paso antes,
|
|
funcionaba sin problema.** Si el registry estuviera mal configurado en
|
|
general, se esperaría que fallara también el push, no solo la firma.
|
|
|
|
## Diagnóstico
|
|
|
|
El mensaje da la pista exacta: al autenticar contra el registry,
|
|
Cosign recibe un header `WWW-Authenticate` cuyo campo `realm` apunta a
|
|
una URL con esquema `http://` en vez de `https://`. Cosign rechaza
|
|
explícitamente seguir un realm `http` contra lo que él considera "un
|
|
registry seguro" (un dominio público, no `localhost`) — es una
|
|
protección intencional del lado de Cosign, no un bug.
|
|
|
|
`docker push`/`docker login` son más permisivos con esto (o cachean la
|
|
sesión de otra forma) y no chocan con el mismo problema, por eso solo
|
|
Cosign lo mostraba.
|
|
|
|
## Causa raíz
|
|
|
|
El realm que arma Gitea en su respuesta `WWW-Authenticate` depende de
|
|
que Gitea sepa correctamente que la petición le llegó por HTTPS
|
|
(típicamente vía el header `X-Forwarded-Proto` o el Server Name que ve
|
|
en la conexión TLS que termina antes de llegar a él). La cadena real
|
|
acá es **Cloudflare Tunnel → NPM → Gitea** — si el proxy host de NPM
|
|
para `gitea.cruzcloud.net` no tiene el *Origin Server Name* (SNI hacia
|
|
el origen) configurado correctamente, Gitea puede terminar creyendo
|
|
que la conexión entrante fue por HTTP plano, y arma el realm con ese
|
|
esquema equivocado.
|
|
|
|
## Fix aplicado
|
|
|
|
Corrección de la regla de ingress de `cloudflared`/NPM para
|
|
`gitea.cruzcloud.net`: HTTPS hacia el origen con el *Origin Server
|
|
Name* correcto. El fix fue enteramente de infraestructura — no hubo
|
|
ningún cambio en este repo más allá de un commit vacío para volver a
|
|
disparar el pipeline y confirmar el fix contra credenciales reales.
|
|
|
|
## La misma causa raíz de fondo, dos síntomas distintos
|
|
|
|
Este incidente **no es el mismo bug** que el
|
|
[504 Gateway Timeout intermitente del túnel](incidente-504-gitea-tunnel.md)
|
|
ya documentado — ese fue inestabilidad de QUIC/UDP en `cloudflared`,
|
|
resuelto forzando `TUNNEL_TRANSPORT_PROTOCOL=http2`. Pero **ambos
|
|
viven en la misma capa**: la cadena de ingress
|
|
Cloudflare Tunnel → NPM → Gitea, mal configurada de dos formas
|
|
distintas, descubiertas en momentos distintos:
|
|
|
|
- Una regla de **transporte** (QUIC vs HTTP/2) causando 504s
|
|
intermitentes en *cualquier* petición HTTP a los dominios detrás del
|
|
túnel.
|
|
- Una regla de **SNI/origin server name** causando que Gitea generara
|
|
un realm HTTP incorrecto, rompiendo específicamente a un cliente
|
|
(Cosign) que valida ese detalle de forma estricta.
|
|
|
|
La lección compartida: en una cadena de proxies con TLS terminando en
|
|
varios saltos, un solo campo de configuración mal puesto en cualquiera
|
|
de los saltos puede manifestarse como fallas completamente distintas
|
|
según qué tan estricto sea el cliente al otro lado — la mayoría de las
|
|
herramientas HTTP normales ni lo notan, pero una herramienta de
|
|
seguridad como Cosign, que valida explícitamente el esquema del
|
|
realm, sí.
|
|
|
|
## Validación
|
|
|
|
Confirmado en una corrida real posterior al fix: `cosign sign` y
|
|
`cosign verify` completaron sin error contra el registry real, con
|
|
credenciales reales, de punta a punta.
|
|
|
|
!!! note "Nota relacionada, no parte de este incidente"
|
|
El mismo log de este fallo mostró, además del error de realm, el
|
|
warning esperado de Cosign sobre firmar por tag en vez de por
|
|
digest — ver
|
|
[limitaciones conocidas de Cosign](../devsecops/cosign.md#limitaciones-conocidas-y-mejoras-futuras).
|