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

verify: fetch rekor public keys before verification #2393

Merged
merged 7 commits into from
Dec 7, 2022

Conversation

asraa
Copy link
Contributor

@asraa asraa commented Oct 31, 2022

Signed-off-by: Asra Ali asraa@google.com

Removes calls to GetRekorPubs in pkg/. This fetches the rekor public keys before verification, making verification commands easier to test in other environments.

TODO: verify blob is currently all in cli/, so there are still some internal TUF calls there. TBD.

THIS SHOULD BE MERGED INTO A v2 BRANCH

@vaikas

Release note:

* feat!: Updates function signature for `cosign.GetRekorPubs` to remove unncessary `RekorClient` parameter.
* feat: Adds a field `RekorPubKeys` in `CheckOpts` that configured the trusted rekor public keys needed for verifying tlog entries. This may be populated with the public TUF instance using `cosign.GetRekorPubs`.
* breaking change: Updates function signatures for `VerifyTLogEntry` and `VerifyBundle` to take a map of trusted Rekor public keys to verify against. This may be populated with the public TUF instance using `cosign.GetRekorPubs`.

Summary

Release Note

Documentation

vaikas
vaikas previously approved these changes Oct 31, 2022
Copy link
Contributor

@vaikas vaikas left a comment

Choose a reason for hiding this comment

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

Thank you so much!! Looking so much lovelier with this refactor :)

pkg/cosign/tlog.go Outdated Show resolved Hide resolved
@@ -138,6 +138,27 @@ func GetRekorPubs(ctx context.Context, _ *client.Rekor) (map[string]RekorPubKey,
return publicKeys, nil
}

// rekorPubsFromClient returns a RekorPubKey keyed by the log ID from the Rekor client.
// NOTE: This should **not** be used in the verification path, but may be used in the
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: 'should not' or 'must not'? I'm just curious with the emphasis on the not, if we should just make it a strong statement to avoid misuse?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

must not, IMO. Yeah: I made this a private func on purpose so that users wouldn't be able to do this (but on the other hand, it would be useful for testing with a custom Rekor). updated the comment.

if err != nil {
return nil, fmt.Errorf("unable to fetch rekor public key from rekor: %w", err)
}
pubFromAPI, err := PemToECDSAKey([]byte(pubOK.Payload))
Copy link
Contributor

Choose a reason for hiding this comment

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

this is just like L103-111, wondering if that could be hoisted out to a function that we can tell call from here (and hopefully remove the ENV stuff from GetRekorPubs but do the equivalent call to it from 'cli' portion instead). I assume at least that would be desirable?
We can do it in a follow up, but just curious if that even makes sense?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

addressed in commit, but only to factor out the logic and make it easier to construct a map of trusted rekor pub keys outside TUF

pkg/cosign/verify.go Show resolved Hide resolved
Copy link
Contributor

@znewman01 znewman01 left a comment

Choose a reason for hiding this comment

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

+1 to Ville's comments, LGTM otherwise

pkg/cosign/tlog.go Outdated Show resolved Hide resolved
pkg/cosign/verify.go Show resolved Hide resolved
@priyawadhwa
Copy link
Contributor

@asraa we decided to branch off 1.0 into the 1.0-fork branch, so you can merge this into main whenever you're ready!

@asraa
Copy link
Contributor Author

asraa commented Nov 1, 2022

Addressed comments, let me know if there's more

@codecov-commenter
Copy link

codecov-commenter commented Nov 1, 2022

Codecov Report

Merging #2393 (d4550bd) into main (5d00b1f) will increase coverage by 0.18%.
The diff coverage is 33.33%.

@@            Coverage Diff             @@
##             main    #2393      +/-   ##
==========================================
+ Coverage   29.98%   30.16%   +0.18%     
==========================================
  Files         139      139              
  Lines        8552     8583      +31     
