docs(docs-portal): reflejar fixes de MTU, gitea-runner y cosign digest/rekor
Nuevo playbook del blackhole MTU cross-node (diagnostico + fix + validacion). Actualiza el playbook de contencion de recursos Gitea/runner de 'pendiente' a 'aplicado'. Actualiza cosign.md: firma por digest ya implementada, Rekor como decision tomada (no TODO). Corrige 2 links que quedaron rotos al renombrar la seccion de limitaciones (validado con mkdocs build --strict). Co-Authored-By: Claude Sonnet 5 <[email protected]> Claude-Session: https://claude.ai/code/session_011FqYP3Wf1W63Qmh7qgXAAT
This commit is contained in:
1 parent
86fcc88a1e
commit
b0b832f142
6 files changed
+200
-81
No files matched your search
@@ -79,51 +79,53 @@ localmente, sin tocar el transparency log público
|
||||
|
||||
## Qué NO se firma
|
||||
|
||||
Solo se firma el tag versionado (`ecommerce-frontend:v1.0.X`), no
|
||||
`:latest`. `:latest` es un tag mutable — se re-apunta a una imagen
|
||||
distinta en cada build — así que firmarlo no significa nada útil: la
|
||||
firma quedaría asociada al digest de turno, y la siguiente build la
|
||||
volvería a mover. Cualquier verificación real de firma debería apuntar
|
||||
siempre a un tag de versión específico (o, mejor todavía, al digest
|
||||
exacto).
|
||||
No se firma `:latest` en ningún caso — es un tag mutable, se re-apunta a
|
||||
una imagen distinta en cada build, así que firmarlo no significaría nada
|
||||
útil. Y desde 2026-08-16 (ver más abajo) tampoco se firma directamente
|
||||
por el tag versionado — se firma por **digest**, que es la única
|
||||
referencia que realmente identifica una imagen de forma inequívoca.
|
||||
|
||||
## Verificar manualmente
|
||||
|
||||
Con la llave pública del repo, cualquiera puede confirmar la firma de
|
||||
una imagen sin necesitar acceso a nada privado:
|
||||
una imagen sin necesitar acceso a nada privado. Apuntando al digest
|
||||
exacto (lo que firma el pipeline hoy):
|
||||
|
||||
```bash
|
||||
cosign verify \
|
||||
--key workloads/ecommerce/cosign.pub \
|
||||
--insecure-ignore-tlog=true \
|
||||
gitea.cruzcloud.net/devops/ecommerce-frontend:v1.0.97
|
||||
gitea.cruzcloud.net/devops/ecommerce-frontend@sha256:<digest>
|
||||
```
|
||||
|
||||
También funciona apuntando a un tag — Cosign lo resuelve al digest que
|
||||
tenga en ese momento antes de verificar —, pero por eso mismo es menos
|
||||
preciso: si el tag fue reasignado después de la firma original, estarías
|
||||
verificando una imagen distinta de la firmada, sin que nada te avise.
|
||||
|
||||
Si la imagen fue firmada por este pipeline, el comando termina con
|
||||
`exit 0` y muestra el detalle de la firma. Si no — sea porque nunca se
|
||||
firmó, porque la firmó otra llave, o porque la imagen fue modificada
|
||||
después — termina con `exit 1` y un error explícito.
|
||||
|
||||
## Limitaciones conocidas y mejoras futuras
|
||||
## Decisiones ya resueltas (antes eran TODO)
|
||||
|
||||
Dos limitaciones identificadas al validar el pipeline end-to-end,
|
||||
documentadas a propósito como TODO — ninguna de las dos se implementó
|
||||
todavía.
|
||||
Dos preguntas abiertas al validar el pipeline end-to-end por primera vez,
|
||||
ambas ya cerradas — se documentan igual, porque el *por qué* de cada
|
||||
decisión sigue siendo útil.
|
||||
|
||||
### 1. Se firma por tag, no por digest
|
||||
### 1. Firma por digest, no por tag — implementado 2026-08-16
|
||||
|
||||
Hoy el pipeline firma `ecommerce-frontend:v1.0.104` — un **tag**, no un
|
||||
**digest** (`sha256:...`). Un tag es una etiqueta mutable: nada impide
|
||||
que, después de firmada la imagen, alguien (o un bug en el propio
|
||||
pipeline) vuelva a subir contenido distinto bajo el mismo tag
|
||||
`v1.0.104`. La firma original seguiría "verificando" — porque Cosign,
|
||||
al verificar por tag, resuelve el tag al digest que tenga *en ese
|
||||
momento*, no al que tenía cuando se firmó. Si el tag fue reasignado,
|
||||
se está verificando una imagen distinta de la que realmente se firmó,
|
||||
sin que nada avise.
|
||||
Hasta el 2026-08-15, el pipeline firmaba `ecommerce-frontend:v1.0.104` —
|
||||
un **tag**, no un **digest** (`sha256:...`). Un tag es una etiqueta
|
||||
mutable: nada impedía que, después de firmada la imagen, alguien (o un
|
||||
bug en el propio pipeline) volviera a subir contenido distinto bajo el
|
||||
mismo tag `v1.0.104`. La firma original seguiría "verificando" — porque
|
||||
Cosign, al verificar por tag, resuelve el tag al digest que tenga *en
|
||||
ese momento*, no al que tenía cuando se firmó.
|
||||
|
||||
Esto no es hipotético: el propio Cosign lo advierte en cada firma de
|
||||
este pipeline (visto en los logs reales de cada run):
|
||||
Esto no era hipotético: el propio Cosign lo advertía en cada firma de
|
||||
este pipeline:
|
||||
|
||||
```text
|
||||
WARNING: Image reference gitea.cruzcloud.net/.../ecommerce-frontend:v1.0.102
|
||||
@@ -131,20 +133,20 @@ uses a tag, not a digest, to identify the image to sign.
|
||||
This can lead you to sign a different image than the intended one.
|
||||
```
|
||||
|
||||
**TODO:** capturar el digest exacto que devuelve `docker push` (o
|
||||
`docker buildx build --metadata-file`) y firmar/verificar contra ese
|
||||
digest en vez del tag —
|
||||
**Fix aplicado:** el pipeline ahora captura el digest real que devuelve
|
||||
`docker push` (parseando `sha256:[a-f0-9]{64}` de la salida) y lo usa
|
||||
tanto para firmar como para verificar —
|
||||
`gitea.cruzcloud.net/devops/ecommerce-frontend@sha256:...` en vez de
|
||||
`:v1.0.104`. No implementado todavía; requiere ajustar el step de
|
||||
build para exponer el digest como output y pasarlo a los steps de
|
||||
firma y verificación.
|
||||
`:v1.0.104` — en los tres pipelines (`ecommerce-frontend`,
|
||||
`commerce-backend`, `docs-portal`). Esa advertencia de Cosign ya no
|
||||
debería aparecer en los logs.
|
||||
|
||||
### 2. El transparency log (Rekor) está deshabilitado
|
||||
### 2. El transparency log (Rekor) se mantiene deshabilitado — decisión, no pendiente
|
||||
|
||||
Ya se explicó arriba, en la sección "Por qué `--tlog-upload=false`" de
|
||||
esta misma página, la decisión consciente de no publicar en el
|
||||
transparency log para este registry privado. Vale la pena nombrar en
|
||||
simple qué es lo que se está dejando afuera:
|
||||
esta misma página, la decisión de no publicar en el transparency log
|
||||
para este registry privado. Vale la pena nombrar en simple qué es lo
|
||||
que se está dejando afuera:
|
||||
|
||||
Un **transparency log** (Rekor, el de Sigstore) es un registro
|
||||
público, append-only, criptográficamente verificable, de "quién firmó
|
||||
@@ -160,17 +162,18 @@ la generó quien tuviera la llave privada en el momento en que se
|
||||
verificó"* — pero no hay ningún registro externo e inmutable que
|
||||
demuestre *cuándo* se generó, ni una forma de detectar si alguien con
|
||||
acceso a la llave privada firmó algo por fuera del pipeline sin que
|
||||
quede rastro. Para un lab personal con un registry privado, ese
|
||||
trade-off es razonable (ver la advertencia más abajo en esta misma
|
||||
página). Pero es una limitación real, no solo un detalle de
|
||||
configuración — importa especialmente el día que este mismo patrón se
|
||||
use en un contexto con más de una persona firmando, o con un registry
|
||||
que deje de ser privado.
|
||||
quede rastro.
|
||||
|
||||
**TODO:** si en algún momento el registry deja de ser exclusivamente
|
||||
privado, o se suma más de una persona con acceso a la llave de firma,
|
||||
reevaluar habilitar el transparency log público de Sigstore (o correr
|
||||
uno privado propio) en vez de mantenerlo deshabilitado.
|
||||
**Revisado explícitamente el 2026-08-16** (ya no es un TODO sin decidir,
|
||||
es una elección consciente confirmada): se mantiene deshabilitado.
|
||||
Motivos concretos para este lab — habilitarlo agregaría una llamada de
|
||||
red saliente por build hacia `rekor.sigstore.dev`, atravesando el mismo
|
||||
túnel de Cloudflare que ya tuvo un incidente de SNI/orden de reglas con
|
||||
Cosign (ver el playbook de [realm HTTP y Cosign](../playbooks/incidente-cosign-realm-http-tunnel-2026-08.md)) — más
|
||||
superficie de fallo por build, sin beneficio real, ya que el registry es
|
||||
privado y no hay a quién auditar públicamente. Revisar esta decisión de
|
||||
nuevo si el registry deja de ser exclusivamente privado, o si se suma
|
||||
más de una persona con acceso a la llave de firma.
|
||||
|
||||
## Qué falta (a propósito, todavía)
|
||||
|
||||
|
||||
@@ -105,9 +105,6 @@ 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.
|
||||
- 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
|
||||
|
||||
Reference in new issue
Block a user