
Firma de código y transparencia para contenedores y binarios
Firma de contenedores OCI (y otros artefactos) con Sigstore!
Cosign tiene como objetivo hacer de las firmas infraestructura invisible.
Cosign admite:
Cosign se desarrolla como parte del proyecto sigstore.
También usamos un canal de Slack!
Haz clic aquí para el enlace de invitación.
Para instalaciones con Homebrew, Arch, Nix, GitHub Action y Kubernetes, consulta la documentación de instalación.
Para los binarios de Linux y macOS, consulta los recursos de lanzamiento de GitHub.
🚨 Si estás descargando lanzamientos de cosign desde nuestro bucket de GCS - consulta más información en el aviso de deprecación del 31 de julio de 2023 🚨
Si tienes Go 1.22+, puedes configurar un entorno de desarrollo:```shell $ git clone https://github.com/sigstore/cosign $ cd cosign $ go install ./cmd/cosign $ $(go env GOPATH)/bin/cosign
## Contributing
Si estás interesado en contribuir a `cosign`, lee la [documentación de contribución](https://github.com/sigstore/cosign/blob/HEAD/CONTRIBUTING.md).
El desarrollo futuro de Cosign se centrará en la próxima versión principal, que estará basada en
[sigstore-go](https://github.com/sigstore/sigstore-go). Los mantenedores se centrarán en el desarrollo de funciones dentro de
sigstore-go. Se agradecen las contribuciones a sigstore-go, especialmente en torno a traer tus propias claves y la firma.
Consulta el [rastreador de incidencias](https://github.com/sigstore/sigstore-go/issues) para ver las good first issues.
Cosign 2.x es una versión estable y seguirá recibiendo actualizaciones periódicas de funciones y correcciones de errores. Los PRs
que sean pequeños en alcance y tamaño son los que con mayor probabilidad se revisarán rápidamente.
No se aceptarán PRs que modifiquen significativamente o rompan la API. Los PRs que sean grandes en tamaño pero que no
introduzcan cambios que rompan la compatibilidad podrían ser aceptados, pero se considerarán de menor prioridad que los PRs en sigstore-go.
## Dockerfile
Así es como se instala y se usa cosign dentro de un Dockerfile mediante la imagen ghcr.io/sigstore/cosign/cosign:```shell
FROM ghcr.io/sigstore/cosign/cosign:v2.4.1 as cosign-bin
# Source: https://github.com/chainguard-images/static
FROM cgr.dev/chainguard/static:latest
COPY --from=cosign-bin /ko-app/cosign /usr/local/bin/cosign
ENTRYPOINT [ "cosign" ]
Esto muestra cómo:
Ten en cuenta que siempre debes firmar imágenes basándote en su digest (@sha256:...)
en lugar de una etiqueta (:latest) porque de lo contrario podrías firmar algo que
¡no tenías intención de firmar!```shell
cosign sign $IMAGE
Generating ephemeral keys... Retrieving signed certificate...
Note that there may be personally identifiable information associated with this signed artifact.
This may include the email address associated with the account with which you authenticate.
This information will be used for signing this artifact and will be stored in public transparency logs and cannot be removed later.
By typing 'y', you attest that you grant (or have permission to grant) and agree to have this information stored permanently in transparency logs. Are you sure you would like to continue? [y/N] y Your browser will now be opened to: https://oauth2.sigstore.dev/auth/auth?access_type=online&client_id=sigstore&code_challenge=OrXitVKUZm2lEWHVt1oQWR4HZvn0rSlKhLcltglYxCY&code_challenge_method=S256&nonce=2KvOWeTFxYfxyzHtssvlIXmY6Jk&redirect_uri=http%3A%2F%2Flocalhost%3A57102%2Fauth%2Fcallback&response_type=code&scope=openid+email&state=2KvOWfbQJ1caqScgjwibzK2qJmb Successfully verified SCT... tlog entry created with index: 12086900 Pushing signature to: $IMAGE
Cosign te pedirá que te autentiques mediante OIDC, donde iniciarás sesión con tu dirección de correo electrónico.
Internamente, cosign solicitará un certificado de firma de código a la autoridad certificadora Fulcio.
El subject del certificado coincidirá con la dirección de correo electrónico con la que iniciaste sesión.
Cosign almacenará entonces la firma y el certificado en el registro de transparencia Rekor, y subirá la firma al registro OCI junto con la imagen que estás firmando.
### Verificar un contenedor
Para verificar la imagen, deberás pasar el subject del certificado esperado y el emisor del certificado mediante las opciones `--certificate-identity` y `--certificate-oidc-issuer`:```
cosign verify $IMAGE --certificate-identity=$IDENTITY --certificate-oidc-issuer=$OIDC_ISSUER
También puedes pasar una expresión regular para las banderas de identidad del certificado y emisor, --certificate-identity-regexp y --certificate-oidc-issuer-regexp.
Este comando devuelve 0 si se encuentra al menos una firma con formato cosign de la imagen que coincida con la clave pública.
Consulta el uso detallado a continuación para obtener información y advertencias sobre otros formatos de firma.
Cualquier payload válido se imprime en stdout, en formato json. Ten en cuenta que estos payloads firmados incluyen el digest de la imagen del contenedor, que es como podemos estar seguros de que estas firmas "separadas" cubren la imagen correcta.```shell $ cosign verify --key cosign.pub $IMAGE_URI:1h The following checks were performed on these signatures:
### Verificar un contenedor en un entorno aislado de red
**Nota:** Esta sección está desactualizada.
**Nota:** La mayoría de los flujos de trabajo de verificación requieren solicitar periódicamente claves de servicio a un repositorio TUF.
Para la verificación aislada de firmas mediante la instancia de bien público, necesitará obtener el archivo
[root de confianza](https://github.com/sigstore/root-signing/blob/main/targets/trusted_root.json) del repositorio
TUF de producción. El contenido de este archivo cambiará sin previo aviso. Al no usar TUF, necesitará
crear su propio mecanismo para mantener actualizada su copia aislada de este archivo.
Cosign puede realizar una verificación totalmente offline verificando un [bundle](https://github.com/sigstore/cosign/blob/HEAD/specs/SIGNATURE_SPEC.md#properties) que normalmente se distribuye como una anotación en el manifiesto de la imagen.
Mientras esta anotación esté presente, se puede realizar la verificación offline.
Esta anotación de bundle siempre se incluye por defecto en la firma sin llave, por lo que la funcionalidad predeterminada de `cosign sign` incluirá todos los materiales necesarios para la verificación offline.
Para verificar una imagen en un entorno aislado de red, la imagen y las firmas deben estar disponibles localmente en el sistema de archivos.
Una imagen se puede guardar localmente usando `cosign save` (nota: este paso debe realizarse con conexión de red):```
cosign initialize # This will pull in the latest TUF root
cosign save $IMAGE_NAME --dir ./path/to/dir
Ahora, en un entorno aislado, esta imagen local puede verificarse:```shell
cosign verify
--certificate-identity $CERT_IDENTITY
--certificate-oidc-issuer $CERT_OIDC_ISSUER
--offline=true
--new-bundle-format=false \ # for artifacts signed without the new protobuf bundle format
--trusted-root ~/.sigstore/root/tuf-repo-cdn.sigstore.dev/targets/trusted_root.json \ # default location of trusted root
--local-image ./path/to/dir
Tendrás que pasar valores esperados para `$CERT_IDENTITY` y `$CERT_OIDC_ISSUER` para verificar correctamente esta imagen.
Si firmaste con un par de claves, el mismo comando funcionará, asumiendo que el material de la clave pública está presente localmente:```
cosign verify --key cosign.pub --offline --local-image ./path/to/dir
Usa la firma de blobs sin claves (cosign sign-blob sin --key) y verifica contra la identidad del firmante esperada:```shell
$ cosign sign-blob artifact --bundle artifact.sigstore.json --yes
$ cosign verify-blob artifact
--bundle artifact.sigstore.json
--certificate-identity "https://github.com/ORG/REPO/.github/workflows/release.yml@refs/heads/main"
--certificate-oidc-issuer "https://token.actions.githubusercontent.com"
### Solución de problemas
Si encuentras problemas con Cosign, primero asegúrate de usar una versión reciente: el proyecto Cosign admite activamente la versión más reciente, así como la última versión de la serie v2.
#### Problemas comunes y soluciones
1. La verificación falla con `failed to verify timestamps: threshold not met for verified log entry integrated timestamps: 0 < 1`: es posible que estés verificando una firma que requiere soporte de marcas de tiempo RFC3161
* Actualiza a la versión más reciente de Cosign o
* Con Cosign 2.6.x, usa `--use-signed-timestamps`
1. La verificación falla con `no signatures found`: es posible que estés verificando una firma de imagen que requiere soporte para el registro de transparencia Rekor v2
* Actualiza a la versión más reciente de Cosign
1. El firmado falla con errores HTTP: firmar con Cosign depende de múltiples servicios de Sigstore. Reintentar ante un fallo puede ser una solución útil si alguno de estos servicios falla; también se agradece que reportes incidencias para fallos específicos.
#### Mi problema es otro
Por favor, abre un [issue](https://github.com/sigstore/cosign/issues/new/choose) o pregunta en el [canal de Slack](#info).
## Trabajar con otros artefactos
¡Los registros OCI son útiles para almacenar algo más que imágenes de contenedores!
`Cosign` también incluye algunas utilidades para publicar artefactos genéricos, incluidos binarios, scripts y archivos de configuración mediante el protocolo OCI.
En esta sección se muestra cómo aprovecharlos para crear un sistema de distribución de artefactos fácil de usar y compatible con versiones anteriores que se integra bien con el resto de Sigstore.
Consulta [la documentación](https://docs.sigstore.dev/cosign/signing/other_types/) para obtener más información.
### Blobs
Puedes publicar un artefacto con `cosign upload blob`:```shell
$ echo "my first artifact" > artifact
$ BLOB_SUM=$(shasum -a 256 artifact | cut -d' ' -f 1) && echo "$BLOB_SUM"
c69d72c98b55258f9026f984e4656f0e9fd3ef024ea3fac1d7e5c7e6249f1626
$ BLOB_NAME=my-artifact-$(uuidgen | head -c 8 | tr 'A-Z' 'a-z')
$ BLOB_URI=ttl.sh/$BLOB_NAME:1h
$ BLOB_URI_DIGEST=$(cosign upload blob -f artifact $BLOB_URI) && echo "$BLOB_URI_DIGEST"
Uploading file from [artifact] to [ttl.sh/my-artifact-f42c22e0:5m] with media type [text/plain]
File [artifact] is available directly at [ttl.sh/v2/my-artifact-f42c22e0/blobs/sha256:c69d72c98b55258f9026f984e4656f0e9fd3ef024ea3fac1d7e5c7e6249f1626]
Uploaded image to:
ttl.sh/my-artifact-f42c22e0@sha256:790d47850411e902aabebc3a684eeb78fcae853d4dd6e1cc554d70db7f05f99f
Sus usuarios pueden descargarlo desde la URL "directa" con herramientas estándar como curl o wget:```shell $ curl -L ttl.sh/v2/$BLOB_NAME/blobs/sha256:$BLOB_SUM > artifact-fetched
El digest está integrado directamente en la URL, para que puedan verificarlo también:```shell
$ cat artifact-fetched | shasum -a 256
c69d72c98b55258f9026f984e4656f0e9fd3ef024ea3fac1d7e5c7e6249f1626 -
Puedes firmarlo con el comando cosign sign normal y sus flags:```shell
$ cosign sign --key cosign.key $BLOB_URI_DIGEST
Enter password for private key:
Pushing signature to: ttl.sh/my-artifact-f42c22e0
Como siempre, asegúrate de referenciar cualquier imagen que firmes por su digest para asegurarte de que no firmas la imagen equivocada.
#### Tekton Bundles
Los bundles de [Tekton](https://tekton.dev) se pueden subir y gestionar dentro de un registro OCI.
La especificación está [aquí](https://tekton.dev/docs/pipelines/tekton-bundle-contracts/).
Esto significa que también se pueden firmar y verificar con `cosign`.
Los Tekton Bundles actualmente se pueden subir con [tkn cli](https://github.com/tektoncd/cli), pero es posible que añadamos esta compatibilidad a `cosign` en el futuro.```shell
$ tkn bundle push us.gcr.io/dlorenc-vmtest2/pipeline:latest -f task-output-image.yaml
Creating Tekton Bundle:
- Added TaskRun: to image
Pushed Tekton Bundle to us.gcr.io/dlorenc-vmtest2/pipeline@sha256:124e1fdee94fe5c5f902bc94da2d6e2fea243934c74e76c2368acdc8d3ac7155
$ cosign sign --key cosign.key us.gcr.io/dlorenc-vmtest2/pipeline@sha256:124e1fdee94fe5c5f902bc94da2d6e2fea243934c74e76c2368acdc8d3ac7155
Enter password for private key:
tlog entry created with index: 5086
Pushing signature to: us.gcr.io/dlorenc-vmtest2/demo:sha256-124e1fdee94fe5c5f902bc94da2d6e2fea243934c74e76c2368acdc8d3ac7155.sig
Los módulos de Web Assembly también pueden almacenarse en un registro OCI, usando esta especificación.
Cosign puede subirlos usando el comando cosign wasm upload:```shell
$ cosign upload wasm -f hello.wasm us.gcr.io/dlorenc-vmtest2/wasm
$ cosign sign --key cosign.key us.gcr.io/dlorenc-vmtest2/wasm@sha256:9e7a511fb3130ee4641baf1adc0400bed674d4afc3f1b81bb581c3c8f613f812
Enter password for private key:
tlog entry created with index: 5198
Pushing signature to: us.gcr.io/dlorenc-vmtest2/wasm:sha256-9e7a511fb3130ee4641baf1adc0400bed674d4afc3f1b81bb581c3c8f613f812.sig
#### eBPF
Los módulos [eBPF](https://ebpf.io) también pueden almacenarse en un registro OCI, utilizando esta [especificación](https://github.com/solo-io/bumblebee/tree/main/spec).
La imagen siguiente se construyó con la herramienta `bee`. Se puede encontrar más información [aquí](https://github.com/solo-io/bumblebee/)
Cosign puede firmar entonces estas imágenes como cualquier otra imagen OCI.```shell
$ bee build ./examples/tcpconnect/tcpconnect.c localhost:5000/tcpconnect:test
$ bee push localhost:5000/tcpconnect:test
$ cosign sign --key cosign.key localhost:5000/tcpconnect@sha256:7a91c50d922925f152fec96ed1d84b7bc6b2079c169d68826f6cf307f22d40e6
Enter password for private key:
Pushing signature to: localhost:5000/tcpconnect
$ cosign verify --key cosign.pub localhost:5000/tcpconnect:test
Verification for localhost:5000/tcpconnect:test --
The following checks were performed on each of these signatures:
- The cosign claims were validated
- The signatures were verified against the specified public key
[{"critical":{"identity":{"docker-reference":"localhost:5000/tcpconnect"},"image":{"docker-manifest-digest":"sha256:7a91c50d922925f152fec96ed1d84b7bc6b2079c169d68826f6cf307f22d40e6"},"type":"cosign container image signature"},"optional":null}]
Cosign también tiene soporte integrado para atestaciones de in-toto. La especificación de estas se define aquí.
Puedes crear y firmar una a partir de un archivo de predicado local con los siguientes comandos:```shell $ cosign attest --predicate --key cosign.key $IMAGE_URI_DIGEST
Todos los sistemas de gestión de claves estándar son compatibles.
Los payloads se firman utilizando la especificación de firma DSSE, definida [aquí](https://github.com/secure-systems-lab/dsse).
Para verificar:```shell
$ cosign verify-attestation --key cosign.pub $IMAGE_URI
Consulta la documentación de uso para más información.
Consulta la documentación de Tokens de hardware para obtener información sobre cómo usar cosign con hardware.
cosign utiliza go-containerregistry para las interacciones con los registros, que en general tiene una compatibilidad excelente, aunque algunos registros pueden tener peculiaridades.
Actualmente, cosign ha sido probado y funciona con los siguientes registros:
Nuestro objetivo es ofrecer un amplio soporte de registros. Para sign (firmar) imágenes en registros que aún no admiten completamente OCI media types, es posible que sea necesario usar COSIGN_DOCKER_MEDIA_TYPES para recurrir a los equivalentes heredados. Por ejemplo:```shell
COSIGN_DOCKER_MEDIA_TYPES=1 cosign sign --key cosign.key legacy-registry.example.com/my/image@$DIGEST
Por favor, ayuda a probar y reporta errores si ves problemas!
Las instrucciones se pueden encontrar en el [issue de seguimiento](https://github.com/sigstore/cosign/issues/40).
## Advertencias
### Características omitidas intencionalmente
`cosign` solo genera claves ECDSA-P256 y utiliza hashes SHA256, tanto para la firma efímera sin clave como para la firma con clave gestionada.
Las claves se almacenan en formato PKCS8 codificado en PEM.
Sin embargo, puedes usar `cosign` para almacenar y recuperar firmas en cualquier formato, de cualquier algoritmo.
### Cosas que probablemente deberían cambiar
#### Formatos de carga útil
`cosign` solo admite el [formato de firma simple](https://www.redhat.com/en/blog/container-image-signing) de Red Hat para las cargas útiles.
Eso se ve así:```json
{
"critical": {
"identity": {
"docker-reference": "testing/manifest"
},
"image": {
"Docker-manifest-digest": "sha256:20be...fe55"
},
"type": "cosign container image signature"
},
"optional": {
"creator": "Bob the Builder",
"timestamp": 1458239713
}
}
Nota: Esto se puede generar para una referencia de imagen usando cosign generate $IMAGE_URI_DIGEST.
Me parece bien cambiar este formato a otro si tiene sentido. Consulta https://github.com/notaryproject/nv2/issues/40 para una opción.
Las firmas de cosign se almacenan como objetos separados en el registro OCI, con solo una
referencia débil al objeto que "firman".
Esto significa que esta relación es opaca para el registro, y las firmas no se eliminarán
ni se recolectarán como basura cuando se elimine la imagen.
Del mismo modo, pueden copiarse fácilmente de un entorno a otro, pero esto no es
automático.
Múltiples firmas se almacenan en una lista, lo que lamentablemente hoy en día es una condición de carrera. Para agregar una firma, los clientes orquestan una operación de "read-append-write", por lo que la última escritura ganará en caso de contención.
cosign almacenará las firmas por defecto en el mismo repositorio que la imagen que está firmando.
Para especificar un repositorio diferente para las firmas, puedes configurar la variable de entorno COSIGN_REPOSITORY.
Esto reemplazará el repositorio en la imagen proporcionada de la siguiente manera:```shell $ export COSIGN_REPOSITORY=gcr.io/my-new-repo $ cosign sign --key cosign.key $IMAGE_URI_DIGEST
Por lo tanto, la firma de `gcr.io/dlorenc-vmtest2/demo` se almacenará en `gcr.io/my-new-repo/demo:sha256-DIGEST.sig`.
Nota: distintos registros podrían esperar formatos diferentes para el "repositorio".
* Para usar [GCR](https://cloud.google.com/container-registry), un nombre de
registro como `gcr.io/$REPO` es suficiente, como en el ejemplo anterior.
* Para usar [Artifact Registry](https://cloud.google.com/artifact-registry),
especifica un nombre de imagen completo como
`$LOCATION-docker.pkg.dev/$PROJECT/$REPO/$STORAGE_IMAGE`, no solo un
repositorio. Por ejemplo, ```shell
$ export COSIGN_REPOSITORY=us-docker.pkg.dev/my-new-repo/demo
$ cosign sign --key cosign.key $IMAGE_URI_DIGEST
donde el sha256-DIGEST coincidirá con el digest de
gcr.io/dlorenc-vmtest2/demo. Especificar solo un repositorio como
$LOCATION-docker.pkg.dev/$PROJECT/$REPO no funcionará en Artifact Registry.
cosign está inspirado en herramientas como minisign y
signify.
Las claves privadas generadas se almacenan en formato PEM. Las claves se cifran con una contraseña usando scrypt como KDF y nacl/secretbox para el cifrado.
Tienen una cabecera PEM de ENCRYPTED SIGSTORE PRIVATE KEY:```shell
-----BEGIN ENCRYPTED SIGSTORE PRIVATE KEY-----
...
-----END ENCRYPTED SIGSTORE PRIVATE KEY-----
Las claves públicas se almacenan en disco en formato PKIX estándar codificado en PEM con un encabezado de `PUBLIC KEY`.```
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAELigCnlLNKgOglRTx1D7JhI7eRw99
QolE9Jo4QUxnbMy5nUuBL+UZF9qqfm/Dg1BNeHRThHzWh2ki9vAEgWEDOw==
-----END PUBLIC KEY-----
cosign almacena las firmas en un registro OCI y utiliza una convención de nombres (etiqueta basada en el sha256 de lo que se está firmando) para localizar el índice de firmas.
reg.example.com/ubuntu@sha256:703218c0465075f4425e58fac086e09e1de5c340b12976ab9eb8ad26615c3715 tiene las firmas ubicadas en reg.example.com/ubuntu:sha256-703218c0465075f4425e58fac086e09e1de5c340b12976ab9eb8ad26615c3715.sig
A grandes rasgos (ignorando los puertos en el nombre de host): s/:/-/g y s/@/:/g para encontrar el índice de firmas.
Consulta Condiciones de carrera para conocer algunas advertencias sobre esta estrategia.
Las implementaciones alternativas podrían usar registros de transparencia, sistema de archivos local, un repositorio separado en el registro, una referencia explícita a un índice de firmas, una nueva API de registro, grafeas, etc.
Actualmente, cosign solo funciona con artefactos almacenados como "manifiestos" en el registro. El mecanismo propuesto es lo suficientemente flexible como para admitir la firma de cualquier tipo de elemento.
cosign admite el uso de un proveedor KMS para generar y firmar claves. Actualmente, cosign es compatible con Hashicorp Vault, AWS KMS, GCP KMS, Azure Key Vault y esperamos añadir más en el futuro.
Hay proveedores KMS adicionales disponibles como complementos externos, como OVHcloud KMS.
Consulta la documentación de KMS para obtener más detalles.
Sube un artefacto a un registro usando oras (¡en este caso, el propio cosign!):```shell
$ oras push us-central1-docker.pkg.dev/dlorenc-vmtest2/test/artifact ./cosign
Uploading f53604826795 cosign
Pushed us-central1-docker.pkg.dev/dlorenc-vmtest2/test/artifact
Digest: sha256:551e6cce7ed2e5c914998f931b277bc879e675b74843e6f29bc17f3b5f692bef
¡Ahora fírmalo! Usando `cosign`, por supuesto:```shell
$ cosign sign --key cosign.key us-central1-docker.pkg.dev/dlorenc-vmtest2/test/artifact@sha256:551e6cce7ed2e5c914998f931b277bc879e675b74843e6f29bc17f3b5f692bef
Enter password for private key:
Pushing signature to: us-central1-docker.pkg.dev/dlorenc-vmtest2/test/artifact:sha256-551e6cce7ed2e5c914998f931b277bc879e675b74843e6f29bc17f3b5f692bef.sig
Finalmente, verifica cosign con cosign de nuevo:```shell
$ cosign verify --key cosign.pub us-central1-docker.pkg.dev/dlorenc-vmtest2/test/artifact@sha256:551e6cce7ed2e5c914998f931b277bc879e675b74843e6f29bc17f3b5f692bef
The following checks were performed on each of these signatures:
{"Critical":{"Identity":{"docker-reference":""},"Image":{"Docker-manifest-digest":"sha256:551e6cce7ed2e5c914998f931b277bc879e675b74843e6f29bc17f3b5f692bef"},"Type":"cosign container image signature"},"Optional":null}
## FAQ
### ¿Por qué no usar Notary v2?
Es difícil responder esto brevemente.
Este artículo contiene algunas comparaciones:
[Notary V2 y Cosign](https://medium.com/@dlorenc/notary-v2-and-cosign-b816658f044d)
Si encuentras otros artículos de comparación, envía un PR aquí y los enlazaremos todos.
### ¿Por qué no usar la firma de containers/image?
La firma de `containers/image` es parecida a la de `cosign`, y reutilizamos los formatos de payload.
`cosign` se diferencia en que firma con claves ECDSA-P256 en lugar de PGP, y almacena las firmas en el registro.
### ¿Por qué no usar TUF?
Creo que esta herramienta es complementaria a TUF, y pueden usarse juntas.
Aún no lo he probado, pero creo que también podemos reutilizar un registro para el almacenamiento de TUF.
## Requisitos de diseño
* Sin servicios externos para almacenamiento, consulta o recuperación de firmas
* Buscamos el mayor soporte de registros posible
* Todo debería funcionar a través de la API del registro
* PGP no debería ser necesario en absoluto.
* Los usuarios deben poder encontrar todas las firmas de una imagen
* Los firmantes pueden firmar una imagen después del push
* Múltiples entidades pueden firmar una imagen
* Firmar una imagen no modifica la imagen
* Implementación pura en Go
## Ideas futuras
### Cambios en la API del registro
La convención de nombres y los patrones de actualización de lectura-modificación-escritura que usamos para almacenar cosas en un registro son un poco, bueno, "chapuceros".
Creo que son la mejor (única) opción real disponible hoy en día, pero si la API del registro cambia, podemos mejorarlos.
### Otros tipos
`cosign` puede firmar cualquier cosa en un registro.
Estos ejemplos muestran cómo firmar una sola imagen, pero también podrías firmar un `Index` multiplataforma, o cualquier otro tipo de artefacto.
Esto incluye Helm Charts, Tekton Pipelines y cualquier otra cosa que actualmente use registros OCI para la distribución.
Esto también significa que nuevos tipos de artefactos pueden subirse a un registro y firmarse.
Un tipo interesante de almacenar y firmar serían los repositorios TUF.
Aún no lo he probado, pero estoy bastante seguro de que TUF podría implementarse sobre esto.
### Firma de etiquetas
Las firmas de `cosign` protegen los digest de los objetos almacenados en un registro.
El soporte opcional de `annotations` (mediante la bandera `-a` de `cosign sign`) puede usarse para añadir datos adicionales al payload que se firma y queda protegido por la firma.
Un caso de uso podría ser firmar un mapeo tag->digest.
Si deseas atestiguar que una etiqueta específica (o un conjunto de etiquetas) debería apuntar a un digest, puedes ejecutar algo como:```shell
$ docker push $IMAGE_URI
The push refers to repository [dlorenc/demo]
994393dc58e7: Pushed
5m: digest: sha256:1304f174557314a7ed9eddb4eab12fed12cb0cd9809e4c28f29af86979a3c870 size: 528
$ TAG=sign-me
$ cosign sign --key cosign.key -a tag=$TAG $IMAGE_URI_DIGEST
Enter password for private key:
Pushing signature to: dlorenc/demo:1304f174557314a7ed9eddb4eab12fed12cb0cd9809e4c28f29af86979a3c870.sig
Luego puedes verificar que la asignación tag->digest también está cubierta en la firma, usando la opción -a de cosign verify. Este ejemplo verifica que el digest $TAG, que apunta a (sha256:1304f174557314a7ed9eddb4eab12fed12cb0cd9809e4c28f29af86979a3c870), ha sido firmado, y también que la anotación tag tiene el valor sign-me:```shell
$ cosign verify --key cosign.pub -a tag=$TAG $IMAGE_URI | jq .
{
"Critical": {
"Identity": {
"docker-reference": ""
},
"Image": {
"Docker-manifest-digest": "97fc222cee7991b5b061d4d4afdb5f3428fcb0c9054e1690313786befa1e4e36"
},
"Type": "cosign container image signature"
},
"Optional": {
"tag": "sign-me"
}
}
Aquí también podrían añadirse marcas de tiempo, para implementar la prevención de ataques de congelación al estilo TUF.
### Firma de Imagen Base/Capa
De nuevo, `cosign` puede firmar cualquier cosa en un registro.
Podrías usar `cosign` para firmar una imagen destinada a usarse como imagen base,
e incluir esos metadatos de procedencia en las imágenes derivadas resultantes.
Esto podría usarse para garantizar que una imagen se construyó a partir de una imagen base autorizada.
Idea aproximada:
* Los manifiestos OCI tienen una lista ordenada de `layer` `Descriptors`, que pueden contener anotaciones.
Consulta [aquí](https://github.com/opencontainers/image-spec/blob/master/manifest.md) para la
especificación.
* Una imagen base es una lista ordenada de capas a las que se añaden otras capas, así como un
objeto de configuración inicial que se modifica.
* Una imagen derivada es libre de eliminar/destruir/recrear por completo la configuración de su imagen base,
por lo que firmar la configuración aportaría un valor limitado.
* Podemos firmar el conjunto completo de capas base ordenadas y adjuntar esa firma como anotación en
la **última** capa de la imagen hija resultante.
Este manifiesto de ejemplo representa una imagen que se ha construido a partir de una imagen base con dos
capas.
Se añade una capa adicional, formando la imagen final.```json
{
"schemaVersion": 2,
"config": {
"mediaType": "application/vnd.oci.image.config.v1+json",
"size": 7023,
"digest": "sha256:b5b2b2c507a0944348e0303114d8d93aaaa081732b86451d9bce1f432a537bc7"
},
"layers": [
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"size": 32654,
"digest": "sha256:9834876dcfb05cb167a5c24953eba58c4ac89b1adf57f28f2f9d09af107ee8f0"
},
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"size": 16724,
"digest": "sha256:3c3a4604a545cdc127456d94e421cd355bca5b528f4a9c1905b15da2eb4a4c6b",
"annotations": {
"dev.cosign.signature.baseimage": "Ejy6ipGJjUzMDoQFePWixqPBYF0iSnIvpMWps3mlcYNSEcRRZelL7GzimKXaMjxfhy5bshNGvDT5QoUJ0tqUAg=="
}
},
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"size": 73109,
"digest": "sha256:ec4b8955958665577945c89419d1af06b5f7636b4ac3da7f12184802ad867736"
}
],
}
Tenga en cuenta que esto podría aplicarse de forma recursiva, para múltiples imágenes base intermedias.
Las firmas de Cosign (y sus cargas útiles protegidas) se almacenan como artefactos en un registro. Estos objetos de firma también se pueden firmar, lo que da como resultado un nuevo artefacto de "contrafirma". Esta "contrafirma" protege la firma (o conjunto de firmas) y el artefacto referenciado, lo que permite que actúe como una atestación de la(s) firma(s) en sí misma(s).
Antes de firmar el artefacto de firma, primero le damos un nombre memorable para poder encontrarlo más tarde.```shell $ cosign sign --key cosign.key -a sig=original $IMAGE_URI_DIGEST Enter password for private key: Pushing signature to: dlorenc/demo:sha256-97fc222cee7991b5b061d4d4afdb5f3428fcb0c9054e1690313786befa1e4e36.sig $ cosign verify --key cosign.pub dlorenc/demo | jq . { "Critical": { "Identity": { "docker-reference": "" }, "Image": { "Docker-manifest-digest": "97fc222cee7991b5b061d4d4afdb5f3428fcb0c9054e1690313786befa1e4e36" }, "Type": "cosign container image signature" }, "Optional": { "sig": "original" } }
<!-- TODO: https://github.com/sigstore/cosign/issues/2333 -->
Ahora dale a esa firma un nombre memorable y luego fírmala:```shell
$ crane tag $(cosign triangulate $IMAGE_URI) mysignature
2021/02/15 20:22:55 dlorenc/demo:mysignature: digest: sha256:71f70e5d29bde87f988740665257c35b1c6f52dafa20fab4ba16b3b1f4c6ba0e size: 556
$ cosign sign --key cosign.key -a sig=counter dlorenc/demo:mysignature
Enter password for private key:
Pushing signature to: dlorenc/demo:sha256-71f70e5d29bde87f988740665257c35b1c6f52dafa20fab4ba16b3b1f4c6ba0e.sig
$ cosign verify --key cosign.pub dlorenc/demo:mysignature
{"Critical":{"Identity":{"docker-reference":""},"Image":{"Docker-manifest-digest":"71f70e5d29bde87f988740665257c35b1c6f52dafa20fab4ba16b3b1f4c6ba0e"},"Type":"cosign container image signature"},"Optional":{"sig":"counter"}}
Finalmente, comprueba la firma original:```shell $ crane manifest dlorenc/demo@sha256:71f70e5d29bde87f988740665257c35b1c6f52dafa20fab4ba16b3b1f4c6ba0e { "schemaVersion": 2, "config": { "mediaType": "application/vnd.oci.image.config.v1+json", "size": 233, "digest": "sha256:3b25a088710d03f39be26629d22eb68cd277a01673b9cb461c4c24fbf8c81c89" }, "layers": [ { "mediaType": "application/vnd.oci.descriptor.v1+json", "size": 217, "digest": "sha256:0e79a356609f038089088ec46fd95f4649d04de989487220b1a0adbcc63fadae", "annotations": { "dev.sigstore.cosign/signature": "5uNZKEP9rm8zxAL0VVX7McMmyArzLqtxMTNPjPO2ns+5GJpBeXg+i9ILU+WjmGAKBCqiexTxzLC1/nkOzD4cDA==" } } ] }
## Ritmo de lanzamiento
Realizamos lanzamientos según sea necesario. Los lanzamientos de parches se realizan para corregir pequeños errores. Los lanzamientos menores se
realizan periódicamente cuando hay múltiples errores corregidos o funciones añadidas. Los lanzamientos principales
se lanzarán cuando haya características que rompan la compatibilidad.
## Seguridad
Si descubres algún problema de seguridad, consulta el [proceso de
seguridad](https://github.com/sigstore/.github/blob/main/SECURITY.md) de sigstore.
## Archivos bundle en los activos de lanzamiento de GitHub
Los activos de lanzamiento de GitHub para `cosign` contienen archivos bundle de Sigstore producidos por [GoReleaser](https://github.com/sigstore/cosign/blob/ac999344eb381ae91455b0a9c5c267e747608d76/.goreleaser.yml#L166) al firmar el blob de cosign que se utiliza para verificar la integridad de los binarios de lanzamiento. Este archivo no es utilizado por el propio cosign, pero se proporciona para los usuarios que deseen [verificar la integridad de los binarios de lanzamiento](https://docs.sigstore.dev/cosign/system_config/installation/#verifying-cosign-with-artifact-key).