From ae7da7397e71a2834906aec766677416559a8df3 Mon Sep 17 00:00:00 2001 From: junczhu Date: Thu, 23 Nov 2023 19:27:58 +0000 Subject: [PATCH 01/38] feat: enable showing verifier name --- pkg/verifier/factory/factory.go | 16 ++++++++-------- pkg/verifier/notation/notation.go | 21 ++++++++++++++------- pkg/verifier/plugin/plugin.go | 12 +++++++++++- pkg/verifier/types/types.go | 1 + 4 files changed, 34 insertions(+), 16 deletions(-) diff --git a/pkg/verifier/factory/factory.go b/pkg/verifier/factory/factory.go index d97bedb8a..1b930ee95 100644 --- a/pkg/verifier/factory/factory.go +++ b/pkg/verifier/factory/factory.go @@ -52,14 +52,14 @@ func Register(name string, factory VerifierFactory) { // returns a single verifier from a verifierConfig // namespace is only applicable in K8s environment, namespace is appended to the certstore of the truststore so it is uniquely identifiable in a cluster env func CreateVerifierFromConfig(verifierConfig config.VerifierConfig, configVersion string, pluginBinDir []string, namespace string) (verifier.ReferenceVerifier, error) { - verifierName, ok := verifierConfig[types.Name] + verifierSpecName, ok := verifierConfig[types.SpecName] if !ok { return nil, re.ErrorCodeConfigInvalid.WithComponentType(re.Verifier).WithDetail(fmt.Sprintf("failed to find verifier name in the verifier config with key %s", "name")) } - verifierNameStr := fmt.Sprintf("%s", verifierName) - if strings.ContainsRune(verifierNameStr, os.PathSeparator) { - return nil, re.ErrorCodeConfigInvalid.WithComponentType(re.Verifier).WithDetail(fmt.Sprintf("invalid plugin name for a verifier: %s", verifierNameStr)) + verifierTypeStr := fmt.Sprintf("%s", verifierSpecName) + if strings.ContainsRune(verifierTypeStr, os.PathSeparator) { + return nil, re.ErrorCodeConfigInvalid.WithComponentType(re.Verifier).WithDetail(fmt.Sprintf("invalid plugin name for a verifier: %s", verifierTypeStr)) } // if source is specified, download the plugin @@ -70,18 +70,18 @@ func CreateVerifierFromConfig(verifierConfig config.VerifierConfig, configVersio return nil, re.ErrorCodeConfigInvalid.NewError(re.Verifier, "", re.EmptyLink, err, "failed to parse plugin source", re.HideStackTrace) } - targetPath := path.Join(pluginBinDir[0], verifierNameStr) + targetPath := path.Join(pluginBinDir[0], verifierTypeStr) err = pluginCommon.DownloadPlugin(source, targetPath) if err != nil { return nil, re.ErrorCodeDownloadPluginFailure.NewError(re.Verifier, "", re.EmptyLink, err, "failed to download plugin", re.HideStackTrace) } - logrus.Infof("downloaded verifier plugin %s from %s to %s", verifierNameStr, source.Artifact, targetPath) + logrus.Infof("downloaded verifier plugin type %s from %s to %s", verifierTypeStr, source.Artifact, targetPath) } else { - logrus.Warnf("%s was specified for verifier plugin %s, but dynamic plugins are currently disabled", types.Source, verifierNameStr) + logrus.Warnf("%s was specified for verifier plugin type %s, but dynamic plugins are currently disabled", types.Source, verifierTypeStr) } } - verifierFactory, ok := builtInVerifiers[verifierNameStr] + verifierFactory, ok := builtInVerifiers[verifierTypeStr] if ok { return verifierFactory.Create(configVersion, verifierConfig, pluginBinDir[0], namespace) } diff --git a/pkg/verifier/notation/notation.go b/pkg/verifier/notation/notation.go index 4f2e808d2..941578e6a 100644 --- a/pkg/verifier/notation/notation.go +++ b/pkg/verifier/notation/notation.go @@ -34,6 +34,7 @@ import ( "github.com/deislabs/ratify/pkg/verifier" "github.com/deislabs/ratify/pkg/verifier/config" "github.com/deislabs/ratify/pkg/verifier/factory" + "github.com/deislabs/ratify/pkg/verifier/types" "github.com/notaryproject/notation-go/log" _ "github.com/notaryproject/notation-core-go/signature/cose" // register COSE signature @@ -45,8 +46,8 @@ import ( ) const ( - verifierName = "notation" - defaultCertPath = "ratify-certs/notation/truststore" + verifierSpecName = "notation" + defaultCertPath = "ratify-certs/notation/truststore" ) // NotationPluginVerifierConfig describes the configuration of notation verifier @@ -63,6 +64,8 @@ type NotationPluginVerifierConfig struct { //nolint:revive // ignore linter to h } type notationPluginVerifier struct { + name string + specName string artifactTypes []string notationVerifier *notation.Verifier } @@ -70,11 +73,12 @@ type notationPluginVerifier struct { type notationPluginVerifierFactory struct{} func init() { - factory.Register(verifierName, ¬ationPluginVerifierFactory{}) + factory.Register(verifierSpecName, ¬ationPluginVerifierFactory{}) } func (f *notationPluginVerifierFactory) Create(_ string, verifierConfig config.VerifierConfig, pluginDirectory string, namespace string) (verifier.ReferenceVerifier, error) { logger.GetLogger(context.Background(), logOpt).Debugf("creating notation with config %v, namespace '%v'", verifierConfig, namespace) + verifierName := verifierConfig[types.Name].(string) conf, err := parseVerifierConfig(verifierConfig, namespace) if err != nil { return nil, re.ErrorCodeConfigInvalid.WithComponentType(re.Verifier).WithPluginName(verifierName) @@ -87,13 +91,15 @@ func (f *notationPluginVerifierFactory) Create(_ string, verifierConfig config.V artifactTypes := strings.Split(conf.ArtifactTypes, ",") return ¬ationPluginVerifier{ + name: verifierName, + specName: verifierSpecName, artifactTypes: artifactTypes, notationVerifier: &verfiyService, }, nil } func (v *notationPluginVerifier) Name() string { - return verifierName + return v.name } func (v *notationPluginVerifier) CanVerify(_ context.Context, referenceDescriptor ocispecs.ReferenceDescriptor) bool { @@ -122,7 +128,7 @@ func (v *notationPluginVerifier) Verify(ctx context.Context, } if len(referenceManifest.Blobs) == 0 { - return verifier.VerifierResult{IsSuccess: false}, re.ErrorCodeSignatureNotFound.NewError(re.Verifier, verifierName, re.EmptyLink, nil, fmt.Sprintf("no signature content found for referrer: %s@%s", subjectReference.Path, referenceDescriptor.Digest.String()), re.HideStackTrace) + return verifier.VerifierResult{IsSuccess: false}, re.ErrorCodeSignatureNotFound.NewError(re.Verifier, v.name, re.EmptyLink, nil, fmt.Sprintf("no signature content found for referrer: %s@%s", subjectReference.Path, referenceDescriptor.Digest.String()), re.HideStackTrace) } for _, blobDesc := range referenceManifest.Blobs { @@ -136,7 +142,7 @@ func (v *notationPluginVerifier) Verify(ctx context.Context, subjectRef := fmt.Sprintf("%s@%s", subjectReference.Path, subjectReference.Digest.String()) outcome, err := v.verifySignature(ctx, subjectRef, blobDesc.MediaType, subjectDesc.Descriptor, refBlob) if err != nil { - return verifier.VerifierResult{IsSuccess: false, Extensions: extensions}, re.ErrorCodeVerifyPluginFailure.NewError(re.Verifier, verifierName, re.NotationTsgLink, err, "failed to verify signature of digest", re.HideStackTrace) + return verifier.VerifierResult{IsSuccess: false, Extensions: extensions}, re.ErrorCodeVerifyPluginFailure.NewError(re.Verifier, v.name, re.NotationTsgLink, err, "failed to verify signature of digest", re.HideStackTrace) } // Note: notation verifier already validates certificate chain is not empty. @@ -146,7 +152,7 @@ func (v *notationPluginVerifier) Verify(ctx context.Context, } return verifier.VerifierResult{ - Name: verifierName, + Name: v.name, IsSuccess: true, Message: "signature verification success", Extensions: extensions, @@ -173,6 +179,7 @@ func (v *notationPluginVerifier) verifySignature(ctx context.Context, subjectRef } func parseVerifierConfig(verifierConfig config.VerifierConfig, namespace string) (*NotationPluginVerifierConfig, error) { + verifierName := verifierConfig[types.Name].(string) conf := &NotationPluginVerifierConfig{} verifierConfigBytes, err := json.Marshal(verifierConfig) diff --git a/pkg/verifier/plugin/plugin.go b/pkg/verifier/plugin/plugin.go index 3ecaf1821..b6f20f4b5 100644 --- a/pkg/verifier/plugin/plugin.go +++ b/pkg/verifier/plugin/plugin.go @@ -36,6 +36,7 @@ import ( // VerifierPlugin describes a verifier that is implemented by invoking the plugins type VerifierPlugin struct { name string + specName string artifactTypes []string nestedReferences []string version string @@ -51,6 +52,11 @@ func NewVerifier(version string, verifierConfig config.VerifierConfig, pluginPat return nil, re.ErrorCodeConfigInvalid.WithDetail(fmt.Sprintf("failed to find verifier name in the verifier config with key: %s", types.Name)) } + verifierSpecName, ok := verifierConfig[types.SpecName] + if !ok { + verifierSpecName = verifierName + } + var nestedReferences []string if vs, ok := verifierConfig[types.NestedReferences]; ok { nestedReferences = strings.Split(fmt.Sprintf("%s", vs), ",") @@ -67,6 +73,7 @@ func NewVerifier(version string, verifierConfig config.VerifierConfig, pluginPat return &VerifierPlugin{ name: fmt.Sprintf("%s", verifierName), + specName: fmt.Sprintf("%s", verifierSpecName), version: version, path: pluginPaths, rawConfig: verifierConfig, @@ -107,7 +114,10 @@ func (vp *VerifierPlugin) verifyReference( subjectReference common.Reference, referenceDescriptor ocispecs.ReferenceDescriptor, referrerStoreConfig *rc.StoreConfig) (*verifier.VerifierResult, error) { - pluginPath, err := vp.executor.FindInPaths(vp.name, vp.path) + if vp.specName == "" { + vp.specName = vp.name + } + pluginPath, err := vp.executor.FindInPaths(vp.specName, vp.path) if err != nil { return nil, re.ErrorCodePluginNotFound.NewError(re.Verifier, vp.name, re.EmptyLink, err, nil, re.HideStackTrace) } diff --git a/pkg/verifier/types/types.go b/pkg/verifier/types/types.go index 65fe199e0..25cdb50da 100644 --- a/pkg/verifier/types/types.go +++ b/pkg/verifier/types/types.go @@ -26,6 +26,7 @@ const ( SpecVersion string = "0.1.0" Version string = "version" Name string = "name" + SpecName string = "specName" ArtifactTypes string = "artifactTypes" NestedReferences string = "nestedReferences" Source string = "source" From 6e96827740eafb62e0753e65636dbdfc9042a87c Mon Sep 17 00:00:00 2001 From: junczhu Date: Thu, 23 Nov 2023 19:51:02 +0000 Subject: [PATCH 02/38] feat: enable showing verifier name 2 --- pkg/controllers/verifier_controller.go | 5 +++-- pkg/verifier/plugin/plugin.go | 5 +---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/pkg/controllers/verifier_controller.go b/pkg/controllers/verifier_controller.go index c6525dba1..9000b450b 100644 --- a/pkg/controllers/verifier_controller.go +++ b/pkg/controllers/verifier_controller.go @@ -98,7 +98,8 @@ func (r *VerifierReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c // creates a verifier reference from CRD spec and add store to map func verifierAddOrReplace(spec configv1beta1.VerifierSpec, objectName string, namespace string) error { verifierConfig, err := specToVerifierConfig(spec) - + // add verifier name to verifier config + verifierConfig[types.Name] = objectName if err != nil { logrus.Error(err, "unable to convert crd specification to verifier config") return fmt.Errorf("unable to convert crd specification to verifier config, err: %w", err) @@ -139,7 +140,7 @@ func specToVerifierConfig(verifierSpec configv1beta1.VerifierSpec) (vc.VerifierC } } - verifierConfig[types.Name] = verifierSpec.Name + verifierConfig[types.SpecName] = verifierSpec.Name verifierConfig[types.ArtifactTypes] = verifierSpec.ArtifactTypes if verifierSpec.Source != nil { verifierConfig[types.Source] = verifierSpec.Source diff --git a/pkg/verifier/plugin/plugin.go b/pkg/verifier/plugin/plugin.go index b6f20f4b5..0132fb81a 100644 --- a/pkg/verifier/plugin/plugin.go +++ b/pkg/verifier/plugin/plugin.go @@ -54,7 +54,7 @@ func NewVerifier(version string, verifierConfig config.VerifierConfig, pluginPat verifierSpecName, ok := verifierConfig[types.SpecName] if !ok { - verifierSpecName = verifierName + return nil, re.ErrorCodeConfigInvalid.WithDetail(fmt.Sprintf("failed to find verifier spec name in the verifier config with key: %s", types.SpecName)) } var nestedReferences []string @@ -114,9 +114,6 @@ func (vp *VerifierPlugin) verifyReference( subjectReference common.Reference, referenceDescriptor ocispecs.ReferenceDescriptor, referrerStoreConfig *rc.StoreConfig) (*verifier.VerifierResult, error) { - if vp.specName == "" { - vp.specName = vp.name - } pluginPath, err := vp.executor.FindInPaths(vp.specName, vp.path) if err != nil { return nil, re.ErrorCodePluginNotFound.NewError(re.Verifier, vp.name, re.EmptyLink, err, nil, re.HideStackTrace) From 2387b5b8f2ce5d290397f00e92515fc8389fee44 Mon Sep 17 00:00:00 2001 From: junczhu Date: Thu, 23 Nov 2023 20:57:01 +0000 Subject: [PATCH 03/38] feat: enable showing verifier name related ut --- pkg/verifier/factory/factory_test.go | 10 ++++++---- pkg/verifier/notation/notation_test.go | 24 ++++++++++++++++++++---- pkg/verifier/plugin/plugin_test.go | 1 + 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/pkg/verifier/factory/factory_test.go b/pkg/verifier/factory/factory_test.go index 6058a0a2f..cc1e99d5f 100644 --- a/pkg/verifier/factory/factory_test.go +++ b/pkg/verifier/factory/factory_test.go @@ -63,7 +63,8 @@ func TestCreateVerifiersFromConfig_BuiltInVerifiers_ReturnsExpected(t *testing.T } verifierConfig := map[string]interface{}{ - "name": "test-verifier", + "name": "test-verifier-0", + "specName": "test-verifier", } verifiersConfig := config.VerifiersConfig{ Verifiers: []config.VerifierConfig{verifierConfig}, @@ -79,8 +80,8 @@ func TestCreateVerifiersFromConfig_BuiltInVerifiers_ReturnsExpected(t *testing.T t.Fatalf("expected to have %d verifiers, actual count %d", 1, len(verifiers)) } - if verifiers[0].Name() != "test-verifier" { - t.Fatalf("expected to create test verifier") + if verifiers[0].Name() != "test-verifier-0" { + t.Fatalf("expected to create test verifier-0 for test case") } if _, ok := verifiers[0].(*plugin.VerifierPlugin); ok { @@ -98,7 +99,8 @@ func TestCreateVerifiersFromConfig_BuiltInVerifiers_ReturnsExpected(t *testing.T func TestCreateVerifiersFromConfig_PluginVerifiers_ReturnsExpected(t *testing.T) { verifierConfig := map[string]interface{}{ - "name": "plugin-verifier", + "name": "plugin-verifier-0", + "specName": "plugin-verifier", } verifiersConfig := config.VerifiersConfig{ Verifiers: []config.VerifierConfig{verifierConfig}, diff --git a/pkg/verifier/notation/notation_test.go b/pkg/verifier/notation/notation_test.go index d7eb7fce9..788457158 100644 --- a/pkg/verifier/notation/notation_test.go +++ b/pkg/verifier/notation/notation_test.go @@ -16,6 +16,8 @@ import ( "github.com/deislabs/ratify/pkg/referrerstore" "github.com/deislabs/ratify/pkg/referrerstore/config" "github.com/deislabs/ratify/pkg/verifier" + vc "github.com/deislabs/ratify/pkg/verifier/config" + "github.com/deislabs/ratify/pkg/verifier/factory" sig "github.com/notaryproject/notation-core-go/signature" "github.com/notaryproject/notation-go" "github.com/opencontainers/go-digest" @@ -130,11 +132,25 @@ func (s mockStore) GetSubjectDescriptor(_ context.Context, _ common.Reference) ( } func TestName(t *testing.T) { - v := ¬ationPluginVerifier{} - name := v.Name() + verifierConfig0 := map[string]interface{}{ + "name": "notation-verifier-0", + "specName": "notation", + } + verifierConfig1 := map[string]interface{}{ + "name": "notation-verifier-1", + "specName": "notation", + } + verifiersConfig := vc.VerifiersConfig{ + Verifiers: []vc.VerifierConfig{verifierConfig0, verifierConfig1}, + } + verifiers, err := factory.CreateVerifiersFromConfig(verifiersConfig, "", "") + if err != nil { + t.Fatalf("create verifiers failed with err %v", err) + } + name0 := verifiers[0].Name() - if name != "notation" { - t.Fatalf("expect name: notation, got: %s", name) + if name0 != "notation-verifier-0" { + t.Fatalf("expect name: notation-verifier-0, got: %s", name0) } } diff --git a/pkg/verifier/plugin/plugin_test.go b/pkg/verifier/plugin/plugin_test.go index 222f4cb76..a93b4b77f 100644 --- a/pkg/verifier/plugin/plugin_test.go +++ b/pkg/verifier/plugin/plugin_test.go @@ -46,6 +46,7 @@ func (e *TestExecutor) FindInPaths(plugin string, paths []string) (string, error func TestNewVerifier_Expected(t *testing.T) { verifierConfig := map[string]interface{}{ "name": "test-verifier", + "specName": "test-verifier", "artifactTypes": "test1,test2", "nestedReferences": "ref1,ref2", } From dcee0b29f1c4d41bf121aa9f832e0ef2a2fdb9cf Mon Sep 17 00:00:00 2001 From: junczhu Date: Thu, 23 Nov 2023 21:39:24 +0000 Subject: [PATCH 04/38] feat: enable showing verifier name related ut2 --- pkg/verifier/factory/factory_test.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pkg/verifier/factory/factory_test.go b/pkg/verifier/factory/factory_test.go index cc1e99d5f..c1b0dc8fe 100644 --- a/pkg/verifier/factory/factory_test.go +++ b/pkg/verifier/factory/factory_test.go @@ -35,7 +35,7 @@ type TestVerifier struct { type TestVerifierFactory struct{} func (s *TestVerifier) Name() string { - return "test-verifier" + return "test-verifier-0" } func (s *TestVerifier) CanVerify(_ context.Context, _ ocispecs.ReferenceDescriptor) bool { @@ -80,8 +80,8 @@ func TestCreateVerifiersFromConfig_BuiltInVerifiers_ReturnsExpected(t *testing.T t.Fatalf("expected to have %d verifiers, actual count %d", 1, len(verifiers)) } - if verifiers[0].Name() != "test-verifier-0" { - t.Fatalf("expected to create test verifier-0 for test case") + if nameResult := verifiers[0].Name(); nameResult != "test-verifier-0" { + t.Fatalf("expected to create test-verifier-0 for test case but got %v", nameResult) } if _, ok := verifiers[0].(*plugin.VerifierPlugin); ok { @@ -116,8 +116,8 @@ func TestCreateVerifiersFromConfig_PluginVerifiers_ReturnsExpected(t *testing.T) t.Fatalf("expected to have %d verifiers, actual count %d", 1, len(verifiers)) } - if verifiers[0].Name() != "plugin-verifier" { - t.Fatalf("expected to create plugin verifier") + if verifiers[0].Name() != "plugin-verifier-0" { + t.Fatalf("expected to create plugin-verifier-0") } if _, ok := verifiers[0].(*plugin.VerifierPlugin); !ok { From e46748cda0970a7aa45abb00601e463b6679a75c Mon Sep 17 00:00:00 2001 From: junczhu Date: Thu, 23 Nov 2023 21:56:59 +0000 Subject: [PATCH 05/38] feat: enable showing verifier name related ut3 --- pkg/verifier/notation/notation_test.go | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/pkg/verifier/notation/notation_test.go b/pkg/verifier/notation/notation_test.go index 788457158..43860fbbe 100644 --- a/pkg/verifier/notation/notation_test.go +++ b/pkg/verifier/notation/notation_test.go @@ -16,8 +16,6 @@ import ( "github.com/deislabs/ratify/pkg/referrerstore" "github.com/deislabs/ratify/pkg/referrerstore/config" "github.com/deislabs/ratify/pkg/verifier" - vc "github.com/deislabs/ratify/pkg/verifier/config" - "github.com/deislabs/ratify/pkg/verifier/factory" sig "github.com/notaryproject/notation-core-go/signature" "github.com/notaryproject/notation-go" "github.com/opencontainers/go-digest" @@ -132,25 +130,18 @@ func (s mockStore) GetSubjectDescriptor(_ context.Context, _ common.Reference) ( } func TestName(t *testing.T) { - verifierConfig0 := map[string]interface{}{ + verifierConfig := map[string]interface{}{ "name": "notation-verifier-0", "specName": "notation", } - verifierConfig1 := map[string]interface{}{ - "name": "notation-verifier-1", - "specName": "notation", - } - verifiersConfig := vc.VerifiersConfig{ - Verifiers: []vc.VerifierConfig{verifierConfig0, verifierConfig1}, - } - verifiers, err := factory.CreateVerifiersFromConfig(verifiersConfig, "", "") + + f := ¬ationPluginVerifierFactory{} + verifier, err := f.Create(testVersion, verifierConfig, "", "") if err != nil { - t.Fatalf("create verifiers failed with err %v", err) + t.Fatalf("failed create notation verifier got error = %v", err) } - name0 := verifiers[0].Name() - - if name0 != "notation-verifier-0" { - t.Fatalf("expect name: notation-verifier-0, got: %s", name0) + if name := verifier.Name(); name != "notation-verifier-0" { + t.Fatalf("expect name: notation-verifier-0, got: %s", name) } } From f7bc7eae37abd95703353233cc0e7b1eb50d6c53 Mon Sep 17 00:00:00 2001 From: junczhu Date: Thu, 23 Nov 2023 22:04:34 +0000 Subject: [PATCH 06/38] feat: enable showing verifier name related ut4 --- pkg/verifier/notation/notation_test.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkg/verifier/notation/notation_test.go b/pkg/verifier/notation/notation_test.go index 43860fbbe..2a408c238 100644 --- a/pkg/verifier/notation/notation_test.go +++ b/pkg/verifier/notation/notation_test.go @@ -131,8 +131,9 @@ func (s mockStore) GetSubjectDescriptor(_ context.Context, _ common.Reference) ( func TestName(t *testing.T) { verifierConfig := map[string]interface{}{ - "name": "notation-verifier-0", - "specName": "notation", + "name": "notation-verifier-0", + "specName": "notation", + "trustPolicyDoc": testTrustPolicy, } f := ¬ationPluginVerifierFactory{} From f52f0ab299693aa2f3c53e92617a17d18da36e65 Mon Sep 17 00:00:00 2001 From: junczhu Date: Thu, 23 Nov 2023 22:42:56 +0000 Subject: [PATCH 07/38] feat: enable showing verifier name related ut5 --- pkg/verifier/notation/notation_test.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkg/verifier/notation/notation_test.go b/pkg/verifier/notation/notation_test.go index 2a408c238..beb60cf7b 100644 --- a/pkg/verifier/notation/notation_test.go +++ b/pkg/verifier/notation/notation_test.go @@ -200,7 +200,9 @@ func TestParseVerifierConfig(t *testing.T) { { name: "failed unmarshalling to notation config", configMap: map[string]interface{}{ - "name": []string{test}, + "key1": 1, + "key2": true, + "key3": make(chan int), }, expectErr: true, expect: nil, From 8d81faea1db7fed9a7c9d194f1083c4b533ff65a Mon Sep 17 00:00:00 2001 From: junczhu Date: Thu, 23 Nov 2023 22:56:37 +0000 Subject: [PATCH 08/38] feat: enable showing verifier name related ut6 --- pkg/verifier/notation/notation_test.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pkg/verifier/notation/notation_test.go b/pkg/verifier/notation/notation_test.go index beb60cf7b..88bd2bb67 100644 --- a/pkg/verifier/notation/notation_test.go +++ b/pkg/verifier/notation/notation_test.go @@ -200,9 +200,8 @@ func TestParseVerifierConfig(t *testing.T) { { name: "failed unmarshalling to notation config", configMap: map[string]interface{}{ - "key1": 1, - "key2": true, - "key3": make(chan int), + "name": test, + "verificationCerts": test, }, expectErr: true, expect: nil, From fdbb17517a2542acf863736bcdf8e7ec83973365 Mon Sep 17 00:00:00 2001 From: junczhu Date: Thu, 23 Nov 2023 23:30:07 +0000 Subject: [PATCH 09/38] feat: enable showing verifier name related ut7 --- pkg/verifier/notation/notation_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/verifier/notation/notation_test.go b/pkg/verifier/notation/notation_test.go index 88bd2bb67..1e01f1402 100644 --- a/pkg/verifier/notation/notation_test.go +++ b/pkg/verifier/notation/notation_test.go @@ -290,7 +290,8 @@ func TestCreate(t *testing.T) { { name: "failed parsing verifier config", configMap: map[string]interface{}{ - "name": []string{test}, + "name": test, + "trustPolicyDoc": 1, }, expectErr: true, }, From a68ecbb3b79bf0dd3a533a797050bea6835f0d1d Mon Sep 17 00:00:00 2001 From: junczhu Date: Wed, 29 Nov 2023 18:38:11 +0000 Subject: [PATCH 10/38] feat: enable showing verifier name related ut8 --- pkg/controllers/verifier_controller.go | 3 ++- pkg/verifier/factory/factory.go | 8 +++++--- pkg/verifier/factory/factory_test.go | 8 ++++---- pkg/verifier/notation/notation.go | 8 ++++---- pkg/verifier/notation/notation_test.go | 2 +- pkg/verifier/plugin/plugin.go | 11 ++++++----- pkg/verifier/plugin/plugin_test.go | 2 +- pkg/verifier/types/types.go | 2 +- 8 files changed, 24 insertions(+), 20 deletions(-) diff --git a/pkg/controllers/verifier_controller.go b/pkg/controllers/verifier_controller.go index 9000b450b..859de392c 100644 --- a/pkg/controllers/verifier_controller.go +++ b/pkg/controllers/verifier_controller.go @@ -112,6 +112,7 @@ func verifierAddOrReplace(spec configv1beta1.VerifierSpec, objectName string, na spec.Address = config.GetDefaultPluginPath() logrus.Infof("Address was empty, setting to default path: %v", spec.Address) } + // we may rename verifierReference to ReferenceVerifier in the future verifierReference, err := vf.CreateVerifierFromConfig(verifierConfig, verifierConfigVersion, []string{spec.Address}, namespace) if err != nil || verifierReference == nil { @@ -140,7 +141,7 @@ func specToVerifierConfig(verifierSpec configv1beta1.VerifierSpec) (vc.VerifierC } } - verifierConfig[types.SpecName] = verifierSpec.Name + verifierConfig[types.Type] = verifierSpec.Name verifierConfig[types.ArtifactTypes] = verifierSpec.ArtifactTypes if verifierSpec.Source != nil { verifierConfig[types.Source] = verifierSpec.Source diff --git a/pkg/verifier/factory/factory.go b/pkg/verifier/factory/factory.go index 1b930ee95..d68e46679 100644 --- a/pkg/verifier/factory/factory.go +++ b/pkg/verifier/factory/factory.go @@ -52,12 +52,14 @@ func Register(name string, factory VerifierFactory) { // returns a single verifier from a verifierConfig // namespace is only applicable in K8s environment, namespace is appended to the certstore of the truststore so it is uniquely identifiable in a cluster env func CreateVerifierFromConfig(verifierConfig config.VerifierConfig, configVersion string, pluginBinDir []string, namespace string) (verifier.ReferenceVerifier, error) { - verifierSpecName, ok := verifierConfig[types.SpecName] + verifierType, ok := verifierConfig[types.Type] if !ok { - return nil, re.ErrorCodeConfigInvalid.WithComponentType(re.Verifier).WithDetail(fmt.Sprintf("failed to find verifier name in the verifier config with key %s", "name")) + // in cli mode verifier type name can only read from Name property + verifierType = verifierConfig[types.Name] + // return nil, re.ErrorCodeConfigInvalid.WithComponentType(re.Verifier).WithDetail(fmt.Sprintf("failed to find verifier name in the verifier config with key %s", "type")) } - verifierTypeStr := fmt.Sprintf("%s", verifierSpecName) + verifierTypeStr := fmt.Sprintf("%s", verifierType) if strings.ContainsRune(verifierTypeStr, os.PathSeparator) { return nil, re.ErrorCodeConfigInvalid.WithComponentType(re.Verifier).WithDetail(fmt.Sprintf("invalid plugin name for a verifier: %s", verifierTypeStr)) } diff --git a/pkg/verifier/factory/factory_test.go b/pkg/verifier/factory/factory_test.go index c1b0dc8fe..2c21bd168 100644 --- a/pkg/verifier/factory/factory_test.go +++ b/pkg/verifier/factory/factory_test.go @@ -63,8 +63,8 @@ func TestCreateVerifiersFromConfig_BuiltInVerifiers_ReturnsExpected(t *testing.T } verifierConfig := map[string]interface{}{ - "name": "test-verifier-0", - "specName": "test-verifier", + "name": "test-verifier-0", + "type": "test-verifier", } verifiersConfig := config.VerifiersConfig{ Verifiers: []config.VerifierConfig{verifierConfig}, @@ -99,8 +99,8 @@ func TestCreateVerifiersFromConfig_BuiltInVerifiers_ReturnsExpected(t *testing.T func TestCreateVerifiersFromConfig_PluginVerifiers_ReturnsExpected(t *testing.T) { verifierConfig := map[string]interface{}{ - "name": "plugin-verifier-0", - "specName": "plugin-verifier", + "name": "plugin-verifier-0", + "type": "plugin-verifier", } verifiersConfig := config.VerifiersConfig{ Verifiers: []config.VerifierConfig{verifierConfig}, diff --git a/pkg/verifier/notation/notation.go b/pkg/verifier/notation/notation.go index 941578e6a..c8c884511 100644 --- a/pkg/verifier/notation/notation.go +++ b/pkg/verifier/notation/notation.go @@ -46,7 +46,7 @@ import ( ) const ( - verifierSpecName = "notation" + verifierTypeName = "notation" defaultCertPath = "ratify-certs/notation/truststore" ) @@ -65,7 +65,7 @@ type NotationPluginVerifierConfig struct { //nolint:revive // ignore linter to h type notationPluginVerifier struct { name string - specName string + typeName string artifactTypes []string notationVerifier *notation.Verifier } @@ -73,7 +73,7 @@ type notationPluginVerifier struct { type notationPluginVerifierFactory struct{} func init() { - factory.Register(verifierSpecName, ¬ationPluginVerifierFactory{}) + factory.Register(verifierTypeName, ¬ationPluginVerifierFactory{}) } func (f *notationPluginVerifierFactory) Create(_ string, verifierConfig config.VerifierConfig, pluginDirectory string, namespace string) (verifier.ReferenceVerifier, error) { @@ -92,7 +92,7 @@ func (f *notationPluginVerifierFactory) Create(_ string, verifierConfig config.V artifactTypes := strings.Split(conf.ArtifactTypes, ",") return ¬ationPluginVerifier{ name: verifierName, - specName: verifierSpecName, + typeName: verifierTypeName, artifactTypes: artifactTypes, notationVerifier: &verfiyService, }, nil diff --git a/pkg/verifier/notation/notation_test.go b/pkg/verifier/notation/notation_test.go index 1e01f1402..ad6c9834e 100644 --- a/pkg/verifier/notation/notation_test.go +++ b/pkg/verifier/notation/notation_test.go @@ -132,7 +132,7 @@ func (s mockStore) GetSubjectDescriptor(_ context.Context, _ common.Reference) ( func TestName(t *testing.T) { verifierConfig := map[string]interface{}{ "name": "notation-verifier-0", - "specName": "notation", + "type": "notation", "trustPolicyDoc": testTrustPolicy, } diff --git a/pkg/verifier/plugin/plugin.go b/pkg/verifier/plugin/plugin.go index 0132fb81a..95b468347 100644 --- a/pkg/verifier/plugin/plugin.go +++ b/pkg/verifier/plugin/plugin.go @@ -36,7 +36,7 @@ import ( // VerifierPlugin describes a verifier that is implemented by invoking the plugins type VerifierPlugin struct { name string - specName string + typeName string artifactTypes []string nestedReferences []string version string @@ -52,9 +52,10 @@ func NewVerifier(version string, verifierConfig config.VerifierConfig, pluginPat return nil, re.ErrorCodeConfigInvalid.WithDetail(fmt.Sprintf("failed to find verifier name in the verifier config with key: %s", types.Name)) } - verifierSpecName, ok := verifierConfig[types.SpecName] + verifierTypeName, ok := verifierConfig[types.Type] if !ok { - return nil, re.ErrorCodeConfigInvalid.WithDetail(fmt.Sprintf("failed to find verifier spec name in the verifier config with key: %s", types.SpecName)) + verifierTypeName = verifierConfig[types.Name] + // return nil, re.ErrorCodeConfigInvalid.WithDetail(fmt.Sprintf("failed to find verifier spec name in the verifier config with key: %s", types.Type)) } var nestedReferences []string @@ -73,7 +74,7 @@ func NewVerifier(version string, verifierConfig config.VerifierConfig, pluginPat return &VerifierPlugin{ name: fmt.Sprintf("%s", verifierName), - specName: fmt.Sprintf("%s", verifierSpecName), + typeName: fmt.Sprintf("%s", verifierTypeName), version: version, path: pluginPaths, rawConfig: verifierConfig, @@ -114,7 +115,7 @@ func (vp *VerifierPlugin) verifyReference( subjectReference common.Reference, referenceDescriptor ocispecs.ReferenceDescriptor, referrerStoreConfig *rc.StoreConfig) (*verifier.VerifierResult, error) { - pluginPath, err := vp.executor.FindInPaths(vp.specName, vp.path) + pluginPath, err := vp.executor.FindInPaths(vp.typeName, vp.path) if err != nil { return nil, re.ErrorCodePluginNotFound.NewError(re.Verifier, vp.name, re.EmptyLink, err, nil, re.HideStackTrace) } diff --git a/pkg/verifier/plugin/plugin_test.go b/pkg/verifier/plugin/plugin_test.go index a93b4b77f..dd6c2faf6 100644 --- a/pkg/verifier/plugin/plugin_test.go +++ b/pkg/verifier/plugin/plugin_test.go @@ -46,7 +46,7 @@ func (e *TestExecutor) FindInPaths(plugin string, paths []string) (string, error func TestNewVerifier_Expected(t *testing.T) { verifierConfig := map[string]interface{}{ "name": "test-verifier", - "specName": "test-verifier", + "type": "test-verifier", "artifactTypes": "test1,test2", "nestedReferences": "ref1,ref2", } diff --git a/pkg/verifier/types/types.go b/pkg/verifier/types/types.go index 25cdb50da..c9c6ce7aa 100644 --- a/pkg/verifier/types/types.go +++ b/pkg/verifier/types/types.go @@ -26,7 +26,7 @@ const ( SpecVersion string = "0.1.0" Version string = "version" Name string = "name" - SpecName string = "specName" + Type string = "type" ArtifactTypes string = "artifactTypes" NestedReferences string = "nestedReferences" Source string = "source" From da1b552ebe0ed63b3aca1df426089ac3b73b8c60 Mon Sep 17 00:00:00 2001 From: junczhu Date: Wed, 29 Nov 2023 20:42:04 +0000 Subject: [PATCH 11/38] feat:set verifier type as optional property, added to notation vResult --- pkg/executor/core/executor.go | 2 ++ pkg/executor/core/executor_test.go | 4 ++++ pkg/executor/core/testtypes.go | 4 ++++ pkg/verifier/api.go | 4 ++++ pkg/verifier/factory/factory.go | 10 ++++------ pkg/verifier/factory/factory_test.go | 4 ++++ pkg/verifier/notation/notation.go | 13 +++++++++++-- pkg/verifier/plugin/plugin.go | 20 +++++++++++++------- pkg/verifier/types/types.go | 2 ++ 9 files changed, 48 insertions(+), 15 deletions(-) diff --git a/pkg/executor/core/executor.go b/pkg/executor/core/executor.go index 116b439c8..91f44f453 100644 --- a/pkg/executor/core/executor.go +++ b/pkg/executor/core/executor.go @@ -177,6 +177,7 @@ func (executor Executor) verifyReferenceForJSONPolicy(ctx context.Context, subje verifyResult = vr.VerifierResult{ IsSuccess: false, Name: verifier.Name(), + Type: verifier.TypeName(), Message: errors.ErrorCodeVerifyReferenceFailure.NewError(errors.Verifier, verifier.Name(), errors.EmptyLink, err, nil, errors.HideStackTrace).Error()} } @@ -225,6 +226,7 @@ func (executor Executor) verifyReferenceForRegoPolicy(ctx context.Context, subje verifierReport = vt.VerifierResult{ IsSuccess: false, Name: verifier.Name(), + Type: verifier.TypeName(), Message: errors.ErrorCodeVerifyReferenceFailure.NewError(errors.Verifier, verifier.Name(), errors.EmptyLink, err, nil, errors.HideStackTrace).Error()} } else { verifierReport = vt.NewVerifierResult(verifierResult) diff --git a/pkg/executor/core/executor_test.go b/pkg/executor/core/executor_test.go index 0e66c8943..6433edab0 100644 --- a/pkg/executor/core/executor_test.go +++ b/pkg/executor/core/executor_test.go @@ -134,6 +134,10 @@ func (v *mockVerifier) Name() string { return "mockVerifier" } +func (v *mockVerifier) TypeName() string { + return "mockVerifier" +} + func (v *mockVerifier) CanVerify(_ context.Context, _ ocispecs.ReferenceDescriptor) bool { return v.canVerify } diff --git a/pkg/executor/core/testtypes.go b/pkg/executor/core/testtypes.go index d5f26d99a..12acb1303 100644 --- a/pkg/executor/core/testtypes.go +++ b/pkg/executor/core/testtypes.go @@ -34,6 +34,10 @@ func (s *TestVerifier) Name() string { return "test-verifier" } +func (s *TestVerifier) TypeName() string { + return "test-verifier" +} + func (s *TestVerifier) CanVerify(_ context.Context, referenceDescriptor ocispecs.ReferenceDescriptor) bool { return s.CanVerifyFunc(referenceDescriptor.ArtifactType) } diff --git a/pkg/verifier/api.go b/pkg/verifier/api.go index 5224c2963..41ac70898 100644 --- a/pkg/verifier/api.go +++ b/pkg/verifier/api.go @@ -28,6 +28,7 @@ type VerifierResult struct { //nolint:revive // ignore linter to have unique typ Subject string `json:"subject,omitempty"` IsSuccess bool `json:"isSuccess"` Name string `json:"name,omitempty"` + Type string `json:"type,omitempty"` Message string `json:"message,omitempty"` Extensions interface{} `json:"extensions,omitempty"` NestedResults []VerifierResult `json:"nestedResults,omitempty"` @@ -40,6 +41,9 @@ type ReferenceVerifier interface { // Name returns the name of the verifier Name() string + // TypeName returns the type name of the verifier + TypeName() string + // CanVerify returns if the verifier can verify the given reference CanVerify(ctx context.Context, referenceDescriptor ocispecs.ReferenceDescriptor) bool diff --git a/pkg/verifier/factory/factory.go b/pkg/verifier/factory/factory.go index d68e46679..ff53501f2 100644 --- a/pkg/verifier/factory/factory.go +++ b/pkg/verifier/factory/factory.go @@ -52,14 +52,12 @@ func Register(name string, factory VerifierFactory) { // returns a single verifier from a verifierConfig // namespace is only applicable in K8s environment, namespace is appended to the certstore of the truststore so it is uniquely identifiable in a cluster env func CreateVerifierFromConfig(verifierConfig config.VerifierConfig, configVersion string, pluginBinDir []string, namespace string) (verifier.ReferenceVerifier, error) { - verifierType, ok := verifierConfig[types.Type] - if !ok { - // in cli mode verifier type name can only read from Name property - verifierType = verifierConfig[types.Name] - // return nil, re.ErrorCodeConfigInvalid.WithComponentType(re.Verifier).WithDetail(fmt.Sprintf("failed to find verifier name in the verifier config with key %s", "type")) + // in cli mode verifier type name can only read from Name property + verifierTypeStr := fmt.Sprintf("%s", verifierConfig[types.Name]) + if _, ok := verifierConfig[types.Type]; ok { + verifierTypeStr = fmt.Sprintf("%s", verifierConfig[types.Type]) } - verifierTypeStr := fmt.Sprintf("%s", verifierType) if strings.ContainsRune(verifierTypeStr, os.PathSeparator) { return nil, re.ErrorCodeConfigInvalid.WithComponentType(re.Verifier).WithDetail(fmt.Sprintf("invalid plugin name for a verifier: %s", verifierTypeStr)) } diff --git a/pkg/verifier/factory/factory_test.go b/pkg/verifier/factory/factory_test.go index 2c21bd168..5a1e97bb1 100644 --- a/pkg/verifier/factory/factory_test.go +++ b/pkg/verifier/factory/factory_test.go @@ -38,6 +38,10 @@ func (s *TestVerifier) Name() string { return "test-verifier-0" } +func (s *TestVerifier) TypeName() string { + return "test-verifier" +} + func (s *TestVerifier) CanVerify(_ context.Context, _ ocispecs.ReferenceDescriptor) bool { return true } diff --git a/pkg/verifier/notation/notation.go b/pkg/verifier/notation/notation.go index c8c884511..e0f1be8a0 100644 --- a/pkg/verifier/notation/notation.go +++ b/pkg/verifier/notation/notation.go @@ -78,7 +78,11 @@ func init() { func (f *notationPluginVerifierFactory) Create(_ string, verifierConfig config.VerifierConfig, pluginDirectory string, namespace string) (verifier.ReferenceVerifier, error) { logger.GetLogger(context.Background(), logOpt).Debugf("creating notation with config %v, namespace '%v'", verifierConfig, namespace) - verifierName := verifierConfig[types.Name].(string) + verifierName := fmt.Sprintf("%s", verifierConfig[types.Name]) + verifierTypeStr := "" + if _, ok := verifierConfig[types.Type]; ok { + verifierTypeStr = fmt.Sprintf("%s", verifierConfig[types.Type]) + } conf, err := parseVerifierConfig(verifierConfig, namespace) if err != nil { return nil, re.ErrorCodeConfigInvalid.WithComponentType(re.Verifier).WithPluginName(verifierName) @@ -92,7 +96,7 @@ func (f *notationPluginVerifierFactory) Create(_ string, verifierConfig config.V artifactTypes := strings.Split(conf.ArtifactTypes, ",") return ¬ationPluginVerifier{ name: verifierName, - typeName: verifierTypeName, + typeName: verifierTypeStr, artifactTypes: artifactTypes, notationVerifier: &verfiyService, }, nil @@ -102,6 +106,10 @@ func (v *notationPluginVerifier) Name() string { return v.name } +func (v *notationPluginVerifier) TypeName() string { + return v.typeName +} + func (v *notationPluginVerifier) CanVerify(_ context.Context, referenceDescriptor ocispecs.ReferenceDescriptor) bool { for _, at := range v.artifactTypes { if at == "*" || at == referenceDescriptor.ArtifactType { @@ -153,6 +161,7 @@ func (v *notationPluginVerifier) Verify(ctx context.Context, return verifier.VerifierResult{ Name: v.name, + Type: v.typeName, IsSuccess: true, Message: "signature verification success", Extensions: extensions, diff --git a/pkg/verifier/plugin/plugin.go b/pkg/verifier/plugin/plugin.go index 95b468347..505310fca 100644 --- a/pkg/verifier/plugin/plugin.go +++ b/pkg/verifier/plugin/plugin.go @@ -51,11 +51,9 @@ func NewVerifier(version string, verifierConfig config.VerifierConfig, pluginPat if !ok { return nil, re.ErrorCodeConfigInvalid.WithDetail(fmt.Sprintf("failed to find verifier name in the verifier config with key: %s", types.Name)) } - - verifierTypeName, ok := verifierConfig[types.Type] - if !ok { - verifierTypeName = verifierConfig[types.Name] - // return nil, re.ErrorCodeConfigInvalid.WithDetail(fmt.Sprintf("failed to find verifier spec name in the verifier config with key: %s", types.Type)) + verifierTypeName := "" + if _, ok := verifierConfig[types.Type]; ok { + verifierTypeName = fmt.Sprintf("%s", verifierConfig[types.Type]) } var nestedReferences []string @@ -74,7 +72,7 @@ func NewVerifier(version string, verifierConfig config.VerifierConfig, pluginPat return &VerifierPlugin{ name: fmt.Sprintf("%s", verifierName), - typeName: fmt.Sprintf("%s", verifierTypeName), + typeName: verifierTypeName, version: version, path: pluginPaths, rawConfig: verifierConfig, @@ -97,6 +95,10 @@ func (vp *VerifierPlugin) Name() string { return vp.name } +func (vp *VerifierPlugin) TypeName() string { + return vp.typeName +} + func (vp *VerifierPlugin) Verify(ctx context.Context, subjectReference common.Reference, referenceDescriptor ocispecs.ReferenceDescriptor, @@ -115,7 +117,11 @@ func (vp *VerifierPlugin) verifyReference( subjectReference common.Reference, referenceDescriptor ocispecs.ReferenceDescriptor, referrerStoreConfig *rc.StoreConfig) (*verifier.VerifierResult, error) { - pluginPath, err := vp.executor.FindInPaths(vp.typeName, vp.path) + verifierTypeStr := vp.name + if vp.typeName != "" { + verifierTypeStr = vp.typeName + } + pluginPath, err := vp.executor.FindInPaths(verifierTypeStr, vp.path) if err != nil { return nil, re.ErrorCodePluginNotFound.NewError(re.Verifier, vp.name, re.EmptyLink, err, nil, re.HideStackTrace) } diff --git a/pkg/verifier/types/types.go b/pkg/verifier/types/types.go index c9c6ce7aa..df9890efb 100644 --- a/pkg/verifier/types/types.go +++ b/pkg/verifier/types/types.go @@ -50,6 +50,7 @@ type VerifierResult struct { IsSuccess bool `json:"isSuccess"` Message string `json:"message"` Name string `json:"name"` + Type string `json:"type,omitempty"` Extensions interface{} `json:"extensions"` } @@ -63,6 +64,7 @@ func GetVerifierResult(result []byte) (*verifier.VerifierResult, error) { IsSuccess: vResult.IsSuccess, Message: vResult.Message, Name: vResult.Name, + Type: vResult.Type, Extensions: vResult.Extensions, }, nil } From e8aea9816c8bca298d35bcca3a4df381d6469ec8 Mon Sep 17 00:00:00 2001 From: junczhu Date: Wed, 29 Nov 2023 21:02:14 +0000 Subject: [PATCH 12/38] chore: create func verifierCreateConfig, added err catcher --- pkg/controllers/verifier_controller.go | 19 ++++++++++++------- pkg/verifier/factory/factory.go | 12 +++++++++--- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/pkg/controllers/verifier_controller.go b/pkg/controllers/verifier_controller.go index 859de392c..061f349bc 100644 --- a/pkg/controllers/verifier_controller.go +++ b/pkg/controllers/verifier_controller.go @@ -97,13 +97,7 @@ func (r *VerifierReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c // creates a verifier reference from CRD spec and add store to map func verifierAddOrReplace(spec configv1beta1.VerifierSpec, objectName string, namespace string) error { - verifierConfig, err := specToVerifierConfig(spec) - // add verifier name to verifier config - verifierConfig[types.Name] = objectName - if err != nil { - logrus.Error(err, "unable to convert crd specification to verifier config") - return fmt.Errorf("unable to convert crd specification to verifier config, err: %w", err) - } + verifierConfig, err := verifierCreateConfig(spec, objectName) // verifier factory only support a single version of configuration today // when we support multi version verifier CRD, we will also pass in the corresponding config version so factory can create different version of the object @@ -125,6 +119,17 @@ func verifierAddOrReplace(spec configv1beta1.VerifierSpec, objectName string, na return nil } +// create verifier config +func verifierCreateConfig(verifierSpec configv1beta1.VerifierSpec, verifierName string) (vc.VerifierConfig, error) { + verifierConfig, err := specToVerifierConfig(verifierSpec) + if err != nil { + logrus.Error(err, "unable to convert crd specification to verifier config") + return nil, fmt.Errorf("unable to convert crd specification to verifier config, err: %w", err) + } + verifierConfig[types.Name] = verifierName + return verifierConfig, nil +} + // remove verifier from map func verifierRemove(objectName string) { delete(VerifierMap, objectName) diff --git a/pkg/verifier/factory/factory.go b/pkg/verifier/factory/factory.go index ff53501f2..64b20dd6e 100644 --- a/pkg/verifier/factory/factory.go +++ b/pkg/verifier/factory/factory.go @@ -53,9 +53,15 @@ func Register(name string, factory VerifierFactory) { // namespace is only applicable in K8s environment, namespace is appended to the certstore of the truststore so it is uniquely identifiable in a cluster env func CreateVerifierFromConfig(verifierConfig config.VerifierConfig, configVersion string, pluginBinDir []string, namespace string) (verifier.ReferenceVerifier, error) { // in cli mode verifier type name can only read from Name property - verifierTypeStr := fmt.Sprintf("%s", verifierConfig[types.Name]) - if _, ok := verifierConfig[types.Type]; ok { - verifierTypeStr = fmt.Sprintf("%s", verifierConfig[types.Type]) + var verifierTypeStr string + if value, ok := verifierConfig[types.Name]; ok { + verifierTypeStr = value.(string) + } else { + return nil, re.ErrorCodeConfigInvalid.WithComponentType(re.Verifier).WithDetail(fmt.Sprintf("failed to find verifier name in the verifier config with key %s", "name")) + } + + if value, ok := verifierConfig[types.Type]; ok { + verifierTypeStr = value.(string) } if strings.ContainsRune(verifierTypeStr, os.PathSeparator) { From 004f8e46988b7ecc3f961aeb10ec5d95fc9d7b87 Mon Sep 17 00:00:00 2001 From: junczhu Date: Wed, 29 Nov 2023 21:19:46 +0000 Subject: [PATCH 13/38] fix: update verifier dynamic cli-test --- test/bats/cli-test.bats | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/bats/cli-test.bats b/test/bats/cli-test.bats index 988abb808..b17abb0e4 100644 --- a/test/bats/cli-test.bats +++ b/test/bats/cli-test.bats @@ -71,7 +71,7 @@ load helpers assert_success # dynamic plugins enabled with feature flag - run bash -c "RATIFY_EXPERIMENTAL_DYNAMIC_PLUGINS=1 bin/ratify verify -c $RATIFY_DIR/dynamic_plugins_config.json -s $TEST_REGISTRY/all:v0 2>&1 >/dev/null | grep 'downloaded verifier plugin dynamic from .* to .*'" + run bash -c "RATIFY_EXPERIMENTAL_DYNAMIC_PLUGINS=1 bin/ratify verify -c $RATIFY_DIR/dynamic_plugins_config.json -s $TEST_REGISTRY/all:v0 2>&1 >/dev/null | grep 'downloaded verifier plugin verifier-dynamic from .* to .*'" assert_success # ensure the plugin is downloaded and marked executable From 9e1505708bce40dddf9f83ddc3cd9d44d1cbb9fc Mon Sep 17 00:00:00 2001 From: junczhu Date: Wed, 29 Nov 2023 21:30:54 +0000 Subject: [PATCH 14/38] fix: update verifier creation llog --- pkg/controllers/verifier_controller.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pkg/controllers/verifier_controller.go b/pkg/controllers/verifier_controller.go index 061f349bc..acbb51fc1 100644 --- a/pkg/controllers/verifier_controller.go +++ b/pkg/controllers/verifier_controller.go @@ -98,7 +98,10 @@ func (r *VerifierReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c // creates a verifier reference from CRD spec and add store to map func verifierAddOrReplace(spec configv1beta1.VerifierSpec, objectName string, namespace string) error { verifierConfig, err := verifierCreateConfig(spec, objectName) - + if err != nil { + logrus.Error(err, "unable to convert crd specification to verifier config") + return fmt.Errorf("unable to convert crd specification to verifier config, err: %w", err) + } // verifier factory only support a single version of configuration today // when we support multi version verifier CRD, we will also pass in the corresponding config version so factory can create different version of the object verifierConfigVersion := "1.0.0" // TODO: move default values to defaulting webhook in the future #413 @@ -123,8 +126,7 @@ func verifierAddOrReplace(spec configv1beta1.VerifierSpec, objectName string, na func verifierCreateConfig(verifierSpec configv1beta1.VerifierSpec, verifierName string) (vc.VerifierConfig, error) { verifierConfig, err := specToVerifierConfig(verifierSpec) if err != nil { - logrus.Error(err, "unable to convert crd specification to verifier config") - return nil, fmt.Errorf("unable to convert crd specification to verifier config, err: %w", err) + return nil, err } verifierConfig[types.Name] = verifierName return verifierConfig, nil From 20a95c5e8099c9be28ce499ed4559841f89b4ea3 Mon Sep 17 00:00:00 2001 From: junczhu Date: Wed, 29 Nov 2023 21:50:34 +0000 Subject: [PATCH 15/38] fix: update verifier creation log2 --- test/bats/cli-test.bats | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/bats/cli-test.bats b/test/bats/cli-test.bats index b17abb0e4..b091c4b38 100644 --- a/test/bats/cli-test.bats +++ b/test/bats/cli-test.bats @@ -71,7 +71,7 @@ load helpers assert_success # dynamic plugins enabled with feature flag - run bash -c "RATIFY_EXPERIMENTAL_DYNAMIC_PLUGINS=1 bin/ratify verify -c $RATIFY_DIR/dynamic_plugins_config.json -s $TEST_REGISTRY/all:v0 2>&1 >/dev/null | grep 'downloaded verifier plugin verifier-dynamic from .* to .*'" + run bash -c "RATIFY_EXPERIMENTAL_DYNAMIC_PLUGINS=1 bin/ratify verify -c $RATIFY_DIR/dynamic_plugins_config.json -s $TEST_REGISTRY/all:v0 2>&1 >/dev/null | grep 'downloaded verifier plugin verifier from .* to .*'" assert_success # ensure the plugin is downloaded and marked executable From a549c0674a0a172b72a3d1bb7a01161fc93cd197 Mon Sep 17 00:00:00 2001 From: junczhu Date: Wed, 29 Nov 2023 21:54:38 +0000 Subject: [PATCH 16/38] fix: update verifier creation log3 --- test/bats/cli-test.bats | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/bats/cli-test.bats b/test/bats/cli-test.bats index b091c4b38..98a1f2ec1 100644 --- a/test/bats/cli-test.bats +++ b/test/bats/cli-test.bats @@ -71,7 +71,7 @@ load helpers assert_success # dynamic plugins enabled with feature flag - run bash -c "RATIFY_EXPERIMENTAL_DYNAMIC_PLUGINS=1 bin/ratify verify -c $RATIFY_DIR/dynamic_plugins_config.json -s $TEST_REGISTRY/all:v0 2>&1 >/dev/null | grep 'downloaded verifier plugin verifier from .* to .*'" + run bash -c "RATIFY_EXPERIMENTAL_DYNAMIC_PLUGINS=1 bin/ratify verify -c $RATIFY_DIR/dynamic_plugins_config.json -s $TEST_REGISTRY/all:v0 2>&1 >/dev/null | grep 'downloaded verifier plugin'" assert_success # ensure the plugin is downloaded and marked executable From 6efa929c63ad02125eecb8175ff971958d0f5a5a Mon Sep 17 00:00:00 2001 From: junczhu Date: Fri, 1 Dec 2023 06:56:30 +0000 Subject: [PATCH 17/38] fix: update verifier plugin log for e2e test --- pkg/verifier/factory/factory.go | 2 +- test/bats/cli-test.bats | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/verifier/factory/factory.go b/pkg/verifier/factory/factory.go index 64b20dd6e..40d70ec3d 100644 --- a/pkg/verifier/factory/factory.go +++ b/pkg/verifier/factory/factory.go @@ -81,7 +81,7 @@ func CreateVerifierFromConfig(verifierConfig config.VerifierConfig, configVersio if err != nil { return nil, re.ErrorCodeDownloadPluginFailure.NewError(re.Verifier, "", re.EmptyLink, err, "failed to download plugin", re.HideStackTrace) } - logrus.Infof("downloaded verifier plugin type %s from %s to %s", verifierTypeStr, source.Artifact, targetPath) + logrus.Infof("downloaded verifier plugin %s from %s to %s", verifierTypeStr, source.Artifact, targetPath) } else { logrus.Warnf("%s was specified for verifier plugin type %s, but dynamic plugins are currently disabled", types.Source, verifierTypeStr) } diff --git a/test/bats/cli-test.bats b/test/bats/cli-test.bats index 437e3930e..531e82995 100644 --- a/test/bats/cli-test.bats +++ b/test/bats/cli-test.bats @@ -84,7 +84,7 @@ load helpers assert_success # dynamic plugins enabled with feature flag - run bash -c "RATIFY_EXPERIMENTAL_DYNAMIC_PLUGINS=1 bin/ratify verify -c $RATIFY_DIR/dynamic_plugins_config.json -s $TEST_REGISTRY/all:v0 2>&1 >/dev/null | grep 'downloaded verifier plugin'" + run bash -c "RATIFY_EXPERIMENTAL_DYNAMIC_PLUGINS=1 bin/ratify verify -c $RATIFY_DIR/dynamic_plugins_config.json -s $TEST_REGISTRY/all:v0 2>&1 >/dev/null | grep 'downloaded verifier plugin dynamic from .* to .*'" assert_success # ensure the plugin is downloaded and marked executable From 78bfe263b370a1e387d8779e64791894483ec23b Mon Sep 17 00:00:00 2001 From: junczhu Date: Mon, 4 Dec 2023 05:43:14 +0000 Subject: [PATCH 18/38] fix: typo; CT for notation plugin --- library/notation-issuer-validation/template.yaml | 4 ++-- library/notation-validation/template.yml | 2 +- pkg/verifier/notation/notation.go | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/library/notation-issuer-validation/template.yaml b/library/notation-issuer-validation/template.yaml index b5dc4238b..44caf1cb7 100644 --- a/library/notation-issuer-validation/template.yaml +++ b/library/notation-issuer-validation/template.yaml @@ -57,7 +57,7 @@ spec: general_violation[{"result": result}] { subject_results := remote_data.responses[_] subject_result := subject_results[1] - notation_results := [res | subject_result.verifierReports[i].name == "notation"; res := subject_result.verifierReports[i]] + notation_results := [res | subject_result.verifierReports[i].type == "notation"; res := subject_result.verifierReports[i]] issuer_results := [res | notation_results[i].extensions.Issuer == input.parameters.issuer; res := notation_results[i]] count(issuer_results) == 0 result := sprintf("Subject %s has no signatures for certificate with Issuer: %s", [subject_results[0], input.parameters.issuer]) @@ -67,7 +67,7 @@ spec: general_violation[{"result": result}] { subject_results := remote_data.responses[_] subject_result := subject_results[1] - notation_results := [res | subject_result.verifierReports[i].name == "notation"; res := subject_result.verifierReports[i]] + notation_results := [res | subject_result.verifierReports[i].type == "notation"; res := subject_result.verifierReports[i]] notation_result := notation_results[_] notation_result.isSuccess == false notation_result.extensions.Issuer == input.parameters.issuer diff --git a/library/notation-validation/template.yml b/library/notation-validation/template.yml index 04f312215..19ca1d8fe 100644 --- a/library/notation-validation/template.yml +++ b/library/notation-validation/template.yml @@ -38,7 +38,7 @@ spec: general_violation[{"result": result}] { subject_results := remote_data.responses[_] subject_result := subject_results[1] - notation_results := [res | subject_result.verifierReports[i].name == "notation"; res := subject_result.verifierReports[i]] + notation_results := [res | subject_result.verifierReports[i].type == "notation"; res := subject_result.verifierReports[i]] successful_result := [ notation_result | notation_result := notation_results[_]; notation_result["isSuccess"] == true] successful_result == [] result = sprintf("signature verification failed for all signatures associated with %s", [subject_results[0]]) diff --git a/pkg/verifier/notation/notation.go b/pkg/verifier/notation/notation.go index e0f1be8a0..d0967cdc2 100644 --- a/pkg/verifier/notation/notation.go +++ b/pkg/verifier/notation/notation.go @@ -88,7 +88,7 @@ func (f *notationPluginVerifierFactory) Create(_ string, verifierConfig config.V return nil, re.ErrorCodeConfigInvalid.WithComponentType(re.Verifier).WithPluginName(verifierName) } - verfiyService, err := getVerifierService(conf, pluginDirectory) + verifyService, err := getVerifierService(conf, pluginDirectory) if err != nil { return nil, re.ErrorCodePluginInitFailure.WithComponentType(re.Verifier).WithPluginName(verifierName).WithError(err) } @@ -98,7 +98,7 @@ func (f *notationPluginVerifierFactory) Create(_ string, verifierConfig config.V name: verifierName, typeName: verifierTypeStr, artifactTypes: artifactTypes, - notationVerifier: &verfiyService, + notationVerifier: &verifyService, }, nil } From 4a8e33c640c9d4905f21d604736da447bd856759 Mon Sep 17 00:00:00 2001 From: junczhu Date: Mon, 4 Dec 2023 07:31:50 +0000 Subject: [PATCH 19/38] test: e2e test for verifier with type and multi verifier --- test/bats/cli-test.bats | 10 ++ test/bats/helpers.bash | 14 +++ .../config_multiple_notation_verifier.json | 79 ++++++++++++++++ .../config_notation_verifier_with_type.json | 94 +++++++++++++++++++ 4 files changed, 197 insertions(+) create mode 100644 test/bats/tests/config/config_multiple_notation_verifier.json create mode 100644 test/bats/tests/config/config_notation_verifier_with_type.json diff --git a/test/bats/cli-test.bats b/test/bats/cli-test.bats index 531e82995..70e942ae4 100644 --- a/test/bats/cli-test.bats +++ b/test/bats/cli-test.bats @@ -31,6 +31,16 @@ load helpers assert_cmd_verify_failure } +@test "notation verifier with type test" { + run bin/ratify verify -c $RATIFY_DIR/config_notation_verifier_with_type.json -s $TEST_REGISTRY/notation:signed + assert_cmd_verify_success_with_type +} + +@test "multiple notation verifiers test" { + run bin/ratify verify -c $RATIFY_DIR/config_multiple_notation_verifier.json -s $TEST_REGISTRY/notation:leafSigned + assert_cmd_verify_success +} + @test "notation verifier leaf cert with rego policy" { run bin/ratify verify -c $RATIFY_DIR/config_rego_policy_notation_root_cert.json -s $TEST_REGISTRY/notation:leafSigned assert_cmd_verify_success diff --git a/test/bats/helpers.bash b/test/bats/helpers.bash index d685a2ee1..62bc3266c 100644 --- a/test/bats/helpers.bash +++ b/test/bats/helpers.bash @@ -41,6 +41,20 @@ assert_cmd_verify_success() { fi } +assert_cmd_verify_success_with_type() { + if [[ "$status" != 0 ]]; then + return 1 + fi + if [[ "$output" == *'"isSuccess": false,'* ]]; then + echo $output + return 1 + fi + if [[ "$output" != *'"type": notation,'* ]]; then + echo $output + return 1 + fi +} + assert_cmd_cosign_keyless_verify_bundle_success() { if [[ "$status" != 0 ]]; then return 1 diff --git a/test/bats/tests/config/config_multiple_notation_verifier.json b/test/bats/tests/config/config_multiple_notation_verifier.json new file mode 100644 index 000000000..77c545ecf --- /dev/null +++ b/test/bats/tests/config/config_multiple_notation_verifier.json @@ -0,0 +1,79 @@ +{ + "store": { + "version": "1.0.0", + "plugins": [ + { + "name": "oras", + "cosignEnabled": true, + "useHttp": true + } + ] + }, + "policy": { + "version": "1.0.0", + "plugin": { + "name": "configPolicy" + } + }, + "verifier": { + "version": "1.0.0", + "plugins": [ + { + "name": "verifier-notation-root", + "type": "notation", + "artifactTypes": "application/vnd.cncf.notary.signature", + "verificationCerts": [ + "~/.config/notation/truststore/x509/ca/leaf-test/root.crt" + ], + "trustPolicyDoc": { + "version": "1.0", + "trustPolicies": [ + { + "name": "default", + "registryScopes": [ + "*" + ], + "signatureVerification": { + "level": "strict" + }, + "trustStores": [ + "ca:certs" + ], + "trustedIdentities": [ + "*" + ] + } + ] + } + }, + { + "name": "verifier-notation-root", + "type": "notation", + "artifactTypes": "application/vnd.cncf.notary.signature", + "verificationCerts": [ + "~/.config/notation/truststore/x509/ca/leaf-test/leaf.crt" + ], + "trustPolicyDoc": { + "version": "1.0", + "trustPolicies": [ + { + "name": "default", + "registryScopes": [ + "*" + ], + "signatureVerification": { + "level": "strict" + }, + "trustStores": [ + "ca:certs" + ], + "trustedIdentities": [ + "*" + ] + } + ] + } + } + ] + } +} \ No newline at end of file diff --git a/test/bats/tests/config/config_notation_verifier_with_type.json b/test/bats/tests/config/config_notation_verifier_with_type.json new file mode 100644 index 000000000..59147b1f3 --- /dev/null +++ b/test/bats/tests/config/config_notation_verifier_with_type.json @@ -0,0 +1,94 @@ +{ + "store": { + "version": "1.0.0", + "plugins": [ + { + "name": "oras", + "cosignEnabled": true, + "useHttp": true + } + ] + }, + "policy": { + "version": "1.0.0", + "plugin": { + "name": "configPolicy" + } + }, + "verifier": { + "version": "1.0.0", + "plugins": [ + { + "name": "schemavalidator", + "artifactTypes": "vnd.aquasecurity.trivy.report.sarif.v1", + "schemas": { + "application/sarif+json": "file:///home/runner/.ratify/schemas/sarif-2.1.0-rtm.5.json" + } + }, + { + "name": "sbom", + "artifactTypes": "org.example.sbom.v0", + "nestedReferences": "application/vnd.cncf.notary.signature" + }, + { + "name": "cosign", + "artifactTypes": "application/vnd.dev.cosign.artifact.sig.v1+json", + "key": ".staging/cosign/cosign.pub" + }, + { + "name": "verifier-notation", + "type": "notation", + "artifactTypes": "application/vnd.cncf.notary.signature", + "verificationCerts": [ + "~/.config/notation/localkeys/ratify-bats-test.crt" + ], + "trustPolicyDoc": { + "version": "1.0", + "trustPolicies": [ + { + "name": "default", + "registryScopes": [ + "*" + ], + "signatureVerification": { + "level": "strict" + }, + "trustStores": [ + "ca:certs" + ], + "trustedIdentities": [ + "*" + ] + } + ] + } + }, + { + "name": "schemavalidator", + "artifactTypes": "vnd.aquasecurity.trivy.report.sarif.v1", + "schemas": { + "application/sarif+json": "https://json.schemastore.org/sarif-2.1.0-rtm.5.json" + } + }, + { + "name": "licensechecker", + "artifactTypes": "application/vnd.ratify.spdx.v0", + "allowedLicenses": [ + "GPL-2.0-only", + "MIT", + "OpenSSL", + "BSD-2-Clause AND BSD-3-Clause", + "Zlib", + "MPL-2.0 AND MIT", + "ISC", + "Apache-2.0", + "MIT AND BSD-2-Clause AND GPL-2.0-or-later", + "MIT AND LicenseRef-AND AND BSD-2-Clause AND LicenseRef-AND AND GPL-2.0-or-later", + "MPL-2.0 AND LicenseRef-AND AND MIT", + "BSD-2-Clause AND LicenseRef-AND AND BSD-3-Clause", + "NONE" + ] + } + ] + } +} \ No newline at end of file From e2f5b4102838ba65d02cfa1692cd71a438adff80 Mon Sep 17 00:00:00 2001 From: junczhu Date: Mon, 4 Dec 2023 08:43:40 +0000 Subject: [PATCH 20/38] feat: resolve comments; fix: e2e test --- pkg/controllers/verifier_controller.go | 16 +++------------- pkg/executor/core/executor.go | 4 ++-- pkg/executor/core/executor_test.go | 4 ++-- pkg/executor/core/testtypes.go | 6 +++--- pkg/verifier/api.go | 4 ++-- pkg/verifier/factory/factory.go | 2 +- pkg/verifier/factory/factory_test.go | 2 +- pkg/verifier/notation/notation.go | 14 +++++++------- pkg/verifier/plugin/plugin.go | 16 ++++++++-------- test/bats/helpers.bash | 2 +- 10 files changed, 30 insertions(+), 40 deletions(-) diff --git a/pkg/controllers/verifier_controller.go b/pkg/controllers/verifier_controller.go index acbb51fc1..8a4be2438 100644 --- a/pkg/controllers/verifier_controller.go +++ b/pkg/controllers/verifier_controller.go @@ -97,7 +97,7 @@ func (r *VerifierReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c // creates a verifier reference from CRD spec and add store to map func verifierAddOrReplace(spec configv1beta1.VerifierSpec, objectName string, namespace string) error { - verifierConfig, err := verifierCreateConfig(spec, objectName) + verifierConfig, err := specToVerifierConfig(spec, objectName) if err != nil { logrus.Error(err, "unable to convert crd specification to verifier config") return fmt.Errorf("unable to convert crd specification to verifier config, err: %w", err) @@ -122,23 +122,13 @@ func verifierAddOrReplace(spec configv1beta1.VerifierSpec, objectName string, na return nil } -// create verifier config -func verifierCreateConfig(verifierSpec configv1beta1.VerifierSpec, verifierName string) (vc.VerifierConfig, error) { - verifierConfig, err := specToVerifierConfig(verifierSpec) - if err != nil { - return nil, err - } - verifierConfig[types.Name] = verifierName - return verifierConfig, nil -} - // remove verifier from map func verifierRemove(objectName string) { delete(VerifierMap, objectName) } // returns a verifier reference from spec -func specToVerifierConfig(verifierSpec configv1beta1.VerifierSpec) (vc.VerifierConfig, error) { +func specToVerifierConfig(verifierSpec configv1beta1.VerifierSpec, verifierName string) (vc.VerifierConfig, error) { verifierConfig := vc.VerifierConfig{} if string(verifierSpec.Parameters.Raw) != "" { @@ -147,7 +137,7 @@ func specToVerifierConfig(verifierSpec configv1beta1.VerifierSpec) (vc.VerifierC return vc.VerifierConfig{}, err } } - + verifierConfig[types.Name] = verifierName verifierConfig[types.Type] = verifierSpec.Name verifierConfig[types.ArtifactTypes] = verifierSpec.ArtifactTypes if verifierSpec.Source != nil { diff --git a/pkg/executor/core/executor.go b/pkg/executor/core/executor.go index 91f44f453..74a071d26 100644 --- a/pkg/executor/core/executor.go +++ b/pkg/executor/core/executor.go @@ -177,7 +177,7 @@ func (executor Executor) verifyReferenceForJSONPolicy(ctx context.Context, subje verifyResult = vr.VerifierResult{ IsSuccess: false, Name: verifier.Name(), - Type: verifier.TypeName(), + Type: verifier.Type(), Message: errors.ErrorCodeVerifyReferenceFailure.NewError(errors.Verifier, verifier.Name(), errors.EmptyLink, err, nil, errors.HideStackTrace).Error()} } @@ -226,7 +226,7 @@ func (executor Executor) verifyReferenceForRegoPolicy(ctx context.Context, subje verifierReport = vt.VerifierResult{ IsSuccess: false, Name: verifier.Name(), - Type: verifier.TypeName(), + Type: verifier.Type(), Message: errors.ErrorCodeVerifyReferenceFailure.NewError(errors.Verifier, verifier.Name(), errors.EmptyLink, err, nil, errors.HideStackTrace).Error()} } else { verifierReport = vt.NewVerifierResult(verifierResult) diff --git a/pkg/executor/core/executor_test.go b/pkg/executor/core/executor_test.go index 6433edab0..36edaff76 100644 --- a/pkg/executor/core/executor_test.go +++ b/pkg/executor/core/executor_test.go @@ -131,10 +131,10 @@ type mockVerifier struct { } func (v *mockVerifier) Name() string { - return "mockVerifier" + return "verifier-mockVerifier" } -func (v *mockVerifier) TypeName() string { +func (v *mockVerifier) Type() string { return "mockVerifier" } diff --git a/pkg/executor/core/testtypes.go b/pkg/executor/core/testtypes.go index 12acb1303..fd28a410d 100644 --- a/pkg/executor/core/testtypes.go +++ b/pkg/executor/core/testtypes.go @@ -31,11 +31,11 @@ type TestVerifier struct { } func (s *TestVerifier) Name() string { - return "test-verifier" + return "verifier-testVerifier" } -func (s *TestVerifier) TypeName() string { - return "test-verifier" +func (s *TestVerifier) Type() string { + return "testVerifier" } func (s *TestVerifier) CanVerify(_ context.Context, referenceDescriptor ocispecs.ReferenceDescriptor) bool { diff --git a/pkg/verifier/api.go b/pkg/verifier/api.go index 41ac70898..00f505de6 100644 --- a/pkg/verifier/api.go +++ b/pkg/verifier/api.go @@ -41,8 +41,8 @@ type ReferenceVerifier interface { // Name returns the name of the verifier Name() string - // TypeName returns the type name of the verifier - TypeName() string + // Type returns the type name of the verifier + Type() string // CanVerify returns if the verifier can verify the given reference CanVerify(ctx context.Context, referenceDescriptor ocispecs.ReferenceDescriptor) bool diff --git a/pkg/verifier/factory/factory.go b/pkg/verifier/factory/factory.go index 40d70ec3d..19e1403cc 100644 --- a/pkg/verifier/factory/factory.go +++ b/pkg/verifier/factory/factory.go @@ -52,7 +52,7 @@ func Register(name string, factory VerifierFactory) { // returns a single verifier from a verifierConfig // namespace is only applicable in K8s environment, namespace is appended to the certstore of the truststore so it is uniquely identifiable in a cluster env func CreateVerifierFromConfig(verifierConfig config.VerifierConfig, configVersion string, pluginBinDir []string, namespace string) (verifier.ReferenceVerifier, error) { - // in cli mode verifier type name can only read from Name property + // in cli mode both `type` and `name`` are read from config, if `type` is not specified, `name` is used as `type` var verifierTypeStr string if value, ok := verifierConfig[types.Name]; ok { verifierTypeStr = value.(string) diff --git a/pkg/verifier/factory/factory_test.go b/pkg/verifier/factory/factory_test.go index 5a1e97bb1..9632f3e77 100644 --- a/pkg/verifier/factory/factory_test.go +++ b/pkg/verifier/factory/factory_test.go @@ -38,7 +38,7 @@ func (s *TestVerifier) Name() string { return "test-verifier-0" } -func (s *TestVerifier) TypeName() string { +func (s *TestVerifier) Type() string { return "test-verifier" } diff --git a/pkg/verifier/notation/notation.go b/pkg/verifier/notation/notation.go index d0967cdc2..56205d318 100644 --- a/pkg/verifier/notation/notation.go +++ b/pkg/verifier/notation/notation.go @@ -46,7 +46,7 @@ import ( ) const ( - verifierTypeName = "notation" + verifierType = "notation" defaultCertPath = "ratify-certs/notation/truststore" ) @@ -65,7 +65,7 @@ type NotationPluginVerifierConfig struct { //nolint:revive // ignore linter to h type notationPluginVerifier struct { name string - typeName string + verifierType string artifactTypes []string notationVerifier *notation.Verifier } @@ -73,7 +73,7 @@ type notationPluginVerifier struct { type notationPluginVerifierFactory struct{} func init() { - factory.Register(verifierTypeName, ¬ationPluginVerifierFactory{}) + factory.Register(verifierType, ¬ationPluginVerifierFactory{}) } func (f *notationPluginVerifierFactory) Create(_ string, verifierConfig config.VerifierConfig, pluginDirectory string, namespace string) (verifier.ReferenceVerifier, error) { @@ -96,7 +96,7 @@ func (f *notationPluginVerifierFactory) Create(_ string, verifierConfig config.V artifactTypes := strings.Split(conf.ArtifactTypes, ",") return ¬ationPluginVerifier{ name: verifierName, - typeName: verifierTypeStr, + verifierType: verifierTypeStr, artifactTypes: artifactTypes, notationVerifier: &verifyService, }, nil @@ -106,8 +106,8 @@ func (v *notationPluginVerifier) Name() string { return v.name } -func (v *notationPluginVerifier) TypeName() string { - return v.typeName +func (v *notationPluginVerifier) Type() string { + return v.verifierType } func (v *notationPluginVerifier) CanVerify(_ context.Context, referenceDescriptor ocispecs.ReferenceDescriptor) bool { @@ -161,7 +161,7 @@ func (v *notationPluginVerifier) Verify(ctx context.Context, return verifier.VerifierResult{ Name: v.name, - Type: v.typeName, + Type: v.verifierType, IsSuccess: true, Message: "signature verification success", Extensions: extensions, diff --git a/pkg/verifier/plugin/plugin.go b/pkg/verifier/plugin/plugin.go index 505310fca..162789baf 100644 --- a/pkg/verifier/plugin/plugin.go +++ b/pkg/verifier/plugin/plugin.go @@ -36,7 +36,7 @@ import ( // VerifierPlugin describes a verifier that is implemented by invoking the plugins type VerifierPlugin struct { name string - typeName string + verifierType string artifactTypes []string nestedReferences []string version string @@ -51,9 +51,9 @@ func NewVerifier(version string, verifierConfig config.VerifierConfig, pluginPat if !ok { return nil, re.ErrorCodeConfigInvalid.WithDetail(fmt.Sprintf("failed to find verifier name in the verifier config with key: %s", types.Name)) } - verifierTypeName := "" + verifierType := "" if _, ok := verifierConfig[types.Type]; ok { - verifierTypeName = fmt.Sprintf("%s", verifierConfig[types.Type]) + verifierType = fmt.Sprintf("%s", verifierConfig[types.Type]) } var nestedReferences []string @@ -72,7 +72,7 @@ func NewVerifier(version string, verifierConfig config.VerifierConfig, pluginPat return &VerifierPlugin{ name: fmt.Sprintf("%s", verifierName), - typeName: verifierTypeName, + verifierType: verifierType, version: version, path: pluginPaths, rawConfig: verifierConfig, @@ -95,8 +95,8 @@ func (vp *VerifierPlugin) Name() string { return vp.name } -func (vp *VerifierPlugin) TypeName() string { - return vp.typeName +func (vp *VerifierPlugin) Type() string { + return vp.verifierType } func (vp *VerifierPlugin) Verify(ctx context.Context, @@ -118,8 +118,8 @@ func (vp *VerifierPlugin) verifyReference( referenceDescriptor ocispecs.ReferenceDescriptor, referrerStoreConfig *rc.StoreConfig) (*verifier.VerifierResult, error) { verifierTypeStr := vp.name - if vp.typeName != "" { - verifierTypeStr = vp.typeName + if vp.verifierType != "" { + verifierTypeStr = vp.verifierType } pluginPath, err := vp.executor.FindInPaths(verifierTypeStr, vp.path) if err != nil { diff --git a/test/bats/helpers.bash b/test/bats/helpers.bash index 62bc3266c..f286a8934 100644 --- a/test/bats/helpers.bash +++ b/test/bats/helpers.bash @@ -49,7 +49,7 @@ assert_cmd_verify_success_with_type() { echo $output return 1 fi - if [[ "$output" != *'"type": notation,'* ]]; then + if [[ "$output" != *'"type": "notation",'* ]]; then echo $output return 1 fi From 0dfeda7459101efb812de368538bd27f2dc7ea32 Mon Sep 17 00:00:00 2001 From: junczhu Date: Mon, 4 Dec 2023 08:54:50 +0000 Subject: [PATCH 21/38] fix: go-lint --- pkg/verifier/notation/notation.go | 2 +- pkg/verifier/plugin/plugin.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/verifier/notation/notation.go b/pkg/verifier/notation/notation.go index 56205d318..d47678f6b 100644 --- a/pkg/verifier/notation/notation.go +++ b/pkg/verifier/notation/notation.go @@ -96,7 +96,7 @@ func (f *notationPluginVerifierFactory) Create(_ string, verifierConfig config.V artifactTypes := strings.Split(conf.ArtifactTypes, ",") return ¬ationPluginVerifier{ name: verifierName, - verifierType: verifierTypeStr, + verifierType: verifierTypeStr, artifactTypes: artifactTypes, notationVerifier: &verifyService, }, nil diff --git a/pkg/verifier/plugin/plugin.go b/pkg/verifier/plugin/plugin.go index 162789baf..2d51ebe50 100644 --- a/pkg/verifier/plugin/plugin.go +++ b/pkg/verifier/plugin/plugin.go @@ -36,7 +36,7 @@ import ( // VerifierPlugin describes a verifier that is implemented by invoking the plugins type VerifierPlugin struct { name string - verifierType string + verifierType string artifactTypes []string nestedReferences []string version string @@ -72,7 +72,7 @@ func NewVerifier(version string, verifierConfig config.VerifierConfig, pluginPat return &VerifierPlugin{ name: fmt.Sprintf("%s", verifierName), - verifierType: verifierType, + verifierType: verifierType, version: version, path: pluginPaths, rawConfig: verifierConfig, From 62ae22232e481c309af83845353c9dd893f04410 Mon Sep 17 00:00:00 2001 From: junczhu Date: Mon, 4 Dec 2023 13:55:24 +0000 Subject: [PATCH 22/38] fix: golangci-lint --- pkg/verifier/notation/notation.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/verifier/notation/notation.go b/pkg/verifier/notation/notation.go index d47678f6b..7ac4b6f9a 100644 --- a/pkg/verifier/notation/notation.go +++ b/pkg/verifier/notation/notation.go @@ -46,8 +46,8 @@ import ( ) const ( - verifierType = "notation" - defaultCertPath = "ratify-certs/notation/truststore" + verifierType = "notation" + defaultCertPath = "ratify-certs/notation/truststore" ) // NotationPluginVerifierConfig describes the configuration of notation verifier @@ -65,7 +65,7 @@ type NotationPluginVerifierConfig struct { //nolint:revive // ignore linter to h type notationPluginVerifier struct { name string - verifierType string + verifierType string artifactTypes []string notationVerifier *notation.Verifier } From 2e0bf7fcc386547f88fac990ac63e3b178c6d960 Mon Sep 17 00:00:00 2001 From: junczhu Date: Wed, 6 Dec 2023 05:20:22 +0000 Subject: [PATCH 23/38] fix: rename variable --- pkg/controllers/verifier_controller.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pkg/controllers/verifier_controller.go b/pkg/controllers/verifier_controller.go index 8a4be2438..f8f6ff829 100644 --- a/pkg/controllers/verifier_controller.go +++ b/pkg/controllers/verifier_controller.go @@ -109,15 +109,15 @@ func verifierAddOrReplace(spec configv1beta1.VerifierSpec, objectName string, na spec.Address = config.GetDefaultPluginPath() logrus.Infof("Address was empty, setting to default path: %v", spec.Address) } - // we may rename verifierReference to ReferenceVerifier in the future - verifierReference, err := vf.CreateVerifierFromConfig(verifierConfig, verifierConfigVersion, []string{spec.Address}, namespace) - if err != nil || verifierReference == nil { + referenceVerifier, err := vf.CreateVerifierFromConfig(verifierConfig, verifierConfigVersion, []string{spec.Address}, namespace) + + if err != nil || referenceVerifier == nil { logrus.Error(err, "unable to create verifier from verifier config") return err } - VerifierMap[objectName] = verifierReference - logrus.Infof("verifier '%v' added to verifier map", verifierReference.Name()) + VerifierMap[objectName] = referenceVerifier + logrus.Infof("verifier '%v' added to verifier map", referenceVerifier.Name()) return nil } From 67d93c9f83e430da0d15f607893c2b34dc8077b9 Mon Sep 17 00:00:00 2001 From: junczhu Date: Wed, 6 Dec 2023 08:00:33 +0000 Subject: [PATCH 24/38] test: update e2e test cases --- test/bats/cli-test.bats | 5 +++ test/bats/helpers.bash | 2 +- .../config_external_verifier_with_type.json | 45 +++++++++++++++++++ ...> config_multiple_notation_verifiers.json} | 2 +- .../config_notation_verifier_with_type.json | 43 ------------------ 5 files changed, 52 insertions(+), 45 deletions(-) create mode 100644 test/bats/tests/config/config_external_verifier_with_type.json rename test/bats/tests/config/{config_multiple_notation_verifier.json => config_multiple_notation_verifiers.json} (98%) diff --git a/test/bats/cli-test.bats b/test/bats/cli-test.bats index 70e942ae4..560d0ec46 100644 --- a/test/bats/cli-test.bats +++ b/test/bats/cli-test.bats @@ -69,6 +69,11 @@ load helpers assert_cmd_verify_failure } +@test "licensechecker verifier with type test" { + run bin/ratify verify -c $RATIFY_DIR/config_external_verifier_with_type.json -s $TEST_REGISTRY/licensechecker:v0 + assert_cmd_verify_success_with_type +} + @test "sbom verifier test" { # Notes: test would fail if sbom/notary types are explicitly specified in the policy run bin/ratify verify -c $RATIFY_DIR/config.json -s $TEST_REGISTRY/sbom:v0 diff --git a/test/bats/helpers.bash b/test/bats/helpers.bash index f286a8934..94e5e8e53 100644 --- a/test/bats/helpers.bash +++ b/test/bats/helpers.bash @@ -49,7 +49,7 @@ assert_cmd_verify_success_with_type() { echo $output return 1 fi - if [[ "$output" != *'"type": "notation",'* ]]; then + if [[ "$output" != *'"type":'* ]]; then echo $output return 1 fi diff --git a/test/bats/tests/config/config_external_verifier_with_type.json b/test/bats/tests/config/config_external_verifier_with_type.json new file mode 100644 index 000000000..fc86027a8 --- /dev/null +++ b/test/bats/tests/config/config_external_verifier_with_type.json @@ -0,0 +1,45 @@ +{ + "store": { + "version": "1.0.0", + "plugins": [ + { + "name": "oras", + "useHttp": true + } + ] + }, + "policy": { + "version": "1.0.0", + "plugin": { + "name": "configPolicy", + "artifactVerificationPolicies": { + "application/vnd.ratify.spdx.v0": "all" + } + } + }, + "verifier": { + "version": "1.0.0", + "plugins": [ + { + "name": "verifier-licensechecker", + "type": "licensechecker", + "artifactTypes": "application/vnd.ratify.spdx.v0", + "allowedLicenses": [ + "GPL-2.0-only", + "MIT", + "OpenSSL", + "BSD-2-Clause AND BSD-3-Clause", + "Zlib", + "MPL-2.0 AND MIT", + "ISC", + "Apache-2.0", + "MIT AND BSD-2-Clause AND GPL-2.0-or-later", + "MIT AND LicenseRef-AND AND BSD-2-Clause AND LicenseRef-AND AND GPL-2.0-or-later", + "MPL-2.0 AND LicenseRef-AND AND MIT", + "BSD-2-Clause AND LicenseRef-AND AND BSD-3-Clause", + "NONE" + ] + } + ] + } +} \ No newline at end of file diff --git a/test/bats/tests/config/config_multiple_notation_verifier.json b/test/bats/tests/config/config_multiple_notation_verifiers.json similarity index 98% rename from test/bats/tests/config/config_multiple_notation_verifier.json rename to test/bats/tests/config/config_multiple_notation_verifiers.json index 77c545ecf..b09941cb1 100644 --- a/test/bats/tests/config/config_multiple_notation_verifier.json +++ b/test/bats/tests/config/config_multiple_notation_verifiers.json @@ -47,7 +47,7 @@ } }, { - "name": "verifier-notation-root", + "name": "verifier-notation-leaf", "type": "notation", "artifactTypes": "application/vnd.cncf.notary.signature", "verificationCerts": [ diff --git a/test/bats/tests/config/config_notation_verifier_with_type.json b/test/bats/tests/config/config_notation_verifier_with_type.json index 59147b1f3..789fb2c59 100644 --- a/test/bats/tests/config/config_notation_verifier_with_type.json +++ b/test/bats/tests/config/config_notation_verifier_with_type.json @@ -18,23 +18,6 @@ "verifier": { "version": "1.0.0", "plugins": [ - { - "name": "schemavalidator", - "artifactTypes": "vnd.aquasecurity.trivy.report.sarif.v1", - "schemas": { - "application/sarif+json": "file:///home/runner/.ratify/schemas/sarif-2.1.0-rtm.5.json" - } - }, - { - "name": "sbom", - "artifactTypes": "org.example.sbom.v0", - "nestedReferences": "application/vnd.cncf.notary.signature" - }, - { - "name": "cosign", - "artifactTypes": "application/vnd.dev.cosign.artifact.sig.v1+json", - "key": ".staging/cosign/cosign.pub" - }, { "name": "verifier-notation", "type": "notation", @@ -62,32 +45,6 @@ } ] } - }, - { - "name": "schemavalidator", - "artifactTypes": "vnd.aquasecurity.trivy.report.sarif.v1", - "schemas": { - "application/sarif+json": "https://json.schemastore.org/sarif-2.1.0-rtm.5.json" - } - }, - { - "name": "licensechecker", - "artifactTypes": "application/vnd.ratify.spdx.v0", - "allowedLicenses": [ - "GPL-2.0-only", - "MIT", - "OpenSSL", - "BSD-2-Clause AND BSD-3-Clause", - "Zlib", - "MPL-2.0 AND MIT", - "ISC", - "Apache-2.0", - "MIT AND BSD-2-Clause AND GPL-2.0-or-later", - "MIT AND LicenseRef-AND AND BSD-2-Clause AND LicenseRef-AND AND GPL-2.0-or-later", - "MPL-2.0 AND LicenseRef-AND AND MIT", - "BSD-2-Clause AND LicenseRef-AND AND BSD-3-Clause", - "NONE" - ] } ] } From b12019df8f6091ed7f4f3b5fb333b846168ad760 Mon Sep 17 00:00:00 2001 From: junczhu Date: Wed, 6 Dec 2023 08:42:35 +0000 Subject: [PATCH 25/38] test: update e2e test cases and reports --- plugins/verifier/cosign/cosign.go | 6 ++++++ .../verifier/licensechecker/licensechecker.go | 9 ++++++++- plugins/verifier/sample/sample.go | 6 ++++++ plugins/verifier/sbom/sbom.go | 14 ++++++++++++-- plugins/verifier/sbom/sbom_test.go | 4 ++-- .../schemavalidator/schema_validator.go | 10 ++++++++-- .../vulnerability_report.go | 18 ++++++++++++++++-- .../vulnerability_report_test.go | 2 +- test/bats/cli-test.bats | 2 +- .../config_notation_verifier_with_type.json | 4 ++-- 10 files changed, 62 insertions(+), 13 deletions(-) diff --git a/plugins/verifier/cosign/cosign.go b/plugins/verifier/cosign/cosign.go index d7c995b85..cc8a97b91 100644 --- a/plugins/verifier/cosign/cosign.go +++ b/plugins/verifier/cosign/cosign.go @@ -47,6 +47,7 @@ import ( type PluginConfig struct { Name string `json:"name"` + Type string `json:"type"` KeyRef string `json:"key"` RekorURL string `json:"rekorURL"` // config specific to the plugin @@ -95,6 +96,10 @@ func VerifyReference(args *skel.CmdArgs, subjectReference common.Reference, refe if err != nil { return nil, err } + verifierType := "" + if input.Config.Type != "" { + verifierType = input.Config.Type + } keyRef := input.Config.KeyRef rekorURL := input.Config.RekorURL cosignOpts := &cosign.CheckOpts{ @@ -193,6 +198,7 @@ func VerifyReference(args *skel.CmdArgs, subjectReference common.Reference, refe if len(signatures) > 0 { return &verifier.VerifierResult{ Name: input.Config.Name, + Type: verifierType, IsSuccess: true, Message: "cosign verification success. valid signatures found", Extensions: Extension{SignatureExtension: sigExtensions}, diff --git a/plugins/verifier/licensechecker/licensechecker.go b/plugins/verifier/licensechecker/licensechecker.go index 3419d41fd..ec7c1dcb9 100644 --- a/plugins/verifier/licensechecker/licensechecker.go +++ b/plugins/verifier/licensechecker/licensechecker.go @@ -32,6 +32,7 @@ import ( type PluginConfig struct { Name string `json:"name"` + Type string `json:"type"` AllowedLicenses []string `json:"allowedLicenses"` } @@ -58,7 +59,10 @@ func VerifyReference(args *skel.CmdArgs, subjectReference common.Reference, desc if err != nil { return nil, err } - + verifierType := "" + if input.Type != "" { + verifierType = input.Type + } allowedLicenses := utils.LoadAllowedLicenses(input.AllowedLicenses) ctx := context.Background() @@ -70,6 +74,7 @@ func VerifyReference(args *skel.CmdArgs, subjectReference common.Reference, desc if len(referenceManifest.Blobs) == 0 { return &verifier.VerifierResult{ Name: input.Name, + Type: verifierType, IsSuccess: false, Message: fmt.Sprintf("License Check FAILED: no blobs found for referrer %s@%s", subjectReference.Path, descriptor.Digest.String()), }, nil @@ -92,6 +97,7 @@ func VerifyReference(args *skel.CmdArgs, subjectReference common.Reference, desc if len(disallowedLicenses) > 0 { return &verifier.VerifierResult{ Name: input.Name, + Type: verifierType, IsSuccess: false, Message: fmt.Sprintf("License Check: FAILED. %s", disallowedLicenses), }, nil @@ -100,6 +106,7 @@ func VerifyReference(args *skel.CmdArgs, subjectReference common.Reference, desc return &verifier.VerifierResult{ Name: input.Name, + Type: verifierType, IsSuccess: true, Message: "License Check: SUCCESS. All packages have allowed licenses", }, nil diff --git a/plugins/verifier/sample/sample.go b/plugins/verifier/sample/sample.go index 27a14b816..7426b1998 100644 --- a/plugins/verifier/sample/sample.go +++ b/plugins/verifier/sample/sample.go @@ -28,6 +28,7 @@ import ( type PluginConfig struct { Name string `json:"name"` + Type string `json:"type"` // config specific to the plugin } @@ -54,9 +55,14 @@ func VerifyReference(args *skel.CmdArgs, _ common.Reference, referenceDescriptor if err != nil { return nil, err } + verifierType := "" + if input.Type != "" { + verifierType = input.Type + } return &verifier.VerifierResult{ Name: input.Name, + Type: verifierType, IsSuccess: referenceDescriptor.Size > 0, Message: "Sample verification success", }, nil diff --git a/plugins/verifier/sbom/sbom.go b/plugins/verifier/sbom/sbom.go index 30f08263d..fb50a1d0a 100644 --- a/plugins/verifier/sbom/sbom.go +++ b/plugins/verifier/sbom/sbom.go @@ -37,6 +37,7 @@ import ( // PluginConfig describes the configuration of the sbom verifier type PluginConfig struct { Name string `json:"name"` + Type string `json:"type"` } type PluginInputConfig struct { @@ -71,12 +72,17 @@ func VerifyReference(args *skel.CmdArgs, subjectReference common.Reference, refe if err != nil { return nil, err } + verifierType := "" + if input.Type != "" { + verifierType = input.Type + } ctx := context.Background() referenceManifest, err := referrerStore.GetReferenceManifest(ctx, subjectReference, referenceDescriptor) if err != nil { return &verifier.VerifierResult{ Name: input.Name, + Type: verifierType, IsSuccess: false, Message: fmt.Sprintf("Error fetching reference manifest for subject: %s reference descriptor: %v", subjectReference, referenceDescriptor.Descriptor), }, err @@ -90,6 +96,7 @@ func VerifyReference(args *skel.CmdArgs, subjectReference common.Reference, refe if err != nil { return &verifier.VerifierResult{ Name: input.Name, + Type: verifierType, IsSuccess: false, Message: fmt.Sprintf("Error fetching blob for subject: %s digest: %s", subjectReference, blobDesc.Digest), }, err @@ -97,24 +104,26 @@ func VerifyReference(args *skel.CmdArgs, subjectReference common.Reference, refe switch mediaType { case SpdxJSONMediaType: - return processSpdxJSONMediaType(input.Name, refBlob) + return processSpdxJSONMediaType(input.Name, verifierType, refBlob) default: } } return &verifier.VerifierResult{ Name: input.Name, + Type: verifierType, IsSuccess: false, Message: fmt.Sprintf("Unsupported mediaType: %s", mediaType), }, nil } -func processSpdxJSONMediaType(name string, refBlob []byte) (*verifier.VerifierResult, error) { +func processSpdxJSONMediaType(name string, verifierType string, refBlob []byte) (*verifier.VerifierResult, error) { var err error var doc *v2_3.Document if doc, err = jsonLoader.Read(bytes.NewReader(refBlob)); doc != nil { return &verifier.VerifierResult{ Name: name, + Type: verifierType, IsSuccess: true, Extensions: doc.CreationInfo, Message: "SBOM verification success. The schema is good.", @@ -122,6 +131,7 @@ func processSpdxJSONMediaType(name string, refBlob []byte) (*verifier.VerifierRe } return &verifier.VerifierResult{ Name: name, + Type: verifierType, IsSuccess: false, Message: fmt.Sprintf("SBOM failed to parse: %v", err), }, err diff --git a/plugins/verifier/sbom/sbom_test.go b/plugins/verifier/sbom/sbom_test.go index 133dd1d19..8ac815405 100644 --- a/plugins/verifier/sbom/sbom_test.go +++ b/plugins/verifier/sbom/sbom_test.go @@ -25,7 +25,7 @@ func TestProcessSPDXJsonMediaType(t *testing.T) { if err != nil { t.Fatalf("error reading %s", filepath.Join("testdata", "bom.json")) } - vr, err := processSpdxJSONMediaType("test", b) + vr, err := processSpdxJSONMediaType("test", "", b) if err != nil { t.Fatalf("expected to process spdx json file: %s", filepath.Join("testdata", "bom.json")) } @@ -39,7 +39,7 @@ func TestProcessInvalidSPDXJsonMediaType(t *testing.T) { if err != nil { t.Fatalf("error reading %s", filepath.Join("testdata", "invalid-bom.json")) } - _, err = processSpdxJSONMediaType("test", b) + _, err = processSpdxJSONMediaType("test", "", b) if err == nil { t.Fatalf("expected to have an error processing spdx json file: %s", filepath.Join("testdata", "bom.json")) } diff --git a/plugins/verifier/schemavalidator/schema_validator.go b/plugins/verifier/schemavalidator/schema_validator.go index ba242dfae..2dd5fec02 100644 --- a/plugins/verifier/schemavalidator/schema_validator.go +++ b/plugins/verifier/schemavalidator/schema_validator.go @@ -31,6 +31,7 @@ import ( type PluginConfig struct { Name string `json:"name"` + Type string `json:"type"` Schemas map[string]string `json:"schemas"` } @@ -54,11 +55,13 @@ func parseInput(stdin []byte) (*PluginConfig, error) { func VerifyReference(args *skel.CmdArgs, subjectReference common.Reference, referenceDescriptor ocispecs.ReferenceDescriptor, referrerStore referrerstore.ReferrerStore) (*verifier.VerifierResult, error) { input, err := parseInput(args.StdinData) - if err != nil { return nil, err } - + verifierType := "" + if input.Type != "" { + verifierType = input.Type + } schemaMap := input.Schemas ctx := context.Background() @@ -70,6 +73,7 @@ func VerifyReference(args *skel.CmdArgs, subjectReference common.Reference, refe if len(referenceManifest.Blobs) == 0 { return &verifier.VerifierResult{ Name: input.Name, + Type: verifierType, IsSuccess: false, Message: fmt.Sprintf("schema validation failed: no blobs found for referrer %s@%s", subjectReference.Path, referenceDescriptor.Digest.String()), }, nil @@ -85,6 +89,7 @@ func VerifyReference(args *skel.CmdArgs, subjectReference common.Reference, refe if err != nil { return &verifier.VerifierResult{ Name: input.Name, + Type: verifierType, IsSuccess: false, Message: fmt.Sprintf("schema validation failed for digest:[%s],media type:[%s],parse errors:[%v]", blobDesc.Digest, blobDesc.MediaType, err.Error()), }, nil @@ -93,6 +98,7 @@ func VerifyReference(args *skel.CmdArgs, subjectReference common.Reference, refe return &verifier.VerifierResult{ Name: input.Name, + Type: verifierType, IsSuccess: true, Message: "schema validation passed for configured media types", }, nil diff --git a/plugins/verifier/vulnerabilityreport/vulnerability_report.go b/plugins/verifier/vulnerabilityreport/vulnerability_report.go index 60d0cd8c1..27b31fefa 100644 --- a/plugins/verifier/vulnerabilityreport/vulnerability_report.go +++ b/plugins/verifier/vulnerabilityreport/vulnerability_report.go @@ -50,6 +50,7 @@ const ( type PluginConfig struct { Name string `json:"name"` + Type string `json:"type"` SchemaURL string `json:"schemaURL,omitempty"` CreatedAnnotationName string `json:"createdAnnotationName,omitempty"` MaximumAge string `json:"maximumAge,omitempty"` @@ -81,6 +82,10 @@ func VerifyReference(args *skel.CmdArgs, subjectReference common.Reference, refe if err != nil { return nil, err } + verifierType := "" + if input.Type != "" { + verifierType = input.Type + } // extract created timestamp from descriptor annotations if input.CreatedAnnotationName == "" { @@ -90,6 +95,7 @@ func VerifyReference(args *skel.CmdArgs, subjectReference common.Reference, refe if err != nil { return &verifier.VerifierResult{ Name: input.Name, + Type: verifierType, IsSuccess: false, Message: fmt.Sprintf("vulnerability report validation failed: error extracting create timestamp annotation:[%v]", err.Error()), }, nil @@ -101,6 +107,7 @@ func VerifyReference(args *skel.CmdArgs, subjectReference common.Reference, refe if err != nil { return &verifier.VerifierResult{ Name: input.Name, + Type: verifierType, IsSuccess: false, Message: fmt.Sprintf("vulnerability report validation failed: error validating maximum age:[%v]", err.Error()), Extensions: map[string]interface{}{ @@ -111,6 +118,7 @@ func VerifyReference(args *skel.CmdArgs, subjectReference common.Reference, refe if !ok { return &verifier.VerifierResult{ Name: input.Name, + Type: verifierType, IsSuccess: false, Message: fmt.Sprintf("vulnerability report validation failed: report is older than maximum age:[%s]", input.MaximumAge), Extensions: map[string]interface{}{ @@ -126,6 +134,7 @@ func VerifyReference(args *skel.CmdArgs, subjectReference common.Reference, refe if err != nil { return &verifier.VerifierResult{ Name: input.Name, + Type: verifierType, IsSuccess: false, Message: fmt.Sprintf("error fetching reference manifest for subject: %s reference descriptor: %v: [%v]", subjectReference, referenceDescriptor.Descriptor, err.Error()), Extensions: map[string]interface{}{ @@ -137,6 +146,7 @@ func VerifyReference(args *skel.CmdArgs, subjectReference common.Reference, refe if len(referenceManifest.Blobs) == 0 { return &verifier.VerifierResult{ Name: input.Name, + Type: verifierType, IsSuccess: false, Message: fmt.Sprintf("vulnerability report validation failed: no layers found in manifest for referrer %s@%s", subjectReference.Path, referenceDescriptor.Digest.String()), Extensions: map[string]interface{}{ @@ -150,6 +160,7 @@ func VerifyReference(args *skel.CmdArgs, subjectReference common.Reference, refe if err != nil { return &verifier.VerifierResult{ Name: input.Name, + Type: verifierType, IsSuccess: false, Message: fmt.Sprintf("error fetching blob for subject:[%s] digest:[%s]: [%v]", subjectReference, blobDesc.Digest, err.Error()), Extensions: map[string]interface{}{ @@ -162,6 +173,7 @@ func VerifyReference(args *skel.CmdArgs, subjectReference common.Reference, refe if input.Passthrough { return &verifier.VerifierResult{ Name: input.Name, + Type: verifierType, IsSuccess: true, Message: "vulnerability report validation skipped", Extensions: map[string]interface{}{ @@ -176,6 +188,7 @@ func VerifyReference(args *skel.CmdArgs, subjectReference common.Reference, refe if err := verifyJSONSchema(referenceDescriptor.ArtifactType, refBlob, input.SchemaURL); err != nil { return &verifier.VerifierResult{ Name: input.Name, + Type: verifierType, IsSuccess: false, Message: fmt.Sprintf("vulnerability report validation failed: schema validation failed for digest:[%s],artifact type:[%s],parse errors:[%v]", blobDesc.Digest, referenceDescriptor.ArtifactType, err.Error()), Extensions: map[string]interface{}{ @@ -185,11 +198,12 @@ func VerifyReference(args *skel.CmdArgs, subjectReference common.Reference, refe } if referenceDescriptor.ArtifactType == SarifArtifactType { - return processSarifReport(input, input.Name, refBlob, createdTime) + return processSarifReport(input, input.Name, verifierType, refBlob, createdTime) } return &verifier.VerifierResult{ Name: input.Name, + Type: verifierType, IsSuccess: true, Message: "vulnerability report validation succeeded", Extensions: map[string]interface{}{ @@ -217,7 +231,7 @@ func verifyJSONSchema(artifactType string, refBlob []byte, schemaURL string) err } // processSarifReport processes the sarif report running individual validations as configured -func processSarifReport(input *PluginConfig, verifierName string, blob []byte, createdTime time.Time) (*verifier.VerifierResult, error) { +func processSarifReport(input *PluginConfig, verifierName string, verifierType string, blob []byte, createdTime time.Time) (*verifier.VerifierResult, error) { sarifReport, err := sarif.FromBytes(blob) if err != nil { return &verifier.VerifierResult{ diff --git a/plugins/verifier/vulnerabilityreport/vulnerability_report_test.go b/plugins/verifier/vulnerabilityreport/vulnerability_report_test.go index d06c5af91..531a41f82 100644 --- a/plugins/verifier/vulnerabilityreport/vulnerability_report_test.go +++ b/plugins/verifier/vulnerabilityreport/vulnerability_report_test.go @@ -398,7 +398,7 @@ func TestProcessSarifReport(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - verifierReport, err := processSarifReport(&tt.args.input, "sample_verifier", []byte(tt.args.blobContent), time.Now()) + verifierReport, err := processSarifReport(&tt.args.input, "sample_verifier", "", []byte(tt.args.blobContent), time.Now()) if err != nil && err.Error() != tt.want.err.Error() { t.Errorf("processSarifReport() error = %v, wantErr %v", err, tt.want.err) return diff --git a/test/bats/cli-test.bats b/test/bats/cli-test.bats index 3e6db306e..ba9178565 100644 --- a/test/bats/cli-test.bats +++ b/test/bats/cli-test.bats @@ -32,7 +32,7 @@ load helpers } @test "notation verifier with type test" { - run bin/ratify verify -c $RATIFY_DIR/config_notation_verifier_with_type.json -s $TEST_REGISTRY/notation:signed + run bin/ratify verify -c $RATIFY_DIR/config_notation_verifier_with_type.json -s $TEST_REGISTRY/notation:leafSigned assert_cmd_verify_success_with_type } diff --git a/test/bats/tests/config/config_notation_verifier_with_type.json b/test/bats/tests/config/config_notation_verifier_with_type.json index 789fb2c59..f7dea47b3 100644 --- a/test/bats/tests/config/config_notation_verifier_with_type.json +++ b/test/bats/tests/config/config_notation_verifier_with_type.json @@ -19,11 +19,11 @@ "version": "1.0.0", "plugins": [ { - "name": "verifier-notation", + "name": "verifier-notation-root", "type": "notation", "artifactTypes": "application/vnd.cncf.notary.signature", "verificationCerts": [ - "~/.config/notation/localkeys/ratify-bats-test.crt" + "~/.config/notation/truststore/x509/ca/leaf-test/root.crt" ], "trustPolicyDoc": { "version": "1.0", From bdb93e2e50ecb023263ecd9d018b0cb9a6b220a0 Mon Sep 17 00:00:00 2001 From: junczhu Date: Wed, 6 Dec 2023 11:05:12 +0000 Subject: [PATCH 26/38] test: update e2e test cases and reports2 --- plugins/verifier/cosign/cosign.go | 29 ++++++++++--------- .../vulnerability_report.go | 19 +++++++++--- .../vulnerability_report_test.go | 4 +-- .../config_multiple_notation_verifiers.json | 8 ++--- 4 files changed, 36 insertions(+), 24 deletions(-) diff --git a/plugins/verifier/cosign/cosign.go b/plugins/verifier/cosign/cosign.go index cc8a97b91..a70a0b2c6 100644 --- a/plugins/verifier/cosign/cosign.go +++ b/plugins/verifier/cosign/cosign.go @@ -111,33 +111,33 @@ func VerifyReference(args *skel.CmdArgs, subjectReference common.Reference, refe if keyRef != "" { ecdsaVerifier, err = loadPublicKey(ctx, keyRef) if err != nil { - return errorToVerifyResult(input.Config.Name, fmt.Errorf("failed to load public key: %w", err)), nil + return errorToVerifyResult(input.Config.Name, verifierType, fmt.Errorf("failed to load public key: %w", err)), nil } cosignOpts.SigVerifier = ecdsaVerifier } else { roots, err = fulcio.GetRoots() if err != nil { - return errorToVerifyResult(input.Config.Name, fmt.Errorf("failed to get fulcio roots: %w", err)), nil + return errorToVerifyResult(input.Config.Name, verifierType, fmt.Errorf("failed to get fulcio roots: %w", err)), nil } cosignOpts.RootCerts = roots if cosignOpts.RootCerts == nil { - return errorToVerifyResult(input.Config.Name, fmt.Errorf("failed to initialize root certificates")), nil + return errorToVerifyResult(input.Config.Name, verifierType, fmt.Errorf("failed to initialize root certificates")), nil } } if rekorURL != "" { cosignOpts.RekorClient, err = rekor.NewClient(rekorURL) if err != nil { - return errorToVerifyResult(input.Config.Name, fmt.Errorf("failed to create Rekor client from URL %s: %w", rekorURL, err)), nil + return errorToVerifyResult(input.Config.Name, verifierType, fmt.Errorf("failed to create Rekor client from URL %s: %w", rekorURL, err)), nil } cosignOpts.CTLogPubKeys, err = cosign.GetCTLogPubs(ctx) if err != nil { - return errorToVerifyResult(input.Config.Name, fmt.Errorf("failed to set Certificate Transparency Log public keys: %w", err)), nil + return errorToVerifyResult(input.Config.Name, verifierType, fmt.Errorf("failed to set Certificate Transparency Log public keys: %w", err)), nil } // Fetches the Rekor public keys from the Rekor server cosignOpts.RekorPubKeys, err = cosign.GetRekorPubs(ctx) if err != nil { - return errorToVerifyResult(input.Config.Name, fmt.Errorf("failed to set Rekor public keys: %w", err)), nil + return errorToVerifyResult(input.Config.Name, verifierType, fmt.Errorf("failed to set Rekor public keys: %w", err)), nil } } else { // if no rekor url is provided, turn off transparency log verification and ignore SCTs @@ -147,17 +147,17 @@ func VerifyReference(args *skel.CmdArgs, subjectReference common.Reference, refe referenceManifest, err := referrerStore.GetReferenceManifest(ctx, subjectReference, referenceDescriptor) if err != nil { - return errorToVerifyResult(input.Config.Name, fmt.Errorf("failed to get reference manifest: %w", err)), nil + return errorToVerifyResult(input.Config.Name, verifierType, fmt.Errorf("failed to get reference manifest: %w", err)), nil } // manifest must be an OCI Image if referenceManifest.MediaType != imgspec.MediaTypeImageManifest { - return errorToVerifyResult(input.Config.Name, fmt.Errorf("reference manifest is not an image")), nil + return errorToVerifyResult(input.Config.Name, verifierType, fmt.Errorf("reference manifest is not an image")), nil } subjectDesc, err := referrerStore.GetSubjectDescriptor(ctx, subjectReference) if err != nil { - return errorToVerifyResult(input.Config.Name, fmt.Errorf("failed to create subject hash: %w", err)), nil + return errorToVerifyResult(input.Config.Name, verifierType, fmt.Errorf("failed to create subject hash: %w", err)), nil } subjectDescHash := v1.Hash{ Algorithm: subjectDesc.Digest.Algorithm().String(), @@ -169,15 +169,15 @@ func VerifyReference(args *skel.CmdArgs, subjectReference common.Reference, refe for _, blob := range referenceManifest.Blobs { blobBytes, err := referrerStore.GetBlobContent(ctx, subjectReference, blob.Digest) if err != nil { - return errorToVerifyResult(input.Config.Name, fmt.Errorf("failed to get blob content: %w", err)), nil + return errorToVerifyResult(input.Config.Name, verifierType, fmt.Errorf("failed to get blob content: %w", err)), nil } staticOpts, err := staticLayerOpts(blob) if err != nil { - return errorToVerifyResult(input.Config.Name, fmt.Errorf("failed to parse static signature opts: %w", err)), nil + return errorToVerifyResult(input.Config.Name, verifierType, fmt.Errorf("failed to parse static signature opts: %w", err)), nil } sig, err := static.NewSignature(blobBytes, blob.Annotations[static.SignatureAnnotationKey], staticOpts...) if err != nil { - return errorToVerifyResult(input.Config.Name, fmt.Errorf("failed to generate static signature: %w", err)), nil + return errorToVerifyResult(input.Config.Name, verifierType, fmt.Errorf("failed to generate static signature: %w", err)), nil } // The verification will return an error if the signature is not valid. bundleVerified, err := cosign.VerifyImageSignature(ctx, sig, subjectDescHash, cosignOpts) @@ -205,7 +205,7 @@ func VerifyReference(args *skel.CmdArgs, subjectReference common.Reference, refe }, nil } - errorResult := errorToVerifyResult(input.Config.Name, fmt.Errorf("no valid signatures found")) + errorResult := errorToVerifyResult(input.Config.Name, verifierType, fmt.Errorf("no valid signatures found")) errorResult.Extensions = Extension{SignatureExtension: sigExtensions} return errorResult, nil } @@ -244,10 +244,11 @@ func staticLayerOpts(desc imgspec.Descriptor) ([]static.Option, error) { return options, nil } -func errorToVerifyResult(name string, err error) *verifier.VerifierResult { +func errorToVerifyResult(name string, verifierType string, err error) *verifier.VerifierResult { return &verifier.VerifierResult{ IsSuccess: false, Name: name, + Type: verifierType, Message: errors.Wrap(err, "cosign verification failed").Error(), } } diff --git a/plugins/verifier/vulnerabilityreport/vulnerability_report.go b/plugins/verifier/vulnerabilityreport/vulnerability_report.go index 27b31fefa..a3eb495c0 100644 --- a/plugins/verifier/vulnerabilityreport/vulnerability_report.go +++ b/plugins/verifier/vulnerabilityreport/vulnerability_report.go @@ -236,6 +236,7 @@ func processSarifReport(input *PluginConfig, verifierName string, verifierType s if err != nil { return &verifier.VerifierResult{ Name: verifierName, + Type: verifierType, IsSuccess: false, Message: fmt.Sprintf("vulnerability report validation failed: error parsing sarif report:[%v]", err.Error()), Extensions: map[string]interface{}{ @@ -247,6 +248,7 @@ func processSarifReport(input *PluginConfig, verifierName string, verifierType s if len(sarifReport.Runs) < 1 { return &verifier.VerifierResult{ Name: verifierName, + Type: verifierType, IsSuccess: false, Message: "vulnerability report validation failed: no runs found in sarif report", Extensions: map[string]interface{}{ @@ -256,7 +258,7 @@ func processSarifReport(input *PluginConfig, verifierName string, verifierType s } scannerName := strings.ToLower(sarifReport.Runs[0].Tool.Driver.Name) if len(input.DenylistCVEs) > 0 { - verifierReport, err := verifyDenyListCVEs(input.Name, scannerName, sarifReport, input.DenylistCVEs, createdTime) + verifierReport, err := verifyDenyListCVEs(input.Name, verifierType, scannerName, sarifReport, input.DenylistCVEs, createdTime) if err != nil { return nil, err } @@ -265,7 +267,7 @@ func processSarifReport(input *PluginConfig, verifierName string, verifierType s } } if len(input.DisallowedSeverities) > 0 { - verifierReport, err := verifyDisallowedSeverities(input.Name, scannerName, sarifReport, input.DisallowedSeverities, createdTime) + verifierReport, err := verifyDisallowedSeverities(input.Name, verifierType, scannerName, sarifReport, input.DisallowedSeverities, createdTime) if err != nil { return nil, err } @@ -276,6 +278,7 @@ func processSarifReport(input *PluginConfig, verifierName string, verifierType s return &verifier.VerifierResult{ Name: verifierName, + Type: verifierType, IsSuccess: true, Message: "vulnerability report validation succeeded", Extensions: map[string]interface{}{ @@ -286,7 +289,7 @@ func processSarifReport(input *PluginConfig, verifierName string, verifierType s } // verifyDenyListCVEs verifies that the report does not contain any deny-listed CVEs -func verifyDenyListCVEs(verifierName string, scannerName string, sarifReport *sarif.Report, denylistCVEs []string, createdTime time.Time) (*verifier.VerifierResult, error) { +func verifyDenyListCVEs(verifierName string, verifierType string, scannerName string, sarifReport *sarif.Report, denylistCVEs []string, createdTime time.Time) (*verifier.VerifierResult, error) { denylistCVESet := make(map[string]bool) denylistViolations := []string{} @@ -300,6 +303,7 @@ func verifyDenyListCVEs(verifierName string, scannerName string, sarifReport *sa if result.RuleID == nil || *result.RuleID == "" { return &verifier.VerifierResult{ Name: verifierName, + Type: verifierType, IsSuccess: false, Message: fmt.Sprintf("vulnerability report validation failed: rule id not found for result:[%v]", result), Extensions: map[string]interface{}{ @@ -324,6 +328,7 @@ func verifyDenyListCVEs(verifierName string, scannerName string, sarifReport *sa if len(denylistViolations) > 0 { return &verifier.VerifierResult{ Name: verifierName, + Type: verifierType, IsSuccess: false, Extensions: map[string]interface{}{ "scanner": scannerName, @@ -336,6 +341,7 @@ func verifyDenyListCVEs(verifierName string, scannerName string, sarifReport *sa return &verifier.VerifierResult{ Name: verifierName, + Type: verifierType, IsSuccess: true, Message: "vulnerability report validation succeeded", Extensions: map[string]interface{}{ @@ -346,7 +352,7 @@ func verifyDenyListCVEs(verifierName string, scannerName string, sarifReport *sa } // verifyDisallowedSeverities verifies that the report does not contain any disallowed severity levels -func verifyDisallowedSeverities(verifierName string, scannerName string, sarifReport *sarif.Report, disallowedSeverities []string, createdTime time.Time) (*verifier.VerifierResult, error) { +func verifyDisallowedSeverities(verifierName string, verifierType string, scannerName string, sarifReport *sarif.Report, disallowedSeverities []string, createdTime time.Time) (*verifier.VerifierResult, error) { ruleMap := make(map[string]*sarif.ReportingDescriptor) violatingRules := make([]sarif.ReportingDescriptor, 0) // create a map of rule id to rule for easy lookup @@ -358,6 +364,7 @@ func verifyDisallowedSeverities(verifierName string, scannerName string, sarifRe if result.RuleID == nil || *result.RuleID == "" { return &verifier.VerifierResult{ Name: verifierName, + Type: verifierType, IsSuccess: false, Message: fmt.Sprintf("vulnerability report validation failed: rule id not found for result:[%v]", result), Extensions: map[string]interface{}{ @@ -370,6 +377,7 @@ func verifyDisallowedSeverities(verifierName string, scannerName string, sarifRe if !ok { return &verifier.VerifierResult{ Name: verifierName, + Type: verifierType, IsSuccess: false, Message: fmt.Sprintf("vulnerability report validation failed: rule not found for result:[%v]", result), Extensions: map[string]interface{}{ @@ -382,6 +390,7 @@ func verifyDisallowedSeverities(verifierName string, scannerName string, sarifRe if err != nil { return &verifier.VerifierResult{ Name: verifierName, + Type: verifierType, IsSuccess: false, Message: fmt.Sprintf("vulnerability report validation failed: error extracting severity:[%v]", err.Error()), Extensions: map[string]interface{}{ @@ -401,6 +410,7 @@ func verifyDisallowedSeverities(verifierName string, scannerName string, sarifRe if len(violatingRules) > 0 { return &verifier.VerifierResult{ Name: verifierName, + Type: verifierType, IsSuccess: false, Extensions: map[string]interface{}{ "scanner": scannerName, @@ -412,6 +422,7 @@ func verifyDisallowedSeverities(verifierName string, scannerName string, sarifRe } return &verifier.VerifierResult{ Name: verifierName, + Type: verifierType, IsSuccess: true, Message: "vulnerability report validation succeeded", Extensions: map[string]interface{}{ diff --git a/plugins/verifier/vulnerabilityreport/vulnerability_report_test.go b/plugins/verifier/vulnerabilityreport/vulnerability_report_test.go index 531a41f82..1e2adff47 100644 --- a/plugins/verifier/vulnerabilityreport/vulnerability_report_test.go +++ b/plugins/verifier/vulnerabilityreport/vulnerability_report_test.go @@ -521,7 +521,7 @@ func TestVerifyDenyListCVEs(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - verifierReport, err := verifyDenyListCVEs("test_verifier", TrivyScannerName, &tt.args.sarifReport, tt.args.denyListCVEs, time.Now()) + verifierReport, err := verifyDenyListCVEs("test_verifier", "", TrivyScannerName, &tt.args.sarifReport, tt.args.denyListCVEs, time.Now()) if err != nil && err.Error() != tt.want.err.Error() { t.Errorf("verifyDenyListCVEs() error = %v, wantErr %v", err, tt.want.err) return @@ -729,7 +729,7 @@ func TestVerifyDisallowedSeverities(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - verifierReport, err := verifyDisallowedSeverities("test_verifier", TrivyScannerName, &tt.args.sarifReport, tt.args.disallowedSeverities, time.Now()) + verifierReport, err := verifyDisallowedSeverities("test_verifier", "", TrivyScannerName, &tt.args.sarifReport, tt.args.disallowedSeverities, time.Now()) if err != nil && err.Error() != tt.want.err.Error() { t.Errorf("verifyDisallowedSeverities() error = %v, wantErr %v", err, tt.want.err) return diff --git a/test/bats/tests/config/config_multiple_notation_verifiers.json b/test/bats/tests/config/config_multiple_notation_verifiers.json index b09941cb1..f45292c38 100644 --- a/test/bats/tests/config/config_multiple_notation_verifiers.json +++ b/test/bats/tests/config/config_multiple_notation_verifiers.json @@ -19,11 +19,11 @@ "version": "1.0.0", "plugins": [ { - "name": "verifier-notation-root", + "name": "verifier-notation-leaf", "type": "notation", "artifactTypes": "application/vnd.cncf.notary.signature", "verificationCerts": [ - "~/.config/notation/truststore/x509/ca/leaf-test/root.crt" + "~/.config/notation/truststore/x509/ca/leaf-test/leaf.crt" ], "trustPolicyDoc": { "version": "1.0", @@ -47,11 +47,11 @@ } }, { - "name": "verifier-notation-leaf", + "name": "verifier-notation-root", "type": "notation", "artifactTypes": "application/vnd.cncf.notary.signature", "verificationCerts": [ - "~/.config/notation/truststore/x509/ca/leaf-test/leaf.crt" + "~/.config/notation/truststore/x509/ca/leaf-test/root.crt" ], "trustPolicyDoc": { "version": "1.0", From 053802c27f587e936a4f13e9db09bf6d37f18124 Mon Sep 17 00:00:00 2001 From: junczhu Date: Wed, 6 Dec 2023 12:14:29 +0000 Subject: [PATCH 27/38] test: update e2e test cases and reports3 --- .../config_multiple_notation_verifiers.json | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/test/bats/tests/config/config_multiple_notation_verifiers.json b/test/bats/tests/config/config_multiple_notation_verifiers.json index f45292c38..2a123ec50 100644 --- a/test/bats/tests/config/config_multiple_notation_verifiers.json +++ b/test/bats/tests/config/config_multiple_notation_verifiers.json @@ -1,29 +1,31 @@ { + "executor": {}, "store": { "version": "1.0.0", "plugins": [ { "name": "oras", - "cosignEnabled": true, - "useHttp": true + "cosignEnabled": true } ] }, "policy": { "version": "1.0.0", "plugin": { - "name": "configPolicy" + "name": "regoPolicy", + "policyPath": "", + "policy": "package ratify.policy\ndefault valid := false\nvalid {\n not failed_verify(input)\n}\nfailed_verify(reports) {\n [path, value] := walk(reports)\n value == false\n path[count(path) - 1] == \"isSuccess\"\n}" } }, "verifier": { "version": "1.0.0", "plugins": [ { - "name": "verifier-notation-leaf", + "name": "verifier-notation-root", "type": "notation", "artifactTypes": "application/vnd.cncf.notary.signature", "verificationCerts": [ - "~/.config/notation/truststore/x509/ca/leaf-test/leaf.crt" + "~/.config/notation/truststore/x509/ca/leaf-test/root.crt" ], "trustPolicyDoc": { "version": "1.0", @@ -47,11 +49,11 @@ } }, { - "name": "verifier-notation-root", + "name": "verifier-notation-leaf", "type": "notation", "artifactTypes": "application/vnd.cncf.notary.signature", "verificationCerts": [ - "~/.config/notation/truststore/x509/ca/leaf-test/root.crt" + "~/.config/notation/truststore/x509/ca/leaf-test/leaf.crt" ], "trustPolicyDoc": { "version": "1.0", From 41a1e9200c80a27a53d26b33d9dd03b0f657b1a1 Mon Sep 17 00:00:00 2001 From: junczhu Date: Wed, 6 Dec 2023 12:17:18 +0000 Subject: [PATCH 28/38] test: update e2e test cases and reports4 --- test/bats/tests/config/config_multiple_notation_verifiers.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/bats/tests/config/config_multiple_notation_verifiers.json b/test/bats/tests/config/config_multiple_notation_verifiers.json index 2a123ec50..b646e38fa 100644 --- a/test/bats/tests/config/config_multiple_notation_verifiers.json +++ b/test/bats/tests/config/config_multiple_notation_verifiers.json @@ -5,7 +5,8 @@ "plugins": [ { "name": "oras", - "cosignEnabled": true + "cosignEnabled": true, + "useHttp": true } ] }, From 8b138d0491f4ac21a28d95a4c3dfbc184137e21d Mon Sep 17 00:00:00 2001 From: junczhu Date: Wed, 6 Dec 2023 12:37:01 +0000 Subject: [PATCH 29/38] test: update e2e test cases and reports5 --- test/bats/tests/config/config_multiple_notation_verifiers.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/bats/tests/config/config_multiple_notation_verifiers.json b/test/bats/tests/config/config_multiple_notation_verifiers.json index b646e38fa..619065334 100644 --- a/test/bats/tests/config/config_multiple_notation_verifiers.json +++ b/test/bats/tests/config/config_multiple_notation_verifiers.json @@ -15,7 +15,7 @@ "plugin": { "name": "regoPolicy", "policyPath": "", - "policy": "package ratify.policy\ndefault valid := false\nvalid {\n not failed_verify(input)\n}\nfailed_verify(reports) {\n [path, value] := walk(reports)\n value == false\n path[count(path) - 1] == \"isSuccess\"\n}" + "policy": "package ratify.policy\ndefault valid := false\nvalid {\n failed_verify(input)\n}\nfailed_verify(reports) {\n [path, value] := walk(reports)\n value == true\n path[count(path) - 1] == \"isSuccess\"\n}" } }, "verifier": { From 46b460f819525de98cd9a426095ec7b3793587c7 Mon Sep 17 00:00:00 2001 From: junczhu Date: Wed, 6 Dec 2023 13:06:27 +0000 Subject: [PATCH 30/38] test: update e2e test cases and reports6 --- .../bats/tests/config/config_multiple_notation_verifiers.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/bats/tests/config/config_multiple_notation_verifiers.json b/test/bats/tests/config/config_multiple_notation_verifiers.json index 619065334..1f5d2185d 100644 --- a/test/bats/tests/config/config_multiple_notation_verifiers.json +++ b/test/bats/tests/config/config_multiple_notation_verifiers.json @@ -22,11 +22,11 @@ "version": "1.0.0", "plugins": [ { - "name": "verifier-notation-root", + "name": "verifier-notation", "type": "notation", "artifactTypes": "application/vnd.cncf.notary.signature", "verificationCerts": [ - "~/.config/notation/truststore/x509/ca/leaf-test/root.crt" + "~/.config/notation/localkeys/ratify-bats-test.crt" ], "trustPolicyDoc": { "version": "1.0", From f34519c97b0d2917462b6902fa41c83834dfd7ab Mon Sep 17 00:00:00 2001 From: junczhu Date: Wed, 6 Dec 2023 13:17:01 +0000 Subject: [PATCH 31/38] test: update e2e test cases and reports7 --- test/bats/cli-test.bats | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/bats/cli-test.bats b/test/bats/cli-test.bats index ba9178565..24d823cb9 100644 --- a/test/bats/cli-test.bats +++ b/test/bats/cli-test.bats @@ -37,7 +37,7 @@ load helpers } @test "multiple notation verifiers test" { - run bin/ratify verify -c $RATIFY_DIR/config_multiple_notation_verifier.json -s $TEST_REGISTRY/notation:leafSigned + run bin/ratify verify -c $RATIFY_DIR/config_multiple_notation_verifier.json -s $TEST_REGISTRY/notation:signed assert_cmd_verify_success } From 9042ff86734f4c3ec926e60c163c775996fa16b4 Mon Sep 17 00:00:00 2001 From: junczhu Date: Wed, 6 Dec 2023 13:33:42 +0000 Subject: [PATCH 32/38] test: update e2e test cases and reports8 --- .../config_multiple_notation_verifiers.json | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/bats/tests/config/config_multiple_notation_verifiers.json b/test/bats/tests/config/config_multiple_notation_verifiers.json index 1f5d2185d..b4ef19529 100644 --- a/test/bats/tests/config/config_multiple_notation_verifiers.json +++ b/test/bats/tests/config/config_multiple_notation_verifiers.json @@ -21,6 +21,23 @@ "verifier": { "version": "1.0.0", "plugins": [ + { + "name": "schemavalidator", + "artifactTypes": "vnd.aquasecurity.trivy.report.sarif.v1", + "schemas": { + "application/sarif+json": "file:///home/runner/.ratify/schemas/sarif-2.1.0-rtm.5.json" + } + }, + { + "name": "sbom", + "artifactTypes": "org.example.sbom.v0", + "nestedReferences": "application/vnd.cncf.notary.signature" + }, + { + "name": "cosign", + "artifactTypes": "application/vnd.dev.cosign.artifact.sig.v1+json", + "key": ".staging/cosign/cosign.pub" + }, { "name": "verifier-notation", "type": "notation", From 516730db6e5eb34b0ab73fc047047a12f64a5fa8 Mon Sep 17 00:00:00 2001 From: junczhu Date: Wed, 6 Dec 2023 13:38:32 +0000 Subject: [PATCH 33/38] test: update e2e test cases and reports9 --- .../config_multiple_notation_verifiers.json | 45 ------------------- 1 file changed, 45 deletions(-) diff --git a/test/bats/tests/config/config_multiple_notation_verifiers.json b/test/bats/tests/config/config_multiple_notation_verifiers.json index b4ef19529..8802eedeb 100644 --- a/test/bats/tests/config/config_multiple_notation_verifiers.json +++ b/test/bats/tests/config/config_multiple_notation_verifiers.json @@ -21,23 +21,6 @@ "verifier": { "version": "1.0.0", "plugins": [ - { - "name": "schemavalidator", - "artifactTypes": "vnd.aquasecurity.trivy.report.sarif.v1", - "schemas": { - "application/sarif+json": "file:///home/runner/.ratify/schemas/sarif-2.1.0-rtm.5.json" - } - }, - { - "name": "sbom", - "artifactTypes": "org.example.sbom.v0", - "nestedReferences": "application/vnd.cncf.notary.signature" - }, - { - "name": "cosign", - "artifactTypes": "application/vnd.dev.cosign.artifact.sig.v1+json", - "key": ".staging/cosign/cosign.pub" - }, { "name": "verifier-notation", "type": "notation", @@ -65,34 +48,6 @@ } ] } - }, - { - "name": "verifier-notation-leaf", - "type": "notation", - "artifactTypes": "application/vnd.cncf.notary.signature", - "verificationCerts": [ - "~/.config/notation/truststore/x509/ca/leaf-test/leaf.crt" - ], - "trustPolicyDoc": { - "version": "1.0", - "trustPolicies": [ - { - "name": "default", - "registryScopes": [ - "*" - ], - "signatureVerification": { - "level": "strict" - }, - "trustStores": [ - "ca:certs" - ], - "trustedIdentities": [ - "*" - ] - } - ] - } } ] } From 869b45de65f2a3c2159d9f559f52533406773ab0 Mon Sep 17 00:00:00 2001 From: junczhu Date: Wed, 6 Dec 2023 13:44:10 +0000 Subject: [PATCH 34/38] test: update e2e test cases and reports0 --- test/bats/tests/config/config_multiple_notation_verifiers.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/bats/tests/config/config_multiple_notation_verifiers.json b/test/bats/tests/config/config_multiple_notation_verifiers.json index 8802eedeb..29c5aff73 100644 --- a/test/bats/tests/config/config_multiple_notation_verifiers.json +++ b/test/bats/tests/config/config_multiple_notation_verifiers.json @@ -15,7 +15,7 @@ "plugin": { "name": "regoPolicy", "policyPath": "", - "policy": "package ratify.policy\ndefault valid := false\nvalid {\n failed_verify(input)\n}\nfailed_verify(reports) {\n [path, value] := walk(reports)\n value == true\n path[count(path) - 1] == \"isSuccess\"\n}" + "policy": "package ratify.policy\ndefault valid := false\nvalid {\n not failed_verify(input)\n}\nfailed_verify(reports) {\n [path, value] := walk(reports)\n value == false\n path[count(path) - 1] == \"isSuccess\"\n}" } }, "verifier": { From 46a35c5b979f97f6e55cd520a527e9cf05a24def Mon Sep 17 00:00:00 2001 From: junczhu Date: Wed, 6 Dec 2023 13:57:19 +0000 Subject: [PATCH 35/38] test: update e2e test cases and reports10 --- test/bats/cli-test.bats | 2 +- .../config_multiple_notation_verifiers.json | 34 +++++++++++++++++-- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/test/bats/cli-test.bats b/test/bats/cli-test.bats index 24d823cb9..780bc1b40 100644 --- a/test/bats/cli-test.bats +++ b/test/bats/cli-test.bats @@ -37,7 +37,7 @@ load helpers } @test "multiple notation verifiers test" { - run bin/ratify verify -c $RATIFY_DIR/config_multiple_notation_verifier.json -s $TEST_REGISTRY/notation:signed + run bin/ratify verify -c $RATIFY_DIR/config_multiple_notation_verifiers.json -s $TEST_REGISTRY/notation:signed assert_cmd_verify_success } diff --git a/test/bats/tests/config/config_multiple_notation_verifiers.json b/test/bats/tests/config/config_multiple_notation_verifiers.json index 29c5aff73..eaa8734e0 100644 --- a/test/bats/tests/config/config_multiple_notation_verifiers.json +++ b/test/bats/tests/config/config_multiple_notation_verifiers.json @@ -15,18 +15,46 @@ "plugin": { "name": "regoPolicy", "policyPath": "", - "policy": "package ratify.policy\ndefault valid := false\nvalid {\n not failed_verify(input)\n}\nfailed_verify(reports) {\n [path, value] := walk(reports)\n value == false\n path[count(path) - 1] == \"isSuccess\"\n}" + "policy": "package ratify.policy\ndefault valid := false\nvalid {\n failed_verify(input)\n}\nfailed_verify(reports) {\n [path, value] := walk(reports)\n value == true\n path[count(path) - 1] == \"isSuccess\"\n}" } }, "verifier": { "version": "1.0.0", "plugins": [ { - "name": "verifier-notation", + "name": "verifier-notation-root", "type": "notation", "artifactTypes": "application/vnd.cncf.notary.signature", "verificationCerts": [ - "~/.config/notation/localkeys/ratify-bats-test.crt" + "~/.config/notation/truststore/x509/ca/leaf-test/root.crt" + ], + "trustPolicyDoc": { + "version": "1.0", + "trustPolicies": [ + { + "name": "default", + "registryScopes": [ + "*" + ], + "signatureVerification": { + "level": "strict" + }, + "trustStores": [ + "ca:certs" + ], + "trustedIdentities": [ + "*" + ] + } + ] + } + }, + { + "name": "verifier-notation-leaf", + "type": "notation", + "artifactTypes": "application/vnd.cncf.notary.signature", + "verificationCerts": [ + "~/.config/notation/truststore/x509/ca/leaf-test/leaf.crt" ], "trustPolicyDoc": { "version": "1.0", From b06bd62d32cecb5b0c4318c7e1c77c4349b2ef9b Mon Sep 17 00:00:00 2001 From: junczhu Date: Wed, 6 Dec 2023 14:20:47 +0000 Subject: [PATCH 36/38] test: update e2e test cases and reports11 --- test/bats/cli-test.bats | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/bats/cli-test.bats b/test/bats/cli-test.bats index 780bc1b40..113420b39 100644 --- a/test/bats/cli-test.bats +++ b/test/bats/cli-test.bats @@ -37,7 +37,7 @@ load helpers } @test "multiple notation verifiers test" { - run bin/ratify verify -c $RATIFY_DIR/config_multiple_notation_verifiers.json -s $TEST_REGISTRY/notation:signed + run bin/ratify verify -c $RATIFY_DIR/config_multiple_notation_verifiers.json -s $TEST_REGISTRY/notation:leafSigned assert_cmd_verify_success } From 92a63a086d9b1fe764158f4f8d450e6c0f9df5fa Mon Sep 17 00:00:00 2001 From: junczhu Date: Wed, 6 Dec 2023 14:33:02 +0000 Subject: [PATCH 37/38] test: update e2e test cases and reports12 --- .../tests/config/config_rego_policy_notation_root_cert.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/bats/tests/config/config_rego_policy_notation_root_cert.json b/test/bats/tests/config/config_rego_policy_notation_root_cert.json index 57757c27d..2af72c8b0 100644 --- a/test/bats/tests/config/config_rego_policy_notation_root_cert.json +++ b/test/bats/tests/config/config_rego_policy_notation_root_cert.json @@ -15,7 +15,7 @@ "plugin": { "name": "regoPolicy", "policyPath": "", - "policy": "package ratify.policy\ndefault valid := false\nvalid {\n not failed_verify(input)\n}\nfailed_verify(reports) {\n [path, value] := walk(reports)\n value == false\n path[count(path) - 1] == \"isSuccess\"\n}" + "policy": "package ratify.policy\ndefault valid := false\nvalid {\n failed_verify(input)\n}\nfailed_verify(reports) {\n [path, value] := walk(reports)\n value == true\n path[count(path) - 1] == \"isSuccess\"\n}" } }, "verifier": { From c8fa6bf09f62dea4ba41365b69ed77cd4cb25183 Mon Sep 17 00:00:00 2001 From: junczhu Date: Wed, 6 Dec 2023 15:03:55 +0000 Subject: [PATCH 38/38] test: update e2e test cases and reports13 --- test/bats/cli-test.bats | 2 +- test/bats/helpers.bash | 10 ++++++++++ .../config/config_rego_policy_notation_root_cert.json | 2 +- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/test/bats/cli-test.bats b/test/bats/cli-test.bats index 113420b39..d36055a8d 100644 --- a/test/bats/cli-test.bats +++ b/test/bats/cli-test.bats @@ -38,7 +38,7 @@ load helpers @test "multiple notation verifiers test" { run bin/ratify verify -c $RATIFY_DIR/config_multiple_notation_verifiers.json -s $TEST_REGISTRY/notation:leafSigned - assert_cmd_verify_success + assert_cmd_multi_verifier_success } @test "notation verifier leaf cert with rego policy" { diff --git a/test/bats/helpers.bash b/test/bats/helpers.bash index 94e5e8e53..d8c872686 100644 --- a/test/bats/helpers.bash +++ b/test/bats/helpers.bash @@ -41,6 +41,16 @@ assert_cmd_verify_success() { fi } +assert_cmd_multi_verifier_success() { + if [[ "$status" != 0 ]]; then + return 1 + fi + if [[ "$output" == *'{ "isSuccess": true, "verifierReports"'* ]]; then + echo $output + return 1 + fi +} + assert_cmd_verify_success_with_type() { if [[ "$status" != 0 ]]; then return 1 diff --git a/test/bats/tests/config/config_rego_policy_notation_root_cert.json b/test/bats/tests/config/config_rego_policy_notation_root_cert.json index 2af72c8b0..eaf786090 100644 --- a/test/bats/tests/config/config_rego_policy_notation_root_cert.json +++ b/test/bats/tests/config/config_rego_policy_notation_root_cert.json @@ -15,7 +15,7 @@ "plugin": { "name": "regoPolicy", "policyPath": "", - "policy": "package ratify.policy\ndefault valid := false\nvalid {\n failed_verify(input)\n}\nfailed_verify(reports) {\n [path, value] := walk(reports)\n value == true\n path[count(path) - 1] == \"isSuccess\"\n}" + "policy": "package ratify.policy\ndefault valid := false\nvalid {\n not failed_verify(input)\n}\nfailed_verify(reports) {\n [path, value] := walk(reports)\n value == false\n path[count(path) - 1] == \"isSuccess\"\n}" } }, "verifier": {