Herramientas de Firma de Imágenes Container Comparadas: Cosign vs Notation vs GPG

Por Qué Importa la Firma de Imágenes Container

Cada vez que descargas una imagen container y la despliegas en producción, estás depositando una confianza implícita en ese artefacto. Pero, ¿cómo verificas que la imagen no ha sido manipulada? ¿Cómo confirmas que fue realmente construida por tu pipeline CI/CD y no inyectada por un atacante que comprometió tu registro?

La firma de imágenes container resuelve este problema adjuntando una firma criptográfica a tus imágenes. Antes del despliegue, tu orquestador o controlador de admisión puede verificar esa firma, asegurando que solo imágenes confiables y autenticadas entren en tu entorno. Este es un pilar fundamental de la seguridad de la cadena de suministro de software y un requisito en marcos como SLSA y NIST SSDF.

Pero las herramientas de firma no son todas iguales. Los tres enfoques dominantes hoy — Cosign (parte del proyecto Sigstore), Notation (el cliente de Notary v2) y GPG (el enfoque tradicional) — cada uno viene con compensaciones radicalmente diferentes en gestión de claves, integración CI/CD y compatibilidad del ecosistema.

En esta guía, haremos una comparación profunda y práctica de los tres para que puedas tomar la decisión correcta para tus pipelines.

Cosign y el Ecosistema Sigstore

Descripción General

Cosign es la herramienta de firma de imágenes container del proyecto Sigstore, que ahora es un proyecto graduado bajo la Linux Foundation. La misión de Sigstore es hacer que la firma de software sea ubicua eliminando la mayor barrera: la gestión de claves.

Cosign almacena las firmas como artefactos OCI directamente junto a la imagen firmada en el mismo registro. Esto significa que no hay un sistema separado de almacenamiento de firmas que mantener — tu registro de contenedores existente (Docker Hub, GitHub Container Registry, AWS ECR, Google Artifact Registry, etc.) cumple doble función.

Firma Keyless con Fulcio y Rekor

La característica más revolucionaria de Cosign es la firma keyless. En lugar de gestionar claves de firma de larga duración, Cosign se integra con dos servicios:

  • Fulcio — Una autoridad certificadora que emite certificados de firma de corta duración basados en una identidad OpenID Connect (OIDC). En un contexto CI/CD, esta es típicamente el token de identidad de tu proveedor de pipeline (GitHub Actions OIDC, GitLab CI OIDC, etc.).
  • Rekor — Un registro de transparencia inmutable que registra cada evento de firma. Esto proporciona una pista de auditoría a prueba de manipulaciones de quién firmó qué y cuándo.

Con la firma keyless, el flujo de trabajo se ve así:

  1. Tu pipeline CI solicita un token OIDC del proveedor del pipeline.
  2. Cosign presenta ese token a Fulcio, que emite un certificado de corta duración vinculando la identidad del pipeline a un par de claves efímero.
  3. Cosign firma el digest de la imagen con la clave privada efímera.
  4. La firma y el certificado se registran en el registro de transparencia de Rekor.
  5. La clave privada efímera se descarta — solo existió durante segundos.

Esto elimina toda la clase de problemas relacionados con la rotación de claves, el almacenamiento de claves y el compromiso de claves. No hay ningún secreto de larga duración que proteger.

Firma Basada en Claves

Cosign también soporta la firma tradicional con par de claves para entornos donde la firma keyless no es factible (redes air-gapped, requisitos regulatorios para custodia específica de claves). Generas un par de claves con cosign generate-key-pair y firmas con cosign sign --key cosign.key.

Ejemplo de Integración CI/CD: GitHub Actions

# .github/workflows/sign.yml
jobs:
  sign:
    runs-on: ubuntu-latest
    permissions:
      id-token: write   # Required for keyless signing
      packages: write   # Required to push signatures to GHCR
    steps:
      - uses: sigstore/cosign-installer@v3

      - name: Sign the container image (keyless)
        env:
          COSIGN_EXPERIMENTAL: 1
        run: |
          cosign sign --yes ghcr.io/myorg/myapp@sha256:abc123...

      - name: Verify the signature
        run: |
          cosign verify \
            --certificate-oidc-issuer https://token.actions.githubusercontent.com \
            --certificate-identity-regexp https://github.com/myorg/myapp/.github/workflows/* \
            ghcr.io/myorg/myapp@sha256:abc123...

El permiso id-token: write es la pieza crítica — permite que GitHub Actions genere el token OIDC que Fulcio usa para emitir el certificado de firma. Sin secretos que configurar, sin claves que almacenar. Para un recorrido práctico, consulta nuestro Laboratorio de Firma Keyless con Cosign.

