Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Representation of Container Image Signature Bundles as OCI Artifacts #3927

Open
codysoyland opened this issue Nov 5, 2024 · 4 comments
Open
Labels
enhancement New feature or request

Comments

@codysoyland
Copy link
Member

Background

The relatively new Cosign Bundle Specification describes how image attestations are to be represented as OCI artifacts, using Sigstore Bundles as referring artifacts, with the subject being the image manifest. This specification is currently being implemented in cosign. This is an improvement over the previous Cosign Attestation Specification which uses Layers to represent attestations and annotations to specify the verification material. These specifications cover the representation of attestations (using cosign attest), but do not cover the representation of plain signatures (using cosign sign).

The Cosign Signature Specification describes how plain signatures are represented and is implemented by cosign sign. This specification, like the Attestation Specification, uses annotations to specify the verification material, and signed paload is represented by a Simple Signing format.

Proposal

A current initiative in Sigstore is to unify verification around the Sigstore Bundle, which contains all data needed to verify an artifact (in conjunction with trusted material provided out-of-band). In order to support container image signatures, we need to represent the signed payload in a way that can be included in a Sigstore Bundle.

I have identified four options for migrating container image signatures to Bundles:

  • Option 1: Add Simple Signing Envelope to the Bundle Specification
  • Option 2: Continue publishing Simple Signing Envelopes as detached payloads
  • Option 3: Create a new attestation predicate type for container image signatures
  • Option 4: Use a MessageSignature over the container image manifest

Option 1: Add Simple Signing Envelope to the Bundle Specification

The first option is to add a new content type to the Bundle Specification that represents a Simple Signing Envelope. This would live alongside MessageSignature and Envelope, as top-level signature formats.

One advantage of this approach is that existing Cosign signatures could be migrated to the new format without re-signing, as the signing payload would be preserved. Additionally, all data needed to verify the signature would be included in the Bundle.

One disadvantage of this approach is the complexity of adding a new top-level signature format to the Bundle Specification. This would require complex changes to the verifier clients, and would require a new version of the Bundle Specification.

Option 2: Continue publishing Simple Signing Envelopes as detached payloads

The second option is to continue publishing Simple Signing Envelopes as detached payloads, and to sign the detached payload with a MessageSignature.

One advantage of this approach is that it doesn't require any changes to the Bundle Specification, and we can migrate existing signatures to Bundles without re-signing.

One disadvantage of this approach is that the Bundle would not contain all data needed to verify the signature, and the detached payload would need to be fetched separately. This option would not be very elegant, and offers little benefit over the current state.

Option 3: Create a new attestation predicate type for container image signatures

The third option is to create a new attestation predicate type for container image signatures. This option would use the same scheme as the Cosign Bundle Specification, and plain signatures would be represented as simple attestations.

This option offers many advantages, as the bundle specification is already designed to represent attestations, we could re-use much of the code that is being developed for the Bundle Specification, and the Bundle would contain all data needed to verify the signature. This option would be the simplest to implement, and would unify the representation of attestations and plain signatures.

A disadvantage of this approach is that it would require re-signing existing signatures to migrate them to the new format. I consider this to be a minor disadvantage, as some migration process would be required for any option, and the benefits of this option outweigh the costs.

Option 4: Use a MessageSignature over the container image manifest

The fourth option is to use a MessageSignature over the container image manifest. This is the simplest option, as we would just sign the entire manifest as a MessageSignature.

This option is simple to implement, and the Bundle would contain all data needed to verify the signature.

A disadvantage of this approach is that it would require re-signing existing signtaures to migrate them to the new format. Additionally, this option would not be able to represent any additional metadata that is currently supported by the Simple Signing Envelope, such as the container image name and optional user-specified claims (specified with cosign sign --annotations)

@codysoyland codysoyland added the enhancement New feature or request label Nov 5, 2024
@sudo-bmitch
Copy link
Contributor

Three things to consider independent of the above options when using OCI Artifacts and the referrers API:

  1. Package each signature as a separate artifact that refers back to the image. This allows workflows that selectively copy image referrers, or prune old content, to do work with generic tooling that doesn't need to be sigstore/cosign aware.
  2. Include the necessary data in annotations to differentiate multiple signatures and attestations. This can be the identity of the signer, the time of time of the signature, and in the attestation case, the type of content being attested (e.g. a media type of the SBOM). These annotations get pulled up in the referrers response, and are useful for those filtering which signatures to pull/verify, and which to include in an image copy.
  3. For small blobs, like a detached signature, consider using the data field to more efficiently pull the content with fewer round trips.

@kommendorkapten
Copy link
Member

Thanks for writing this up Cody!

I think options #3 and #4 are the most interesting. While I like the simplicity of option #4, having an extra layer of inversion is almost always preferable, as we can easily accommodate future needs not known right now.

Thinking about option #3, we can either create a new in-toto Predicate type for an OCI artifact (note that we don't need the digest of the manifest as it's part of the in-toto statement). Another option is to include create store the Simple Signing document as the payload, but that would lead to some duplication, as it already contains the digest (and so a more complex format as verifiers would need to verify all occurrences of the the digest). This makes me in favour of option #3 with a new OCI predicate type (v0.1 can be the an empty JSON document if we don't know about any extra attributes to store right now).

@haydentherapper
Copy link
Contributor

Thanks for this thorough investigation Cody!

I like Option #3 though we need to decide what is the predicate and subject of the intoto attestation. Would the digest of the container image manifest be the subject? Is there any better representation of the container? What content would you like in the predicate, if any? If the subject is sufficient, we could have an empty predicate like what PyPI chose to do for PEP 740.

@kommendorkapten, a related idea would be to use a DSSE rather than intoto attestation. The DSSE payload would be the Simple Signing payload with the signature in the envelope. The downside to this would be that most of the supply chain tools expect intoto DSSEs.

I like moving away from raw signatures to attestations, so I'm less keen on #4.

For #1, adding support for the Simple Signing payload to the bundle would mean inventing an envelope to hold both the Simple Signing payload and the signature, since the former has no field for a signature. At that point, we've more or less recreated a DSSE.

For #2, I agree this approach doesn't make a significant improvement over the current state, and has a problem of not knowing what the signature is over since there is no predicate type.

@kommendorkapten
Copy link
Member

Agreed, option #3 with in-toto is what I think we should do. By always using an in-toto statement, any artifact matching can be general, and verifiers can have policies that only demands a certain predicate type signed by a known identity.

An empty predicate is what I proposed too, as I'm not aware of any extra data needed. With proper versioning, we can always add that later if needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants