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

cosign for git #865

Closed
mattmoor opened this issue Oct 9, 2021 · 27 comments
Closed

cosign for git #865

mattmoor opened this issue Oct 9, 2021 · 27 comments
Labels
enhancement New feature or request

Comments

@mattmoor
Copy link
Member

mattmoor commented Oct 9, 2021

Description

Today cosign is very oriented around OCI entities as both the thing being signed, as well as the medium for storing signatures, attestations, etc. While this is a pervasive medium for binaries, it doesn't capture another critical lifecycle stage: source, which has an even more pervasive medium: Git.

🚨🚨 This conversation will be muddied by the existence of git commit -s, which solves one specific part of the problem, but hopefully I will motivate the ways this is insufficient here 🚨🚨

git commit -s solves a very focused problem: authenticating commit authors (assuming publicly verifiable keys for that author). However, git commit -s encodes the signature into the Merkle DAG, which suffers similar problems with early container image signing efforts: it's presence changes the DAG, and post-facto attachment is impossible without changing the DAG. This is fine for the authentication use-case, but not for the breadth of use-cases cosign is pursuing.

Let's look in particular at "attestations". Some of these (e.g. provenance) can be established at the point of authoring, but the vast majority of attestations will be attached post-facto, and often by a diverse set of authors. Some examples here would be:

  • "review" attestations: looking at compliance requirements and things like SLSA it is just as important to know who reviewed a change as who authored the change.
  • "validated" attestations: an example of a "robot" attestation would be the completion of various presubmit checks. You can think of this as a portable medium for encoding Github's "checks" or "commit status" information. This could include various levels of testing, style checking, or source-level vulnerability scanning.

Fortunately, (unlike OCI) Git already has an established medium for attaching metadata to commits called git notes:

Commit notes are blobs containing extra information about an object (usually information to supplement a commit’s message). These blobs are taken from notes refs. A notes ref is usually a branch which contains "files" whose paths are the object names for the objects they describe, with some directory separators included for performance reasons

You can even see that the examples of how to use these encompass some of the use cases above:

git show -s 72a144e
[...]
    Signed-off-by: Junio C Hamano <[email protected]>

Notes:
    Tested-by: Johannes Sixt <[email protected]>

I would be remiss at this point if I did not h/t git-appraise and @ojarjur who taught me about Git notes! This project touches on the other use case I mention above: reviews (although more for content than attestation).


So what am I actually proposing?

I think that it would be interesting to start thinking about a pkg/git to match pkg/oci which enables us to use cosign to sign and attest to things using git notes post-facto. e.g. passing a remote/refspec to:

COSIGN_EXPERIMENTAL=1 cosign attest --predicate <FILE> --type <TYPE> <REMOTE/REFSPEC>
@mattmoor mattmoor added the enhancement New feature or request label Oct 9, 2021
@dlorenc
Copy link
Member

dlorenc commented Oct 9, 2021

  • "review" attestations: looking at compliance requirements and things like SLSA it is just as important to know who reviewed a change as who authored the change.
  • "validated" attestations: an example of a "robot" attestation would be the completion of various presubmit checks. You can think of this as a portable medium for encoding Github's "checks" or "commit status" information. This could include various levels of testing, style checking, or source-level vulnerability scanning.

These examples are great and really motivate the use case.

@JimBugwadia
Copy link
Contributor

With OCI registries its possible to sign and verify a bundle/zip with a set of YAMLs. With Git, would the unit of signing and verification always be at a file level, or is it possible to somehow group at a folder? A potential concern is the processing time at admission control.

Another consideration for GitOps workflows use like Kustomize to process a set of files. It would be nice to sign/verify the results.

@mattmoor
Copy link
Member Author

mattmoor commented Oct 9, 2021

My expectation was still sort of that the unit of signing would be the git SHA, but given that SHA1 is broken we might also consider something like: https://pkg.go.dev/golang.org/x/mod/sumdb/dirhash

I like the idea of using the SHA because it's a first-class thing, but I could also see us incorporating a second hash to strengthen things (then one becomes more lookup oriented, and the other becomes the unit for verification).

That said, I'd love to here what other folks think. 🤷