==========================================
+ Hits         2564     2589      +25     
+ Misses       5633     5621      -12     
- Partials      355      373      +18     
Impacted Files Coverage Δ
cmd/cosign/cli/verify/verify.go 19.36% <0.00%> (-0.38%) ⬇️
cmd/cosign/cli/verify/verify_attestation.go 0.00% <0.00%> (ø)
pkg/cosign/tlog.go 38.43% <34.14%> (-2.74%) ⬇️
cmd/cosign/cli/verify/verify_blob.go 49.56% <50.00%> (+0.01%) ⬆️
pkg/cosign/verify.go 41.65% <60.00%> (+2.92%) ⬆️

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

Copy link
Contributor

@vaikas vaikas left a comment

Choose a reason for hiding this comment

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

Awesomesauce! Just couple of lint warnings about names and from my pov it's good to go.

pkg/cosign/tlog.go Show resolved Hide resolved
pkg/cosign/verify_test.go Outdated Show resolved Hide resolved
pkg/cosign/tlog.go Outdated Show resolved Hide resolved
pkg/cosign/tlog.go Outdated Show resolved Hide resolved
pkg/cosign/tlog.go Outdated Show resolved Hide resolved
vaikas
vaikas previously approved these changes Nov 1, 2022
Copy link
Contributor

@vaikas vaikas left a comment

Choose a reason for hiding this comment

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

Thank you!!!

znewman01
znewman01 previously approved these changes Nov 1, 2022
Copy link
Contributor

@znewman01 znewman01 left a comment

Choose a reason for hiding this comment

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

This LGTM. Is there a code path we can hit for online verification?

@asraa
Copy link
Contributor Author

asraa commented Nov 1, 2022

Is there a code path we can hit for online verification?

What do you mean? I'm not sure it's relevant for this PR. We're discussing the design for the necessary flags/behavior here: https://docs.google.com/document/d/1E-cB0OdABTi4BXnRV9oBzdbUgRk3cJ-jw0E5KGE3Eiw/edit?resourcekey=0-TCQAQ1H_pAiRzC7avDt1LA#

@znewman01
Copy link
Contributor

Is there a code path we can hit for online verification?

What do you mean? I'm not sure it's relevant for this PR. We're discussing the design for the necessary flags/behavior here: https://docs.google.com/document/d/1E-cB0OdABTi4BXnRV9oBzdbUgRk3cJ-jw0E5KGE3Eiw/edit?resourcekey=0-TCQAQ1H_pAiRzC7avDt1LA#

I think what I mean is VerifyTlogEntry now doesn't take a RekorClient. What's my entry point in pkg/cosign/verify.go if I want to do online verification? I guess...FindTlogEntry? That feels very manual, I would like a Verify*() call instead.

But agreed it's not super relevant for this PR, I was just wondering because now there's no RekorClient getting passed in

@asraa
Copy link
Contributor Author

asraa commented Nov 2, 2022

I was just wondering because now there's no RekorClient getting passed in

You already have all the online data inside the tlog entry to do the validation. This is verifying the already fetched TLOG ENTRY, not performing a lookup. This is just the verification portion, which does internally validate the provided inclusion proof.

You're right though that the cosign API is unclear. :)

because now there's no RekorClient getting passed in

This was never used to fetch the inclusion proof. If anything it makes it more clear that the args supply the entry itself. This was INSECURELY used previously to fetch the public key.

@asraa
Copy link
Contributor Author

asraa commented Nov 2, 2022

I can't repro the failure locally :| Still trying

@asraa
Copy link
Contributor Author

asraa commented Nov 2, 2022

@priyawadhwa @vaikas Do either of you know if there's a difference in the environments running ./test/e2e_test.sh locally or on CI? https://github.com/sigstore/cosign/actions/runs/3373442220/workflow#L123

In CI we set up scaffolding first, but either way the tests run in test/e2e_test.go use the public Rekor: https://github.com/sigstore/cosign/blob/main/test/e2e_test.go#L73

Unless somehow they're not. If they're using the public Rekor (and it is on my laptop, since I printed the log ID of the failing bundle), then I wouldn't need to customize the trust root. However, on CI it fails saying the trust root has no matching Rekor keys.

@asraa
Copy link
Contributor Author

asraa commented Nov 2, 2022

However, on CI it fails saying the trust root has no matching Rekor keys.

I think @loosebazooka helped deduce that CI must be running with the local scaffolding .sigstore and root of trust. I have no idea how this test was working before then.

