-
Notifications
You must be signed in to change notification settings - Fork 537
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
Attestation/Blob signing and verification using a RFC3161 time-stamping server #2464
Conversation
Codecov Report
@@ Coverage Diff @@
## main #2464 +/- ##
==========================================
- Coverage 30.34% 29.98% -0.37%
==========================================
Files 139 139
Lines 8469 8605 +136
==========================================
+ Hits 2570 2580 +10
- Misses 5546 5666 +120
- Partials 353 359 +6
Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. |
cmd/cosign/cli/verify/verify_blob.go
Outdated
// b. We can make an online lookup to the transparency log since we don't have an entry. | ||
// b. We can make an online lookup to the transparency log since we don't have an entry. | ||
case tsaBundle != nil: | ||
// TODO: Verify TSA only and return the result with the tsa bundle |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you would need to set the validity time here
RE the open questions, I think they should be handled separately. Can we supersede the logic changes in the |
I am pausing this work until #2461 gets merged! |
e0982e6
to
d7a28bd
Compare
Signed-off-by: Hector Fernandez <hector@chainguard.dev>
Signed-off-by: Hector Fernandez <hector@chainguard.dev>
Signed-off-by: Hector Fernandez <hector@chainguard.dev>
Signed-off-by: Hector Fernandez <hector@chainguard.dev>
Signed-off-by: Hector Fernandez <hector@chainguard.dev>
Signed-off-by: Hector Fernandez <hector@chainguard.dev>
Signed-off-by: Hector Fernandez <hector@chainguard.dev>
Signed-off-by: Hector Fernandez <hector@chainguard.dev>
Signed-off-by: Hector Fernandez <hector@chainguard.dev>
d7a28bd
to
3f6115b
Compare
@priyawadhwa @haydentherapper This PR is ready for a review. I was planning to increase the test coverage and perhaps add this experimental flag/env var that we discussed, as part of future PRs. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tests look great! just a few comments.
Signed-off-by: Hector Fernandez <hector@chainguard.dev>
Cc @asraa |
Signed-off-by: Hector Fernandez <hector@chainguard.dev>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@hectorj2f Left some comments, happy to implement the changes if you are busy.
"url to the Timestamp RFC3161 server, default none") | ||
|
||
cmd.Flags().StringVar(&o.RFC3161TimestampPath, "rfc3161-timestamp-bundle", "", | ||
"write everything required to verify the blob to a FILE") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Description needs to be updated, this was copied from BundlePath.
return fmt.Errorf("failed to create TSA client: %w", err) | ||
} | ||
// Here we get the response from the timestamped authority server | ||
_, err = tsa.GetTimestampedSignature(signed.Signed, clientTSA) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit for style: if _, err := tsa.GetTimestampedSignature(...); err != nil { ... }
if err != nil { | ||
return nil, fmt.Errorf("failed to create TSA client: %w", err) | ||
} | ||
b64Sig := []byte(base64.StdEncoding.EncodeToString(sig)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we document somewhere that we're generating a timestamp over the base64 signature, not the raw bytes? This was somewhat discussed in sigstore/timestamp-authority#116 - Cosign is being opinionated in using the base64-encoded sig, which I agree with, just think we should be explicit about this.
Update the SPEC docs for the OCI annotations?
@@ -82,6 +98,20 @@ func SignBlobCmd(ro *options.RootOptions, ko options.KeyOpts, regOpts options.Re | |||
signedPayload.Bundle = cbundle.EntryToBundle(entry) | |||
} | |||
|
|||
// if bundle is specified, just do that and ignore the rest | |||
if ko.RFC3161TimestampPath != "" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we require that if ko.TSAServerURL
is set, ko.RFC3161TimestampPath
must also be? Otherwise it's unnecessarily fetching a timestamp without persisting it.
if ko.RFC3161TimestampPath != "" { | ||
signedPayload.Base64Signature = base64.StdEncoding.EncodeToString(sig) | ||
|
||
contents, err := json.Marshal(signedPayload) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this be writing signedPayload.RFC3161Timestamp
, not signedPayload.Base64Signature
?
@@ -72,16 +73,16 @@ func (c *VerifyBlobCmd) Exec(ctx context.Context, blobRef string) error { | |||
opts := make([]static.Option, 0) | |||
|
|||
// Require a certificate/key OR a local bundle file that has the cert. | |||
if options.NOf(c.KeyRef, c.CertRef, c.Sk, c.BundlePath) == 0 { | |||
return fmt.Errorf("please provide a cert to verify against via --certificate or a bundle via --bundle") | |||
if options.NOf(c.KeyRef, c.CertRef, c.Sk, c.BundlePath, c.RFC3161TimestampPath) == 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't seem correct, RFC3161TimestampPath
should contain a timestamp, not a code-signing certificate.
if err != nil { | ||
return err | ||
} | ||
// Note: RFC3161 timestamp does not set the certificate. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm confused by this, b.Cert
is always ""
, so isn't this never run?
@@ -273,6 +323,12 @@ func base64signature(sigRef string, bundlePath string) (string, error) { | |||
return "", err | |||
} | |||
targetSig = []byte(b.Base64Signature) | |||
case rfc3161TimestampPath != "": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left a comment above about this, but rfc3161TimestampPath
should be storing a timestamp, not a signature, correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Further, a 3161 timestamp should be in addition to the bundle, this makes it either/or.
Follow up PR #2499 |
Summary
This PR adds support for signing and verification for blobs/attestations using a RFC3161 time-stamping server. This PR assumes we can rely on two different bundles when signing by passing the flags
--rfc3161-timestamp-bundle
and the former--bundle
.Bundle format in case both verification mechanism are used (TSA and Rekor):
A similar set of command flags are used for attestations:
Release Note
Add support for signing/verification for attestations and blobs using a RFC3161 time-stamping server.
Documentation