Package: wnpp
Severity: wishlist
Owner: Simon Josefsson <si...@josefsson.org>

* Package name    : cosign
  Version         : 2.2.2-1
  Upstream Author : The Sigstore Authors
* URL             : https://github.com/sigstore/cosign
* License         : Apache-2.0
  Programming Lang: Go
  Description     : Code signing and transparency for containers and binaries

 Signing OCI containers (and other artifacts) using Sigstore
 (https://sigstore.dev/)!
 .
 Go Report Card
 (https://goreportcard.com/report/github.com/sigstore/cosign) e2e-tests
 (https://github.com/sigstore/cosign/actions/workflows/e2e-tests.yml) CII
 Best Practices
 (https://bestpractices.coreinfrastructure.org/projects/5715) OpenSSF
 Scorecard
 (https://api.securityscorecards.dev/projects/github.com/sigstore/cosign)
 .
 Cosign aims to make signatures **invisible infrastructure**.
 .
 Cosign supports:
 .
  * "Keyless signing" with the Sigstore public good Fulcio certificate
    authority and Rekor transparency log (default)
  * Hardware and KMS signing
  * Signing with a cosign generated encrypted private/public keypair
  * Container Signing, Verification and Storage in an OCI registry.
  * Bring-your-own PKI
 .
 Info
 .
 Cosign is developed as part of the sigstore (https://sigstore.dev)
 project. We also use a slack channel (https://sigstore.slack.com)! Click
 here (https://join.slack.com/t/sigstore/shared_invite/zt-mhs55zh0-
 XmY3bcfWn4XEyMqUUutbUQ) for the invite link.
 .
 Installation
 .
 For Homebrew, Arch, Nix, GitHub Action, and Kubernetes installs see the
 installation docs
 (https://docs.sigstore.dev/system_config/installation/).
 .
 For Linux and macOS binaries see the GitHub release assets
 (https://github.com/sigstore/cosign/releases/latest).
 .
 :rotating_light: If you are downloading releases of cosign from our GCS
 bucket - please see more information on the July 31, 2023 deprecation
 notice (https://blog.sigstore.dev/cosign-releases-bucket-deprecation/)
 :rotating_light:
 .
 Developer Installation
 .
 If you have Go 1.19+, you can setup a development environment:
 .
   $ git clone https://github.com/sigstore/cosign
   $ cd cosign
   $ go install ./cmd/cosign
   $ $(go env GOPATH)/bin/cosign
 .
 Contributing
 .
 If you are interested in contributing to cosign, please read the
 contributing documentation (/CONTRIBUTING.md).
 .
 Dockerfile
 .
 Here is how to install and use cosign inside a Dockerfile through the
 gcr.io/projectsigstore/cosign image:
 .
   FROM gcr.io/projectsigstore/cosign:v1.13.0 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" ]
 .
 Quick Start
 .
 This shows how to:
 .
  * sign a container image with the default "keyless signing" method (see
    KEYLESS.md (/KEYLESS.md))
  * verify the container image
 .
 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 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 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
 issuer and certificate subject via the --certificate-identity and --
 certificate-oidc-issuer flags:
 .
   cosign verify $IMAGE --certificate-identity=$IDENTITY --certificate-oidc-
 issuer=$OIDC_ISSUER
 .
 You can also pass in a regex for the certificate identity and issuer
 flags, --certificate-identity-regexp and --certificate-oidc-issuer-regexp.
 .
 Verify a container against a public key
 .
 This command returns 0 if *at least one* cosign formatted 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.
 .
   $ cosign verify --key cosign.pub $IMAGE_URI:1h
   The following checks were performed on these signatures:
     - The cosign claims were validated
     - The signatures were verified against the specified public key
   {"Critical":{"Identity":{"docker-reference":""},"Image":{"Docker-
 manifest-
 
digest":"sha256:87ef60f558bad79beea6425a3b28989f01dd417164150ab3baab98dcbf04def8"},"Type":"cosign
 container image signature"},"Optional":null}
 .
 Verify a container in an air-gapped environment
 .
 Cosign can do completely offline verification by verifying a bundle
 (/specs/SIGNATURE_SPEC.md#properties) 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
 sign functionality 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):
 .
   cosign initialize # This will pull in the latest TUF root
   cosign save $IMAGE_NAME --dir ./path/to/dir
 .
 Now, in an air-gapped environment, this local image can be verified:
 .
   cosign verify --certificate-identity $CERT_IDENTITY --certificate-oidc-issuer
 $CERT_OIDC_ISSUER --offline --local-image ./path/to/dir
 .
 You'll need to pass in expected values for $CERT_IDENTITY and
 $CERT_OIDC_ISSUER to correctly verify this image. If you signed with a
 keypair, the same command will work, assuming the public key material is
 present locally:
 .
   cosign verify --key cosign.pub --offline --local-image ./path/to/dir
 .
 What ** is not ** production ready?
 .
 While parts of cosign are stable, we are continuing to experiment and
 add new features. The following feature set is not considered stable
 yet, but we are committed to stabilizing it over time!
 .
 Formats/Specifications
 .
 While the cosign code for uploading, signing, retrieving, and verifying
 several artifact types is stable, the format specifications for some of
 those types may not be considered stable yet. Some of these are
 developed outside of the cosign project, so we are waiting for them to
 stabilize first.
 .
 These include:
 .
  * The SBOM specification for storing SBOMs in a container registry
  * The In-Toto attestation format
 .
 Working with Other Artifacts
 .
 OCI registries are useful for storing more than just container images!
 Cosign also 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.
 .
 Blobs
 .
 You can publish an artifact with cosign upload blob:
 .
   $ echo "my first artifact" > artifact
   $ BLOB_SUM=$(shasum -a 256 artifact | cut -d' ' -f 1)
   c69d72c98b55258f9026f984e4656f0e9fd3ef024ea3fac1d7e5c7e6249f1626
 artifact
   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)
   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
 .
 Your users can download it from the "direct" url with standard tools
 like curl or wget:
 .
   $ curl -L ttl.sh/v2/$BLOB_NAME/blobs/sha256:$BLOB_SUM > artifact-fetched
 .
 The digest is baked right into the URL, so they can check that as well:
 .
   $ cat artifact-fetched | shasum -a 256
   c69d72c98b55258f9026f984e4656f0e9fd3ef024ea3fac1d7e5c7e6249f1626  -
 .
 You can sign it with the normal cosign sign command and flags:
 .
   $ cosign sign --key cosign.key $BLOB_URI_DIGEST
   Enter password for private key:
   Pushing signature to: ttl.sh/my-artifact-f42c22e0
 .
 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 (https://tekton.dev) bundles can be uploaded and managed within
 an OCI registry. The specification is here
 (https://tekton.dev/docs/pipelines/tekton-bundle-contracts/). This means
 they can also be signed and verified with cosign.
 .
 Tekton Bundles can currently be uploaded with the tkn cli
 (https://github.com/tektoncd/cli), but we may add this support to cosign
 in the future.
 .
   $ 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
 .
 WASM
 .
 Web Assembly Modules can also be stored in an OCI registry, using this
 specification (https://github.com/solo-io/wasm/tree/master/spec).
 .
 Cosign can upload these using the cosign wasm upload command:
 .
   $ 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
 .
 eBPF (https://ebpf.io) modules can also be stored in an OCI registry,
 using this specification (https://github.com/solo-
 io/bumblebee/tree/main/spec).
 .
 The image below was built using the bee tool. More information can be
 found here (https://github.com/solo-io/bumblebee/)
 .
 Cosign can then sign these images as they can any other OCI image.
 .
   $ 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}]
 .
 .
 In-Toto Attestations
 .
 Cosign also has built-in support for in-toto (https://in-toto.io)
 attestations. The specification for these is defined here
 (https://github.com/in-toto/attestation).
 .
 You can create and sign one from a local predicate file using the
 following commands:
 .
   $ cosign attest --predicate <file> --key cosign.key $IMAGE_URI_DIGEST
 .
 All of the standard key management systems are supported. Payloads are
 signed using the DSSE signing spec, defined here
 (https://github.com/secure-systems-lab/dsse).
 .
 To verify:
 .
   $ cosign verify-attestation --key cosign.pub $IMAGE_URI
 .
 Detailed Usage
 .
 See the Usage documentation (/USAGE.md) for more commands!
 .
 Hardware-based Tokens
 .
 See the Hardware Tokens documentation (/TOKENS.md) for information on
 how to use cosign with hardware.
 .
 Keyless
 .
 🚨 🚨 🚨 See here (/KEYLESS.md) for info on the experimental Keyless
 signatures mode. 🚨 🚨 🚨
 .
 Registry Support
 .
 cosign uses go-containerregistry (https://github.com/google/go-
 containerregistry) for registry interactions, which has generally
 excellent compatibility, but some registries may have quirks.
 .
 Today, cosign has been tested and works against the following
 registries:
 .
  * AWS Elastic Container Registry
  * GCP's Artifact Registry and Container Registry
  * Docker Hub
  * Azure Container Registry
  * JFrog Artifactory Container Registry
  * The CNCF distribution/distribution Registry
  * GitLab Container Registry
  * GitHub Container Registry
  * The CNCF Harbor Registry
  * Digital Ocean Container Registry
  * Sonatype Nexus Container Registry
  * Alibaba Cloud Container Registry
  * Red Hat Quay Container Registry 3.6+ / Red Hat quay.io
  * Elastic Container Registry
  * IBM Cloud Container Registry
  * Cloudsmith Container Registry
  * The CNCF zot Registry
 .
 We aim for wide registry support. To sign images in registries which do
 not yet fully support OCI media types
 (https://github.com/sigstore/cosign/blob/main/SPEC.md#object-types), one
 may need to use COSIGN_DOCKER_MEDIA_TYPES to fall back to legacy
 equivalents. For example:
 .
   COSIGN_DOCKER_MEDIA_TYPES=1 cosign sign --key cosign.key legacy-
 registry.example.com/my/image@$DIGEST
 .
 Please help test and file bugs if you see issues! Instructions can be
 found in the tracking issue
 (https://github.com/sigstore/cosign/issues/40).
 .
 Caveats
 .
 Intentionally Missing Features
 .
 cosign only generates ECDSA-P256 keys and uses SHA256 hashes. Keys are
 stored in PEM-encoded PKCS8 format. However, you can use cosign to store
 and retrieve signatures in any format, from any algorithm.
 .
 Unintentionally Missing Features
 .
 cosign will integrate with transparency logs! See
 (https://github.com/sigstore/cosign/issues/34) for more info.
 .
 cosign will integrate with even more transparency logs, and a PKI. See
 (https://github.com/sigStore/fulcio) for more info.
 .
 cosign will also support The Update Framework for delegations, key
 discovery and expiration. See
 (https://github.com/sigstore/cosign/issues/86) for more info!
 .
 Things That Should Probably Change
 .
 Payload Formats
 .
 cosign only supports Red Hat's simple signing
 (https://www.redhat.com/en/blog/container-image-signing) format for
 payloads. That looks like:
 .
   {
       "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
       }
   }
 .
 **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/nv2/issues/40) for one option.
 .
 Registry Details
 .
 cosign signatures 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
 .
 cosign will default to storing signatures in the same repo as the image
 it is signing. To specify a different repo for signatures, you can set
 the COSIGN_REPOSITORY environment variable.
 .
 This will replace the repo in the provided image like this:
 .
   $ export COSIGN_REPOSITORY=gcr.io/my-new-repo
   $ cosign sign --key cosign.key $IMAGE_URI_DIGEST
 .
 So the signature for gcr.io/dlorenc-vmtest2/demo will be stored in
 gcr.io/my-new-repo/demo:sha256-DIGEST.sig.
 .
 Note: different registries might expect different formats for the
 "repository."
 .
  * To use GCR (https://cloud.google.com/container-registry), a registry
    name
    like gcr.io/$REPO is sufficient, as in the example above.
  * To use Artifact Registry (https://cloud.google.com/artifact-registry),
    specify a full image name like
    $LOCATION-docker.pkg.dev/$PROJECT/$REPO/$STORAGE_IMAGE, not just a
    repository. For example,
      $ export COSIGN_REPOSITORY=us-docker.pkg.dev/my-new-repo/demo
      $ cosign sign --key cosign.key $IMAGE_URI_DIGEST
    where the sha256-DIGEST will match the digest for
    gcr.io/dlorenc-vmtest2/demo. Specifying just a repo like
    $LOCATION-docker.pkg.dev/$PROJECT/$REPO will not work in Artifact
    Registry.
 .
 Signature Specification
 .
 cosign is inspired by tools like minisign
 (https://jedisct1.github.io/minisign/) and signify
 (https://www.openbsd.org/papers/bsdcan-signify.html).
 .
 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:
 .
   -----BEGIN ENCRYPTED SIGSTORE PRIVATE KEY-----
   ...
   -----END ENCRYPTED SIGSTORE PRIVATE KEY-----
 .
 Public keys are stored on disk in PEM-encoded standard PKIX format with a
 header of PUBLIC KEY.
 .
   -----BEGIN PUBLIC KEY-----
   MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAELigCnlLNKgOglRTx1D7JhI7eRw99
   QolE9Jo4QUxnbMy5nUuBL+UZF9qqfm/Dg1BNeHRThHzWh2ki9vAEgWEDOw==
   -----END PUBLIC KEY-----
 .
 Storage Specification
 .
 cosign stores 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:703218c0465075f4425e58fac086e09e1de5c340b12976ab9eb8ad26615c3715
 has signatures located at reg.example.com/ubuntu:sha256-
 703218c0465075f4425e58fac086e09e1de5c340b12976ab9eb8ad26615c3715.sig
 .
 Roughly (ignoring ports in the hostname): s/:/-/g and s/@/:/g to 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
 .
 cosign only works for artifacts stored as "manifests" in the registry
 today. The proposed mechanism is flexible enough to support signing
 arbitrary things.
 .
 KMS Support
 .
 cosign supports 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!
 .
 See the KMS docs (/KMS.md) for more details.
 .
 OCI Artifacts
 .
 Push an artifact to a registry using oras
 (https://github.com/deislabs/oras) (in this case, cosign itself!):
 .
   $ 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
 .
 Now sign it! Using cosign of course:
 .
   $ 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
 .
 Finally, verify cosign with cosign again:
 .
   $ 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:
     - The cosign claims were validated
     - The claims were present in the transparency log
     - The signatures were integrated into the transparency log when the
 certificate was valid
     - The signatures were verified against the specified public key
     - The code-signing certificate was verified using trusted certificate
 authority certificates
 .
   {"Critical":{"Identity":{"docker-reference":""},"Image":{"Docker-
 manifest-
 
digest":"sha256:551e6cce7ed2e5c914998f931b277bc879e675b74843e6f29bc17f3b5f692bef"},"Type":"cosign
 container image signature"},"Optional":null}
 .
 FAQ
 .
 Why not use Notary v2
 .
 It's hard to answer this briefly. This post contains some comparisons:
 .
 Notary V2 and Cosign (https://medium.com/@dlorenc/notary-v2-and-cosign-
 b816658f044d)
 .
 If you find other comparison posts, please send a PR here and we'll link
 them all.
 .
 Why not use containers/image signing
 .
 containers/image signing is close to cosign, and we reuse payload
 formats. cosign differs 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.
 .
 Why not use Blockchain?
 .
 Just kidding. Nobody actually asked this. Don't be that person.
 .
 Why not use $FOO?
 .
 See the next section, Requirements. I designed this tool to meet a few
 specific requirements, and didn't find anything else that met all of
 these. If you're aware of another system that does meet these, please
 let me know!
 .
 Design Requirements
 .
  * No external services for signature storage, querying, or retrieval
  * We aim for as much registry support as possible
  * Everything should work over the registry API
  * PGP should not be required at all.
  * Users must be able to find all signatures for an image
  * Signers can sign an image after push
  * Multiple entities can sign an image
  * Signing an image does not mutate the image
  * Pure-go implementation
 .
 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
 .
 cosign can sign anything in a registry. These examples show signing a
 single image, but you could also sign a multi-platform Index, 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
 .
 cosign signatures protect the digests of objects stored in a registry.
 The optional annotations support (via the -a flag to cosign 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:
 .
   $ 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
 .
 Then you can verify that the tag->digest mapping is also covered in the
 signature, using the -a flag to cosign verify. This example verifies that
 the digest $TAG which points to
 (sha256:1304f174557314a7ed9eddb4eab12fed12cb0cd9809e4c28f29af86979a3c870)
 has been signed, **and also** that the tag annotation has the value sign-
 me:
 .
   $ 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"
     }
   }
 .
 Timestamps could also be added here, to implement TUF-style freeze-attack
 prevention.
 .
 Base Image/Layer Signing
 .
 Again, cosign can sign anything in a registry. You could use cosign to
 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:
 .
  * OCI manifests have an ordered list of layer Descriptors, which can
    contain annotations.
    See here (https://github.com/opencontainers/image-
    spec/blob/master/manifest.md) for the
    specification.
  * A base image is an ordered list of layers to which other layers are
    appended, as well as an
    initial configuration object that is mutated.
        * A derived image is free to completely delete/destroy/recreate the
        config from its base image,
        so signing the config would provided limited value.
  * We can sign the full set of ordered base layers, and attach that
    signature as an annotation to
    the **last** layer in the resulting child image.
 .
 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.
 .
   {
     "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"
       }
     ],
   }
 .
 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.
 .
   $ 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"
     }
   }
 .
 .
 Now give that signature a memorable name, then sign that:
 .
   $ 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"}}
 .
 Finally, check the original signature:
 .
   $ 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=="
         }
       }
     ]
   }
 .
 Release Cadence
 .
 We are intending to move to a monthly cadence for minor releases. Minor
 releases will be published around the beginning of the month. We may cut
 a patch release instead, if the changes are small enough not to warrant
 a minor release. We will also cut patch releases periodically as needed
 to address bugs.
 .
 Security
 .
 Should you discover any security issues, please refer to sigstore's
 security process
 (https://github.com/sigstore/.github/blob/main/SECURITY.md)
 .
 PEM files in GitHub Release Assets
 .
 The GitHub release assets for cosign contain a PEM file produced by
 GoReleaser
 
(https://github.com/sigstore/cosign/blob/ac999344eb381ae91455b0a9c5c267e747608d76/.goreleaser.yml#L166)
 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.
 .
 By default, cosign output these PEM files in base64 encoded format
 (https://github.com/sigstore/cosign/blob/main/doc/cosign_sign-
 blob.md#options), this approach might be good for air-gapped environments
 where the PEM file is stored in a file system. So, you should decode
 these PEM files before using them to verify the blobs.

I hope to maintain this package as part of Debian Go Packaging Team:

https://salsa.debian.org/go-team/packages/cosign

/Simon

Attachment: signature.asc
Description: PGP signature

Reply via email to