Repository: aquasecurity/starboard
Pull request #376 (2021-02-03 11:46:29)

feat: Manage pods controlled by third parties
Pods created and controlled by third party frameworks,
such as Argo workflow engine, are considered as unmanaged.
Otherwise we'd need to maintain and extend the list of
RBAC permissions over time.

Resolves: #373

Signed-off-by: Daniel Pacak <pacak.daniel@gmail.com>

codecov[bot]: # [Codecov](https://codecov.io/gh/aquasecurity/starboard/pull/376?src=pr&el=h1) Report
> Merging [#376](https://codecov.io/gh/aquasecurity/starboard/pull/376?src=pr&el=desc) (1586314) into [main](https://codecov.io/gh/aquasecurity/starboard/commit/39126780c680c8191137917dd417402d4114e856?el=desc) (3912678) will **decrease** coverage by `37.64%`.
> The diff coverage is `100.00%`.

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

```diff
@@             Coverage Diff             @@
##             main     #376       +/-   ##
===========================================
- Coverage   68.34%   30.69%   -37.65%     
===========================================
  Files          58       57        -1     
  Lines        3064     2981       -83     
===========================================
- Hits         2094      915     -1179     
- Misses        714     2003     +1289     
+ Partials      256       63      -193     
```


| [Impacted Files](https://codecov.io/gh/aquasecurity/starboard/pull/376?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pkg/resources/resources.go](https://codecov.io/gh/aquasecurity/starboard/pull/376/diff?src=pr&el=tree#diff-cGtnL3Jlc291cmNlcy9yZXNvdXJjZXMuZ28=) | `72.09% <100.00%> (-17.10%)` | :arrow_down: |
| [pkg/cmd/get.go](https://codecov.io/gh/aquasecurity/starboard/pull/376/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/376/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/376/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/376/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/376/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/376/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/376/diff?src=pr&el=tree#diff-cGtnL2NtZC9rdWJlX2JlbmNoLmdv) | `0.00% <0.00%> (-100.00%)` | :arrow_down: |
| [pkg/cmd/kube\_hunter.go](https://codecov.io/gh/aquasecurity/starboard/pull/376/diff?src=pr&el=tree#diff-cGtnL2NtZC9rdWJlX2h1bnRlci5nbw==) | `0.00% <0.00%> (-100.00%)` | :arrow_down: |
| [pkg/cmd/find\_vulnerabilities.go](https://codecov.io/gh/aquasecurity/starboard/pull/376/diff?src=pr&el=tree#diff-cGtnL2NtZC9maW5kX3Z1bG5lcmFiaWxpdGllcy5nbw==) | `0.00% <0.00%> (-100.00%)` | :arrow_down: |
| ... and [32 more](https://codecov.io/gh/aquasecurity/starboard/pull/376/diff?src=pr&el=tree-more) | |

------

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


Patch:
diff --git a/pkg/resources/resources.go b/pkg/resources/resources.go
index 6c7cd19..8e362c2 100644
--- a/pkg/resources/resources.go
+++ b/pkg/resources/resources.go
@@ -48,26 +48,25 @@ func GetContainerImagesFromJob(job *batchv1.Job) (kube.ContainerImages, error) {
 // cluster-scoped permissions to get Nodes in order to set the owner reference
 // when we create an instance of custom security report.)
 //
+// Pods created and controlled by third party frameworks, such as Argo workflow
+// engine, are considered as unmanaged. Otherwise we'd need to maintain and
+// extend the list of RBAC permissions over time.
 // TODO Merge this method with OwnerResolver, which accepts kube.Object and resolves client.Object.
 func GetImmediateOwnerReference(pod *corev1.Pod) kube.Object {
 	ownerRef := metav1.GetControllerOf(pod)
 
 	if ownerRef != nil {
-		if ownerRef.Kind == "Node" {
-			// Static pod ~ unmanaged pod
+		switch ownerRef.Kind {
+		case "Pod", "ReplicaSet", "ReplicationController", "Deployment", "StatefulSet", "DaemonSet", "CronJob", "Job":
 			return kube.Object{
-				Kind:      kube.KindPod,
 				Namespace: pod.Namespace,
-				Name:      pod.Name,
+				Kind:      kube.Kind(ownerRef.Kind),
+				Name:      ownerRef.Name,
 			}
 		}
-
-		return kube.Object{
-			Namespace: pod.Namespace,
-			Kind:      kube.Kind(ownerRef.Kind),
-			Name:      ownerRef.Name,
-		}
 	}
+
+	// Pod owned by anything else is treated the same as an unmanaged pod
 	return kube.Object{
 		Kind:      kube.KindPod,
 		Namespace: pod.Namespace,


Test patch:
diff --git a/pkg/resources/resources_test.go b/pkg/resources/resources_test.go
index 30a796c..26e0fe1 100644
--- a/pkg/resources/resources_test.go
+++ b/pkg/resources/resources_test.go
@@ -77,6 +77,28 @@ func TestGetImmediateOwnerReference(t *testing.T) {
 				Name:      "etcd-kind-control-plane",
 			},
 		},
+		{
+			name: "Should return pod as owner of pod managed by third party workload",
+			pod: &corev1.Pod{
+				ObjectMeta: metav1.ObjectMeta{
+					Namespace: "dev",
+					Name:      "hello-world-argo",
+					OwnerReferences: []metav1.OwnerReference{
+						{
+							APIVersion: "argoproj.io/v1alpha1",
+							Kind:       "Workflow",
+							Name:       "hello-world-argo-r99sq",
+							Controller: pointer.BoolPtr(true),
+						},
+					},
+				},
+			},
+			expectedOwner: kube.Object{
+				Kind:      "Pod",
+				Namespace: "dev",
+				Name:      "hello-world-argo",
+			},
+		},
 	}
 
 	for _, tc := range testCases {