Fortalezas

  • La firma keyless elimina completamente la gestión de claves en CI/CD
  • El registro de transparencia (Rekor) proporciona una pista de auditoría inmutable
  • Almacenamiento nativo de artefactos OCI — no se necesita un almacén de firmas externo
  • Verificación de políticas enriquecida con coincidencia de identidad de certificados
  • Amplio soporte del ecosistema (Kyverno, OPA Gatekeeper, controladores de políticas de Kubernetes)
  • Comunidad open-source activa y bien financiada

Limitaciones

  • El modo keyless requiere acceso a internet para Fulcio y Rekor (desafiante para entornos air-gapped)
  • La verificación en entornos air-gapped requiere duplicar el registro de transparencia
  • Proyecto relativamente joven comparado con GPG (aunque ahora estable y graduado)

Notation y Notary v2

Descripción General

Notation es el cliente CLI para la especificación Notary v2, un proyecto CNCF respaldado principalmente por Microsoft y AWS. Donde Cosign fue construido específicamente para el ecosistema Sigstore, Notation fue diseñado para integrarse con infraestructura PKI empresarial y flujos de trabajo existentes de certificados X.509.

Notation utiliza firmas COSE (CBOR Object Signing and Encryption) almacenadas como artefactos OCI adjuntos a la imagen firmada usando la especificación ORAS (OCI Registry As Storage). Al igual que Cosign, esto significa que las firmas residen en el registro OCI junto a las imágenes.

Gestión de Claves con Plugins

Notation utiliza una arquitectura de plugins para la gestión de claves. En lugar de manejar las claves directamente, delega en plugins que se comunican con almacenes de claves externos:

  • Plugin de Azure Key Vault — Firma usando claves almacenadas en Azure Key Vault.
  • Plugin de AWS Signer — Utiliza AWS Signer, un servicio de firma completamente gestionado.
  • Plugin de HashiCorp Vault — Se integra con el motor de secretos transit de Vault.

Este modelo de plugins es una opción natural para empresas que ya tienen gestión centralizada de claves e infraestructura PKI. La clave de firma nunca sale del HSM o cloud KMS — Notation envía el digest al plugin, y el plugin devuelve la firma.

Políticas de Confianza y Almacenes de Confianza

Notation utiliza un sistema de políticas de confianza basado en JSON para la verificación. Defines qué registros, repositorios e imágenes confías y qué certificados o cadenas de certificados están autorizados para firmarlos. Esto es poderoso para escenarios de gobernanza empresarial donde diferentes equipos tienen diferentes autoridades de firma.

// trustpolicy.json
{
  "version": "1.0",
  "trustPolicies": [
    {
      "name": "production-images",
      "registryScopes": ["registry.example.com/prod/*"],
      "signatureVerification": {
        "level": "strict"
      },
      "trustStores": ["ca:production-ca"],
      "trustedIdentities": ["x509.subject: CN=prod-signer, O=MyOrg"]
    }
  ]
}

Ejemplo de Integración CI/CD: GitHub Actions con AWS Signer

# .github/workflows/notation-sign.yml
jobs:
  sign:
    runs-on: ubuntu-latest
    permissions:
      id-token: write  # For AWS OIDC federation
    steps:
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123456789012:role/signer-role
          aws-region: us-east-1

      - name: Setup Notation
        uses: notaryproject/notation-action/setup@v1

      - name: Install AWS Signer plugin
        run: |
          notation plugin install \
            --url https://d2hvyiie56hcat.cloudfront.net/linux/amd64/plugin/latest/notation-aws-signer-plugin.zip

      - name: Sign the container image
        run: |
          notation sign \
            --plugin com.amazonaws.signer.notation.plugin \
            --id arn:aws:signer:us-east-1:123456789012:/signing-profiles/MyProfile \
            registry.example.com/myapp@sha256:abc123...

Fortalezas

  • Arquitectura de plugins amigable con empresas que se integra con PKI y KMS existentes
  • Marco de políticas de confianza enriquecido para verificación granular por alcance de registro
  • El formato de firma COSE es un estándar IETF bien establecido
  • Fuerte respaldo de Microsoft (Azure) y AWS
  • Diseñado para organizaciones con flujos de trabajo existentes de certificados X.509
  • La verificación offline es sencilla — solo necesitas los certificados del almacén de confianza

Limitaciones

  • Sin firma keyless — debes gestionar certificados y claves (incluso si se delegan a un KMS)
  • Sin equivalente de registro de transparencia integrado
  • El ecosistema de plugins aún está creciendo; menos plugins que los puntos de integración de Cosign
  • Comunidad más pequeña y menos tutoriales comparado con Cosign
  • La configuración de políticas de confianza puede ser compleja para casos de uso simples

GPG: El Enfoque Tradicional

Descripción General

GPG (GNU Privacy Guard) es el veterano del mundo de la firma. Mucho antes de que existieran las herramientas de firma nativas para contenedores, GPG se usaba para firmar todo, desde correos electrónicos hasta commits de Git y paquetes de Linux. Algunos equipos aún usan GPG para firmar imágenes container, particularmente a través de herramientas como Docker Content Trust (DCT) o firmando manifiestos de imágenes fuera de banda.

Cómo Funciona la Firma GPG para Contenedores

La firma GPG de contenedores típicamente sigue uno de dos patrones:

  • Firma fuera de banda: Exporta el manifiesto o digest de la imagen, fírmalo con gpg --detach-sign, y almacena el archivo .sig junto a la imagen (en un almacén de artefactos separado, bucket S3 o repositorio Git).
  • Integración con Podman/Skopeo: Podman y Skopeo tienen soporte nativo de firmas GPG. Las firmas se almacenan en un servidor de firmas separado (un servidor web que sirve firmas independientes) y se verifican al momento de la descarga usando un archivo de políticas (/etc/containers/policy.json).

Docker Content Trust (DCT) utiliza un enfoque relacionado pero distinto basado en The Update Framework (TUF), con Notary v1 como backend. Aunque DCT usa primitivos criptográficos diferentes al GPG puro, comparte el mismo desafío fundamental: la gestión de claves de larga duración.

Desafíos de la Gestión de Claves

La mayor debilidad de GPG en un contexto CI/CD es la gestión de claves:

  • Debes generar, distribuir, rotar y revocar pares de claves de larga duración
  • Las claves privadas necesitan ser inyectadas de forma segura en los runners de CI/CD como secretos
  • No hay mecanismo integrado de custodia o recuperación de claves
  • La distribución de claves a los verificadores (nodos del clúster, controladores de admisión) requiere procesos manuales o un servidor de claves
  • El compromiso de claves requiere rotación de emergencia en todos los sistemas

Ejemplo de Integración CI/CD: GitLab CI con GPG

# .gitlab-ci.yml
sign-image:
  stage: sign
  image: alpine:latest
  before_script:
    - apk add --no-cache gnupg skopeo
    - echo "$GPG_PRIVATE_KEY" | gpg --batch --import
  script:
    - skopeo copy \
        --sign-by signing-key@myorg.com \
        docker://registry.example.com/myapp:${CI_COMMIT_SHORT_SHA} \
        docker://registry.example.com/myapp:${CI_COMMIT_SHORT_SHA}
  variables:
    GPG_PRIVATE_KEY: $GPG_SIGNING_KEY  # Stored in CI/CD variables

Observa cómo la clave privada debe almacenarse como un secreto de CI/CD e inyectarse en tiempo de ejecución — exactamente el tipo de gestión de secretos de larga duración que la firma keyless fue diseñada para eliminar.

Fortalezas

  • Criptografía probada en batalla — GPG ha sido auditado y endurecido durante décadas
  • Funciona en entornos completamente air-gapped con cero dependencias externas
  • Familiar para equipos de operaciones con experiencia en Linux/seguridad
  • Amplio soporte de herramientas en el ecosistema Podman/Skopeo
  • Control total sobre el material de claves (importante para ciertos marcos de cumplimiento)

Limitaciones

  • La gestión manual y propensa a errores de claves es la mayor carga operacional
  • Sin modo keyless — las claves privadas deben estar en algún lugar accesible para CI/CD
  • Sin almacenamiento nativo de artefactos OCI — las firmas se almacenan fuera de banda
  • Sin registro de transparencia para pistas de auditoría
  • La distribución y descubrimiento de firmas está fragmentado
  • Docker/containerd no verifican nativamente las firmas GPG (requiere Podman/Skopeo o herramientas personalizadas)

Comparación Lado a Lado

