Repository: aquasecurity/starboard
Pull request #329 (2021-01-11 18:33:31)

refactor: kubebench package
Signed-off-by: Daniel Pacak <pacak.daniel@gmail.com>

codecov[bot]: # [Codecov](https://codecov.io/gh/aquasecurity/starboard/pull/329?src=pr&el=h1) Report
> Merging [#329](https://codecov.io/gh/aquasecurity/starboard/pull/329?src=pr&el=desc) (e55e249) into [main](https://codecov.io/gh/aquasecurity/starboard/commit/b42ffb5e994741cb1fa0c03f8b7e1a05cf1e7981?el=desc) (b42ffb5) will **decrease** coverage by `35.59%`.
> The diff coverage is `71.05%`.

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

```diff
@@             Coverage Diff             @@
##             main     #329       +/-   ##
===========================================
- Coverage   62.20%   26.61%   -35.60%     
===========================================
  Files          56       50        -6     
  Lines        2773     2446      -327     
===========================================
- Hits         1725      651     -1074     
- Misses        822     1743      +921     
+ Partials      226       52      -174     
```


| [Impacted Files](https://codecov.io/gh/aquasecurity/starboard/pull/329?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pkg/cmd/scan\_ciskubebench.go](https://codecov.io/gh/aquasecurity/starboard/pull/329/diff?src=pr&el=tree#diff-cGtnL2NtZC9zY2FuX2Npc2t1YmViZW5jaC5nbw==) | `0.00% <0.00%> (-54.35%)` | :arrow_down: |
| [pkg/kubebench/scanner.go](https://codecov.io/gh/aquasecurity/starboard/pull/329/diff?src=pr&el=tree#diff-cGtnL2t1YmViZW5jaC9zY2FubmVyLmdv) | `0.00% <0.00%> (-87.98%)` | :arrow_down: |
| [pkg/kubebench/writer.go](https://codecov.io/gh/aquasecurity/starboard/pull/329/diff?src=pr&el=tree#diff-cGtnL2t1YmViZW5jaC93cml0ZXIuZ28=) | `87.09% <87.09%> (ø)` | |
| [pkg/cmd/get.go](https://codecov.io/gh/aquasecurity/starboard/pull/329/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/329/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/329/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/329/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/329/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/329/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/329/diff?src=pr&el=tree#diff-cGtnL2NtZC9rdWJlX2JlbmNoLmdv) | `0.00% <0.00%> (-100.00%)` | :arrow_down: |
| ... and [34 more](https://codecov.io/gh/aquasecurity/starboard/pull/329/diff?src=pr&el=tree-more) | |

------

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


Patch:
diff --git a/pkg/cmd/scan_ciskubebench.go b/pkg/cmd/scan_ciskubebench.go
index 98e9e9f..545bf4f 100644
--- a/pkg/cmd/scan_ciskubebench.go
+++ b/pkg/cmd/scan_ciskubebench.go
@@ -5,14 +5,11 @@ import (
 	"fmt"
 	"sync"
 
-	"github.com/aquasecurity/starboard/pkg/starboard"
-
-	corev1 "k8s.io/api/core/v1"
-
-	apis "github.com/aquasecurity/starboard/pkg/generated/clientset/versioned"
+	"github.com/aquasecurity/starboard/pkg/generated/clientset/versioned"
 	"github.com/aquasecurity/starboard/pkg/kubebench"
-	"github.com/aquasecurity/starboard/pkg/kubebench/crd"
+	"github.com/aquasecurity/starboard/pkg/starboard"
 	"github.com/spf13/cobra"
+	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/cli-runtime/pkg/genericclioptions"
 	"k8s.io/client-go/kubernetes"
@@ -50,7 +47,7 @@ func ScanKubeBenchReports(cf *genericclioptions.ConfigFlags) func(cmd *cobra.Com
 		if err != nil {
 			return err
 		}
-		starboardClientset, err := apis.NewForConfig(kubernetesConfig)
+		starboardClientset, err := versioned.NewForConfig(kubernetesConfig)
 		if err != nil {
 			return err
 		}
@@ -65,7 +62,7 @@ func ScanKubeBenchReports(cf *genericclioptions.ConfigFlags) func(cmd *cobra.Com
 
 		scheme := starboard.NewScheme()
 		scanner := kubebench.NewScanner(scheme, kubernetesClientset, config, opts)
-		writer := crd.NewReadWriter(scheme, starboardClientset)
+		writer := kubebench.NewReadWriter(scheme, starboardClientset)
 
 		var wg sync.WaitGroup
 
diff --git a/pkg/kubebench/crd/writer.go b/pkg/kubebench/crd/writer.go
deleted file mode 100644
index 7c30742..0000000
--- a/pkg/kubebench/crd/writer.go
+++ /dev/null
@@ -1,72 +0,0 @@
-package crd
-
-import (
-	"context"
-
-	"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
-
-	"k8s.io/apimachinery/pkg/runtime"
-
-	"github.com/aquasecurity/starboard/pkg/generated/clientset/versioned/typed/aquasecurity/v1alpha1"
-	"k8s.io/klog"
-
-	"k8s.io/apimachinery/pkg/api/errors"
-
-	"github.com/aquasecurity/starboard/pkg/kube"
-
-	starboard "github.com/aquasecurity/starboard/pkg/apis/aquasecurity/v1alpha1"
-	starboardapi "github.com/aquasecurity/starboard/pkg/generated/clientset/versioned"
-	corev1 "k8s.io/api/core/v1"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-)
-
-type ReadWriter struct {
-	scheme  *runtime.Scheme
-	reports v1alpha1.CISKubeBenchReportInterface
-}
-
-func NewReadWriter(scheme *runtime.Scheme, clientset starboardapi.Interface) *ReadWriter {
-	return &ReadWriter{
-		scheme:  scheme,
-		reports: clientset.AquasecurityV1alpha1().CISKubeBenchReports(),
-	}
-}
-
-func (w *ReadWriter) Write(ctx context.Context, report starboard.CISKubeBenchOutput, node *corev1.Node) error {
-	reportExisting, err := w.reports.Get(ctx, node.Name, metav1.GetOptions{})
-	if err != nil && errors.IsNotFound(err) {
-		klog.V(3).Infof("Creating CISKubeBenchReport for %s node", node.Name)
-		report := &starboard.CISKubeBenchReport{
-			ObjectMeta: metav1.ObjectMeta{
-				Name: node.Name,
-				Labels: map[string]string{
-					kube.LabelResourceKind: string(kube.KindNode),
-					kube.LabelResourceName: node.Name,
-				},
-			},
-			Report: report,
-		}
-		err = controllerutil.SetOwnerReference(node, report, w.scheme)
-		if err != nil {
-			return err
-		}
-		_, err = w.reports.Create(ctx, report, metav1.CreateOptions{})
-		return err
-	}
-	if err != nil {
-		return err
-	}
-	klog.V(3).Infof("Updating existing CISKubeBenchReport for %s node", node.Name)
-	reportCopied := reportExisting.DeepCopy()
-	reportCopied.Report = report
-	_, err = w.reports.Update(ctx, reportCopied, metav1.UpdateOptions{})
-	return err
-}
-
-func (w *ReadWriter) Read(ctx context.Context, node kube.Object) (starboard.CISKubeBenchOutput, error) {
-	report, err := w.reports.Get(ctx, node.Name, metav1.GetOptions{})
-	if err != nil {
-		return starboard.CISKubeBenchOutput{}, err
-	}
-	return report.Report, nil
-}
diff --git a/pkg/kubebench/doc.go b/pkg/kubebench/doc.go
new file mode 100644
index 0000000..cb7b9f0
--- /dev/null
+++ b/pkg/kubebench/doc.go
@@ -0,0 +1,2 @@
+// This package provides primitives for working with CIS Kubernetes benchmarks.
+package kubebench
diff --git a/pkg/kubebench/scanner.go b/pkg/kubebench/scanner.go
index e2ad7b3..1d0fb08 100644
--- a/pkg/kubebench/scanner.go
+++ b/pkg/kubebench/scanner.go
@@ -56,18 +56,17 @@ func NewScanner(
 	}
 }
 
-func (s *Scanner) Scan(ctx context.Context, node corev1.Node) (report v1alpha1.CISKubeBenchOutput, err error) {
+func (s *Scanner) Scan(ctx context.Context, node corev1.Node) (v1alpha1.CISKubeBenchOutput, error) {
 	// 1. Prepare descriptor for the Kubernetes Job which will run kube-bench
 	job, err := s.prepareKubeBenchJob(node)
 	if err != nil {
-		return report, err
+		return v1alpha1.CISKubeBenchOutput{}, err
 	}
 
 	// 2. Run the prepared Job and wait for its completion or failure
 	err = runner.New().Run(ctx, kube.NewRunnableJob(s.scheme, s.clientset, job))
 	if err != nil {
-		err = fmt.Errorf("running kube-bench job: %w", err)
-		return
+		return v1alpha1.CISKubeBenchOutput{}, fmt.Errorf("running kube-bench job: %w", err)
 	}
 
 	defer func() {
@@ -75,7 +74,7 @@ func (s *Scanner) Scan(ctx context.Context, node corev1.Node) (report v1alpha1.C
 			klog.V(3).Infof("Skipping scan job deletion: %s/%s", job.Namespace, job.Name)
 			return
 		}
-		// 6. Delete the kube-bench Job
+		// 5. Delete the kube-bench Job
 		klog.V(3).Infof("Deleting job: %s/%s", job.Namespace, job.Name)
 		background := metav1.DeletePropagationBackground
 		_ = s.clientset.BatchV1().Jobs(job.Namespace).Delete(ctx, job.Name, metav1.DeleteOptions{
@@ -83,33 +82,19 @@ func (s *Scanner) Scan(ctx context.Context, node corev1.Node) (report v1alpha1.C
 		})
 	}()
 
-	// 3. Get the Pod controlled by the kube-bench Job
-	kubeBenchPod, err := s.pods.GetPodByJob(ctx, job)
-	if err != nil {
-		err = fmt.Errorf("getting kube-bench pod: %w", err)
-		return
-	}
-
-	// 4. Get kube-bench JSON output from the kube-bench Pod
+	// 3. Get kube-bench JSON output from the kube-bench Pod
 	klog.V(3).Infof("Getting logs for %s container in job: %s/%s", kubeBenchContainerName,
 		job.Namespace, job.Name)
-	logsReader, err := s.pods.GetPodLogs(ctx, kubeBenchPod, kubeBenchContainerName)
+	logsReader, err := s.pods.GetContainerLogsByJob(ctx, job, kubeBenchContainerName)
 	if err != nil {
-		err = fmt.Errorf("getting logs: %w", err)
-		return
+		return v1alpha1.CISKubeBenchOutput{}, fmt.Errorf("getting logs: %w", err)
 	}
 	defer func() {
 		_ = logsReader.Close()
 	}()
 
-	// 5. Parse the CISBenchmarkReport from the logs Reader
-	report, err = s.converter.Convert(s.config, logsReader)
-	if err != nil {
-		err = fmt.Errorf("parsing CIS benchmark report: %w", err)
-		return
-	}
-
-	return
+	// 4. Parse the CISBenchmarkReport from the logs Reader
+	return s.converter.Convert(s.config, logsReader)
 }
 
 func (s *Scanner) prepareKubeBenchJob(node corev1.Node) (*batchv1.Job, error) {
diff --git a/pkg/kubebench/writer.go b/pkg/kubebench/writer.go
index 01c1cec..85fe65c 100644
--- a/pkg/kubebench/writer.go
+++ b/pkg/kubebench/writer.go
@@ -3,21 +3,77 @@ package kubebench
 import (
 	"context"
 
+	"github.com/aquasecurity/starboard/pkg/apis/aquasecurity/v1alpha1"
+	"github.com/aquasecurity/starboard/pkg/generated/clientset/versioned"
 	"github.com/aquasecurity/starboard/pkg/kube"
-
-	starboard "github.com/aquasecurity/starboard/pkg/apis/aquasecurity/v1alpha1"
-	core "k8s.io/api/core/v1"
+	corev1 "k8s.io/api/core/v1"
+	"k8s.io/apimachinery/pkg/api/errors"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/runtime"
+	"k8s.io/klog"
+	"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
 )
 
 type Writer interface {
-	Write(ctx context.Context, report starboard.CISKubeBenchOutput, node *core.Node) error
+	Write(ctx context.Context, report v1alpha1.CISKubeBenchOutput, node *corev1.Node) error
 }
 
 type Reader interface {
-	Read(ctx context.Context, node kube.Object) (starboard.CISKubeBenchOutput, error)
+	Read(ctx context.Context, node kube.Object) (v1alpha1.CISKubeBenchOutput, error)
 }
 
 type ReadWriter interface {
 	Writer
 	Reader
 }
+
+type rw struct {
+	scheme    *runtime.Scheme
+	clientset versioned.Interface
+}
+
+func NewReadWriter(scheme *runtime.Scheme, clientset versioned.Interface) ReadWriter {
+	return &rw{
+		scheme:    scheme,
+		clientset: clientset,
+	}
+}
+
+func (w *rw) Write(ctx context.Context, report v1alpha1.CISKubeBenchOutput, node *corev1.Node) error {
+	reportExisting, err := w.clientset.AquasecurityV1alpha1().CISKubeBenchReports().Get(ctx, node.Name, metav1.GetOptions{})
+	if err != nil && errors.IsNotFound(err) {
+		klog.V(3).Infof("Creating CISKubeBenchReport for %s node", node.Name)
+		report := &v1alpha1.CISKubeBenchReport{
+			ObjectMeta: metav1.ObjectMeta{
+				Name: node.Name,
+				Labels: map[string]string{
+					kube.LabelResourceKind: string(kube.KindNode),
+					kube.LabelResourceName: node.Name,
+				},
+			},
+			Report: report,
+		}
+		err = controllerutil.SetOwnerReference(node, report, w.scheme)
+		if err != nil {
+			return err
+		}
+		_, err = w.clientset.AquasecurityV1alpha1().CISKubeBenchReports().Create(ctx, report, metav1.CreateOptions{})
+		return err
+	}
+	if err != nil {
+		return err
+	}
+	klog.V(3).Infof("Updating existing CISKubeBenchReport for %s node", node.Name)
+	reportCopied := reportExisting.DeepCopy()
+	reportCopied.Report = report
+	_, err = w.clientset.AquasecurityV1alpha1().CISKubeBenchReports().Update(ctx, reportCopied, metav1.UpdateOptions{})
+	return err
+}
+
+func (w *rw) Read(ctx context.Context, node kube.Object) (v1alpha1.CISKubeBenchOutput, error) {
+	report, err := w.clientset.AquasecurityV1alpha1().CISKubeBenchReports().Get(ctx, node.Name, metav1.GetOptions{})
+	if err != nil {
+		return v1alpha1.CISKubeBenchOutput{}, err
+	}
+	return report.Report, nil
+}
diff --git a/pkg/vulnerabilityreport/doc.go b/pkg/vulnerabilityreport/doc.go
index 39c31ff..2c20227 100644
--- a/pkg/vulnerabilityreport/doc.go
+++ b/pkg/vulnerabilityreport/doc.go
@@ -1,3 +1,2 @@
-// Package vulnerabilityreport provides primitives for working with vulnerability
-// scanners.
+// This package provides primitives for working with vulnerability scanners.
 package vulnerabilityreport


Test patch:
diff --git a/itest/starboard/starboard_cli_test.go b/itest/starboard/starboard_cli_test.go
index 8e1f7c5..6049588 100644
--- a/itest/starboard/starboard_cli_test.go
+++ b/itest/starboard/starboard_cli_test.go
@@ -946,7 +946,8 @@ var _ = Describe("Starboard CLI", func() {
 		It("should run kube-bench", func() {
 			err := cmd.Run(versionInfo, []string{
 				"starboard",
-				"kube-bench",
+				"generate",
+				"ciskubebenchreports",
 				"-v", starboardCLILogLevel,
 			}, GinkgoWriter, GinkgoWriter)
 			Expect(err).ToNot(HaveOccurred())
diff --git a/pkg/kubebench/crd/writer_test.go b/pkg/kubebench/writer_test.go
similarity index 88%
rename from pkg/kubebench/crd/writer_test.go
rename to pkg/kubebench/writer_test.go
index bae6ba3..ccf9ebe 100644
--- a/pkg/kubebench/crd/writer_test.go
+++ b/pkg/kubebench/writer_test.go
@@ -1,25 +1,22 @@
-package crd_test
+package kubebench_test
 
 import (
 	"context"
 	"testing"
 
-	"github.com/aquasecurity/starboard/pkg/starboard"
-
-	"k8s.io/apimachinery/pkg/labels"
-
 	"github.com/aquasecurity/starboard/pkg/apis/aquasecurity/v1alpha1"
-	starboardClientset "github.com/aquasecurity/starboard/pkg/generated/clientset/versioned"
-	starboardClientsetFake "github.com/aquasecurity/starboard/pkg/generated/clientset/versioned/fake"
+	"github.com/aquasecurity/starboard/pkg/generated/clientset/versioned"
+	"github.com/aquasecurity/starboard/pkg/generated/clientset/versioned/fake"
 	"github.com/aquasecurity/starboard/pkg/kube"
-	"github.com/aquasecurity/starboard/pkg/kubebench/crd"
+	"github.com/aquasecurity/starboard/pkg/kubebench"
+	"github.com/aquasecurity/starboard/pkg/starboard"
+	. "github.com/onsi/ginkgo"
+	. "github.com/onsi/gomega"
 	. "github.com/onsi/gomega/gstruct"
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/labels"
 	"k8s.io/apimachinery/pkg/runtime"
-
-	. "github.com/onsi/ginkgo"
-	. "github.com/onsi/gomega"
 )
 
 func TestReadWriter(t *testing.T) {
@@ -45,14 +42,14 @@ var _ = Describe("ReadWriter", func() {
 
 	var (
 		objects   []runtime.Object
-		clientset starboardClientset.Interface
-		rw        *crd.ReadWriter
+		clientset versioned.Interface
+		rw        kubebench.ReadWriter
 	)
 
 	BeforeEach(func() {
 		objects = []runtime.Object{}
-		clientset = starboardClientsetFake.NewSimpleClientset(objects...)
-		rw = crd.NewReadWriter(starboard.NewScheme(), clientset)
+		clientset = fake.NewSimpleClientset(objects...)
+		rw = kubebench.NewReadWriter(starboard.NewScheme(), clientset)
 	})
 
 	Describe("Writing report", func() {