From d740ba3ed2f39361fbcb9202a30653547d136e8f Mon Sep 17 00:00:00 2001 From: Amir Malka Date: Thu, 27 Jul 2023 18:25:37 +0300 Subject: [PATCH 1/2] remove namespace argument from pullSingleResource, using field selector instead Signed-off-by: Amir Malka --- core/pkg/resourcehandler/fieldselector.go | 10 +++++--- core/pkg/resourcehandler/k8sresources.go | 30 +++++++++-------------- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/core/pkg/resourcehandler/fieldselector.go b/core/pkg/resourcehandler/fieldselector.go index 71eb3372..0ec86116 100644 --- a/core/pkg/resourcehandler/fieldselector.go +++ b/core/pkg/resourcehandler/fieldselector.go @@ -77,20 +77,24 @@ func getNamespacesSelector(kind, ns, operator string) string { } if kind == "namespaces" || kind == "Namespace" { - return getNameFieldSelector(ns, operator) + return getNameFieldSelectorString(ns, operator) } if k8sinterface.IsResourceInNamespaceScope(kind) { - return fmt.Sprintf("metadata.namespace%s%s", operator, ns) + return getNamespaceFieldSelectorString(ns, operator) } return "" } -func getNameFieldSelector(resourceName, operator string) string { +func getNameFieldSelectorString(resourceName, operator string) string { return fmt.Sprintf("metadata.name%s%s", operator, resourceName) } +func getNamespaceFieldSelectorString(namespace, operator string) string { + return fmt.Sprintf("metadata.namespace%s%s", operator, namespace) +} + func combineFieldSelectors(selectors ...string) string { var nonEmptyStrings []string for i := range selectors { diff --git a/core/pkg/resourcehandler/k8sresources.go b/core/pkg/resourcehandler/k8sresources.go index 00a866a8..ce41c4d8 100644 --- a/core/pkg/resourcehandler/k8sresources.go +++ b/core/pkg/resourcehandler/k8sresources.go @@ -28,7 +28,6 @@ import ( k8slabels "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/version" - "k8s.io/client-go/dynamic" ) type cloudResourceGetter func(string, string) (workloadinterface.IMetadata, error) @@ -79,13 +78,13 @@ func (k8sHandler *K8sResourceHandler) GetResources(ctx context.Context, sessionO ksResourceMap := setKSResourceMap(sessionObj.Policies, resourceToControl) // get namespace and labels from designator (ignore cluster labels) - _, namespace, labels := armotypes.DigestPortalDesignator(designator) + _, _, labels := armotypes.DigestPortalDesignator(designator) // map of Kubescape resources to control_ids sessionObj.ResourceToControlsMap = resourceToControl // pull k8s resources - k8sResourcesMap, allResources, err := k8sHandler.pullResources(queryableResources, namespace, labels) + k8sResourcesMap, allResources, err := k8sHandler.pullResources(queryableResources, labels) if err != nil { cautils.StopSpinner() return k8sResourcesMap, allResources, ksResourceMap, excludedRulesMap, err @@ -183,7 +182,11 @@ func (k8sHandler *K8sResourceHandler) findWorkloadToScan(workloadIdentifier *cau return nil, err } - result, err := k8sHandler.pullSingleResource(&gvr, workloadIdentifier.Namespace, nil, getNameFieldSelector(workloadIdentifier.Name, "=")) + fieldSelectors := getNameFieldSelectorString(workloadIdentifier.Name, "=") + if workloadIdentifier.Namespace != "" && k8sinterface.IsNamespaceScope(&gvr) { + fieldSelectors = combineFieldSelectors(fieldSelectors, getNamespaceFieldSelectorString(workloadIdentifier.Namespace, "=")) + } + result, err := k8sHandler.pullSingleResource(&gvr, nil, fieldSelectors) if err != nil { return nil, fmt.Errorf("failed to get resource %s, reason: %v", workloadIdentifier.String(), err) } @@ -316,7 +319,7 @@ func setMapNamespaceToNumOfResources(ctx context.Context, allResources map[strin sessionObj.SetMapNamespaceToNumberOfResources(mapNamespaceToNumberOfResources) } -func (k8sHandler *K8sResourceHandler) pullResources(queryableResources QueryableResources, namespace string, labels map[string]string) (cautils.K8SResources, map[string]workloadinterface.IMetadata, error) { +func (k8sHandler *K8sResourceHandler) pullResources(queryableResources QueryableResources, labels map[string]string) (cautils.K8SResources, map[string]workloadinterface.IMetadata, error) { k8sResources := queryableResources.ToK8sResourceMap() allResources := map[string]workloadinterface.IMetadata{} @@ -324,7 +327,7 @@ func (k8sHandler *K8sResourceHandler) pullResources(queryableResources Queryable for _, qr := range queryableResources { apiGroup, apiVersion, resource := k8sinterface.StringToResourceGroup(qr.GroupVersionResourceTriplet) gvr := schema.GroupVersionResource{Group: apiGroup, Version: apiVersion, Resource: resource} - result, err := k8sHandler.pullSingleResource(&gvr, namespace, labels, qr.FieldSelectors) + result, err := k8sHandler.pullSingleResource(&gvr, labels, qr.FieldSelectors) if err != nil { if !strings.Contains(err.Error(), "the server could not find the requested resource") { // handle error @@ -366,7 +369,7 @@ func (k8sHandler *K8sResourceHandler) GetWorkloadParentKind(workload workloadint return "" } -func (k8sHandler *K8sResourceHandler) pullSingleResource(resource *schema.GroupVersionResource, namespace string, labels map[string]string, fields string) ([]unstructured.Unstructured, error) { +func (k8sHandler *K8sResourceHandler) pullSingleResource(resource *schema.GroupVersionResource, labels map[string]string, fields string) ([]unstructured.Unstructured, error) { resourceList := []unstructured.Unstructured{} // set labels listOptions := metav1.ListOptions{} @@ -384,21 +387,12 @@ func (k8sHandler *K8sResourceHandler) pullSingleResource(resource *schema.GroupV } // set dynamic object - var clientResource dynamic.ResourceInterface - if namespace != "" { - clientResource = k8sHandler.k8s.DynamicClient.Resource(*resource) - } else if k8sinterface.IsNamespaceScope(resource) { - clientResource = k8sHandler.k8s.DynamicClient.Resource(*resource).Namespace(namespace) - } else if k8sHandler.fieldSelector.GetClusterScope(resource) { - clientResource = k8sHandler.k8s.DynamicClient.Resource(*resource) - } else { - continue - } + clientResource := k8sHandler.k8s.DynamicClient.Resource(*resource) // list resources result, err := clientResource.List(context.Background(), listOptions) if err != nil || result == nil { - return nil, fmt.Errorf("failed to get resource: %v, namespace: %s, labelSelector: %v, reason: %v", resource, namespace, listOptions.LabelSelector, err) + return nil, fmt.Errorf("failed to get resource: %v, labelSelector: %v, fieldSelector: %v, reason: %v", resource, listOptions.LabelSelector, listOptions.FieldSelector, err) } resourceList = append(resourceList, result.Items...) From e972df933a9794b07694650313b25dce9a2eeb11 Mon Sep 17 00:00:00 2001 From: Amir Malka Date: Thu, 27 Jul 2023 19:32:23 +0300 Subject: [PATCH 2/2] removed designators (unused) field from PolicyIdentifier, and designators argument from GetResources function Signed-off-by: Amir Malka --- core/cautils/scaninfo.go | 6 ++---- core/pkg/resourcehandler/filesloader.go | 3 +-- core/pkg/resourcehandler/handlerpullresources.go | 2 +- core/pkg/resourcehandler/interface.go | 3 +-- core/pkg/resourcehandler/k8sresources.go | 13 ++++--------- .../resourcehandler/resourcehandlerutils_test.go | 2 +- 6 files changed, 10 insertions(+), 19 deletions(-) diff --git a/core/cautils/scaninfo.go b/core/cautils/scaninfo.go index c0bff9ca..5e023c93 100644 --- a/core/cautils/scaninfo.go +++ b/core/cautils/scaninfo.go @@ -8,7 +8,6 @@ import ( "path/filepath" "strings" - "github.com/armosec/armoapi-go/armotypes" giturl "github.com/kubescape/go-git-url" "github.com/kubescape/go-logger" "github.com/kubescape/go-logger/helpers" @@ -94,9 +93,8 @@ const ( ) type PolicyIdentifier struct { - Identifier string // policy Identifier e.g. c-0012 for control, nsa,mitre for frameworks - Kind apisv1.NotificationPolicyKind // policy kind e.g. Framework,Control,Rule - Designators armotypes.PortalDesignator + Identifier string // policy Identifier e.g. c-0012 for control, nsa,mitre for frameworks + Kind apisv1.NotificationPolicyKind // policy kind e.g. Framework,Control,Rule } type WorkloadIdentifier struct { diff --git a/core/pkg/resourcehandler/filesloader.go b/core/pkg/resourcehandler/filesloader.go index 00683f52..6a3aa6ec 100644 --- a/core/pkg/resourcehandler/filesloader.go +++ b/core/pkg/resourcehandler/filesloader.go @@ -6,7 +6,6 @@ import ( "os" "path/filepath" - "github.com/armosec/armoapi-go/armotypes" "github.com/kubescape/k8s-interface/workloadinterface" "github.com/kubescape/opa-utils/reporthandling" "k8s.io/apimachinery/pkg/version" @@ -32,7 +31,7 @@ func NewFileResourceHandler(_ context.Context, inputPatterns []string, workloadI } } -func (fileHandler *FileResourceHandler) GetResources(ctx context.Context, sessionObj *cautils.OPASessionObj, _ *armotypes.PortalDesignator, progressListener opaprocessor.IJobProgressNotificationClient) (cautils.K8SResources, map[string]workloadinterface.IMetadata, cautils.KSResources, map[string]bool, error) { +func (fileHandler *FileResourceHandler) GetResources(ctx context.Context, sessionObj *cautils.OPASessionObj, progressListener opaprocessor.IJobProgressNotificationClient) (cautils.K8SResources, map[string]workloadinterface.IMetadata, cautils.KSResources, map[string]bool, error) { allResources := map[string]workloadinterface.IMetadata{} ksResources := cautils.KSResources{} diff --git a/core/pkg/resourcehandler/handlerpullresources.go b/core/pkg/resourcehandler/handlerpullresources.go index 0462c2ba..c3aa3a8e 100644 --- a/core/pkg/resourcehandler/handlerpullresources.go +++ b/core/pkg/resourcehandler/handlerpullresources.go @@ -29,7 +29,7 @@ func CollectResources(ctx context.Context, rsrcHandler IResourceHandler, policyI setCloudMetadata(opaSessionObj) } - resourcesMap, allResources, ksResources, excludedRulesMap, err := rsrcHandler.GetResources(ctx, opaSessionObj, &policyIdentifier[0].Designators, progressListener) + resourcesMap, allResources, ksResources, excludedRulesMap, err := rsrcHandler.GetResources(ctx, opaSessionObj, progressListener) if err != nil { return err } diff --git a/core/pkg/resourcehandler/interface.go b/core/pkg/resourcehandler/interface.go index 2e2cddd9..49f281f6 100644 --- a/core/pkg/resourcehandler/interface.go +++ b/core/pkg/resourcehandler/interface.go @@ -3,7 +3,6 @@ package resourcehandler import ( "context" - "github.com/armosec/armoapi-go/armotypes" "github.com/kubescape/k8s-interface/workloadinterface" "github.com/kubescape/kubescape/v2/core/cautils" "github.com/kubescape/kubescape/v2/core/pkg/opaprocessor" @@ -11,7 +10,7 @@ import ( ) type IResourceHandler interface { - GetResources(context.Context, *cautils.OPASessionObj, *armotypes.PortalDesignator, opaprocessor.IJobProgressNotificationClient) (cautils.K8SResources, map[string]workloadinterface.IMetadata, cautils.KSResources, map[string]bool, error) + GetResources(context.Context, *cautils.OPASessionObj, opaprocessor.IJobProgressNotificationClient) (cautils.K8SResources, map[string]workloadinterface.IMetadata, cautils.KSResources, map[string]bool, error) GetClusterAPIServerInfo(ctx context.Context) *version.Info GetWorkloadParentKind(workloadinterface.IWorkload) string } diff --git a/core/pkg/resourcehandler/k8sresources.go b/core/pkg/resourcehandler/k8sresources.go index ce41c4d8..a56e2576 100644 --- a/core/pkg/resourcehandler/k8sresources.go +++ b/core/pkg/resourcehandler/k8sresources.go @@ -20,8 +20,6 @@ import ( "github.com/kubescape/k8s-interface/k8sinterface" "github.com/kubescape/k8s-interface/workloadinterface" - "github.com/armosec/armoapi-go/armotypes" - v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" @@ -59,7 +57,7 @@ func NewK8sResourceHandler(k8s *k8sinterface.KubernetesApi, fieldSelector IField } } -func (k8sHandler *K8sResourceHandler) GetResources(ctx context.Context, sessionObj *cautils.OPASessionObj, designator *armotypes.PortalDesignator, progressListener opaprocessor.IJobProgressNotificationClient) (cautils.K8SResources, map[string]workloadinterface.IMetadata, cautils.KSResources, map[string]bool, error) { +func (k8sHandler *K8sResourceHandler) GetResources(ctx context.Context, sessionObj *cautils.OPASessionObj, progressListener opaprocessor.IJobProgressNotificationClient) (cautils.K8SResources, map[string]workloadinterface.IMetadata, cautils.KSResources, map[string]bool, error) { // get k8s resources logger.L().Info("Accessing Kubernetes objects") @@ -77,14 +75,11 @@ func (k8sHandler *K8sResourceHandler) GetResources(ctx context.Context, sessionO queryableResources, excludedRulesMap := getQueryableResourceMapFromPolicies(k8sHandler, sessionObj.Policies, workload) ksResourceMap := setKSResourceMap(sessionObj.Policies, resourceToControl) - // get namespace and labels from designator (ignore cluster labels) - _, _, labels := armotypes.DigestPortalDesignator(designator) - // map of Kubescape resources to control_ids sessionObj.ResourceToControlsMap = resourceToControl // pull k8s resources - k8sResourcesMap, allResources, err := k8sHandler.pullResources(queryableResources, labels) + k8sResourcesMap, allResources, err := k8sHandler.pullResources(queryableResources) if err != nil { cautils.StopSpinner() return k8sResourcesMap, allResources, ksResourceMap, excludedRulesMap, err @@ -319,7 +314,7 @@ func setMapNamespaceToNumOfResources(ctx context.Context, allResources map[strin sessionObj.SetMapNamespaceToNumberOfResources(mapNamespaceToNumberOfResources) } -func (k8sHandler *K8sResourceHandler) pullResources(queryableResources QueryableResources, labels map[string]string) (cautils.K8SResources, map[string]workloadinterface.IMetadata, error) { +func (k8sHandler *K8sResourceHandler) pullResources(queryableResources QueryableResources) (cautils.K8SResources, map[string]workloadinterface.IMetadata, error) { k8sResources := queryableResources.ToK8sResourceMap() allResources := map[string]workloadinterface.IMetadata{} @@ -327,7 +322,7 @@ func (k8sHandler *K8sResourceHandler) pullResources(queryableResources Queryable for _, qr := range queryableResources { apiGroup, apiVersion, resource := k8sinterface.StringToResourceGroup(qr.GroupVersionResourceTriplet) gvr := schema.GroupVersionResource{Group: apiGroup, Version: apiVersion, Resource: resource} - result, err := k8sHandler.pullSingleResource(&gvr, labels, qr.FieldSelectors) + result, err := k8sHandler.pullSingleResource(&gvr, nil, qr.FieldSelectors) if err != nil { if !strings.Contains(err.Error(), "the server could not find the requested resource") { // handle error diff --git a/core/pkg/resourcehandler/resourcehandlerutils_test.go b/core/pkg/resourcehandler/resourcehandlerutils_test.go index ef0878f3..648622fd 100644 --- a/core/pkg/resourcehandler/resourcehandlerutils_test.go +++ b/core/pkg/resourcehandler/resourcehandlerutils_test.go @@ -133,7 +133,7 @@ func mockWorkload(apiVersion, kind, namespace, name, ownerReferenceKind string) type ResourceHandlerMock struct { } -func (mock *ResourceHandlerMock) GetResources(context.Context, *cautils.OPASessionObj, *armotypes.PortalDesignator, opaprocessor.IJobProgressNotificationClient) (cautils.K8SResources, map[string]workloadinterface.IMetadata, cautils.KSResources, map[string]bool, error) { +func (mock *ResourceHandlerMock) GetResources(context.Context, *cautils.OPASessionObj, opaprocessor.IJobProgressNotificationClient) (cautils.K8SResources, map[string]workloadinterface.IMetadata, cautils.KSResources, map[string]bool, error) { return nil, nil, nil, nil, nil }