Repository: aquasecurity/starboard
Pull request #577 (2021-05-14 09:51:34)

fix: Handle legacy image pull secrets of type kubernetes.io/dockercfg
Resolves: #569

Signed-off-by: Daniel Pacak <pacak.daniel@gmail.com>

codecov[bot]: # [Codecov](https://codecov.io/gh/aquasecurity/starboard/pull/577?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aquasecurity) Report
> Merging [#577](https://codecov.io/gh/aquasecurity/starboard/pull/577?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aquasecurity) (e908c2c) into [main](https://codecov.io/gh/aquasecurity/starboard/commit/903d2faf6d2c7fe26883d47d80d36c4837e67e74?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aquasecurity) (903d2fa) will **decrease** coverage by `33.39%`.
> The diff coverage is `70.00%`.

[![Impacted file tree graph](https://codecov.io/gh/aquasecurity/starboard/pull/577/graphs/tree.svg?width=650&height=150&src=pr&token=qqTGKAJ0Wb&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aquasecurity)](https://codecov.io/gh/aquasecurity/starboard/pull/577?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aquasecurity)

```diff
@@             Coverage Diff             @@
##             main     #577       +/-   ##
===========================================
- Coverage   71.18%   37.78%   -33.40%     
===========================================
  Files          63       62        -1     
  Lines        4074     3946      -128     
===========================================
- Hits         2900     1491     -1409     
- Misses        854     2360     +1506     
+ Partials      320       95      -225     
```


| [Impacted Files](https://codecov.io/gh/aquasecurity/starboard/pull/577?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aquasecurity) | Coverage Δ | |
|---|---|---|
| [pkg/kube/secrets.go](https://codecov.io/gh/aquasecurity/starboard/pull/577/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aquasecurity#diff-cGtnL2t1YmUvc2VjcmV0cy5nbw==) | `43.66% <57.14%> (-16.95%)` | :arrow_down: |
| [pkg/plugin/trivy/plugin.go](https://codecov.io/gh/aquasecurity/starboard/pull/577/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aquasecurity#diff-cGtnL3BsdWdpbi90cml2eS9wbHVnaW4uZ28=) | `78.28% <100.00%> (-0.88%)` | :arrow_down: |
| [pkg/cmd/get.go](https://codecov.io/gh/aquasecurity/starboard/pull/577/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aquasecurity#diff-cGtnL2NtZC9nZXQuZ28=) | `0.00% <0.00%> (-100.00%)` | :arrow_down: |
| [pkg/cmd/find.go](https://codecov.io/gh/aquasecurity/starboard/pull/577/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aquasecurity#diff-cGtnL2NtZC9maW5kLmdv) | `0.00% <0.00%> (-100.00%)` | :arrow_down: |
| [pkg/cmd/root.go](https://codecov.io/gh/aquasecurity/starboard/pull/577/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aquasecurity#diff-cGtnL2NtZC9yb290Lmdv) | `0.00% <0.00%> (-100.00%)` | :arrow_down: |
| [pkg/cmd/scan.go](https://codecov.io/gh/aquasecurity/starboard/pull/577/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aquasecurity#diff-cGtnL2NtZC9zY2FuLmdv) | `0.00% <0.00%> (-100.00%)` | :arrow_down: |
| [pkg/cmd/polaris.go](https://codecov.io/gh/aquasecurity/starboard/pull/577/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aquasecurity#diff-cGtnL2NtZC9wb2xhcmlzLmdv) | `0.00% <0.00%> (-100.00%)` | :arrow_down: |
| [pkg/cmd/version.go](https://codecov.io/gh/aquasecurity/starboard/pull/577/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aquasecurity#diff-cGtnL2NtZC92ZXJzaW9uLmdv) | `0.00% <0.00%> (-100.00%)` | :arrow_down: |
| [pkg/cmd/kube\_bench.go](https://codecov.io/gh/aquasecurity/starboard/pull/577/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aquasecurity#diff-cGtnL2NtZC9rdWJlX2JlbmNoLmdv) | `0.00% <0.00%> (-100.00%)` | :arrow_down: |
| [pkg/cmd/kube\_hunter.go](https://codecov.io/gh/aquasecurity/starboard/pull/577/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aquasecurity#diff-cGtnL2NtZC9rdWJlX2h1bnRlci5nbw==) | `0.00% <0.00%> (-100.00%)` | :arrow_down: |
| ... and [36 more](https://codecov.io/gh/aquasecurity/starboard/pull/577/diff?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aquasecurity) | |

------

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


Patch:
diff --git a/pkg/kube/secrets.go b/pkg/kube/secrets.go
index 8f29218..770df7d 100644
--- a/pkg/kube/secrets.go
+++ b/pkg/kube/secrets.go
@@ -62,10 +62,22 @@ func MapContainerNamesToDockerAuths(images ContainerImages, secrets []corev1.Sec
 func MapDockerRegistryServersToAuths(imagePullSecrets []corev1.Secret) (map[string]docker.Auth, error) {
 	auths := make(map[string]docker.Auth)
 	for _, secret := range imagePullSecrets {
+		// Skip a deprecated secret of type "kubernetes.io/dockercfg" which contains a dockercfg file
+		// that follows the same format rules as ~/.dockercfg
+		// See https://docs.docker.com/engine/deprecated/#support-for-legacy-dockercfg-configuration-files
+		if secret.Type != corev1.SecretTypeDockerConfigJson {
+			continue
+		}
+		data, hasRequiredData := secret.Data[corev1.DockerConfigJsonKey]
+		// Skip a secrets of type "kubernetes.io/dockerconfigjson" which does not contain
+		// the required ".dockerconfigjson" key.
+		if !hasRequiredData {
+			continue
+		}
 		dockerConfig := &docker.Config{}
-		err := dockerConfig.Read(secret.Data[corev1.DockerConfigJsonKey])
+		err := dockerConfig.Read(data)
 		if err != nil {
-			return nil, err
+			return nil, fmt.Errorf("reading content of %s: %w", corev1.DockerConfigJsonKey, err)
 		}
 		for authKey, auth := range dockerConfig.Auths {
 			server, err := docker.GetServerFromDockerAuthKey(authKey)
diff --git a/pkg/plugin/trivy/plugin.go b/pkg/plugin/trivy/plugin.go
index 15f6ef1..3869e8d 100644
--- a/pkg/plugin/trivy/plugin.go
+++ b/pkg/plugin/trivy/plugin.go
@@ -329,15 +329,9 @@ func (s *scanner) getPodSpecForStandaloneMode(spec corev1.PodSpec, credentials m
 				},
 			},
 		},
-		InitContainers: []corev1.Container{initContainer},
-		Containers:     containers,
-		SecurityContext: &corev1.PodSecurityContext{
-			RunAsUser:  pointer.Int64Ptr(1000),
-			RunAsGroup: pointer.Int64Ptr(1000),
-			SeccompProfile: &corev1.SeccompProfile{
-				Type: corev1.SeccompProfileTypeRuntimeDefault,
-			},
-		},
+		InitContainers:  []corev1.Container{initContainer},
+		Containers:      containers,
+		SecurityContext: &corev1.PodSecurityContext{},
 	}, secrets, nil
 }
 


Test patch:
diff --git a/pkg/kube/secrets_test.go b/pkg/kube/secrets_test.go
index 75d3a72..522a7bb 100644
--- a/pkg/kube/secrets_test.go
+++ b/pkg/kube/secrets_test.go
@@ -1,41 +1,36 @@
 package kube_test
 
 import (
+	. "github.com/onsi/gomega"
+	. "github.com/onsi/gomega/gstruct"
+
 	"testing"
 
 	"github.com/aquasecurity/starboard/pkg/docker"
 	"github.com/aquasecurity/starboard/pkg/kube"
-	. "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"
 )
 
-func TestSecrets(t *testing.T) {
-	RegisterFailHandler(Fail)
-	RunSpecs(t, "Secrets")
-}
+func TestNewImagePullSecret(t *testing.T) {
+
+	t.Run("should construct a new image secret with encoded data", func(t *testing.T) {
+		g := NewGomegaWithT(t)
+
+		secret, err := kube.NewImagePullSecret(metav1.ObjectMeta{
+			Name:      "my-secret",
+			Namespace: "my-namespace",
+		}, "http://index.docker.io/v1", "root", "s3cret")
 
-var _ = Describe("Secrets", func() {
-
-	Context("NewImagePullSecret", func() {
-
-		It("should construct a new image secret with encoded data", func() {
-			secret, err := kube.NewImagePullSecret(metav1.ObjectMeta{
-				Name:      "my-secret",
-				Namespace: "my-namespace",
-			}, "http://index.docker.io/v1", "root", "s3cret")
-
-			Expect(err).ToNot(HaveOccurred())
-			Expect(*secret).To(MatchFields(IgnoreExtras, Fields{
-				"ObjectMeta": MatchFields(IgnoreExtras, Fields{
-					"Name":      Equal("my-secret"),
-					"Namespace": Equal("my-namespace"),
-				}),
-				"Type": Equal(corev1.SecretTypeDockerConfigJson),
-				"Data": MatchAllKeys(Keys{
-					".dockerconfigjson": MatchJSON(`{
+		g.Expect(err).ToNot(HaveOccurred())
+		g.Expect(*secret).To(MatchFields(IgnoreExtras, Fields{
+			"ObjectMeta": MatchFields(IgnoreExtras, Fields{
+				"Name":      Equal("my-secret"),
+				"Namespace": Equal("my-namespace"),
+			}),
+			"Type": Equal(corev1.SecretTypeDockerConfigJson),
+			"Data": MatchAllKeys(Keys{
+				".dockerconfigjson": MatchJSON(`{
   "auths": {
     "http://index.docker.io/v1": {
       "auth": "cm9vdDpzM2NyZXQ=",
@@ -44,111 +39,142 @@ var _ = Describe("Secrets", func() {
     }
   }
 }`),
-				}),
-			}))
-		})
-
+			}),
+		}))
 	})
+}
+
+func TestMapDockerRegistryServersToAuths(t *testing.T) {
 
-	Context("MapDockerRegistryServersToAuths", func() {
+	t.Run("should map Docker registry servers to Docker authentication credentials", func(t *testing.T) {
+		g := NewGomegaWithT(t)
 
-		It("should map Docker registry servers to Docker authentication credentials", func() {
-			auths, err := kube.MapDockerRegistryServersToAuths([]corev1.Secret{
-				{
-					Type: corev1.SecretTypeDockerConfigJson,
-					Data: map[string][]byte{
-						corev1.DockerConfigJsonKey: []byte(`{
+		auths, err := kube.MapDockerRegistryServersToAuths([]corev1.Secret{
+			{
+				Type: corev1.SecretTypeDockerConfigJson,
+				Data: map[string][]byte{
+					corev1.DockerConfigJsonKey: []byte(`{
   "auths": {
     "http://index.docker.io/v1": {
       "auth": "cm9vdDpzM2NyZXQ="
     }
   }
 }`),
-					},
 				},
-				{
-					Type: corev1.SecretTypeDockerConfigJson,
-					Data: map[string][]byte{
-						corev1.DockerConfigJsonKey: []byte(`{
+			},
+			{
+				Type: corev1.SecretTypeDockerConfigJson,
+				Data: map[string][]byte{
+					corev1.DockerConfigJsonKey: []byte(`{
   "auths": {
     "quay.io": {
       "auth": "dXNlcjpBZG1pbjEyMzQ1"
     }
   }
 }`),
-					},
 				},
-			})
-			Expect(err).ToNot(HaveOccurred())
-			Expect(auths).To(MatchAllKeys(Keys{
-				"index.docker.io": Equal(docker.Auth{
-					Auth:     "cm9vdDpzM2NyZXQ=",
-					Username: "root",
-					Password: "s3cret",
-				}),
-				"quay.io": Equal(docker.Auth{
-					Auth:     "dXNlcjpBZG1pbjEyMzQ1",
-					Username: "user",
-					Password: "Admin12345",
-				}),
-			}))
+			},
 		})
+		g.Expect(err).ToNot(HaveOccurred())
+		g.Expect(auths).To(MatchAllKeys(Keys{
+			"index.docker.io": Equal(docker.Auth{
+				Auth:     "cm9vdDpzM2NyZXQ=",
+				Username: "root",
+				Password: "s3cret",
+			}),
+			"quay.io": Equal(docker.Auth{
+				Auth:     "dXNlcjpBZG1pbjEyMzQ1",
+				Username: "user",
+				Password: "Admin12345",
+			}),
+		}))
+	})
+
+	t.Run(`should skip secret of type "kubernetes.io/dockercfg"`, func(t *testing.T) {
+		g := NewGomegaWithT(t)
 
+		auths, err := kube.MapDockerRegistryServersToAuths([]corev1.Secret{
+			{
+				Type: corev1.SecretTypeDockercfg,
+				Data: map[string][]byte{},
+			},
+			{
+				Type: corev1.SecretTypeDockerConfigJson,
+				Data: map[string][]byte{
+					corev1.DockerConfigJsonKey: []byte(`{
+  "auths": {
+    "http://index.docker.io/v1": {
+      "auth": "cm9vdDpzM2NyZXQ="
+    }
+  }
+}`),
+				},
+			},
+		})
+
+		g.Expect(err).ToNot(HaveOccurred())
+		g.Expect(auths).To(MatchAllKeys(Keys{
+			"index.docker.io": Equal(docker.Auth{
+				Auth:     "cm9vdDpzM2NyZXQ=",
+				Username: "root",
+				Password: "s3cret",
+			}),
+		}))
 	})
+}
+
+func TestMapContainerNamesToDockerAuths(t *testing.T) {
+
+	t.Run("should map container images to Docker authentication credentials", func(t *testing.T) {
+		g := NewGomegaWithT(t)
 
-	Context("MapContainerNamesToDockerAuths", func() {
-
-		It("should map container images to Docker authentication credentials", func() {
-			auths, err := kube.MapContainerNamesToDockerAuths(kube.ContainerImages{
-				"container-1": "docker.io/my-organization/my-app-backend:0.1.0",
-				"container-2": "my-organization/my-app-frontend:0.3.2",
-				"container-3": "quay.io/my-company/my-service:2.0",
-			}, []corev1.Secret{
-				{
-					Type: corev1.SecretTypeDockerConfigJson,
-					Data: map[string][]byte{
-						corev1.DockerConfigJsonKey: []byte(`{
+		auths, err := kube.MapContainerNamesToDockerAuths(kube.ContainerImages{
+			"container-1": "docker.io/my-organization/my-app-backend:0.1.0",
+			"container-2": "my-organization/my-app-frontend:0.3.2",
+			"container-3": "quay.io/my-company/my-service:2.0",
+		}, []corev1.Secret{
+			{
+				Type: corev1.SecretTypeDockerConfigJson,
+				Data: map[string][]byte{
+					corev1.DockerConfigJsonKey: []byte(`{
   "auths": {
     "http://index.docker.io/v1": {
       "auth": "cm9vdDpzM2NyZXQ="
     }
   }
 }`),
-					},
 				},
-				{
-					Type: corev1.SecretTypeDockerConfigJson,
-					Data: map[string][]byte{
-						corev1.DockerConfigJsonKey: []byte(`{
+			},
+			{
+				Type: corev1.SecretTypeDockerConfigJson,
+				Data: map[string][]byte{
+					corev1.DockerConfigJsonKey: []byte(`{
   "auths": {
     "quay.io": {
       "auth": "dXNlcjpBZG1pbjEyMzQ1"
     }
   }
 }`),
-					},
 				},
-			})
-			Expect(err).ToNot(HaveOccurred())
-			Expect(auths).To(MatchAllKeys(Keys{
-				"container-1": Equal(docker.Auth{
-					Auth:     "cm9vdDpzM2NyZXQ=",
-					Username: "root",
-					Password: "s3cret",
-				}),
-				"container-2": Equal(docker.Auth{
-					Auth:     "cm9vdDpzM2NyZXQ=",
-					Username: "root",
-					Password: "s3cret",
-				}),
-				"container-3": Equal(docker.Auth{
-					Auth:     "dXNlcjpBZG1pbjEyMzQ1",
-					Username: "user",
-					Password: "Admin12345",
-				}),
-			}))
+			},
 		})
-
+		g.Expect(err).ToNot(HaveOccurred())
+		g.Expect(auths).To(MatchAllKeys(Keys{
+			"container-1": Equal(docker.Auth{
+				Auth:     "cm9vdDpzM2NyZXQ=",
+				Username: "root",
+				Password: "s3cret",
+			}),
+			"container-2": Equal(docker.Auth{
+				Auth:     "cm9vdDpzM2NyZXQ=",
+				Username: "root",
+				Password: "s3cret",
+			}),
+			"container-3": Equal(docker.Auth{
+				Auth:     "dXNlcjpBZG1pbjEyMzQ1",
+				Username: "user",
+				Password: "Admin12345",
+			}),
+		}))
 	})
-
-})
+}
diff --git a/pkg/plugin/trivy/plugin_test.go b/pkg/plugin/trivy/plugin_test.go
index a0cae05..7ab86f6 100644
--- a/pkg/plugin/trivy/plugin_test.go
+++ b/pkg/plugin/trivy/plugin_test.go
@@ -227,13 +227,7 @@ func TestScanner_GetScanJobSpec(t *testing.T) {
 						},
 					},
 				},
-				SecurityContext: &corev1.PodSecurityContext{
-					RunAsUser:  pointer.Int64Ptr(1000),
-					RunAsGroup: pointer.Int64Ptr(1000),
-					SeccompProfile: &corev1.SeccompProfile{
-						Type: corev1.SeccompProfileTypeRuntimeDefault,
-					},
-				},
+				SecurityContext: &corev1.PodSecurityContext{},
 			},
 		},
 		{
@@ -443,13 +437,7 @@ func TestScanner_GetScanJobSpec(t *testing.T) {
 						},
 					},
 				},
-				SecurityContext: &corev1.PodSecurityContext{
-					RunAsUser:  pointer.Int64Ptr(1000),
-					RunAsGroup: pointer.Int64Ptr(1000),
-					SeccompProfile: &corev1.SeccompProfile{
-						Type: corev1.SeccompProfileTypeRuntimeDefault,
-					},
-				},
+				SecurityContext: &corev1.PodSecurityContext{},
 			},
 		},
 		{