Característica Cosign (Sigstore) Notation (Notary v2) GPG
Gestión de Claves Keyless (OIDC) o pares de claves estáticos Basado en plugins (KMS, HSM, almacenes cloud) Pares de claves PGP manuales
Firma Keyless Sí (Fulcio + OIDC) No No
Formato de Firma Envelope JSON (in-toto/DSSE) Firmas COSE (CBOR) Firmas PGP independientes
Almacenamiento de Firmas Registro OCI (como artefactos OCI) Registro OCI (vía ORAS) Fuera de banda (servidor web, S3, Git)
Compatibilidad con Registros OCI Excelente — funciona con todos los registros principales Buena — requiere soporte de la API de referrers OCI 1.1 Ninguna — firmas almacenadas externamente
Registro de Transparencia Sí (Rekor) No (planificado) No
Integración CI/CD Excelente — GitHub Actions, GitLab CI, Tekton, soporte nativo OIDC Buena — GitHub Actions, funciona con cualquier CI vía plugins Manual — requiere inyección de secretos de claves privadas
Políticas de Kubernetes Kyverno, OPA Gatekeeper, Sigstore Policy Controller Ratify (con Gatekeeper), Kyverno (limitado) Requiere webhook de admisión personalizado
Soporte Air-Gapped Posible (requiere mirror de raíz TUF, mirror de Rekor) Sí (sencillo con almacén de confianza local) Sí (totalmente capaz offline)
Ecosistema y Comunidad Grande — Linux Foundation, Google, Red Hat, GitHub Creciendo — CNCF, Microsoft, AWS Maduro pero en declive para uso con contenedores
Curva de Aprendizaje Baja (keyless) a Media (basada en claves con políticas) Media a Alta (plugins, políticas de confianza, PKI) Media (herramientas familiares, operaciones dolorosas)
Soporte de Attestations Sí (SBOM, provenance SLSA, predicados personalizados) Sí (vía artefactos adjuntos ORAS) Sin soporte nativo

Matriz de Decisión: Cuándo Usar Cada Herramienta

Elegir la herramienta de firma correcta depende de tu contexto organizacional. Aquí tienes un marco de decisión práctico:

Elige Cosign Si:

  • Estás empezando desde cero con la firma de contenedores y quieres el camino más rápido a producción.
  • Usas GitHub Actions, GitLab CI u otro sistema CI/CD con capacidad OIDC — la firma keyless simplemente funciona.
  • Quieres un registro de transparencia para auditoría y cumplimiento sin construir uno tú mismo.
  • Estás adoptando attestations SLSA o in-toto — Cosign tiene soporte de primera clase para adjuntar SBOMs y metadatos de provenance.
  • Quieres amplia integración con políticas de Kubernetes con Kyverno o Sigstore Policy Controller.
  • Eres una startup u organización mediana sin un equipo dedicado de PKI.

Para una guía completa sobre Sigstore y la firma keyless, consulta nuestra Guía de Firma Keyless con Sigstore y Cosign.

Elige Notation Si:

  • Tu organización tiene infraestructura PKI existente y flujos de trabajo de gestión de certificados X.509 que quieres aprovechar.
  • Estás fuertemente invertido en Azure o AWS y quieres integración nativa con Azure Key Vault o AWS Signer.
  • Necesitas políticas de confianza granulares con alcance a registros, repositorios o equipos específicos.
  • Los requisitos de cumplimiento exigen custodia específica de claves (FIPS 140-2, FedRAMP) donde la firma keyless no cumple el estándar.
  • Operas en un entorno donde la infraestructura pública de Sigstore no es accesible pero tienes PKI interna.

Elige GPG Si:

  • Estás en un entorno completamente air-gapped sin dependencias de servicios externos permitidas.
  • Usas Podman/Skopeo como tu runtime principal de contenedores y ya tienes infraestructura de claves GPG.
  • Los requisitos regulatorios exigen GPG específicamente (raro, pero algunos contratos gubernamentales lo especifican).
  • Estás firmando artefactos no-OCI junto con contenedores y quieres una única herramienta de firma.

Para la mayoría de los equipos que construyen aplicaciones cloud-native modernas, Cosign con firma keyless es la opción recomendada por defecto. Proporciona la mejor relación seguridad-complejidad operacional y elimina la carga de gestión de claves que causa que la mayoría de las iniciativas de firma fracasen en la práctica.

Patrones de Integración CI/CD

Más allá de los ejemplos individuales anteriores, aquí hay patrones arquitectónicos para integrar la firma en tu pipeline:

Patrón 1: Firma en la Construcción (Cosign Keyless)

El patrón más simple. El mismo job del pipeline que construye y publica la imagen también la firma. La firma keyless significa que no hay secretos que gestionar:

Build Image → Push to Registry → Cosign Sign (keyless) → Record in Rekor

Esto funciona perfectamente con GitHub Actions, GitLab CI 16.0+ y cualquier sistema CI que proporcione tokens OIDC. La identidad OIDC del pipeline se convierte en la identidad de firma, creando una cadena verificable desde el commit fuente hasta la imagen firmada.

