Skip to content

Commit

Permalink
✨ focus scanning on customer workloads (#1153)
Browse files Browse the repository at this point in the history
* feat: focus scanning on "customer" workloads

* fix: existing tests - mock k8s.Get call

* feat: add tests for skipped workloads

* fix: tests helper GetWorkloadNames with skipping child workloads
  • Loading branch information
slntopp authored Jul 30, 2024
1 parent e28adf9 commit 0f5e02e
Show file tree
Hide file tree
Showing 5 changed files with 610 additions and 784 deletions.
17 changes: 17 additions & 0 deletions controllers/resource_monitor/resource_monitor_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/apiutil"
"sigs.k8s.io/controller-runtime/pkg/log"

cnquery_k8s "go.mondoo.com/cnquery/v11/providers/k8s/resources"
)

var logger = log.Log.WithName("resource-monitor")
Expand Down Expand Up @@ -82,8 +84,23 @@ func (r *ResourceMonitorController) Start(ctx context.Context) error {
}

func (r *ResourceMonitorController) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
obj := r.createRes()
if err := r.Client.Get(ctx, req.NamespacedName, obj); err != nil {
return ctrl.Result{}, client.IgnoreNotFound(err)
}

refs := obj.GetOwnerReferences()
if r.resourceType == "job" && cnquery_k8s.JobOwnerReferencesFilter(refs) {
return ctrl.Result{}, nil
} else if r.resourceType == "pod" && cnquery_k8s.PodOwnerReferencesFilter(refs) {
return ctrl.Result{}, nil
} else if r.resourceType == "replicaset" && cnquery_k8s.ReplicaSetOwnerReferencesFilter(refs) {
return ctrl.Result{}, nil
}

if len(r.scanApiStore.GetAll()) > 0 {
r.debouncer.Add(fmt.Sprintf("%s:%s:%s", r.resourceType, req.Namespace, req.Name))
}

return ctrl.Result{}, nil
}
156 changes: 149 additions & 7 deletions controllers/resource_monitor/resource_monitor_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import (
"go.mondoo.com/mondoo-operator/controllers/resource_monitor/scan_api_store"
scanapistoremock "go.mondoo.com/mondoo-operator/controllers/resource_monitor/scan_api_store/mock"
"go.mondoo.com/mondoo-operator/tests/framework/utils"
appsv1 "k8s.io/api/apps/v1"
batchv1 "k8s.io/api/batch/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
Expand Down Expand Up @@ -42,15 +44,25 @@ func (s *ResourceMonitorControllerSuite) AfterTest(suiteName, testName string) {
func (s *ResourceMonitorControllerSuite) TestReconcile_Pod() {
ctx := context.Background()
scanApiStore := scanapistoremock.NewMockScanApiStore(s.mockCtrl)

ns := utils.RandString(10)
name := utils.RandString(10)
createRes := func() client.Object {
return &corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: ns,
},
}
}

r, err := NewResourceMonitorController(
s.fakeClientBuilder.Build(),
func() client.Object { return &corev1.Pod{} },
s.fakeClientBuilder.WithObjects(createRes()).Build(),
createRes,
scanApiStore)
s.Require().NoError(err)
r.debouncer = s.debouncerMock

ns := utils.RandString(10)
name := utils.RandString(10)
scanApiStore.EXPECT().GetAll().Return([]scan_api_store.ClientConfiguration{{}}).Times(1)
s.debouncerMock.EXPECT().Add(fmt.Sprintf("pod:%s:%s", ns, name)).Times(1)

Expand All @@ -67,16 +79,146 @@ func (s *ResourceMonitorControllerSuite) TestReconcile_Pod() {
func (s *ResourceMonitorControllerSuite) TestReconcile_Pod_NoScanApi() {
ctx := context.Background()
scanApiStore := scanapistoremock.NewMockScanApiStore(s.mockCtrl)

ns := utils.RandString(10)
name := utils.RandString(10)
createRes := func() client.Object {
return &corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: ns,
},
}
}

r, err := NewResourceMonitorController(
s.fakeClientBuilder.Build(),
func() client.Object { return &corev1.Pod{} },
s.fakeClientBuilder.WithObjects(createRes()).Build(),
createRes,
scanApiStore)
s.Require().NoError(err)
r.debouncer = s.debouncerMock

scanApiStore.EXPECT().GetAll().Return(nil)

res, err := r.Reconcile(ctx, controllerruntime.Request{
NamespacedName: types.NamespacedName{
Namespace: ns,
Name: name,
},
})
s.True(res.IsZero())
s.NoError(err)
}

