Repository: aquasecurity/starboard
Pull request #475 (2021-04-06 12:57:36)

feat: Add plugin name and config getter to PluginContext
Signed-off-by: Daniel Pacak <pacak.daniel@gmail.com>

codecov[bot]: # [Codecov](https://codecov.io/gh/aquasecurity/starboard/pull/475?src=pr&el=h1) Report
> Merging [#475](https://codecov.io/gh/aquasecurity/starboard/pull/475?src=pr&el=desc) (78483ed) into [main](https://codecov.io/gh/aquasecurity/starboard/commit/56c1a3b3707b751d4a25ab371484fdcb6e156c23?el=desc) (56c1a3b) will **decrease** coverage by `35.26%`.
> The diff coverage is `28.94%`.

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

```diff
@@             Coverage Diff             @@
##             main     #475       +/-   ##
===========================================
- Coverage   69.47%   34.20%   -35.27%     
===========================================
  Files          60       59        -1     
  Lines        3695     3616       -79     
===========================================
- Hits         2567     1237     -1330     
- Misses        843     2306     +1463     
+ Partials      285       73      -212     
```


| [Impacted Files](https://codecov.io/gh/aquasecurity/starboard/pull/475?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pkg/cmd/scan\_configaudit.go](https://codecov.io/gh/aquasecurity/starboard/pull/475/diff?src=pr&el=tree#diff-cGtnL2NtZC9zY2FuX2NvbmZpZ2F1ZGl0Lmdv) | `0.00% <0.00%> (-59.10%)` | :arrow_down: |
| [pkg/plugin/factory.go](https://codecov.io/gh/aquasecurity/starboard/pull/475/diff?src=pr&el=tree#diff-cGtnL3BsdWdpbi9mYWN0b3J5Lmdv) | `0.00% <0.00%> (-50.00%)` | :arrow_down: |
| [pkg/starboard/plugin.go](https://codecov.io/gh/aquasecurity/starboard/pull/475/diff?src=pr&el=tree#diff-cGtnL3N0YXJib2FyZC9wbHVnaW4uZ28=) | `80.00% <100.00%> (+80.00%)` | :arrow_up: |
| [pkg/cmd/get.go](https://codecov.io/gh/aquasecurity/starboard/pull/475/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/475/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/475/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/475/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/475/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/475/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/475/diff?src=pr&el=tree#diff-cGtnL2NtZC9rdWJlX2JlbmNoLmdv) | `0.00% <0.00%> (-100.00%)` | :arrow_down: |
| ... and [36 more](https://codecov.io/gh/aquasecurity/starboard/pull/475/diff?src=pr&el=tree-more) | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/aquasecurity/starboard/pull/475?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/475?src=pr&el=footer). Last update [56c1a3b...78483ed](https://codecov.io/gh/aquasecurity/starboard/pull/475?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/pkg/cmd/scan_configaudit.go b/pkg/cmd/scan_configaudit.go
index 87bb786..2df1dac 100644
--- a/pkg/cmd/scan_configaudit.go
+++ b/pkg/cmd/scan_configaudit.go
@@ -62,15 +62,17 @@ func ScanConfigAuditReports(buildInfo starboard.BuildInfo, cf *genericclioptions
 		if err != nil {
 			return err
 		}
-		instance, err := plugin.GetConfigAuditReportPlugin(buildInfo, starboardConfig)
+		plugin, pluginContext, err := plugin.NewResolver().
+			WithBuildInfo(buildInfo).
+			WithNamespace(starboard.NamespaceName).
+			WithServiceAccountName(starboard.ServiceAccountName).
+			WithConfig(starboardConfig).
+			WithClient(kubeClient).
+			GetConfigAuditPlugin()
 		if err != nil {
 			return err
 		}
-		pluginContext := starboard.NewPluginContext().
-			WithNamespace(starboard.NamespaceName).
-			WithServiceAccountName(starboard.ServiceAccountName).
-			Build()
-		scanner := configauditreport.NewScanner(kubeClientset, kubeClient, opts, instance, pluginContext)
+		scanner := configauditreport.NewScanner(kubeClientset, kubeClient, opts, plugin, pluginContext)
 		report, err := scanner.Scan(ctx, workload)
 		if err != nil {
 			return err
diff --git a/pkg/operator/operator.go b/pkg/operator/operator.go
index 8c30412..6335e1c 100644
--- a/pkg/operator/operator.go
+++ b/pkg/operator/operator.go
@@ -128,12 +128,18 @@ func Run(buildInfo starboard.BuildInfo, operatorConfig etc.Config) error {
 	logsReader := kube.NewLogsReader(kubeClientset)
 	secretsReader := kube.NewSecretsReader(mgr.GetClient())
 
-	vulnerabilityReportPlugin, err := plugin.GetVulnerabilityReportPlugin(buildInfo, starboardConfig)
-	if err != nil {
-		return err
-	}
-
 	if operatorConfig.VulnerabilityScannerEnabled {
+		plugin, err := plugin.NewResolver().
+			WithBuildInfo(buildInfo).
+			WithNamespace(operatorNamespace).
+			WithServiceAccountName(operatorConfig.ServiceAccount).
+			WithConfig(starboardConfig).
+			WithClient(mgr.GetClient()).
+			GetVulnerabilityPlugin()
+		if err != nil {
+			return err
+		}
+
 		if err = (&controller.VulnerabilityReportReconciler{
 			Logger:         ctrl.Log.WithName("reconciler").WithName("vulnerabilityreport"),
 			Config:         operatorConfig,
@@ -142,7 +148,7 @@ func Run(buildInfo starboard.BuildInfo, operatorConfig etc.Config) error {
 			LimitChecker:   limitChecker,
 			LogsReader:     logsReader,
 			SecretsReader:  secretsReader,
-			Plugin:         vulnerabilityReportPlugin,
+			Plugin:         plugin,
 			ReadWriter:     vulnerabilityreport.NewReadWriter(mgr.GetClient()),
 		}).SetupWithManager(mgr); err != nil {
 			return fmt.Errorf("unable to setup vulnerabilityreport reconciler: %w", err)
@@ -150,7 +156,13 @@ func Run(buildInfo starboard.BuildInfo, operatorConfig etc.Config) error {
 	}
 
 	if operatorConfig.ConfigAuditScannerEnabled {
-		configAuditReportPlugin, err := plugin.GetConfigAuditReportPlugin(buildInfo, starboardConfig)
+		plugin, pluginContext, err := plugin.NewResolver().
+			WithBuildInfo(buildInfo).
+			WithNamespace(operatorNamespace).
+			WithServiceAccountName(operatorConfig.ServiceAccount).
+			WithConfig(starboardConfig).
+			WithClient(mgr.GetClient()).
+			GetConfigAuditPlugin()
 		if err != nil {
 			return err
 		}
@@ -162,12 +174,9 @@ func Run(buildInfo starboard.BuildInfo, operatorConfig etc.Config) error {
 			ObjectResolver: objectResolver,
 			LimitChecker:   limitChecker,
 			LogsReader:     logsReader,
-			Plugin:         configAuditReportPlugin,
-			PluginContext: starboard.NewPluginContext().
-				WithNamespace(operatorNamespace).
-				WithServiceAccountName(operatorConfig.ServiceAccount).
-				Build(),
-			ReadWriter: configauditreport.NewReadWriter(mgr.GetClient()),
+			Plugin:         plugin,
+			PluginContext:  pluginContext,
+			ReadWriter:     configauditreport.NewReadWriter(mgr.GetClient()),
 		}).SetupWithManager(mgr); err != nil {
 			return fmt.Errorf("unable to setup configauditreport reconciler: %w", err)
 		}
diff --git a/pkg/plugin/factory.go b/pkg/plugin/factory.go
index e24e040..3d40abe 100644
--- a/pkg/plugin/factory.go
+++ b/pkg/plugin/factory.go
@@ -10,8 +10,60 @@ import (
 	"github.com/aquasecurity/starboard/pkg/plugin/trivy"
 	"github.com/aquasecurity/starboard/pkg/starboard"
 	"github.com/aquasecurity/starboard/pkg/vulnerabilityreport"
+	"sigs.k8s.io/controller-runtime/pkg/client"
 )
 
+type Resolver struct {
+	buildInfo          starboard.BuildInfo
+	config             starboard.ConfigData
+	namespace          string
+	serviceAccountName string
+	client             client.Client
+}
+
+func NewResolver() *Resolver {
+	return &Resolver{}
+}
+
+func (r *Resolver) WithBuildInfo(buildInfo starboard.BuildInfo) *Resolver {
+	r.buildInfo = buildInfo
+	return r
+}
+
+func (r *Resolver) WithConfig(config starboard.ConfigData) *Resolver {
+	r.config = config
+	return r
+}
+
+func (r *Resolver) WithNamespace(namespace string) *Resolver {
+	r.namespace = namespace
+	return r
+}
+
+func (r *Resolver) WithServiceAccountName(name string) *Resolver {
+	r.serviceAccountName = name
+	return r
+}
+
+func (r *Resolver) WithClient(client client.Client) *Resolver {
+	r.client = client
+	return r
+}
+
+func (r *Resolver) GetVulnerabilityPlugin() (vulnerabilityreport.Plugin, error) {
+	return GetVulnerabilityReportPlugin(r.buildInfo, r.config)
+}
+
+func (r *Resolver) GetConfigAuditPlugin() (configauditreport.Plugin, starboard.PluginContext, error) {
+	return polaris.NewPlugin(ext.NewSystemClock(), r.config), starboard.NewPluginContext().
+			WithName("Polaris").
+			WithNamespace(r.namespace).
+			WithServiceAccountName(r.serviceAccountName).
+			WithClient(r.client).
+			Build(),
+		nil
+}
+
 // GetVulnerabilityReportPlugin is a factory method that instantiates the
 // vulnerabilityreport.Plugin for the specified starboard.ConfigData.
 //
@@ -20,6 +72,7 @@ import (
 //
 // You could add your own scanner by implementing the
 // vulnerabilityreport.Plugin interface.
+// Deprecated
 func GetVulnerabilityReportPlugin(buildInfo starboard.BuildInfo, config starboard.ConfigData) (vulnerabilityreport.Plugin, error) {
 	scanner, err := config.GetVulnerabilityReportsScanner()
 	if err != nil {
@@ -41,6 +94,7 @@ func GetVulnerabilityReportPlugin(buildInfo starboard.BuildInfo, config starboar
 //
 // You could add your own scanner by implementing the configauditreport.Plugin
 // interface.
+// Deprecated
 func GetConfigAuditReportPlugin(_ starboard.BuildInfo, config starboard.ConfigData) (configauditreport.Plugin, error) {
 	return polaris.NewPlugin(ext.NewSystemClock(), config), nil
 }
diff --git a/pkg/starboard/plugin.go b/pkg/starboard/plugin.go
index 2a9f953..26452d5 100644
--- a/pkg/starboard/plugin.go
+++ b/pkg/starboard/plugin.go
@@ -1,9 +1,23 @@
 package starboard
 
+import (
+	"context"
+	"fmt"
+	"strings"
+
+	corev1 "k8s.io/api/core/v1"
+	"k8s.io/apimachinery/pkg/types"
+	"sigs.k8s.io/controller-runtime/pkg/client"
+)
+
 // PluginContext is plugin's execution context within the Starboard toolkit.
 // The context is used to grant access to other methods so that this plugin
 // can interact with the toolkit.
 type PluginContext interface {
+	// GetName returns the name of the plugin.
+	GetName() string
+	// GetConfig returns the v1.ConfigMap object that holds configuration settings of the plugin.
+	GetConfig() (*corev1.ConfigMap, error)
 	// GetNamespace return the name of the K8s Namespace where Starboard creates Jobs
 	// and other helper objects.
 	GetNamespace() string
@@ -13,10 +27,25 @@ type PluginContext interface {
 }
 
 type pluginContext struct {
+	name               string
+	client             client.Client
 	namespace          string
 	serviceAccountName string
 }
 
+func (p *pluginContext) GetName() string {
+	return p.name
+}
+
+func (p *pluginContext) GetConfig() (*corev1.ConfigMap, error) {
+	cm := &corev1.ConfigMap{}
+	err := p.client.Get(context.Background(), types.NamespacedName{
+		Namespace: p.namespace,
+		Name:      fmt.Sprintf("starboard-%s-config", strings.ToLower(p.GetName())),
+	}, cm)
+	return cm.DeepCopy(), err
+}
+
 func (p *pluginContext) GetNamespace() string {
 	return p.namespace
 }
@@ -35,6 +64,16 @@ func NewPluginContext() *PluginContextBuilder {
 	}
 }
 
+func (b *PluginContextBuilder) WithName(name string) *PluginContextBuilder {
+	b.ctx.name = name
+	return b
+}
+
+func (b *PluginContextBuilder) WithClient(client client.Client) *PluginContextBuilder {
+	b.ctx.client = client
+	return b
+}
+
 func (b *PluginContextBuilder) WithNamespace(namespace string) *PluginContextBuilder {
 	b.ctx.namespace = namespace
 	return b


Test patch:
diff --git a/pkg/starboard/plugin_test.go b/pkg/starboard/plugin_test.go
index 8cb5fc2..4e77a9f 100644
--- a/pkg/starboard/plugin_test.go
+++ b/pkg/starboard/plugin_test.go
@@ -1,1 +1,51 @@
-package starboard
+package starboard_test
+
+import (
+	"testing"
+
+	"github.com/aquasecurity/starboard/pkg/starboard"
+	"github.com/onsi/gomega"
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"sigs.k8s.io/controller-runtime/pkg/client/fake"
+)
+
+func TestPluginContext_GetConfig(t *testing.T) {
+	g := gomega.NewGomegaWithT(t)
+
+	client := fake.NewClientBuilder().
+		WithScheme(starboard.NewScheme()).
+		WithObjects(&corev1.ConfigMap{
+			ObjectMeta: metav1.ObjectMeta{
+				Name:      "starboard-polaris-config",
+				Namespace: "starboard-ns",
+			},
+			Data: map[string]string{
+				"foo": "bar",
+			},
+		}).
+		Build()
+
+	pluginContext := starboard.NewPluginContext().
+		WithName("polaris").
+		WithNamespace("starboard-ns").
+		WithClient(client).
+		Build()
+
+	cm, err := pluginContext.GetConfig()
+
+	g.Expect(err).ToNot(gomega.HaveOccurred())
+	g.Expect(cm).To(gomega.Equal(&corev1.ConfigMap{
+		TypeMeta: metav1.TypeMeta{
+			APIVersion: "v1",
+			Kind:       "ConfigMap",
+		},
+		ObjectMeta: metav1.ObjectMeta{
+			Name:      "starboard-polaris-config",
+			Namespace: "starboard-ns",
+		},
+		Data: map[string]string{
+			"foo": "bar",
+		},
+	}))
+}