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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: Remove an extra registry request from verification path. #2285

Merged
merged 1 commit into from Sep 27, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
49 changes: 26 additions & 23 deletions pkg/cosign/verify.go
Expand Up @@ -118,19 +118,6 @@ type CheckOpts struct {
Identities []Identity
}

func getSignedEntity(signedImgRef name.Reference, regClientOpts []ociremote.Option) (oci.SignedEntity, v1.Hash, error) {
se, err := ociremote.SignedEntity(signedImgRef, regClientOpts...)
if err != nil {
return nil, v1.Hash{}, err
}
// Both of the SignedEntity types implement Digest()
h, err := se.(interface{ Digest() (v1.Hash, error) }).Digest()
if err != nil {
return nil, v1.Hash{}, err
}
return se, h, nil
}

func verifyOCISignature(ctx context.Context, verifier signature.Verifier, sig oci.Signature) error {
b64sig, err := sig.Base64Signature()
if err != nil {
Expand Down Expand Up @@ -427,17 +414,25 @@ func VerifyImageSignatures(ctx context.Context, signedImgRef name.Reference, co
return nil, false, errors.New("one of verifier or root certs is required")
}

// TODO(mattmoor): We could implement recursive verification if we just wrapped
// most of the logic below here in a call to mutate.Map
se, h, err := getSignedEntity(signedImgRef, co.RegistryClientOpts)
// This is a carefully optimized sequence for fetching the signatures of the
// entity that minimizes registry requests when supplied with a digest input
digest, err := ociremote.ResolveDigest(signedImgRef, co.RegistryClientOpts...)
if err != nil {
return nil, false, err
}
h, err := v1.NewHash(digest.Identifier())
if err != nil {
return nil, false, err
}

var sigs oci.Signatures
sigRef := co.SignatureRef
if sigRef == "" {
sigs, err = se.Signatures()
st, err := ociremote.SignatureTag(digest, co.RegistryClientOpts...)
if err != nil {
return nil, false, err
}
sigs, err = ociremote.Signatures(st, co.RegistryClientOpts...)
if err != nil {
return nil, false, err
}
Expand Down Expand Up @@ -625,22 +620,30 @@ func loadSignatureFromFile(sigRef string, signedImgRef name.Reference, co *Check
}, nil
}

// VerifyAttestations does all the main cosign checks in a loop, returning the verified attestations.
// VerifyImageAttestations does all the main cosign checks in a loop, returning the verified attestations.
// If there were no valid attestations, we return an error.
func VerifyImageAttestations(ctx context.Context, signedImgRef name.Reference, co *CheckOpts) (checkedAttestations []oci.Signature, bundleVerified bool, err error) {
// Enforce this up front.
if co.RootCerts == nil && co.SigVerifier == nil {
return nil, false, errors.New("one of verifier or root certs is required")
}

// TODO(mattmoor): We could implement recursive verification if we just wrapped
// most of the logic below here in a call to mutate.Map

se, h, err := getSignedEntity(signedImgRef, co.RegistryClientOpts)
// This is a carefully optimized sequence for fetching the attestations of
// the entity that minimizes registry requests when supplied with a digest
// input.
digest, err := ociremote.ResolveDigest(signedImgRef, co.RegistryClientOpts...)
if err != nil {
return nil, false, err
}
atts, err := se.Attestations()
h, err := v1.NewHash(digest.Identifier())
if err != nil {
return nil, false, err
}
st, err := ociremote.AttestationTag(digest, co.RegistryClientOpts...)
if err != nil {
return nil, false, err
}
atts, err := ociremote.Signatures(st, co.RegistryClientOpts...)
if err != nil {
return nil, false, err
}
Expand Down