func (s *ResourceMonitorControllerSuite) TestReconcile_Child_Pod() {
ctx := context.Background()
scanApiStore := scanapistoremock.NewMockScanApiStore(s.mockCtrl)

ns := utils.RandString(10)
name := utils.RandString(10)
scanApiStore.EXPECT().GetAll().Return(nil)
createRes := func() client.Object {
return &corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: ns,
OwnerReferences: []metav1.OwnerReference{
{
Kind: "ReplicaSet",
},
},
},
}
}

r, err := NewResourceMonitorController(
s.fakeClientBuilder.WithObjects(createRes()).Build(),
createRes,
scanApiStore)
s.Require().NoError(err)
r.debouncer = s.debouncerMock

scanApiStore.EXPECT().GetAll().Return([]scan_api_store.ClientConfiguration{{}}).Times(0)
s.debouncerMock.EXPECT().Add(fmt.Sprintf("pod:%s:%s", ns, name)).Times(0)

res, err := r.Reconcile(ctx, controllerruntime.Request{
NamespacedName: types.NamespacedName{
Namespace: ns,
Name: name,
},
})
s.True(res.IsZero())
s.NoError(err)
}

func (s *ResourceMonitorControllerSuite) TestReconcile_Child_Job() {
ctx := context.Background()
scanApiStore := scanapistoremock.NewMockScanApiStore(s.mockCtrl)

ns := utils.RandString(10)
name := utils.RandString(10)
createRes := func() client.Object {
return &batchv1.Job{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: ns,
OwnerReferences: []metav1.OwnerReference{
{
Kind: "CronJob",
},
},
},
}
}

r, err := NewResourceMonitorController(
s.fakeClientBuilder.WithObjects(createRes()).Build(),
createRes,
scanApiStore)
s.Require().NoError(err)
r.debouncer = s.debouncerMock

scanApiStore.EXPECT().GetAll().Return([]scan_api_store.ClientConfiguration{{}}).Times(0)
s.debouncerMock.EXPECT().Add(fmt.Sprintf("pod:%s:%s", ns, name)).Times(0)

res, err := r.Reconcile(ctx, controllerruntime.Request{
NamespacedName: types.NamespacedName{
Namespace: ns,
Name: name,
},
})
s.True(res.IsZero())
s.NoError(err)
}

func (s *ResourceMonitorControllerSuite) TestReconcile_Child_ReplicaSet() {
ctx := context.Background()
scanApiStore := scanapistoremock.NewMockScanApiStore(s.mockCtrl)

ns := utils.RandString(10)
name := utils.RandString(10)
createRes := func() client.Object {
return &appsv1.ReplicaSet{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: ns,
OwnerReferences: []metav1.OwnerReference{
{
Kind: "Deployment",
},
},
},
}
}

r, err := NewResourceMonitorController(
s.fakeClientBuilder.WithObjects(createRes()).Build(),
createRes,
scanApiStore)
s.Require().NoError(err)
r.debouncer = s.debouncerMock

scanApiStore.EXPECT().GetAll().Return([]scan_api_store.ClientConfiguration{{}}).Times(0)
s.debouncerMock.EXPECT().Add(fmt.Sprintf("pod:%s:%s", ns, name)).Times(0)

res, err := r.Reconcile(ctx, controllerruntime.Request{
NamespacedName: types.NamespacedName{
Expand Down
Loading

0 comments on commit 0f5e02e

Please sign in to comment.