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

Attestation/Blob signing and verification using a RFC3161 time-stamping server #2464

Merged
merged 11 commits into from
Nov 23, 2022

Conversation

hectorj2f
Copy link
Contributor

@hectorj2f hectorj2f commented Nov 16, 2022

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.

$ cosign sign-blob --timestamp-server-url=http://localhost:5555 --key cosign.key README.md  --rfc3161-timestamp-bundle mytimestampbundle

$ cosign verify-blob --timestamp-cert-chain ts_chain.pem --key cosign.pub README.md --rfc3161-timestamp-bundle mytimestampbundle

Bundle format in case both verification mechanism are used (TSA and Rekor):

{
	"base64Signature": "xxxx/8tmKUTTOHLBTHn",
	"cert": "xx==",
	"rekorBundle": {
		"SignedEntryTimestamp": "xxx+T3qDZtg0=",
		"Payload": {
			"body": "xxxxxxx=",
			"integratedTime": 1,
			"logIndex": 1,
			"logID": "xxxxx"
		}
	},
	"rfc3161timestamp": {
		"SignedRFC3161Timestamp": "xxxx"
	}
}

A similar set of command flags are used for attestations:

$ cosign attest --predicate predicate --timestamp-server-url=http://localhost:5555 <YOUR_IMAGE> 

$ cosign verify-attestation --timestamp-cert-chain ts_chain.pem <YOUR_IMAGE>  --insecure-skip-tlog-verify

Release Note

Add support for signing/verification for attestations and blobs using a RFC3161 time-stamping server.

Documentation

@hectorj2f hectorj2f added the enhancement New feature or request label Nov 16, 2022
@hectorj2f hectorj2f self-assigned this Nov 16, 2022
@codecov-commenter
Copy link

codecov-commenter commented Nov 16, 2022

Codecov Report

Merging #2464 (3f6115b) into main (8f66577) will decrease coverage by 0.36%.
The diff coverage is 10.69%.

@@            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     
Impacted Files Coverage Δ
cmd/cosign/cli/attest.go 0.00% <0.00%> (ø)
cmd/cosign/cli/options/attest.go 0.00% <0.00%> (ø)
cmd/cosign/cli/options/policy.go 0.00% <0.00%> (ø)
cmd/cosign/cli/options/signblob.go 0.00% <0.00%> (ø)
cmd/cosign/cli/options/verify.go 0.00% <0.00%> (ø)
cmd/cosign/cli/policy_init.go 1.30% <0.00%> (-0.06%) ⬇️
cmd/cosign/cli/sign/sign.go 15.34% <0.00%> (ø)
cmd/cosign/cli/sign/sign_blob.go 0.00% <0.00%> (ø)
cmd/cosign/cli/signblob.go 0.00% <0.00%> (ø)
cmd/cosign/cli/verify.go 0.00% <0.00%> (ø)
... and 8 more

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

// 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
Copy link
Contributor

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

@asraa
Copy link
Contributor

asraa commented Nov 16, 2022

RE the open questions, I think they should be handled separately.

Can we supersede the logic changes in the verifyBlob inner call with the PR that combines the OCI logic?

@hectorj2f
Copy link
Contributor Author

I am pausing this work until #2461 gets merged!

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>
@hectorj2f hectorj2f changed the title Blob signing and verification using a RFC3161 time-stamping server Attestation/Blob signing and verification using a RFC3161 time-stamping server Nov 22, 2022
@hectorj2f hectorj2f marked this pull request as ready for review November 22, 2022 15:23
@hectorj2f
Copy link
Contributor Author

@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.

Copy link
Contributor

@priyawadhwa priyawadhwa left a 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.

cmd/cosign/cli/options/verify.go Show resolved Hide resolved
cmd/cosign/cli/sign/sign.go Show resolved Hide resolved
cmd/cosign/cli/sign/sign_blob.go Outdated Show resolved Hide resolved
cmd/cosign/cli/verify/verify_attestation.go Outdated Show resolved Hide resolved
Signed-off-by: Hector Fernandez <hector@chainguard.dev>
@haydentherapper
Copy link
Contributor

Cc @asraa

Signed-off-by: Hector Fernandez <hector@chainguard.dev>
Copy link
Contributor

@priyawadhwa priyawadhwa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm!

@priyawadhwa priyawadhwa merged commit 7e967e8 into sigstore:main Nov 23, 2022
@github-actions github-actions bot added this to the v1.14.0 milestone Nov 23, 2022
@hectorj2f hectorj2f deleted the blob_signing_with_tsa branch November 23, 2022 16:34
Copy link
Contributor

@haydentherapper haydentherapper left a 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")
Copy link
Contributor

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)
Copy link
Contributor

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))
Copy link
Contributor

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 != "" {
Copy link
Contributor

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)
Copy link
Contributor

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 {
Copy link
Contributor

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.
Copy link
Contributor

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 != "":
Copy link
Contributor

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?

Copy link
Contributor

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.

@haydentherapper
Copy link
Contributor

Follow up PR #2499

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

Successfully merging this pull request may close these issues.

5 participants