Patrón 2: Servicio de Firma Centralizado (Notation + KMS)

Para empresas que quieren separación de responsabilidades, un servicio de firma centralizado recibe artefactos de construcción y los firma usando claves en un KMS:

Build Pipeline → Push to Registry → Request Signing → Notation Sign (KMS plugin) → Approval Workflow

Este patrón habilita escenarios donde el equipo de construcción no puede firmar directamente — un equipo de seguridad separado o un motor de políticas automatizado debe aprobar y firmar el artefacto. Las políticas de acceso de AWS Signer y Azure Key Vault controlan quién puede solicitar firmas.

Patrón 3: Puertas de Verificación (Cualquier Herramienta)

Independientemente de qué herramienta de firma uses, el lado de la verificación es igualmente importante. Implementa la verificación en múltiples puntos:

  • Puerta de pre-despliegue: Un controlador de admisión de Kubernetes (Kyverno, Gatekeeper + Ratify, Sigstore Policy Controller) rechaza imágenes sin firmar o firmadas incorrectamente.
  • Puerta de promoción: Antes de promover una imagen del registro de staging al de producción, verifica su firma.
  • Auditoría en tiempo de ejecución: Escanea periódicamente las cargas de trabajo en ejecución y verifica que sus firmas aún sean válidas contra las políticas de confianza actuales.

Estrategia Multi-Herramienta

Algunas organizaciones usan múltiples herramientas. Por ejemplo, Cosign para la firma del pipeline CI/CD (conveniencia keyless) y Notation para la firma de releases (cumplimiento PKI empresarial). Ambas almacenan firmas como artefactos OCI, por lo que pueden coexistir en la misma imagen. Las políticas de verificación pueden requerir firmas de ambas herramientas antes de permitir el despliegue.

El Futuro de la Firma de Contenedores

El panorama de la firma de contenedores está convergiendo en varias tendencias importantes:

  • OCI 1.1 y la API de Referrers: La especificación de distribución OCI ahora soporta nativamente referencias de artefactos, que tanto Cosign como Notation aprovechan. Esto estandariza cómo las firmas, SBOMs y attestations se adjuntan a las imágenes.
  • Attestations SLSA e in-toto: La firma está evolucionando más allá de «quién construyó esto» para incluir provenance verificable de la construcción, manifiestos de dependencias y resultados de escaneos de seguridad — todo firmado y adjunto a la imagen.
  • Policy-as-Code: Herramientas como Kyverno y Gatekeeper están haciendo posible expresar requisitos complejos de firma como políticas declarativas, reduciendo la brecha entre la intención de seguridad y la aplicación.
  • Adopción de Sigstore: Los principales ecosistemas de paquetes (npm, PyPI, Maven Central) están adoptando Sigstore, lo que aumenta la familiaridad y madurez de las herramientas en toda la industria.

Conclusión y Recomendación

Las tres herramientas resuelven el problema fundamental de verificar la autenticidad de las imágenes container, pero sirven a diferentes contextos:

  • Cosign es la mejor opción para la mayoría de los equipos. La firma keyless elimina la carga operacional que mata las iniciativas de firma, el registro de transparencia proporciona capacidades de auditoría listas para usar, y la integración del ecosistema es la más amplia. Si estás iniciando una nueva iniciativa de firma de contenedores, comienza aquí.
  • Notation es la elección correcta para empresas con PKI establecida y requisitos específicos de cumplimiento en torno a la custodia de claves. Su modelo de plugins y marco de políticas de confianza están diseñados para organizaciones que necesitan autoridad de firma granular y delegada.
  • GPG debería reservarse para entornos legacy, sistemas completamente air-gapped o flujos de trabajo nativos de Podman donde las otras herramientas genuinamente no pueden usarse. Para nuevos despliegues, la carga operacional de la gestión de claves GPG es difícil de justificar.

Lo más importante es empezar a firmar. Una implementación de firma imperfecta que realmente se despliega es infinitamente más valiosa que una perfecta que se queda en un roadmap. Elige la herramienta que coincida con las capacidades de tu equipo, impleméntala en tu pipeline y agrega puertas de verificación en Kubernetes. Siempre puedes evolucionar tus herramientas después — el paso crítico es establecer la práctica.

¿Listo para ponerte manos a la obra? Comienza con nuestra Guía de Firma Keyless con Sigstore para los fundamentos conceptuales, luego trabaja a través del Laboratorio de Firma Keyless con Cosign para implementarlo en un pipeline real de GitHub Actions.