Repository: aquasecurity/starboard
Pull request #484 (2021-04-08 13:28:27)

refactor: Embed vulnerabilityreports CRD
This change required bumping up Go from v1.15 to v1.16
to take advantage of embed package.

Signed-off-by: Daniel Pacak <pacak.daniel@gmail.com>

codecov[bot]: # [Codecov](https://codecov.io/gh/aquasecurity/starboard/pull/484?src=pr&el=h1) Report
> Merging [#484](https://codecov.io/gh/aquasecurity/starboard/pull/484?src=pr&el=desc) (f4f631b) into [main](https://codecov.io/gh/aquasecurity/starboard/commit/63d5f8dd5f499ef7f944facd99a61a9c99670456?el=desc) (63d5f8d) will **decrease** coverage by `34.08%`.
> The diff coverage is `0.00%`.

[![Impacted file tree graph](https://codecov.io/gh/aquasecurity/starboard/pull/484/graphs/tree.svg?width=650&height=150&src=pr&token=qqTGKAJ0Wb)](https://codecov.io/gh/aquasecurity/starboard/pull/484?src=pr&el=tree)

```diff
@@             Coverage Diff             @@
##             main     #484       +/-   ##
===========================================
- Coverage   69.02%   34.94%   -34.09%     
===========================================
  Files          62       61        -1     
  Lines        3984     3858      -126     
===========================================
- Hits         2750     1348     -1402     
- Misses        935     2431     +1496     
+ Partials      299       79      -220     
```


| [Impacted Files](https://codecov.io/gh/aquasecurity/starboard/pull/484?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pkg/kube/cr\_manager.go](https://codecov.io/gh/aquasecurity/starboard/pull/484/diff?src=pr&el=tree#diff-cGtnL2t1YmUvY3JfbWFuYWdlci5nbw==) | `0.00% <0.00%> (-50.69%)` | :arrow_down: |
| [pkg/cmd/get.go](https://codecov.io/gh/aquasecurity/starboard/pull/484/diff?src=pr&el=tree#diff-cGtnL2NtZC9nZXQuZ28=) | `0.00% <0.00%> (-100.00%)` | :arrow_down: |
| [pkg/cmd/find.go](https://codecov.io/gh/aquasecurity/starboard/pull/484/diff?src=pr&el=tree#diff-cGtnL2NtZC9maW5kLmdv) | `0.00% <0.00%> (-100.00%)` | :arrow_down: |
| [pkg/cmd/root.go](https://codecov.io/gh/aquasecurity/starboard/pull/484/diff?src=pr&el=tree#diff-cGtnL2NtZC9yb290Lmdv) | `0.00% <0.00%> (-100.00%)` | :arrow_down: |
| [pkg/cmd/scan.go](https://codecov.io/gh/aquasecurity/starboard/pull/484/diff?src=pr&el=tree#diff-cGtnL2NtZC9zY2FuLmdv) | `0.00% <0.00%> (-100.00%)` | :arrow_down: |
| [pkg/cmd/polaris.go](https://codecov.io/gh/aquasecurity/starboard/pull/484/diff?src=pr&el=tree#diff-cGtnL2NtZC9wb2xhcmlzLmdv) | `0.00% <0.00%> (-100.00%)` | :arrow_down: |
| [pkg/cmd/version.go](https://codecov.io/gh/aquasecurity/starboard/pull/484/diff?src=pr&el=tree#diff-cGtnL2NtZC92ZXJzaW9uLmdv) | `0.00% <0.00%> (-100.00%)` | :arrow_down: |
| [pkg/cmd/kube\_bench.go](https://codecov.io/gh/aquasecurity/starboard/pull/484/diff?src=pr&el=tree#diff-cGtnL2NtZC9rdWJlX2JlbmNoLmdv) | `0.00% <0.00%> (-100.00%)` | :arrow_down: |
| [pkg/cmd/kube\_hunter.go](https://codecov.io/gh/aquasecurity/starboard/pull/484/diff?src=pr&el=tree#diff-cGtnL2NtZC9rdWJlX2h1bnRlci5nbw==) | `0.00% <0.00%> (-100.00%)` | :arrow_down: |
| [pkg/cmd/find\_vulnerabilities.go](https://codecov.io/gh/aquasecurity/starboard/pull/484/diff?src=pr&el=tree#diff-cGtnL2NtZC9maW5kX3Z1bG5lcmFiaWxpdGllcy5nbw==) | `0.00% <0.00%> (-100.00%)` | :arrow_down: |
| ... and [34 more](https://codecov.io/gh/aquasecurity/starboard/pull/484/diff?src=pr&el=tree-more) | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/aquasecurity/starboard/pull/484?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/aquasecurity/starboard/pull/484?src=pr&el=footer). Last update [63d5f8d...f4f631b](https://codecov.io/gh/aquasecurity/starboard/pull/484?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml
index 86fdf3c..3f49755 100644
--- a/.github/workflows/build.yaml
+++ b/.github/workflows/build.yaml
@@ -24,7 +24,7 @@ on:
       - 'LICENSE'
       - 'NOTICE'
 env:
-  GO_VERSION: "1.15"
+  GO_VERSION: "1.16"
   KIND_VERSION: "v0.9.0"
   KIND_IMAGE: "kindest/node:v1.19.7@sha256:a70639454e97a4b733f9d9b67e12c01f6b0297449d5b9cbbef87473458e26dca"
 jobs:
diff --git a/.github/workflows/mkdocs-deploy.yaml b/.github/workflows/mkdocs-deploy.yaml
index 01a3ef0..c9d28ee 100644
--- a/.github/workflows/mkdocs-deploy.yaml
+++ b/.github/workflows/mkdocs-deploy.yaml
@@ -30,7 +30,7 @@ jobs:
           # Note: It is not the same as ${{ secrets.GITHUB_TOKEN }} !
           GH_TOKEN: ${{ secrets.MKDOCS_GH_TOKEN }}
       - run: |
-          git config user.name "Daniel Pacak"
-          git config user.email "pacak.daniel@gmail.com"
+          git config user.name "aqua-bot"
+          git config user.email "aqua-bot@users.noreply.github.com"
       - run: |
           mike deploy --push --update-aliases ${{ github.event.inputs.version }} latest
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
index cd3919d..a62d86a 100644
--- a/.github/workflows/release.yaml
+++ b/.github/workflows/release.yaml
@@ -4,7 +4,7 @@ on:
     tags:
       - "v*"
 env:
-  GO_VERSION: "1.15"
+  GO_VERSION: "1.16"
   KIND_VERSION: "v0.9.0"
   KIND_IMAGE: "kindest/node:v1.18.8@sha256:f4bcc97a0ad6e7abaf3f643d890add7efe6ee4ab90baeb374b4f41a4c95567eb"
 jobs:
diff --git a/deploy/crd/vulnerabilityreports.crd.yaml b/deploy/crd/vulnerabilityreports.crd.yaml
index 4b03b7f..a293ce0 100644
--- a/deploy/crd/vulnerabilityreports.crd.yaml
+++ b/deploy/crd/vulnerabilityreports.crd.yaml
@@ -12,6 +12,9 @@ spec:
       storage: true
       schema:
         openAPIV3Schema:
+          description: |
+            VulnerabilityReport summarizes vulnerabilities in application dependencies and operating system packages
+            built into container images.
           type: object
           required:
             - apiVersion
diff --git a/embedded.go b/embedded.go
new file mode 100644
index 0000000..aebdda4
--- /dev/null
+++ b/embedded.go
@@ -0,0 +1,22 @@
+package starboard
+
+import (
+	_ "embed"
+
+	apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
+	"k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/scheme"
+)
+
+var (
+	//go:embed deploy/crd/vulnerabilityreports.crd.yaml
+	vulnerabilityReportsCRD []byte
+)
+
+func GetVulnerabilityReportsCRD() (apiextensionsv1.CustomResourceDefinition, error) {
+	var crd apiextensionsv1.CustomResourceDefinition
+	_, _, err := scheme.Codecs.UniversalDecoder().Decode(vulnerabilityReportsCRD, nil, &crd)
+	if err != nil {
+		return apiextensionsv1.CustomResourceDefinition{}, err
+	}
+	return crd, nil
+}
diff --git a/go.mod b/go.mod
index a3fa3e5..6e011e2 100644
--- a/go.mod
+++ b/go.mod
@@ -1,6 +1,6 @@
 module github.com/aquasecurity/starboard
 
-go 1.15
+go 1.16
 
 require (
 	github.com/caarlos0/env/v6 v6.4.0
diff --git a/pkg/apis/aquasecurity/v1alpha1/vulnerability_types.go b/pkg/apis/aquasecurity/v1alpha1/vulnerability_types.go
index b213e67..515640f 100644
--- a/pkg/apis/aquasecurity/v1alpha1/vulnerability_types.go
+++ b/pkg/apis/aquasecurity/v1alpha1/vulnerability_types.go
@@ -1,13 +1,7 @@
 package v1alpha1
 
 import (
-	"strconv"
-
-	"github.com/aquasecurity/starboard/pkg/apis/aquasecurity"
-	apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	"k8s.io/apimachinery/pkg/labels"
-	"k8s.io/utils/pointer"
 )
 
 const (
@@ -17,208 +11,6 @@ const (
 	VulnerabilityReportListKind   = "VulnerabilityReportList"
 )
 
-var (
-	// TODO Once we migrate to Go 1.16 we can use the embed package to load the CRD from ./deploy/crd/vulnerabilityreports.crd.yaml
-	VulnerabilityReportsCRD = apiextensionsv1.CustomResourceDefinition{
-		ObjectMeta: metav1.ObjectMeta{
-			Name: VulnerabilityReportsCRName,
-			Labels: labels.Set{
-				"app.kubernetes.io/managed-by": "starboard",
-			},
-		},
-		Spec: apiextensionsv1.CustomResourceDefinitionSpec{
-			Group: aquasecurity.GroupName,
-			Versions: []apiextensionsv1.CustomResourceDefinitionVersion{
-				{
-					Name:    VulnerabilityReportsCRVersion,
-					Served:  true,
-					Storage: true,
-					AdditionalPrinterColumns: []apiextensionsv1.CustomResourceColumnDefinition{
-						{
-							JSONPath: ".report.artifact.repository",
-							Type:     "string",
-							Name:     "Repository",
-						},
-						{
-							JSONPath: ".report.artifact.tag",
-							Type:     "string",
-							Name:     "Tag",
-						},
-						{
-							JSONPath: ".report.scanner.name",
-							Type:     "string",
-							Name:     "Scanner",
-						},
-						{
-							JSONPath: ".metadata.creationTimestamp",
-							Type:     "date",
-							Name:     "Age",
-						},
-						{
-							JSONPath: ".report.summary.criticalCount",
-							Type:     "integer",
-							Name:     "Critical",
-							Priority: 1,
-						},
-						{
-							JSONPath: ".report.summary.highCount",
-							Type:     "integer",
-							Name:     "High",
-							Priority: 1,
-						},
-						{
-							JSONPath: ".report.summary.mediumCount",
-							Type:     "integer",
-							Name:     "Medium",
-							Priority: 1,
-						},
-						{
-							JSONPath: ".report.summary.lowCount",
-							Type:     "integer",
-							Name:     "Low",
-							Priority: 1,
-						},
-						{
-							JSONPath: ".report.summary.unknownCount",
-							Type:     "integer",
-							Name:     "Unknown",
-							Priority: 1,
-						},
-					},
-					Schema: &apiextensionsv1.CustomResourceValidation{
-						OpenAPIV3Schema: &apiextensionsv1.JSONSchemaProps{
-							Type: "object",
-							Required: []string{
-								"apiVersion",
-								"kind",
-								"metadata",
-								"report",
-							},
-							Properties: map[string]apiextensionsv1.JSONSchemaProps{
-								"apiVersion": {Type: "string"},
-								"kind":       {Type: "string"},
-								"metadata":   {Type: "object"},
-								"report": {
-									Type: "object",
-									Required: []string{
-										"scanner",
-										"artifact",
-										"vulnerabilities",
-									},
-									Properties: map[string]apiextensionsv1.JSONSchemaProps{
-										"scanner": {
-											Type: "object",
-											Required: []string{
-												"name",
-												"vendor",
-												"version",
-											},
-											Properties: map[string]apiextensionsv1.JSONSchemaProps{
-												"name":    {Type: "string"},
-												"vendor":  {Type: "string"},
-												"version": {Type: "string"},
-											},
-										},
-										"registry": {
-											Type: "object",
-											Properties: map[string]apiextensionsv1.JSONSchemaProps{
-												"server": {Type: "string"},
-											},
-										},
-										"artifact": {
-											Type: "object",
-											Properties: map[string]apiextensionsv1.JSONSchemaProps{
-												"repository": {Type: "string"},
-												"digest":     {Type: "string"},
-												"tag":        {Type: "string"},
-												"mimeType":   {Type: "string"},
-											},
-										},
-										"summary": {
-											Type: "object",
-											Required: []string{
-												"criticalCount",
-												"highCount",
-												"mediumCount",
-												"lowCount",
-												"unknownCount",
-											},
-											Properties: map[string]apiextensionsv1.JSONSchemaProps{
-												"criticalCount": {Type: "integer", Minimum: pointer.Float64Ptr(0)},
-												"highCount":     {Type: "integer", Minimum: pointer.Float64Ptr(0)},
-												"mediumCount":   {Type: "integer", Minimum: pointer.Float64Ptr(0)},
-												"lowCount":      {Type: "integer", Minimum: pointer.Float64Ptr(0)},
-												"unknownCount":  {Type: "integer", Minimum: pointer.Float64Ptr(0)},
-											},
-										},
-										"updateTimestamp": {
-											Type:   "string",
-											Format: "date-time",
-										},
-										"vulnerabilities": {
-											Type: "array",
-											Items: &apiextensionsv1.JSONSchemaPropsOrArray{
-												Schema: &apiextensionsv1.JSONSchemaProps{
-													Type: "object",
-													Required: []string{
-														"vulnerabilityID",
-														"resource",
-														"installedVersion",
-														"fixedVersion",
-														"severity",
-														"title",
-													},
-													Properties: map[string]apiextensionsv1.JSONSchemaProps{
-														"vulnerabilityID":  {Type: "string"},
-														"resource":         {Type: "string"},
-														"installedVersion": {Type: "string"},
-														"fixedVersion":     {Type: "string"},
-														"severity": {
-															Type: "string",
-															Enum: []apiextensionsv1.JSON{
-																{Raw: []byte(strconv.Quote(string(SeverityCritical)))},
-																{Raw: []byte(strconv.Quote(string(SeverityHigh)))},
-																{Raw: []byte(strconv.Quote(string(SeverityMedium)))},
-																{Raw: []byte(strconv.Quote(string(SeverityLow)))},
-																{Raw: []byte(strconv.Quote(string(SeverityUnknown)))},
-															},
-														},
-														"title":       {Type: "string"},
-														"description": {Type: "string"},
-														"primaryLink": {Type: "string"},
-														"score":       {Type: "number"},
-														"links": {
-															Type: "array",
-															Items: &apiextensionsv1.JSONSchemaPropsOrArray{
-																Schema: &apiextensionsv1.JSONSchemaProps{
-																	Type: "string",
-																},
-															},
-														},
-													},
-												},
-											},
-										},
-									},
-								},
-							},
-						},
-					},
-				},
-			},
-			Scope: apiextensionsv1.NamespaceScoped,
-			Names: apiextensionsv1.CustomResourceDefinitionNames{
-				Singular:   "vulnerabilityreport",
-				Plural:     "vulnerabilityreports",
-				Kind:       VulnerabilityReportKind,
-				ListKind:   VulnerabilityReportListKind,
-				Categories: []string{"all"},
-				ShortNames: []string{"vulns", "vuln"},
-			},
-		},
-	}
-)
-
 type Severity string
 
 const (
diff --git a/pkg/kube/cr_manager.go b/pkg/kube/cr_manager.go
index 058833a..81c16ff 100644
--- a/pkg/kube/cr_manager.go
+++ b/pkg/kube/cr_manager.go
@@ -5,6 +5,7 @@ import (
 	"fmt"
 	"time"
 
+	embedded "github.com/aquasecurity/starboard"
 	"github.com/aquasecurity/starboard/pkg/apis/aquasecurity/v1alpha1"
 	"github.com/aquasecurity/starboard/pkg/starboard"
 	corev1 "k8s.io/api/core/v1"
@@ -136,40 +137,43 @@ func NewCRManager(
 	}
 }
 
-func (m *CRManager) Init(ctx context.Context) (err error) {
-	err = m.createOrUpdateCRD(ctx, &v1alpha1.VulnerabilityReportsCRD)
+func (m *CRManager) Init(ctx context.Context) error {
+	vulnerabilityReportsCRD, err := embedded.GetVulnerabilityReportsCRD()
 	if err != nil {
-		return
+		return err
+	}
+	err = m.createOrUpdateCRD(ctx, &vulnerabilityReportsCRD)
+	if err != nil {
+		return err
 	}
 
 	err = m.createOrUpdateCRD(ctx, &v1alpha1.CISKubeBenchReportCRD)
 	if err != nil {
-		return
+		return err
 	}
 
 	err = m.createOrUpdateCRD(ctx, &v1alpha1.KubeHunterReportCRD)
 	if err != nil {
-		return
+		return err
 	}
 
 	err = m.createOrUpdateCRD(ctx, &v1alpha1.ConfigAuditReportCRD)
 	if err != nil {
-		return
+		return err
 	}
 	// TODO We should wait for CRD statuses and make sure that the names were accepted
 
 	err = m.createNamespaceIfNotFound(ctx, namespace)
 	if err != nil {
-		return
+		return err
 	}
 
 	err = m.configManager.EnsureDefault(ctx)
 	if err != nil {
-		return
+		return err
 	}
 
-	err = m.initRBAC(ctx)
-	return
+	return m.initRBAC(ctx)
 }
 
 func (m *CRManager) initRBAC(ctx context.Context) (err error) {
diff --git a/pkg/operator/controller/plugins_config.go b/pkg/operator/controller/plugins_config.go
index 098f648..498b0ba 100644
--- a/pkg/operator/controller/plugins_config.go
+++ b/pkg/operator/controller/plugins_config.go
@@ -3,7 +3,6 @@ package controller
 import (
 	"context"
 	"fmt"
-	"strings"
 
 	"github.com/aquasecurity/starboard/pkg/apis/aquasecurity/v1alpha1"
 	"github.com/aquasecurity/starboard/pkg/configauditreport"
@@ -32,6 +31,7 @@ func (r *PluginsConfigReconciler) SetupWithManager(mgr ctrl.Manager) error {
 	return ctrl.NewControllerManagedBy(mgr).
 		For(&corev1.ConfigMap{}, builder.WithPredicates(
 			predicate.Not(predicate.IsBeingTerminated),
+			predicate.HasName(starboard.GetPluginConfigMapName(r.PluginContext.GetName())),
 			predicate.InNamespace(r.Config.Namespace))).
 		Complete(r)
 }
@@ -39,11 +39,6 @@ func (r *PluginsConfigReconciler) SetupWithManager(mgr ctrl.Manager) error {
 func (r *PluginsConfigReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
 	log := r.Logger.WithValues("configMap", req.NamespacedName)
 
-	// TODO Use Predicate instead
-	if req.Name != "starboard-"+strings.ToLower(r.PluginContext.GetName())+"-config" {
-		return ctrl.Result{}, nil
-	}
-
 	cm := &corev1.ConfigMap{}
 
 	err := r.Client.Get(ctx, req.NamespacedName, cm)
diff --git a/pkg/operator/predicate/predicate.go b/pkg/operator/predicate/predicate.go
index 3dd487b..7c1c60c 100644
--- a/pkg/operator/predicate/predicate.go
+++ b/pkg/operator/predicate/predicate.go
@@ -42,6 +42,14 @@ var InstallModePredicate = func(config etc.Config) (predicate.Predicate, error)
 	}), nil
 }
 
+// HasName is predicate.Predicate that returns true if the
+// specified client.Object has the desired name.
+var HasName = func(name string) predicate.Predicate {
+	return predicate.NewPredicateFuncs(func(obj client.Object) bool {
+		return name == obj.GetName()
+	})
+}
+
 // InNamespace is a predicate.Predicate that returns true if the
 // specified client.Object is in the desired namespace.
 var InNamespace = func(namespace string) predicate.Predicate {
@@ -68,8 +76,8 @@ var IsBeingTerminated = predicate.NewPredicateFuncs(func(obj client.Object) bool
 	return obj.GetDeletionTimestamp() != nil
 })
 
-// JobHasConditions is a predicate.Predicate that returns true if the
-// specified client.Object is a batchv1.Job with any batchv1.JobConditionType.
+// JobHasAnyCondition is a predicate.Predicate that returns true if the
+// specified client.Object is a v1.Job with any v1.JobConditionType.
 var JobHasAnyCondition = predicate.NewPredicateFuncs(func(obj client.Object) bool {
 	if job, ok := obj.(*batchv1.Job); ok {
 		return len(job.Status.Conditions) > 0
diff --git a/pkg/starboard/plugin.go b/pkg/starboard/plugin.go
index 26452d5..646da3e 100644
--- a/pkg/starboard/plugin.go
+++ b/pkg/starboard/plugin.go
@@ -26,6 +26,12 @@ type PluginContext interface {
 	GetServiceAccountName() string
 }
 
+// GetPluginConfigMapName returns the name of a ConfigMap used to configure a plugin
+// with the given name.
+func GetPluginConfigMapName(pluginName string) string {
+	return "starboard-" + strings.ToLower(pluginName) + "-config"
+}
+
 type pluginContext struct {
 	name               string
 	client             client.Client


Test patch:
diff --git a/itest/starboard/starboard_cli_test.go b/itest/starboard/starboard_cli_test.go
index bc71fd5..3844efa 100644
--- a/itest/starboard/starboard_cli_test.go
+++ b/itest/starboard/starboard_cli_test.go
@@ -46,11 +46,11 @@ var _ = Describe("Starboard CLI", func() {
 			crdList, err := customResourceDefinitions.List(context.TODO(), metav1.ListOptions{})
 			Expect(err).ToNot(HaveOccurred())
 
-			id := func(element interface{}) string {
+			groupByName := func(element interface{}) string {
 				return element.(apiextensionsv1beta1.CustomResourceDefinition).Name
 			}
 
-			Expect(crdList.Items).To(MatchAllElements(id, Elements{
+			Expect(crdList.Items).To(MatchAllElements(groupByName, Elements{
 				"vulnerabilityreports.aquasecurity.github.io": MatchFields(IgnoreExtras, Fields{
 					"Spec": MatchFields(IgnoreExtras, Fields{
 						"Group":   Equal("aquasecurity.github.io"),
@@ -58,7 +58,7 @@ var _ = Describe("Starboard CLI", func() {
 						"Names": Equal(apiextensionsv1beta1.CustomResourceDefinitionNames{
 							Plural:     "vulnerabilityreports",
 							Singular:   "vulnerabilityreport",
-							ShortNames: []string{"vulns", "vuln"},
+							ShortNames: []string{"vuln", "vulns"},
 							Kind:       "VulnerabilityReport",
 							ListKind:   "VulnerabilityReportList",
 							Categories: []string{"all"},
diff --git a/pkg/operator/predicate/predicate_test.go b/pkg/operator/predicate/predicate_test.go
index c371e12..a60ea1c 100644
--- a/pkg/operator/predicate/predicate_test.go
+++ b/pkg/operator/predicate/predicate_test.go
@@ -121,6 +121,43 @@ var _ = Describe("Predicate", func() {
 		})
 	})
 
+	Describe("When checking a HasName predicate", func() {
+
+		Context("When object has desired name", func() {
+
+			It("Should return true", func() {
+				instance := predicate.HasName("starboard-polaris-config")
+				obj := &corev1.Pod{
+					ObjectMeta: metav1.ObjectMeta{
+						Name: "starboard-polaris-config",
+					},
+				}
+
+				Expect(instance.Create(event.CreateEvent{Object: obj})).To(BeTrue())
+				Expect(instance.Update(event.UpdateEvent{ObjectNew: obj})).To(BeTrue())
+				Expect(instance.Delete(event.DeleteEvent{Object: obj})).To(BeTrue())
+				Expect(instance.Generic(event.GenericEvent{Object: obj})).To(BeTrue())
+			})
+		})
+
+		Context("When object does not have desired name", func() {
+
+			It("Should return false", func() {
+				instance := predicate.HasName("starboard-conftest-config")
+				obj := &corev1.Pod{
+					ObjectMeta: metav1.ObjectMeta{
+						Name: "starboard",
+					},
+				}
+
+				Expect(instance.Create(event.CreateEvent{Object: obj})).To(BeFalse())
+				Expect(instance.Update(event.UpdateEvent{ObjectNew: obj})).To(BeFalse())
+				Expect(instance.Delete(event.DeleteEvent{Object: obj})).To(BeFalse())
+				Expect(instance.Generic(event.GenericEvent{Object: obj})).To(BeFalse())
+			})
+		})
+	})
+
 	Describe("When checking a InNamespace predicate", func() {
 
 		Context("When object is in desired namespace", func() {
diff --git a/pkg/plugin/conftest/plugin.go b/pkg/plugin/conftest/plugin.go
index 9f1968e..9cbed27 100644
--- a/pkg/plugin/conftest/plugin.go
+++ b/pkg/plugin/conftest/plugin.go
@@ -115,7 +115,7 @@ func (p *plugin) GetScanJobSpec(ctx starboard.PluginContext, obj client.Object)
 				VolumeSource: corev1.VolumeSource{
 					ConfigMap: &corev1.ConfigMapVolumeSource{
 						LocalObjectReference: corev1.LocalObjectReference{
-							Name: "starboard-conftest-config",
+							Name: starboard.GetPluginConfigMapName(ctx.GetName()),
 						},
 						Items: volumeItems,
 					},
diff --git a/pkg/starboard/plugin_test.go b/pkg/starboard/plugin_test.go
index 4e77a9f..050f3e9 100644
--- a/pkg/starboard/plugin_test.go
+++ b/pkg/starboard/plugin_test.go
@@ -10,6 +10,12 @@ import (
 	"sigs.k8s.io/controller-runtime/pkg/client/fake"
 )
 
+func TestGetPluginConfigMapName(t *testing.T) {
+	g := gomega.NewGomegaWithT(t)
+	name := starboard.GetPluginConfigMapName("Conftest")
+	g.Expect(name).To(gomega.Equal("starboard-conftest-config"))
+}
+
 func TestPluginContext_GetConfig(t *testing.T) {
 	g := gomega.NewGomegaWithT(t)