sigstore / cosign

Code signing and transparency for containers and binaries
Apache License 2.0
4.46k stars 545 forks source link

Log verification for expired targets #1273

Open haydentherapper opened 2 years ago

haydentherapper commented 2 years ago

Overview

This is a tracking issue for supporting verification for expired/rotated targets. @asraa and I will be working on this.

Currently, cosign assumes the latest TUF metadata can be used to validate signatures. As the Fulcio CA certificate will expire, we will have to rotate that target at some point. This will cause cosign to not be able to validate the signatures that chain up to the expired CA certificate, since the TUF metadata will contain a different certificate.

We propose bundling a pointer to the metadata used when generating the signature. We will do this by including the snapshot or timestamp JSON in the signature bundle. Cosign will use this to find versioned TUF metadata.

Design doc

Tasks

For cosign:

There are a few tasks for the Sigstore TUF repo.

asraa commented 2 years ago

Some more thoughts to make the experience of expired target verification along with BYO TUF root:

haydentherapper commented 2 years ago

A few other things we'll need to consider:

haydentherapper commented 2 years ago

As I was implementing verification using the TUF timestamp, I ran into an issue. As a reminder, the verification flow is roughly:

  1. Read the timestamp from an annotation on the OCI image
  2. Using the timestamp, fetch the versioned snapshot
  3. Using the snapshot, fetch the versioned root (N) and targets
  4. Verify the root by walking the chain from 1.root.json to N.root.json
  5. Verify the timestamp, snapshot and targets
  6. Use the old targets to verify the OCI image

The TUF spec no longer requires that the root metadata be included with the snapshot. Recently, go-tuf removed including root.json in the snapshot. This means step (3) is not possible, because there will be no reference to a versioned root.

This leaves us a few options:

To summarize, this solution is far simpler. On verification, we will simply load all targets from the target metadata. For the verification of the signature, we will load all Fulcio certs into the root pool. We will have something similar for bundle verification using the Rekor public keys. We'll keep track in custom TUF metadata of which target is active, and use that to inform users when they're verifying a signature using old targets.

The main trade-off is that the targets metadata will grow over time. If we want to cap its size, we will need to decide on how long we'll keep old targets around. This can be decided later though, as we aren't frequently rotating targets.

This also simplifies the revocation story. To mark a target as revoked, we simply remove it from the set of targets, which is aligned with how TUF expects revocation to occur. @asraa and I do think there's still value in tracking revocation somehow, through a TUF delegation - I have a separate doc discussing this in more detail that I'll circulate shortly.

@dlorenc @bobcallaway - Y'all reviewed the original proposal, lemme know if you have any concerns with this other approach.