Repository: aquasecurity/starboard
Pull request #420 (2021-03-05 08:42:54)

feat: Pass K8s object to configauditreport.Plugin
Signed-off-by: Daniel Pacak <pacak.daniel@gmail.com>

codecov[bot]: # [Codecov](https://codecov.io/gh/aquasecurity/starboard/pull/420?src=pr&el=h1) Report
> Merging [#420](https://codecov.io/gh/aquasecurity/starboard/pull/420?src=pr&el=desc) (e772817) into [main](https://codecov.io/gh/aquasecurity/starboard/commit/a36725a9658c9e9e750484ff50b728304b08c5bd?el=desc) (a36725a) will **decrease** coverage by `37.31%`.
> The diff coverage is `4.76%`.

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

```diff
@@             Coverage Diff             @@
##             main     #420       +/-   ##
===========================================
- Coverage   67.07%   29.75%   -37.32%     
===========================================
  Files          59       58        -1     
  Lines        3371     3280       -91     
===========================================
- Hits         2261      976     -1285     
- Misses        830     2243     +1413     
+ Partials      280       61      -219     
```


| [Impacted Files](https://codecov.io/gh/aquasecurity/starboard/pull/420?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pkg/configauditreport/scanner.go](https://codecov.io/gh/aquasecurity/starboard/pull/420/diff?src=pr&el=tree#diff-cGtnL2NvbmZpZ2F1ZGl0cmVwb3J0L3NjYW5uZXIuZ28=) | `0.00% <0.00%> (-81.95%)` | :arrow_down: |
| [pkg/kube/pod/manager.go](https://codecov.io/gh/aquasecurity/starboard/pull/420/diff?src=pr&el=tree#diff-cGtnL2t1YmUvcG9kL21hbmFnZXIuZ28=) | `0.00% <ø> (-40.00%)` | :arrow_down: |
| [pkg/operator/controller/configauditreport.go](https://codecov.io/gh/aquasecurity/starboard/pull/420/diff?src=pr&el=tree#diff-cGtnL29wZXJhdG9yL2NvbnRyb2xsZXIvY29uZmlnYXVkaXRyZXBvcnQuZ28=) | `0.00% <0.00%> (-64.37%)` | :arrow_down: |
| [pkg/plugin/polaris/plugin.go](https://codecov.io/gh/aquasecurity/starboard/pull/420/diff?src=pr&el=tree#diff-cGtnL3BsdWdpbi9wb2xhcmlzL3BsdWdpbi5nbw==) | `91.17% <50.00%> (ø)` | |
| [pkg/cmd/get.go](https://codecov.io/gh/aquasecurity/starboard/pull/420/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/420/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/420/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/420/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/420/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/420/diff?src=pr&el=tree#diff-cGtnL2NtZC92ZXJzaW9uLmdv) | `0.00% <0.00%> (-100.00%)` | :arrow_down: |
| ... and [37 more](https://codecov.io/gh/aquasecurity/starboard/pull/420/diff?src=pr&el=tree-more) | |

------

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


Patch:
diff --git a/pkg/configauditreport/plugin.go b/pkg/configauditreport/plugin.go
index 1b98500..5605d9c 100644
--- a/pkg/configauditreport/plugin.go
+++ b/pkg/configauditreport/plugin.go
@@ -7,6 +7,7 @@ import (
 	"github.com/aquasecurity/starboard/pkg/kube"
 	corev1 "k8s.io/api/core/v1"
 	"k8s.io/apimachinery/pkg/runtime/schema"
+	"sigs.k8s.io/controller-runtime/pkg/client"
 )
 
 // Plugin defines the interface between Starboard and Kubernetes workload
@@ -14,7 +15,7 @@ import (
 // first step to separate generic workloads discovery code and Polaris
 // implementation details.
 type Plugin interface {
-	GetScanJobSpec(workload kube.Object, gvk schema.GroupVersionKind) (corev1.PodSpec, error)
+	GetScanJobSpec(workload kube.Object, obj client.Object, gvk schema.GroupVersionKind) (corev1.PodSpec, []*corev1.Secret, error)
 
 	GetContainerName() string
 
diff --git a/pkg/configauditreport/scanner.go b/pkg/configauditreport/scanner.go
index 70ab341..a1a2388 100644
--- a/pkg/configauditreport/scanner.go
+++ b/pkg/configauditreport/scanner.go
@@ -18,6 +18,7 @@ import (
 	"k8s.io/client-go/kubernetes"
 	"k8s.io/klog"
 	"k8s.io/utils/pointer"
+	"sigs.k8s.io/controller-runtime/pkg/client"
 )
 
 type Scanner struct {
@@ -56,12 +57,12 @@ func (s *Scanner) Scan(ctx context.Context, workload kube.Object, gvk schema.Gro
 	}
 
 	klog.V(3).Infof("Scanning with options: %+v", s.opts)
-	job, err := s.getScanJob(workload, gvk)
+	job, secrets, err := s.getScanJob(workload, owner, gvk)
 	if err != nil {
 		return v1alpha1.ConfigAuditReport{}, err
 	}
 
-	err = runner.New().Run(ctx, kube.NewRunnableJob(s.scheme, s.clientset, job))
+	err = runner.New().Run(ctx, kube.NewRunnableJob(s.scheme, s.clientset, job, secrets...))
 	if err != nil {
 		return v1alpha1.ConfigAuditReport{}, fmt.Errorf("running scan job: %w", err)
 	}
@@ -98,10 +99,10 @@ func (s *Scanner) Scan(ctx context.Context, workload kube.Object, gvk schema.Gro
 		Get()
 }
 
-func (s *Scanner) getScanJob(workload kube.Object, gvk schema.GroupVersionKind) (*batchv1.Job, error) {
-	jobSpec, err := s.plugin.GetScanJobSpec(workload, gvk)
+func (s *Scanner) getScanJob(workload kube.Object, obj client.Object, gvk schema.GroupVersionKind) (*batchv1.Job, []*corev1.Secret, error) {
+	jobSpec, secrets, err := s.plugin.GetScanJobSpec(workload, obj, gvk)
 	if err != nil {
-		return nil, err
+		return nil, nil, err
 	}
 	return &batchv1.Job{
 		ObjectMeta: metav1.ObjectMeta{
@@ -128,5 +129,5 @@ func (s *Scanner) getScanJob(workload kube.Object, gvk schema.GroupVersionKind)
 				Spec: jobSpec,
 			},
 		},
-	}, nil
+	}, secrets, nil
 }
diff --git a/pkg/docker/doc.go b/pkg/docker/doc.go
index b9613ff..366bff8 100644
--- a/pkg/docker/doc.go
+++ b/pkg/docker/doc.go
@@ -1,2 +1,2 @@
-// This package provides primitives for working with Docker.
+// This docker package provides primitives for working with Docker.
 package docker
diff --git a/pkg/kube/pod/manager.go b/pkg/kube/pod/manager.go
index a8e1799..1bf42ff 100644
--- a/pkg/kube/pod/manager.go
+++ b/pkg/kube/pod/manager.go
@@ -11,6 +11,7 @@ import (
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/client-go/kubernetes"
+	"sigs.k8s.io/controller-runtime/pkg/client"
 )
 
 type Manager struct {
@@ -24,7 +25,7 @@ func NewPodManager(clientset kubernetes.Interface) *Manager {
 }
 
 // GetPodSpecByWorkload returns a PodSpec of the specified Workload.
-func (pw *Manager) GetPodSpecByWorkload(ctx context.Context, workload kube.Object) (spec corev1.PodSpec, object metav1.Object, err error) {
+func (pw *Manager) GetPodSpecByWorkload(ctx context.Context, workload kube.Object) (spec corev1.PodSpec, object client.Object, err error) {
 	ns := workload.Namespace
 	switch workload.Kind {
 	case kube.KindPod:
diff --git a/pkg/operator/controller/configauditreport.go b/pkg/operator/controller/configauditreport.go
index 0742ada..d14b636 100644
--- a/pkg/operator/controller/configauditreport.go
+++ b/pkg/operator/controller/configauditreport.go
@@ -20,6 +20,7 @@ import (
 	"sigs.k8s.io/controller-runtime/pkg/builder"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 	"sigs.k8s.io/controller-runtime/pkg/client/apiutil"
+	"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
 	"sigs.k8s.io/controller-runtime/pkg/reconcile"
 )
 
@@ -121,15 +122,35 @@ func (r *ConfigAuditReportReconciler) reconcilePods() reconcile.Func {
 		if err != nil {
 			return ctrl.Result{}, err
 		}
-		job, err = r.getScanJob(owner, gvk, hash)
+		job, secrets, err := r.getScanJob(owner, ownerObj, gvk, hash)
 		if err != nil {
 			return ctrl.Result{}, err
 		}
+
+		for _, secret := range secrets {
+			secret.Namespace = r.Config.Namespace
+			err := r.Client.Create(ctx, secret)
+			if err != nil {
+				return ctrl.Result{}, fmt.Errorf("creating secret: %w", err)
+			}
+		}
+
 		err = r.Client.Create(ctx, job)
 		if err != nil {
 			return ctrl.Result{}, fmt.Errorf("creating job: %w", err)
 		}
 
+		for _, secret := range secrets {
+			err = controllerutil.SetOwnerReference(job, secret, r.Client.Scheme())
+			if err != nil {
+				return ctrl.Result{}, fmt.Errorf("setting owner reference: %w", err)
+			}
+			err := r.Client.Update(ctx, secret)
+			if err != nil {
+				return ctrl.Result{}, fmt.Errorf("updating secret: %w", err)
+			}
+		}
+
 		return ctrl.Result{}, nil
 	}
 }
@@ -167,11 +188,11 @@ func (r *ConfigAuditReportReconciler) getScanJobName(workload kube.Object) strin
 	return fmt.Sprintf("scan-configauditreport-%s", resources.ComputeHash(workload))
 }
 
-func (r *ConfigAuditReportReconciler) getScanJob(workload kube.Object, gvk schema.GroupVersionKind, hash string) (*batchv1.Job, error) {
-	jobSpec, err := r.Plugin.GetScanJobSpec(workload, gvk)
+func (r *ConfigAuditReportReconciler) getScanJob(workload kube.Object, obj client.Object, gvk schema.GroupVersionKind, hash string) (*batchv1.Job, []*corev1.Secret, error) {
+	jobSpec, secrets, err := r.Plugin.GetScanJobSpec(workload, obj, gvk)
 
 	if err != nil {
-		return nil, err
+		return nil, nil, err
 	}
 
 	jobSpec.ServiceAccountName = r.Config.ServiceAccount
@@ -209,7 +230,7 @@ func (r *ConfigAuditReportReconciler) getScanJob(workload kube.Object, gvk schem
 				Spec: jobSpec,
 			},
 		},
-	}, nil
+	}, secrets, nil
 }
 
 func (r *ConfigAuditReportReconciler) reconcileJobs() reconcile.Func {
diff --git a/pkg/plugin/polaris/plugin.go b/pkg/plugin/polaris/plugin.go
index e754445..e8bfff1 100644
--- a/pkg/plugin/polaris/plugin.go
+++ b/pkg/plugin/polaris/plugin.go
@@ -15,6 +15,7 @@ import (
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/runtime/schema"
 	"k8s.io/utils/pointer"
+	"sigs.k8s.io/controller-runtime/pkg/client"
 )
 
 const (
@@ -40,10 +41,10 @@ func NewPlugin(clock ext.Clock, config Config) configauditreport.Plugin {
 	}
 }
 
-func (p *plugin) GetScanJobSpec(workload kube.Object, gvk schema.GroupVersionKind) (corev1.PodSpec, error) {
+func (p *plugin) GetScanJobSpec(workload kube.Object, obj client.Object, gvk schema.GroupVersionKind) (corev1.PodSpec, []*corev1.Secret, error) {
 	imageRef, err := p.config.GetPolarisImageRef()
 	if err != nil {
-		return corev1.PodSpec{}, err
+		return corev1.PodSpec{}, nil, err
 	}
 	sourceName := p.sourceNameFrom(workload, gvk)
 
@@ -110,7 +111,7 @@ func (p *plugin) GetScanJobSpec(workload kube.Object, gvk schema.GroupVersionKin
 				Type: corev1.SeccompProfileTypeRuntimeDefault,
 			},
 		},
-	}, nil
+	}, nil, nil
 }
 
 func (p *plugin) GetContainerName() string {


Test patch:
diff --git a/pkg/plugin/polaris/plugin_test.go b/pkg/plugin/polaris/plugin_test.go
index e2ec42f..7d268a2 100644
--- a/pkg/plugin/polaris/plugin_test.go
+++ b/pkg/plugin/polaris/plugin_test.go
@@ -119,8 +119,9 @@ func TestPlugin_GetScanJobSpec(t *testing.T) {
 	for _, tc := range testCases {
 		t.Run(tc.name, func(t *testing.T) {
 			plugin := polaris.NewPlugin(fixedClock, tc.config)
-			jobSpec, err := plugin.GetScanJobSpec(tc.workload, tc.gvk)
+			jobSpec, secrets, err := plugin.GetScanJobSpec(tc.workload, &corev1.Pod{}, tc.gvk)
 			require.NoError(t, err, tc.name)
+			assert.Nil(t, secrets)
 			assert.Equal(t, tc.expectedJobSpec, jobSpec, tc.name)
 		})
 	}