@lukehinds
Copy link
Member

I don't understand git notes to well (my own lack of understanding, not any fault with the technology). I have been playing around with generating provenance pre-commit which then stages the provenance (intoto link) into the commit before the post commit hook, it also has a fulcio oidc identity allowing some level of non-repudiation. This way its still part of the git commit flow.

I suspect the above way may be more much rudimentary than what your aiming for (or perhaps it would just be one one part of it).

@mattmoor
Copy link
Member Author

mattmoor commented Oct 9, 2021

@lukehinds This would be a separate commit (in a whole separate part of the DAG), but each note is associated with a specific commit, so the key thing here is that it provides a way to do the post-facto "attachment", which I think we need.

I'm not sure how you are including the information you are including (maybe link from commit message?) but you could do something very similar in a post-commit hook (once you have the SHA) to attach the same metadata as a "note".

@lukehinds
Copy link
Member

Its pretty much this

  1. A pre-commit hook enacts
  2. All of the staged files are hashed into in-toto products
  3. The fulcio signing certs are procured
  4. the signed envelope containing the digests in 2, are signed over
  5. The staged files and the in-toto link file are commited in one.

It's just a prototype in python right now I worked on with Santiago https://github.com/OpenSecureSupplyChain/githook-provenance

I don't want to muddy this issue discussion anymore though, I am interested in learning more about this and just wanting to find the best solution (which this looks like it might be).

@mattmoor
Copy link
Member Author

mattmoor commented Oct 9, 2021

@lukehinds I wonder whether there are any ways to guarantee a pre-commit hook runs last, or this shift might also close a race where I register zzz-my-exploit-hook as a pre-commit hook to get you to sign it before I modify it 🤔 😅

@lukehinds
Copy link
Member

from what I know its a unique namespace , there can only be one pre-commit. It's a pretty simple system, you can throw anything in there (bash script, py / ruby script or binary) and as long as its named pre-commit / post-commit etc it gets run.

@dlorenc
Copy link
Member

dlorenc commented Oct 9, 2021

This feels like the same kind of general discussion we've had a few times around the combination of signatures and CAS's.

Attached signatures have their merits, and getting the signature into the CAS is a really good thing in some cases. It's also limiting, because you can't change or add or remove, etc. those signatures later without breaking the CAS.

@justaugustus
Copy link

cc: @edwarnicke @AevaOnline
(to chat about GitBOM and any potential collab here)

@dlorenc
Copy link
Member

dlorenc commented Oct 10, 2021

Another thing to think through as we go down this road with git: it would be awesome to make these somehow safe for the common merge strategies. If you sign a commit, but then it's rebase/merged, the commit you signed is gone making the signature a bit less useful.

@wlynch
Copy link
Member

wlynch commented Apr 21, 2022

👋 I was playing around with Git x509 signing this week, and got a demo working signing commits with sigstore ephemeral certs. 🎉

image

Demo: https://drive.google.com/file/d/1Q_qC3LteEIwiehl-G0KvtMQEWDNlkzz2/view?usp=sharing

Code can be found at github/smimesign@main...wlynch:cosign (still super hacky)

This doesn't solve the problem of additional source attestations (e.g. code review, etc.), but it does let us use keyless cosign with existing Git signing mechanisms today!

My plan is to add this to the cosign repo as a separate tool that can be installed similar to the existing smimesign (need naming ideas - smime-cosign?)

@dlorenc
Copy link
Member

dlorenc commented Apr 21, 2022

Does the x509 signing work with short lived certs, similar to ssh?

@lukehinds
Copy link
Member

I think this merits being its own tool, especially if our friends over at github could trust the sigstore chain and show it as verified.

These is no OCI interaction in this?

@wlynch
Copy link
Member

wlynch commented Apr 21, 2022

Does the x509 signing work with short lived certs, similar to ssh?

noob question: Is there a distinction between short-lived certs and the ephemeral certs issued by Fulcio?

