Unify attach signature and attestation under new bundle format (#5141)
- Unify attach signature and attestation under new bundle format
Signed-off-by: Aaron Lew 64337293+aaronlew02@users.noreply.github.com
- fix(attach): honor –allow-http-registry when writing referrers
Signed-off-by: Aaron Lew 64337293+aaronlew02@users.noreply.github.com
Signed-off-by: Aaron Lew 64337293+aaronlew02@users.noreply.github.com
版权所有:中国计算机学会技术支持:开源发展技术委员会
京ICP备13000930号-9
京公网安备 11010802047560号
cosign
Signing OCI containers (and other artifacts) using Sigstore!
Cosign aims to make signatures invisible infrastructure.
Cosign supports:
Info
Cosignis developed as part of thesigstoreproject. We also use a slack channel! Click here for the invite link.Installation
For Homebrew, Arch, Nix, GitHub Action, and Kubernetes installs see the installation docs.
For Linux, macOS and Windows binaries, see the GitHub release assets.
🚨 If you are downloading releases of cosign from our GCS bucket - please see more information on the July 31, 2023 deprecation notice 🚨
Developer Installation
If you have Go 1.22+, you can setup a development environment:
Contributing
If you are interested in contributing to
cosign, please read the contributing documentation.Future Cosign development will be focused the next major release which will be based on sigstore-go. Maintainers will be focused on feature development within sigstore-go. Contributions to sigstore-go, particularly around bring-your-own keys and signing, are appreciated. Please see the issue tracker for good first issues.
Cosign 2.x is a stable release and will continue to receive periodic feature updates and bug fixes. PRs that are small in scope and size are most likely to be quickly reviewed.
PRs which significantly modify or break the API will not be accepted. PRs which are significant in size but do not introduce breaking changes may be accepted, but will be considered lower priority than PRs in sigstore-go.
Dockerfile
Here is how to install and use cosign inside a Dockerfile through the ghcr.io/sigstore/cosign/cosign image:
Quick Start
This shows how to:
Sign a container and store the signature in the registry
Note that you should always sign images based on their digest (
@sha256:...) rather than a tag (:latest) because otherwise you might sign something you didn’t intend to!Cosign will prompt you to authenticate via OIDC, where you’ll sign in with your email address. Under the hood, cosign will request a code signing certificate from the Fulcio certificate authority. The subject of the certificate will match the email address you logged in with. Cosign will then store the signature and certificate in the Rekor transparency log, and upload the signature to the OCI registry alongside the image you’re signing.
Verify a container
To verify the image, you’ll need to pass in the expected certificate subject and certificate issuer via the
--certificate-identityand--certificate-oidc-issuerflags:You can also pass in a regex for the certificate identity and issuer flags,
--certificate-identity-regexpand--certificate-oidc-issuer-regexp.Verify a container against a public key
This command returns
0if at least onecosignformatted signature for the image is found matching the public key. See the detailed usage below for information and caveats on other signature formats.Any valid payloads are printed to stdout, in json format. Note that these signed payloads include the digest of the container image, which is how we can be sure these “detached” signatures cover the correct image.
Verify a container in an air-gapped environment
Note: This section is out of date.
Note: Most verification workflows require periodically requesting service keys from a TUF repository. For airgapped verification of signatures using the public-good instance, you will need to retrieve the trusted root file from the production TUF repository. The contents of this file will change without notification. By not using TUF, you will need to build your own mechanism to keep your airgapped copy of this file up-to-date.
Cosign can do completely offline verification by verifying a bundle which is typically distributed as an annotation on the image manifest. As long as this annotation is present, then offline verification can be done. This bundle annotation is always included by default for keyless signing, so the default
cosign signfunctionality will include all materials needed for offline verification.To verify an image in an air-gapped environment, the image and signatures must be available locally on the filesystem.
An image can be saved locally using
cosign save(note, this step must be done with a network connection):Now, in an air-gapped environment, this local image can be verified:
You’ll need to pass in expected values for
$CERT_IDENTITYand$CERT_OIDC_ISSUERto correctly verify this image. If you signed with a keypair, the same command will work, assuming the public key material is present locally:Identity-based blob signing and verification
Use keyless blob signing (
cosign sign-blobwithout--key) and verify against the expected signer identity:Troubleshooting
If you encounter issues with Cosign, first make sure you are using a recent release: The Cosign project actively supports the most recent release as well as the last release in the v2 series.
Common issues and remedies
failed to verify timestamps: threshold not met for verified log entry integrated timestamps: 0 < 1: You may be verifying a signature that requires RFC3161 timestamp support--use-signed-timestampsno signatures found: You may be verifying an image signature that requires support for Rekor v2 transparency logMy problem is something else
Please open an issue or ask in the slack channel.
Working with Other Artifacts
OCI registries are useful for storing more than just container images!
Cosignalso includes some utilities for publishing generic artifacts, including binaries, scripts, and configuration files using the OCI protocol.This section shows how to leverage these for an easy-to-use, backwards-compatible artifact distribution system that integrates well with the rest of Sigstore.
See the documentation for more information.
Blobs
You can publish an artifact with
cosign upload blob:Your users can download it from the “direct” url with standard tools like curl or wget:
The digest is baked right into the URL, so they can check that as well:
You can sign it with the normal
cosign signcommand and flags:As usual, make sure to reference any images you sign by their digest to make sure you don’t sign the wrong thing!
Tekton Bundles
Tekton bundles can be uploaded and managed within an OCI registry. The specification is here. This means they can also be signed and verified with
cosign.Tekton Bundles can currently be uploaded with the tkn cli, but we may add this support to
cosignin the future.WASM
Web Assembly Modules can also be stored in an OCI registry, using this specification.
Cosign can upload these using the
cosign wasm uploadcommand:eBPF
eBPF modules can also be stored in an OCI registry, using this specification.
The image below was built using the
beetool. More information can be found hereCosign can then sign these images as they can any other OCI image.
In-Toto Attestations
Cosign also has built-in support for in-toto attestations. The specification for these is defined here.
You can create and sign one from a local predicate file using the following commands:
All of the standard key management systems are supported. Payloads are signed using the DSSE signing spec, defined here.
To verify:
Detailed Usage
See the Usage documentation for more information.
Hardware-based Tokens
See the Hardware Tokens documentation for information on how to use
cosignwith hardware.Registry Support
cosignuses go-containerregistry for registry interactions, which has generally excellent compatibility, but some registries may have quirks.Today,
cosignhas been tested and works against the following registries:We aim for wide registry support. To
signimages in registries which do not yet fully support OCI media types, one may need to useCOSIGN_DOCKER_MEDIA_TYPESto fall back to legacy equivalents. For example:Please help test and file bugs if you see issues! Instructions can be found in the tracking issue.
Caveats
Intentionally Missing Features
cosignonly generates ECDSA-P256 keys and uses SHA256 hashes, for both ephemeral keyless signing and managed key signing. Keys are stored in PEM-encoded PKCS8 format. However, you can usecosignto store and retrieve signatures in any format, from any algorithm.Things That Should Probably Change
Payload Formats
cosignonly supports Red Hat’s simple signing format for payloads. That looks like:Note: This can be generated for an image reference using
cosign generate $IMAGE_URI_DIGEST.I’m happy to switch this format to something else if it makes sense. See https://github.com/notaryproject/notation/issues/40 for one option.
Registry Details
cosignsignatures are stored as separate objects in the OCI registry, with only a weak reference back to the object they “sign”. This means this relationship is opaque to the registry, and signatures will not be deleted or garbage-collected when the image is deleted. Similarly, they can easily be copied from one environment to another, but this is not automatic.Multiple signatures are stored in a list which is unfortunately a race condition today. To add a signature, clients orchestrate a “read-append-write” operation, so the last write will win in the case of contention.
Specifying Registry
cosignwill default to storing signatures in the same repo as the image it is signing. To specify a different repo for signatures, you can set theCOSIGN_REPOSITORYenvironment variable.This will replace the repo in the provided image like this:
So the signature for
gcr.io/dlorenc-vmtest2/demowill be stored ingcr.io/my-new-repo/demo:sha256-DIGEST.sig.Note: different registries might expect different formats for the “repository.”
To use GCR, a registry name like
gcr.io/$REPOis sufficient, as in the example above.To use Artifact Registry, specify a full image name like
$LOCATION-docker.pkg.dev/$PROJECT/$REPO/$STORAGE_IMAGE, not just a repository. For example,where the
sha256-DIGESTwill match the digest forgcr.io/dlorenc-vmtest2/demo. Specifying just a repo like$LOCATION-docker.pkg.dev/$PROJECT/$REPOwill not work in Artifact Registry.Signature Specification
cosignis inspired by tools like minisign and signify.Generated private keys are stored in PEM format. The keys encrypted under a password using scrypt as a KDF and nacl/secretbox for encryption.
They have a PEM header of
ENCRYPTED SIGSTORE PRIVATE KEY:Public keys are stored on disk in PEM-encoded standard PKIX format with a header of
PUBLIC KEY.Storage Specification
cosignstores signatures in an OCI registry, and uses a naming convention (tag based on the sha256 of what we’re signing) for locating the signature index.reg.example.com/ubuntu@sha256:703218c0465075f4425e58fac086e09e1de5c340b12976ab9eb8ad26615c3715has signatures located atreg.example.com/ubuntu:sha256-703218c0465075f4425e58fac086e09e1de5c340b12976ab9eb8ad26615c3715.sigRoughly (ignoring ports in the hostname):
s/:/-/gands/@/:/gto find the signature index.See Race conditions for some caveats around this strategy.
Alternative implementations could use transparency logs, local filesystem, a separate repository registry, an explicit reference to a signature index, a new registry API, grafeas, etc.
Signing subjects
cosignonly works for artifacts stored as “manifests” in the registry today. The proposed mechanism is flexible enough to support signing arbitrary things.KMS Support
cosignsupports using a KMS provider to generate and sign keys. Right now cosign supports Hashicorp Vault, AWS KMS, GCP KMS, Azure Key Vault and we are hoping to support more in the future!Additional KMS providers are available as external plugins, such as OVHcloud KMS.
See the KMS docs for more details.
OCI Artifacts
Push an artifact to a registry using oras (in this case,
cosignitself!):Now sign it! Using
cosignof course:Finally, verify
cosignwithcosignagain:FAQ
Why not use Notary v2
It’s hard to answer this briefly. This post contains some comparisons:
Notary V2 and Cosign
If you find other comparison posts, please send a PR here and we’ll link them all.
Why not use containers/image signing
containers/imagesigning is close tocosign, and we reuse payload formats.cosigndiffers in that it signs with ECDSA-P256 keys instead of PGP, and stores signatures in the registry.Why not use TUF?
I believe this tool is complementary to TUF, and they can be used together. I haven’t tried yet, but think we can also reuse a registry for TUF storage.
Design Requirements
Future Ideas
Registry API Changes
The naming convention and read-modify-write update patterns we use to store things in a registry are a bit, well, “hacky”. I think they’re the best (only) real option available today, but if the registry API changes we can improve these.
Other Types
cosigncan sign anything in a registry. These examples show signing a single image, but you could also sign a multi-platformIndex, or any other type of artifact. This includes Helm Charts, Tekton Pipelines, and anything else currently using OCI registries for distribution.This also means new artifact types can be uploaded to a registry and signed. One interesting type to store and sign would be TUF repositories. I haven’t tried yet, but I’m fairly certain TUF could be implemented on top of this.
Tag Signing
cosignsignatures protect the digests of objects stored in a registry. The optionalannotationssupport (via the-aflag tocosign sign) can be used to add extra data to the payload that is signed and protected by the signature. One use-case for this might be to sign a tag->digest mapping.If you would like to attest that a specific tag (or set of tags) should point at a digest, you can run something like:
Then you can verify that the tag->digest mapping is also covered in the signature, using the
-aflag tocosign verify. This example verifies that the digest$TAGwhich points to (sha256:1304f174557314a7ed9eddb4eab12fed12cb0cd9809e4c28f29af86979a3c870) has been signed, and also that thetagannotation has the valuesign-me:Timestamps could also be added here, to implement TUF-style freeze-attack prevention.
Base Image/Layer Signing
Again,
cosigncan sign anything in a registry. You could usecosignto sign an image that is intended to be used as a base image, and include that provenance metadata in resulting derived images. This could be used to enforce that an image was built from an authorized base image.Rough Idea:
layerDescriptors, which can contain annotations. See here for the specification.This example manifest manifest represents an image that has been built from a base image with two layers. One additional layer is added, forming the final image.
Note that this could be applied recursively, for multiple intermediate base images.
Counter-Signing
Cosign signatures (and their protected payloads) are stored as artifacts in a registry. These signature objects can also be signed, resulting in a new, “counter-signature” artifact. This “counter-signature” protects the signature (or set of signatures) and the referenced artifact, which allows it to act as an attestation to the signature(s) themselves.
Before we sign the signature artifact, we first give it a memorable name so we can find it later.
Now give that signature a memorable name, then sign that:
Finally, check the original signature:
Release Cadence
We cut releases as needed. Patch releases are cut to fix small bugs. Minor releases are cut periodically when there are multiple bugs fixed or features added. Major releases will be released when there are breaking features.
Security
Should you discover any security issues, please refer to sigstore’s security process
Bundle files in GitHub Release Assets
The GitHub release assets for
cosigncontain Sigstore bundle files produced by GoReleaser while signing the cosign blob that is used to verify the integrity of the release binaries. This file is not used by cosign itself, but is provided for users who wish to verify the integrity of the release binaries.