From cee72e1b73ee20ac55b885a4f45fe20399a77187 Mon Sep 17 00:00:00 2001 From: Zachary Newman Date: Fri, 2 Sep 2022 20:51:19 -0400 Subject: [PATCH] Clarify error when KMS provider fails to load Before: $ KEY_REF=gcpkms://projects/test/locations/global/keyRings/test/cryptoKeys/mykey/cryptoKeyVersions/1 $ cosign verify-blob --key $KEY_REF --signature /dev/null /dev/null Error: verifying blob [/dev/null]: loading public key: loading URL: unrecognized scheme: gcpkms:// main.go:62: error during command execution: verifying blob [/dev/null]: loading public key: loading URL: unrecognized scheme: gcpkms:// After: $ KEY_REF=gcpkms://projects/test/locations/global/keyRings/test/cryptoKeys/mykey/cryptoKeyVersions/1 $ cosign verify-blob --key $KEY_REF --signature /dev/null /dev/null Error: verifying blob [/dev/null]: loading public key: new gcp kms client: google: could not find default credentials. See https://developers.google.com/accounts/docs/application-default-credentials for more information. main.go:62: error during command execution: verifying blob [/dev/null]: loading public key: new gcp kms client: google: could not find default credentials. See https://developers.google.com/accounts/docs/application-default-credentials for more information. Addresses #2094; I'm not sure if this fixes it, but it'll give us more information. Signed-off-by: Zachary Newman --- pkg/blob/load.go | 10 +++++++++- pkg/signature/keys.go | 12 +++++++++++- pkg/signature/keys_test.go | 27 +++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 2 deletions(-) diff --git a/pkg/blob/load.go b/pkg/blob/load.go index c92d49c4ca3..26db1367848 100644 --- a/pkg/blob/load.go +++ b/pkg/blob/load.go @@ -23,6 +23,14 @@ import ( "strings" ) +type UnrecognizedSchemeError struct { + Scheme string +} + +func (e *UnrecognizedSchemeError) Error() string { + return fmt.Sprintf("loading URL: unrecognized scheme: %s", e.Scheme) +} + func LoadFileOrURL(fileRef string) ([]byte, error) { var raw []byte var err error @@ -51,7 +59,7 @@ func LoadFileOrURL(fileRef string) ([]byte, error) { } raw = []byte(value) default: - return nil, fmt.Errorf("loading URL: unrecognized scheme: %s", scheme) + return nil, &UnrecognizedSchemeError{Scheme: scheme} } } else { raw, err = os.ReadFile(filepath.Clean(fileRef)) diff --git a/pkg/signature/keys.go b/pkg/signature/keys.go index 21f22ce5ef8..6c89d22b974 100644 --- a/pkg/signature/keys.go +++ b/pkg/signature/keys.go @@ -43,9 +43,19 @@ func LoadPublicKey(ctx context.Context, keyRef string) (verifier signature.Verif // verifier using the provided hash algorithm func VerifierForKeyRef(ctx context.Context, keyRef string, hashAlgorithm crypto.Hash) (verifier signature.Verifier, err error) { // The key could be plaintext, in a file, at a URL, or in KMS. - if kmsKey, err := kms.Get(ctx, keyRef, hashAlgorithm); err == nil { + var perr *kms.ProviderNotFoundError + kmsKey, err := kms.Get(ctx, keyRef, hashAlgorithm) + switch { + case err == nil: // KMS specified return kmsKey, nil + case errors.As(err, &perr): + // We can ignore ProviderNotFoundError; that just means the keyRef + // didn't match any of the KMS schemes. + default: + // But other errors indicate something more insidious; pass those + // through. + return nil, err } raw, err := blob.LoadFileOrURL(keyRef) diff --git a/pkg/signature/keys_test.go b/pkg/signature/keys_test.go index ef5600d104d..fc1ed81f18f 100644 --- a/pkg/signature/keys_test.go +++ b/pkg/signature/keys_test.go @@ -16,10 +16,15 @@ package signature import ( "context" + "crypto" + "errors" "os" "testing" + "github.com/sigstore/cosign/pkg/blob" "github.com/sigstore/cosign/pkg/cosign" + sigsignature "github.com/sigstore/sigstore/pkg/signature" + "github.com/sigstore/sigstore/pkg/signature/kms" ) func generateKeyFile(t *testing.T, tmpDir string, pf cosign.PassFunc) (privFile, pubFile string) { @@ -134,6 +139,28 @@ func TestSignerVerifierFromEnvVar(t *testing.T) { } } +func TestVerifierForKeyRefError(t *testing.T) { + kms.AddProvider("errorkms://", func(ctx context.Context, _ string, hf crypto.Hash, _ ...sigsignature.RPCOption) (kms.SignerVerifier, error) { + return nil, errors.New("bad") + }) + var uerr *blob.UnrecognizedSchemeError + + ctx := context.Background() + _, err := PublicKeyFromKeyRef(ctx, "errorkms://bad") + if err == nil { + t.Fatalf("PublicKeyFromKeyRef didn't return any error") + } else if errors.As(err, &uerr) { + t.Fatalf("PublicKeyFromKeyRef returned UnrecognizedSchemeError: %v", err) + } + + _, err = PublicKeyFromKeyRef(ctx, "badscheme://bad") + if err == nil { + t.Fatalf("PublicKeyFromKeyRef didn't return any error") + } else if !errors.As(err, &uerr) { + t.Fatalf("PublicKeyFromKeyRef didn't return UnrecognizedSchemeError: %v", err) + } +} + func pass(s string) cosign.PassFunc { return func(_ bool) ([]byte, error) { return []byte(s), nil