If this is more "what happens if we verify a commit after a cert's NotAfter time?" then it depends. Obviously vanilla x509 validation won't work because the cert won't be considered valid, but the tool in the demo uses the tlog to verify the cert by doing something like-

  1. Verify the commit signature (ignoring NotAfter time)
  2. Check that the commit SHA exists in the tlog with a valid sig + cert as normal with cosign
  3. (not implemented) Check that the key used to sign the commit SHA is the same as the one used to sign the commit

There is also timestamp metadata separate from the commit timestamps embedded in the signature that might be useful to add further verification, though I haven't worked out how this might be useful yet given that it's still provided by the client.

@wlynch
Copy link
Member

wlynch commented Apr 21, 2022

These is no OCI interaction in this?

Nope! The commit signature is stored in the commit itself - what gets passed to the tool by Git for signing is basically everything else but the signature. The tool then computes what the resulting commit SHA will be, and uses the same signing key to populate a rekor entry using the commit SHA.

If you look in the code there's also an alt rekor entry being created that uses the raw data signature that's being stored in the commit itself, but one of the nice things I liked and wanted to preserve about Dan's original FUN.md was the ability to look up commits in the tlog with rekor-cli search --artifact <(git rev-parse HEAD | tr -d '\n').

@dlorenc
Copy link
Member

dlorenc commented Apr 21, 2022

I agree with Luke (and you I think), I'd get this hacked up as a working prototype standalone tool and then see where it makes sense to live after we see the rough scope.

@wlynch
Copy link
Member

wlynch commented May 3, 2022

Demoed at today's WG - an installable tool is available here to try out: https://github.com/wlynch/smimecosign

@wlynch
Copy link
Member

wlynch commented May 10, 2022

Following up on last week's demo - would there be interest in moving https://github.com/wlynch/smimecosign to a sigstore-owned repo (either it's own repo or another cmd under cosign?) 👀

cc @dlorenc @lukehinds @bobcallaway

@imjasonh
Copy link
Member

Following up on last week's demo - would there be interest in moving https://github.com/wlynch/smimecosign to a sigstore-owned repo (either it's own repo or another cmd under cosign?) 👀

cc @dlorenc @lukehinds @bobcallaway

I don't have a vote, but I'd have a slight preference for putting it in a separate repo, since it doesn't exactly have anything to do with cosign itself, as it's not signing containers.

Otherwise, +1 to having this live in the sigstore org.

@ojarjur
Copy link

ojarjur commented May 10, 2022

I don't have a vote, but I'd have a slight preference for putting it in a separate repo, since it doesn't exactly have anything to do with cosign itself, as it's not signing containers.

As an outside observer, I strongly agree with this recommendation.

It makes sense to be in the cosign org due to the dependencies on Rekor and Fulcio, but I would expect it to be installed by a lot of people who don't use cosign. As such, I would encourage you to make it its own top-level thing within the cosign org.

@imjasonh
Copy link
Member

It makes sense to be in the cosign org due to the dependencies on Rekor and Fulcio, but I would expect it to be installed by a lot of people who don't use cosign. As such, I would encourage you to make it its own top-level thing within the cosign org.

I think by "the cosign org" you mean "the sigstore org", which only highlights how much assigning synonymity to "cosign" and "sigstore" may lead to unnecessary confusion 😆

@wlynch
Copy link
Member

wlynch commented May 10, 2022

(fwiw also leaning towards a separate repo, but figured a different binary in the cosign repo similar to sget with its own module would also be okay if that was the preference)

Also open to any clever naming suggestions if anyone has any!

@imjasonh
Copy link
Member

(fwiw also leaning towards a separate repo, but figured a different binary in the cosign repo similar to sget with its own module would also be okay if that was the preference)

sget is also moving out of the cosign repo, into https://github.com/sigstore/sget, blocked on sigstore/sget#11 😄

@dlorenc
Copy link
Member

dlorenc commented May 10, 2022

+1 to a separate repo. If there's consensus to put it in the sigstore org, can you open a request over at the TAC repo? https://github.com/sigstore/tac

@lukehinds
Copy link
Member

separate sounds good to me, as Dan says , please raise a TAC issue and we can vote this Thursday (see community calender)

@mattmoor
Copy link
Member Author

Let's use: sigstore/gitsign#94 to track this work!

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

8 participants