Repository: aquasecurity/starboard
Pull request #276 (2020-12-14 16:43:29)

feat(config): Add starboard secret to store sensitive config params
The init command creates the starboard ConfigMap in the starboard namespace.
This is not suitable for setting sensitive params such as tokens or passwords.

Signed-off-by: Daniel Pacak <pacak.daniel@gmail.com>

codecov[bot]: # [Codecov](https://codecov.io/gh/aquasecurity/starboard/pull/276?src=pr&el=h1) Report
> Merging [#276](https://codecov.io/gh/aquasecurity/starboard/pull/276?src=pr&el=desc) (007d6a2) into [master](https://codecov.io/gh/aquasecurity/starboard/commit/5d7d11a808095fcbf0de27f08f521fd36c5bdb7c?el=desc) (5d7d11a) will **decrease** coverage by `10.55%`.
> The diff coverage is `100.00%`.

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

```diff
@@             Coverage Diff             @@
##           master     #276       +/-   ##
===========================================
- Coverage   60.49%   49.94%   -10.56%     
===========================================
  Files          56       12       -44     
  Lines        2630      885     -1745     
===========================================
- Hits         1591      442     -1149     
+ Misses        832      378      -454     
+ Partials      207       65      -142     
```


| [Impacted Files](https://codecov.io/gh/aquasecurity/starboard/pull/276?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pkg/trivy/scanner.go](https://codecov.io/gh/aquasecurity/starboard/pull/276/diff?src=pr&el=tree#diff-cGtnL3RyaXZ5L3NjYW5uZXIuZ28=) | `52.88% <100.00%> (ø)` | |
| [pkg/vulnerabilityreport/writer.go](https://codecov.io/gh/aquasecurity/starboard/pull/276/diff?src=pr&el=tree#diff-cGtnL3Z1bG5lcmFiaWxpdHlyZXBvcnQvd3JpdGVyLmdv) | `0.00% <0.00%> (-84.38%)` | :arrow_down: |
| [pkg/vulnerabilityreport/scanner.go](https://codecov.io/gh/aquasecurity/starboard/pull/276/diff?src=pr&el=tree#diff-cGtnL3Z1bG5lcmFiaWxpdHlyZXBvcnQvc2Nhbm5lci5nbw==) | `0.00% <0.00%> (-73.47%)` | :arrow_down: |
| [pkg/vulnerabilityreport/store.go](https://codecov.io/gh/aquasecurity/starboard/pull/276/diff?src=pr&el=tree#diff-cGtnL3Z1bG5lcmFiaWxpdHlyZXBvcnQvc3RvcmUuZ28=) | `65.51% <0.00%> (-17.25%)` | :arrow_down: |
| [pkg/trivy/converter.go](https://codecov.io/gh/aquasecurity/starboard/pull/276/diff?src=pr&el=tree#diff-cGtnL3RyaXZ5L2NvbnZlcnRlci5nbw==) | `83.60% <0.00%> (-9.84%)` | :arrow_down: |
| [pkg/cmd/version.go](https://codecov.io/gh/aquasecurity/starboard/pull/276/diff?src=pr&el=tree#diff-cGtnL2NtZC92ZXJzaW9uLmdv) | | |
| [pkg/polaris/scanner.go](https://codecov.io/gh/aquasecurity/starboard/pull/276/diff?src=pr&el=tree#diff-cGtnL3BvbGFyaXMvc2Nhbm5lci5nbw==) | | |
| [pkg/cmd/find.go](https://codecov.io/gh/aquasecurity/starboard/pull/276/diff?src=pr&el=tree#diff-cGtnL2NtZC9maW5kLmdv) | | |
| [pkg/kube/pod/manager.go](https://codecov.io/gh/aquasecurity/starboard/pull/276/diff?src=pr&el=tree#diff-cGtnL2t1YmUvcG9kL21hbmFnZXIuZ28=) | | |
| [pkg/operator/etc/config.go](https://codecov.io/gh/aquasecurity/starboard/pull/276/diff?src=pr&el=tree#diff-cGtnL29wZXJhdG9yL2V0Yy9jb25maWcuZ28=) | | |
| ... and [34 more](https://codecov.io/gh/aquasecurity/starboard/pull/276/diff?src=pr&el=tree-more) | |

------

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


Patch:
diff --git a/pkg/cmd/cleanup.go b/pkg/cmd/cleanup.go
index d49cdb4..3c9ea38 100644
--- a/pkg/cmd/cleanup.go
+++ b/pkg/cmd/cleanup.go
@@ -3,9 +3,8 @@ package cmd
 import (
 	"context"
 
-	"github.com/aquasecurity/starboard/pkg/starboard"
-
 	"github.com/aquasecurity/starboard/pkg/kube"
+	"github.com/aquasecurity/starboard/pkg/starboard"
 	"github.com/spf13/cobra"
 	extapi "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1"
 	"k8s.io/cli-runtime/pkg/genericclioptions"
@@ -15,9 +14,8 @@ import (
 func NewCleanupCmd(cf *genericclioptions.ConfigFlags) *cobra.Command {
 	cmd := &cobra.Command{
 		Use:   "cleanup",
-		Short: "Delete custom resource definitions created by starboard",
+		Short: "Delete Kubernetes resources created by Starboard",
 		RunE: func(cmd *cobra.Command, args []string) error {
-			ctx := context.Background()
 			config, err := cf.ToRESTConfig()
 			if err != nil {
 				return err
@@ -30,8 +28,9 @@ func NewCleanupCmd(cf *genericclioptions.ConfigFlags) *cobra.Command {
 			if err != nil {
 				return err
 			}
-			return kube.NewCRManager(starboard.NewConfigManager(clientset, starboard.NamespaceName), clientset, clientsetext).
-				Cleanup(ctx)
+			configManager := starboard.NewConfigManager(clientset, starboard.NamespaceName)
+			return kube.NewCRManager(clientset, clientsetext, configManager).
+				Cleanup(context.TODO())
 		},
 	}
 	return cmd
diff --git a/pkg/cmd/config.go b/pkg/cmd/config.go
index 778960d..f99f315 100644
--- a/pkg/cmd/config.go
+++ b/pkg/cmd/config.go
@@ -7,7 +7,6 @@ import (
 	"strings"
 
 	"github.com/aquasecurity/starboard/pkg/starboard"
-
 	"github.com/spf13/cobra"
 	"k8s.io/cli-runtime/pkg/genericclioptions"
 	"k8s.io/client-go/kubernetes"
@@ -22,27 +21,27 @@ func NewConfigCmd(cf *genericclioptions.ConfigFlags, outWriter io.Writer) *cobra
 	var localFlags LocalFlags
 	cmd := &cobra.Command{
 		Use:   "config",
-		Short: "View the configuration parameters used by starboard scanners",
-		RunE: func(cmd *cobra.Command, args []string) (err error) {
+		Short: "View the configuration parameters used by Starboard scanners",
+		RunE: func(cmd *cobra.Command, args []string) error {
 			ctx := context.Background()
 			kubernetesConfig, err := cf.ToRESTConfig()
 			if err != nil {
-				return
+				return err
 			}
 			clientset, err := kubernetes.NewForConfig(kubernetesConfig)
 			if err != nil {
-				return
+				return err
 			}
 			config, err := starboard.NewConfigManager(clientset, starboard.NamespaceName).Read(ctx)
 			if err != nil {
-				return
+				return err
 			}
 			filteredValues, err := getFilteredValues(config, &localFlags)
 			if err != nil {
-				return
+				return err
 			}
 			_, _ = fmt.Fprintf(outWriter, "%s\n", filteredValues)
-			return
+			return nil
 		},
 	}
 	setLocalFlags(cmd, &localFlags)
diff --git a/pkg/cmd/init.go b/pkg/cmd/init.go
index 8c0239b..4c14c3e 100644
--- a/pkg/cmd/init.go
+++ b/pkg/cmd/init.go
@@ -3,9 +3,8 @@ package cmd
 import (
 	"context"
 
-	"github.com/aquasecurity/starboard/pkg/starboard"
-
 	"github.com/aquasecurity/starboard/pkg/kube"
+	"github.com/aquasecurity/starboard/pkg/starboard"
 	"github.com/spf13/cobra"
 	extensionsapi "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1"
 	"k8s.io/cli-runtime/pkg/genericclioptions"
@@ -15,22 +14,30 @@ import (
 func NewInitCmd(cf *genericclioptions.ConfigFlags) *cobra.Command {
 	cmd := &cobra.Command{
 		Use:   "init",
-		Short: "Create custom resource definitions used by starboard",
-		Long: `Create all the resources used by starboard. It will create the following
-in the cluster:
+		Short: "Create Kubernetes resources used by Starboard",
+		Long: `Create all the resources used by Starboard. It will create the following in your
+Kubernetes cluster:
 
- - custom resource definitions
- - starboard namespace
- - starboard service account
- - starboard cluster role and cluster role binding
- - config map
+ - CustomResourceDefinition objects:
+   - "vulnerabilityreports.aquasecurity.github.io"
+   - "configauditreports.aquasecurity.github.io"
+   - "ciskubebenchreports.aquasecurity.github.io"
+   - "kubehunterreports.aquasecurity.github.io"
+ - RBAC objects:
+   - The "starboard" ClusterRole
+   - The "starboard" ClusterRoleBinding
+ - The "starboard" namespace with the following objects:
+   - The "starboard" service account
+   - The "starboard" ConfigMap
+   - The "starboard" secret
 
-The config map contains the default configuration parameters. However this
-can be modified to change the behaviour of the scanner.
+The "starboard" ConfigMap and the "starboard" secret contain the default
+config parameters. However this can be modified to change the behaviour
+of the scanners.
 
-These resources can be removed from the cluster using the "cleanup" command.`,
+All resources created by this command can be removed from the cluster using
+the "cleanup" command.`,
 		RunE: func(cmd *cobra.Command, args []string) error {
-			ctx := context.Background()
 			config, err := cf.ToRESTConfig()
 			if err != nil {
 				return err
@@ -43,8 +50,9 @@ These resources can be removed from the cluster using the "cleanup" command.`,
 			if err != nil {
 				return err
 			}
-			return kube.NewCRManager(starboard.NewConfigManager(clientset, starboard.NamespaceName), clientset, clientsetext).
-				Init(ctx)
+			configManager := starboard.NewConfigManager(clientset, starboard.NamespaceName)
+			return kube.NewCRManager(clientset, clientsetext, configManager).
+				Init(context.TODO())
 		},
 	}
 	return cmd
diff --git a/pkg/kube/cr_manager.go b/pkg/kube/cr_manager.go
index a7add34..8b82421 100644
--- a/pkg/kube/cr_manager.go
+++ b/pkg/kube/cr_manager.go
@@ -5,21 +5,18 @@ import (
 	"fmt"
 	"time"
 
-	"github.com/aquasecurity/starboard/pkg/starboard"
-
-	"k8s.io/utils/pointer"
-
-	"k8s.io/apimachinery/pkg/labels"
-
 	aquasecurityv1alpha1 "github.com/aquasecurity/starboard/pkg/apis/aquasecurity/v1alpha1"
+	"github.com/aquasecurity/starboard/pkg/starboard"
 	core "k8s.io/api/core/v1"
 	rbac "k8s.io/api/rbac/v1"
 	ext "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
 	extapi "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1"
 	"k8s.io/apimachinery/pkg/api/errors"
 	meta "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/labels"
 	"k8s.io/client-go/kubernetes"
 	"k8s.io/klog"
+	"k8s.io/utils/pointer"
 )
 
 const (
@@ -120,32 +117,26 @@ var (
 	}
 )
 
-// TODO This is no longer CRManager as we're creating other resources, such as ClusterRoles and ConfigMaps
-// CRManager defined methods for managing Kubernetes custom resources.
-type CRManager interface {
-	Init(ctx context.Context) error
-	Cleanup(ctx context.Context) error
-}
-
-type crManager struct {
-	configManager starboard.ConfigManager
+type CRManager struct {
 	clientset     kubernetes.Interface
 	clientsetext  extapi.ApiextensionsV1beta1Interface
+	configManager starboard.ConfigManager
 }
 
 // NewCRManager constructs a CRManager with the given starboard.ConfigManager and kubernetes.Interface.
 func NewCRManager(
-	configManager starboard.ConfigManager,
 	clientset kubernetes.Interface,
-	clientsetext extapi.ApiextensionsV1beta1Interface) CRManager {
-	return &crManager{
+	clientsetext extapi.ApiextensionsV1beta1Interface,
+	configManager starboard.ConfigManager,
+) *CRManager {
+	return &CRManager{
 		configManager: configManager,
 		clientset:     clientset,
 		clientsetext:  clientsetext,
 	}
 }
 
-func (m *crManager) Init(ctx context.Context) (err error) {
+func (m *CRManager) Init(ctx context.Context) (err error) {
 	err = m.createOrUpdateCRD(ctx, &aquasecurityv1alpha1.VulnerabilityReportsCRD)
 	if err != nil {
 		return
@@ -181,7 +172,7 @@ func (m *crManager) Init(ctx context.Context) (err error) {
 	return
 }
 
-func (m *crManager) initRBAC(ctx context.Context) (err error) {
+func (m *CRManager) initRBAC(ctx context.Context) (err error) {
 	err = m.createServiceAccountIfNotFound(ctx, serviceAccount)
 	if err != nil {
 		return
@@ -197,7 +188,7 @@ func (m *crManager) initRBAC(ctx context.Context) (err error) {
 	return
 }
 
-func (m *crManager) cleanupRBAC(ctx context.Context) (err error) {
+func (m *CRManager) cleanupRBAC(ctx context.Context) (err error) {
 	klog.V(3).Infof("Deleting ClusterRoleBinding %q", clusterRoleBindingStarboard)
 	err = m.clientset.RbacV1().ClusterRoleBindings().Delete(ctx, clusterRoleBindingStarboard, meta.DeleteOptions{})
 	if err != nil && !errors.IsNotFound(err) {
@@ -221,7 +212,7 @@ var (
 	cleanupTimeout         = 30 * time.Second
 )
 
-func (m *crManager) cleanupNamespace(ctx context.Context) error {
+func (m *CRManager) cleanupNamespace(ctx context.Context) error {
 	klog.V(3).Infof("Deleting Namespace %q", starboard.NamespaceName)
 	err := m.clientset.CoreV1().Namespaces().Delete(ctx, starboard.NamespaceName, meta.DeleteOptions{})
 	if err != nil && !errors.IsNotFound(err) {
@@ -243,7 +234,7 @@ func (m *crManager) cleanupNamespace(ctx context.Context) error {
 	}
 }
 
-func (m *crManager) createNamespaceIfNotFound(ctx context.Context, ns *core.Namespace) (err error) {
+func (m *CRManager) createNamespaceIfNotFound(ctx context.Context, ns *core.Namespace) (err error) {
 	_, err = m.clientset.CoreV1().Namespaces().Get(ctx, ns.Name, meta.GetOptions{})
 	switch {
 	case err == nil:
@@ -257,7 +248,7 @@ func (m *crManager) createNamespaceIfNotFound(ctx context.Context, ns *core.Name
 	return
 }
 
-func (m *crManager) createServiceAccountIfNotFound(ctx context.Context, sa *core.ServiceAccount) (err error) {
+func (m *CRManager) createServiceAccountIfNotFound(ctx context.Context, sa *core.ServiceAccount) (err error) {
 	name := sa.Name
 	_, err = m.clientset.CoreV1().ServiceAccounts(starboard.NamespaceName).Get(ctx, name, meta.GetOptions{})
 	switch {
@@ -272,7 +263,7 @@ func (m *crManager) createServiceAccountIfNotFound(ctx context.Context, sa *core
 	return
 }
 
-func (m *crManager) createOrUpdateClusterRole(ctx context.Context, cr *rbac.ClusterRole) (err error) {
+func (m *CRManager) createOrUpdateClusterRole(ctx context.Context, cr *rbac.ClusterRole) (err error) {
 	existingRole, err := m.clientset.RbacV1().ClusterRoles().Get(ctx, cr.GetName(), meta.GetOptions{})
 	switch {
 	case err == nil:
@@ -289,7 +280,7 @@ func (m *crManager) createOrUpdateClusterRole(ctx context.Context, cr *rbac.Clus
 	return
 }
 
-func (m *crManager) createOrUpdateClusterRoleBinding(ctx context.Context, crb *rbac.ClusterRoleBinding) (err error) {
+func (m *CRManager) createOrUpdateClusterRoleBinding(ctx context.Context, crb *rbac.ClusterRoleBinding) (err error) {
 	existingBinding, err := m.clientset.RbacV1().ClusterRoleBindings().Get(ctx, crb.Name, meta.GetOptions{})
 	switch {
 	case err == nil:
@@ -307,7 +298,7 @@ func (m *crManager) createOrUpdateClusterRoleBinding(ctx context.Context, crb *r
 	return
 }
 
-func (m *crManager) createOrUpdateCRD(ctx context.Context, crd *ext.CustomResourceDefinition) (err error) {
+func (m *CRManager) createOrUpdateCRD(ctx context.Context, crd *ext.CustomResourceDefinition) (err error) {
 	existingCRD, err := m.clientsetext.CustomResourceDefinitions().Get(ctx, crd.Name, meta.GetOptions{})
 
 	switch {
@@ -325,7 +316,7 @@ func (m *crManager) createOrUpdateCRD(ctx context.Context, crd *ext.CustomResour
 	return
 }
 
-func (m *crManager) deleteCRD(ctx context.Context, name string) (err error) {
+func (m *CRManager) deleteCRD(ctx context.Context, name string) (err error) {
 	klog.V(3).Infof("Deleting CRD %q", name)
 	err = m.clientsetext.CustomResourceDefinitions().Delete(ctx, name, meta.DeleteOptions{})
 	if err != nil && errors.IsNotFound(err) {
@@ -334,7 +325,7 @@ func (m *crManager) deleteCRD(ctx context.Context, name string) (err error) {
 	return
 }
 
-func (m *crManager) Cleanup(ctx context.Context) (err error) {
+func (m *CRManager) Cleanup(ctx context.Context) (err error) {
 	err = m.deleteCRD(ctx, aquasecurityv1alpha1.VulnerabilityReportsCRName)
 	if err != nil {
 		return
diff --git a/pkg/starboard/config.go b/pkg/starboard/config.go
index feb4574..d252a03 100644
--- a/pkg/starboard/config.go
+++ b/pkg/starboard/config.go
@@ -3,6 +3,7 @@ package starboard
 import (
 	"context"
 	"fmt"
+	"k8s.io/apimachinery/pkg/labels"
 
 	starboardv1alpha1 "github.com/aquasecurity/starboard/pkg/apis/aquasecurity/v1alpha1"
 	appsv1 "k8s.io/api/apps/v1"
@@ -12,7 +13,6 @@ import (
 	corev1 "k8s.io/api/core/v1"
 	apierrors "k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	"k8s.io/apimachinery/pkg/labels"
 	"k8s.io/client-go/kubernetes"
 
 	"github.com/google/go-containerregistry/pkg/name"
@@ -332,7 +332,21 @@ func (c *configManager) EnsureDefault(ctx context.Context) error {
 		Data: GetDefaultConfig(),
 	}
 	_, err := c.client.CoreV1().ConfigMaps(c.namespace).Create(ctx, cm, metav1.CreateOptions{})
-	if !apierrors.IsAlreadyExists(err) {
+	if err != nil && !apierrors.IsAlreadyExists(err) {
+		return err
+	}
+
+	secret := &corev1.Secret{
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: c.namespace,
+			Name:      SecretName,
+			Labels: labels.Set{
+				"app.kubernetes.io/managed-by": "starboard",
+			},
+		},
+	}
+	_, err = c.client.CoreV1().Secrets(c.namespace).Create(ctx, secret, metav1.CreateOptions{})
+	if err != nil && !apierrors.IsAlreadyExists(err) {
 		return err
 	}
 	return nil
@@ -343,13 +357,32 @@ func (c *configManager) Read(ctx context.Context) (ConfigData, error) {
 	if err != nil {
 		return nil, err
 	}
-	return cm.Data, nil
+	secret, err := c.client.CoreV1().Secrets(c.namespace).Get(ctx, SecretName, metav1.GetOptions{})
+	if err != nil {
+		return nil, err
+	}
+
+	var data = make(map[string]string)
+
+	for k, v := range cm.Data {
+		data[k] = v
+	}
+
+	for k, v := range secret.Data {
+		data[k] = string(v)
+	}
+
+	return data, nil
 }
 
 func (c *configManager) Delete(ctx context.Context) error {
 	err := c.client.CoreV1().ConfigMaps(c.namespace).Delete(ctx, ConfigMapName, metav1.DeleteOptions{})
-	if apierrors.IsNotFound(err) {
-		return nil
+	if err != nil && !apierrors.IsNotFound(err) {
+		return err
 	}
-	return err
+	err = c.client.CoreV1().Secrets(c.namespace).Delete(ctx, SecretName, metav1.DeleteOptions{})
+	if err != nil && !apierrors.IsNotFound(err) {
+		return err
+	}
+	return nil
 }
diff --git a/pkg/starboard/constants.go b/pkg/starboard/constants.go
index e20e967..081c7df 100644
--- a/pkg/starboard/constants.go
+++ b/pkg/starboard/constants.go
@@ -2,13 +2,18 @@ package starboard
 
 const (
 	// NamespaceName the name of the namespace in which Starboard stores its
-	// configuration and runs scan Jobs.
+	// configuration and where it runs scan jobs.
 	NamespaceName = "starboard"
 
-	// ServiceAccountName the name of the ServiceAccount used to run scan Jobs.
+	// ServiceAccountName the name of the service account used to provide
+	// identity for scan jobs run by Starboard.
 	ServiceAccountName = "starboard"
 
-	// ConfigMapName the name of the ConfigMap that stored configuration of
-	// Starboard and the underlying scanners.
+	// ConfigMapName the name of the ConfigMap where Starboard stores its
+	// configuration.
 	ConfigMapName = "starboard"
+
+	// SecretName the name of the secret where Starboard stores is sensitive
+	// configuration.
+	SecretName = "starboard"
 )
diff --git a/pkg/trivy/scanner.go b/pkg/trivy/scanner.go
index 27b123f..315b3d6 100644
--- a/pkg/trivy/scanner.go
+++ b/pkg/trivy/scanner.go
@@ -39,11 +39,11 @@ type scanner struct {
 // NewScanner constructs a new Plugin, which is using an official
 // Trivy container image to scan Kubernetes workloads.
 //
-// This Plugin supports both trivy.Standalone and trivy.ClientServer
+// This Plugin supports both starboard.Standalone and starboard.ClientServer
 // client modes depending on the current starboard.TrivyConfig.
 //
-// The trivy.ClientServer more is usually more performant, however it requires
-// a Trivy server to be hosted and accessible at the configurable URL.
+// The starboard.ClientServer more is usually more performant, however it
+// requires a Trivy server to be hosted and accessible at the configurable URL.
 func NewScannerPlugin(idGenerator ext.IDGenerator, config starboard.TrivyConfig) vulnerabilityreport.Plugin {
 	return &scanner{
 		idGenerator: idGenerator,
@@ -121,9 +121,9 @@ func (s *scanner) getPodSpecForStandaloneMode(spec corev1.PodSpec, credentials m
 			{
 				Name: "GITHUB_TOKEN",
 				ValueFrom: &corev1.EnvVarSource{
-					ConfigMapKeyRef: &corev1.ConfigMapKeySelector{
+					SecretKeyRef: &corev1.SecretKeySelector{
 						LocalObjectReference: corev1.LocalObjectReference{
-							Name: starboard.ConfigMapName,
+							Name: starboard.SecretName,
 						},
 						Key:      "trivy.githubToken",
 						Optional: pointer.BoolPtr(true),


Test patch:
diff --git a/itest/starboard/starboard_cli_test.go b/itest/starboard/starboard_cli_test.go
index 6a32e18..6f9c270 100644
--- a/itest/starboard/starboard_cli_test.go
+++ b/itest/starboard/starboard_cli_test.go
@@ -8,6 +8,7 @@ import (
 	"github.com/aquasecurity/starboard/pkg/apis/aquasecurity/v1alpha1"
 	"github.com/aquasecurity/starboard/pkg/cmd"
 	"github.com/aquasecurity/starboard/pkg/kube"
+	"github.com/aquasecurity/starboard/pkg/starboard"
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/gomega"
 	. "github.com/onsi/gomega/gbytes"
@@ -143,10 +144,22 @@ var _ = Describe("Starboard CLI", func() {
 				}),
 			}))
 
-			_, err = namespaces.Get(context.TODO(), "starboard", metav1.GetOptions{})
+			_, err = namespaces.Get(context.TODO(), starboard.NamespaceName, metav1.GetOptions{})
 			Expect(err).ToNot(HaveOccurred())
 
-			// TODO Assert other Kubernetes resources that we create in the init command
+			cm, err := kubernetesClientset.CoreV1().ConfigMaps(starboard.NamespaceName).
+				Get(context.TODO(), starboard.ConfigMapName, metav1.GetOptions{})
+			Expect(err).ToNot(HaveOccurred())
+			Expect(cm.Data).To(BeEquivalentTo(starboard.GetDefaultConfig()))
+
+			secret, err := kubernetesClientset.CoreV1().Secrets(starboard.NamespaceName).
+				Get(context.TODO(), starboard.SecretName, metav1.GetOptions{})
+			Expect(err).ToNot(HaveOccurred())
+			Expect(secret.Data).To(Equal(map[string][]byte(nil)))
+
+			_, err = kubernetesClientset.CoreV1().ServiceAccounts(starboard.NamespaceName).
+				Get(context.TODO(), starboard.ServiceAccountName, metav1.GetOptions{})
+			Expect(err).ToNot(HaveOccurred())
 		})
 	})
 
diff --git a/pkg/starboard/config_test.go b/pkg/starboard/config_test.go
index 9e3b131..b0f35dc 100644
--- a/pkg/starboard/config_test.go
+++ b/pkg/starboard/config_test.go
@@ -4,14 +4,12 @@ import (
 	"context"
 	"testing"
 
-	"k8s.io/apimachinery/pkg/api/errors"
-
+	"github.com/aquasecurity/starboard/pkg/starboard"
+	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
 	corev1 "k8s.io/api/core/v1"
+	"k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-
-	"github.com/aquasecurity/starboard/pkg/starboard"
-	"github.com/stretchr/testify/assert"
 	"k8s.io/client-go/kubernetes/fake"
 )
 
@@ -107,25 +105,40 @@ func TestConfigData_GetKubeBenchImageRef(t *testing.T) {
 }
 
 func TestConfigManager_Read(t *testing.T) {
-	clientset := fake.NewSimpleClientset(&corev1.ConfigMap{
-		ObjectMeta: metav1.ObjectMeta{
-			Namespace: starboard.NamespaceName,
-			Name:      starboard.ConfigMapName,
+	clientset := fake.NewSimpleClientset(
+		&corev1.ConfigMap{
+			ObjectMeta: metav1.ObjectMeta{
+				Namespace: starboard.NamespaceName,
+				Name:      starboard.ConfigMapName,
+			},
+			Data: map[string]string{
+				"foo": "bar",
+			},
 		},
-		Data: map[string]string{
-			"foo": "bar",
+		&corev1.Secret{
+			ObjectMeta: metav1.ObjectMeta{
+				Namespace: starboard.NamespaceName,
+				Name:      starboard.SecretName,
+			},
+			Data: map[string][]byte{
+				"baz": []byte("s3cret"),
+			},
 		},
-	})
-	configData, err := starboard.NewConfigManager(clientset, starboard.NamespaceName).Read(context.TODO())
+	)
+
+	data, err := starboard.NewConfigManager(clientset, starboard.NamespaceName).
+		Read(context.TODO())
+
 	require.NoError(t, err)
 	assert.Equal(t, starboard.ConfigData{
 		"foo": "bar",
-	}, configData)
+		"baz": "s3cret",
+	}, data)
 }
 
 func TestConfigManager_EnsureDefault(t *testing.T) {
 
-	t.Run("Should create the ConfigMap with the default configuration settings", func(t *testing.T) {
+	t.Run("Should create ConfigMap with default values, and empty secret", func(t *testing.T) {
 		clientset := fake.NewSimpleClientset()
 
 		err := starboard.NewConfigManager(clientset, starboard.NamespaceName).EnsureDefault(context.TODO())
@@ -136,18 +149,35 @@ func TestConfigManager_EnsureDefault(t *testing.T) {
 			Get(context.TODO(), starboard.ConfigMapName, metav1.GetOptions{})
 		require.NoError(t, err)
 		assert.Equal(t, starboard.GetDefaultConfig(), starboard.ConfigData(cm.Data))
+
+		secret, err := clientset.CoreV1().
+			Secrets(starboard.NamespaceName).
+			Get(context.TODO(), starboard.SecretName, metav1.GetOptions{})
+		require.NoError(t, err)
+		assert.Equal(t, map[string][]byte(nil), secret.Data)
 	})
 
-	t.Run("Should not modify the ConfigMap if it already exists", func(t *testing.T) {
-		clientset := fake.NewSimpleClientset(&corev1.ConfigMap{
-			ObjectMeta: metav1.ObjectMeta{
-				Namespace: starboard.NamespaceName,
-				Name:      starboard.ConfigMapName,
+	t.Run("Should not modify ConfigMap nor secret if they already exist", func(t *testing.T) {
+		clientset := fake.NewSimpleClientset(
+			&corev1.ConfigMap{
+				ObjectMeta: metav1.ObjectMeta{
+					Namespace: starboard.NamespaceName,
+					Name:      starboard.ConfigMapName,
+				},
+				Data: map[string]string{
+					"foo": "bar",
+				},
 			},
-			Data: map[string]string{
-				"foo": "bar",
+			&corev1.Secret{
+				ObjectMeta: metav1.ObjectMeta{
+					Namespace: starboard.NamespaceName,
+					Name:      starboard.SecretName,
+				},
+				Data: map[string][]byte{
+					"baz": []byte("s3cret"),
+				},
 			},
-		})
+		)
 
 		err := starboard.NewConfigManager(clientset, starboard.NamespaceName).EnsureDefault(context.TODO())
 		require.NoError(t, err)
@@ -156,37 +186,60 @@ func TestConfigManager_EnsureDefault(t *testing.T) {
 			ConfigMaps(starboard.NamespaceName).
 			Get(context.TODO(), starboard.ConfigMapName, metav1.GetOptions{})
 		require.NoError(t, err)
-
 		assert.Equal(t, map[string]string{
 			"foo": "bar",
 		}, cm.Data)
+
+		secret, err := clientset.CoreV1().
+			Secrets(starboard.NamespaceName).
+			Get(context.TODO(), starboard.SecretName, metav1.GetOptions{})
+		require.NoError(t, err)
+		assert.Equal(t, map[string][]byte{
+			"baz": []byte("s3cret"),
+		}, secret.Data)
 	})
 
 }
 
 func TestConfigManager_Delete(t *testing.T) {
 
-	t.Run("Should not return error when ConfigMap does not exist", func(t *testing.T) {
+	t.Run("Should not return error when ConfigMap and secret do not exist", func(t *testing.T) {
 		clientset := fake.NewSimpleClientset()
 		err := starboard.NewConfigManager(clientset, starboard.NamespaceName).Delete(context.TODO())
 		require.NoError(t, err)
 	})
 
-	t.Run("Should delete the ConfigMap", func(t *testing.T) {
-		clientset := fake.NewSimpleClientset(&corev1.ConfigMap{
-			ObjectMeta: metav1.ObjectMeta{
-				Namespace: starboard.NamespaceName,
-				Name:      starboard.ConfigMapName,
+	t.Run("Should delete ConfigMap and secret", func(t *testing.T) {
+		clientset := fake.NewSimpleClientset(
+			&corev1.ConfigMap{
+				ObjectMeta: metav1.ObjectMeta{
+					Namespace: starboard.NamespaceName,
+					Name:      starboard.ConfigMapName,
+				},
+				Data: map[string]string{
+					"foo": "bar",
+				},
 			},
-			Data: map[string]string{
-				"foo": "bar",
+			&corev1.Secret{
+				ObjectMeta: metav1.ObjectMeta{
+					Namespace: starboard.NamespaceName,
+					Name:      starboard.SecretName,
+				},
+				Data: map[string][]byte{
+					"baz": []byte("s3cret"),
+				},
 			},
-		})
+		)
 
 		err := starboard.NewConfigManager(clientset, starboard.NamespaceName).Delete(context.TODO())
 		require.NoError(t, err)
 
-		_, err = clientset.CoreV1().ConfigMaps(starboard.NamespaceName).Get(context.TODO(), starboard.ConfigMapName, metav1.GetOptions{})
+		_, err = clientset.CoreV1().ConfigMaps(starboard.NamespaceName).
+			Get(context.TODO(), starboard.ConfigMapName, metav1.GetOptions{})
+		assert.True(t, errors.IsNotFound(err))
+
+		_, err = clientset.CoreV1().Secrets(starboard.NamespaceName).
+			Get(context.TODO(), starboard.SecretName, metav1.GetOptions{})
 		assert.True(t, errors.IsNotFound(err))
 	})
 }