@asraa
Copy link
Contributor Author

asraa commented Nov 2, 2022

Resolved: the problem was that this test didn't add TUF root public keys because it's not a keyless verification. I added a TODO. We'll have this resolved when we have the online proof option for checking existing PKI log entries.

@github-actions
Copy link

github-actions bot commented Dec 3, 2022

This PR is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 10 days.

@vaikas
Copy link
Contributor

vaikas commented Dec 5, 2022

Looks like there was some flakiness checking out the repo, retrying.

Copy link
Contributor

@znewman01 znewman01 left a comment

Choose a reason for hiding this comment

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

seems fine to me, couple final nits

@@ -159,6 +159,11 @@ func (c *VerifyCommand) Exec(ctx context.Context, images []string) (err error) {
return fmt.Errorf("getting Fulcio intermediates: %w", err)
}
}
// TODO: We only need this when we are doing online verification.
Copy link
Contributor

Choose a reason for hiding this comment

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

Hm, I would really prefer to turn this off by default before merge as this might break otherwise-offline flows.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh, updating the comment that was incorrect. This is needed for offline verification as well. You still need the rekor pubkeys to verify an offline bundle.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I can gate it with --skip-tlog-verify though.

cmd/cosign/cli/verify/verify_attestation.go Outdated Show resolved Hide resolved
// rekorPubsFromClient returns a RekorPubKey keyed by the log ID from the Rekor client.
// NOTE: This **must not** be used in the verification path, but may be used in the
// sign path to validate return responses are consistent from Rekor.
func rekorPubsFromClient(rekorClient *client.Rekor) (*TrustedRekorPubKeys, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Does the benefits of having this outweigh the risks that it'll be used inappropriately?

The alternative involves a real TUF root, which IMO we should want anyway even for signing. I think the post-sign verification should be identical to typical verification in every way.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's a private function though, so I'm not sure it's that "risky". I think it's pretty clear it's retrieving the rekor pub from the rekor client.

Plumbing a TUF root into the sign path is somewhat difficult. I can file a TODO follow-up, but it really requires changing a lot more than what's here.

Copy link
Contributor

Choose a reason for hiding this comment

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

Great, TODO SGTM

Copy link
Contributor

Choose a reason for hiding this comment

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

It's also worth considering that this now doubles the amount of traffic to Rekor from Cosign. Is this needed, or can we add a follow up to plumb through TUF to verify the response?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There's a follow-up issue posted. I can get to it after the attestation support :/
it doesn't really double, but I get that it's an extra call on the sign path.

pkg/cosign/tlog.go Outdated Show resolved Hide resolved
@asraa
Copy link
Contributor Author

asraa commented Dec 6, 2022

Looking at some e2e test failures:

2022-12-06T15:16:31.6270119Z     e2e_test.go:161: no matching signatures:
2022-12-06T15:16:31.6271235Z         searching log query: [POST /api/v1/log/entries/retrieve][404] searchLogQuery default  &{Code:404 Message:no responses found}

Copy link
Contributor

@znewman01 znewman01 left a comment

Choose a reason for hiding this comment

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

lgtm other than test failures

@asraa
Copy link
Contributor Author

asraa commented Dec 6, 2022

lgtm other than test failures

Yep -- Hayden alerted me that it was the SkipTlog issues, they're in #2505 too, that I can rebase on

Signed-off-by: Asra Ali <asraa@google.com>

update

Signed-off-by: Asra Ali <asraa@google.com>

lint

Signed-off-by: Asra Ali <asraa@google.com>
Signed-off-by: Asra Ali <asraa@google.com>
Signed-off-by: Asra Ali <asraa@google.com>
Signed-off-by: Asra Ali <asraa@google.com>
Signed-off-by: Asra Ali <asraa@google.com>
Signed-off-by: Asra Ali <asraa@google.com>
znewman01
znewman01 previously approved these changes Dec 7, 2022
Signed-off-by: Asra Ali <asraa@google.com>
@asraa asraa merged commit 7813599 into sigstore:main Dec 7, 2022
@github-actions github-actions bot added this to the v1.14.0 milestone Dec 7, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants