mirror of
https://github.com/kubescape/kubescape.git
synced 2026-04-15 06:58:11 +00:00
Merge remote-tracking branch 'other/scan-workload' into new-output
This commit is contained in:
@@ -56,8 +56,7 @@ type OPASessionObj struct {
|
||||
Exceptions []armotypes.PostureExceptionPolicy // list of exceptions to apply on scan results
|
||||
OmitRawResources bool // omit raw resources from output
|
||||
ScanType ScanTypes // scan type
|
||||
ResourceIDToImageMap map[string][]string
|
||||
ScannedWorkload workloadinterface.IWorkload // single workload scan
|
||||
ScannedWorkload workloadinterface.IWorkload // single workload scan
|
||||
}
|
||||
|
||||
func NewOPASessionObj(ctx context.Context, frameworks []reporthandling.Framework, k8sResources K8SResources, scanInfo *ScanInfo) *OPASessionObj {
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/armosec/armoapi-go/identifiers"
|
||||
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 identifiers.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 {
|
||||
|
||||
@@ -65,13 +65,13 @@ func getRBACHandler(tenantConfig cautils.ITenantConfig, k8s *k8sinterface.Kubern
|
||||
return nil
|
||||
}
|
||||
|
||||
func getReporter(ctx context.Context, tenantConfig cautils.ITenantConfig, reportID string, submit, fwScan bool, scanningContext cautils.ScanningContext) reporter.IReport {
|
||||
func getReporter(ctx context.Context, tenantConfig cautils.ITenantConfig, reportID string, submit, fwScan bool, scanInfo cautils.ScanInfo) reporter.IReport {
|
||||
_, span := otel.Tracer("").Start(ctx, "getReporter")
|
||||
defer span.End()
|
||||
|
||||
if submit {
|
||||
submitData := reporterv2.SubmitContextScan
|
||||
if scanningContext != cautils.ContextCluster {
|
||||
if scanInfo.GetScanningContext() != cautils.ContextCluster {
|
||||
submitData = reporterv2.SubmitContextRepository
|
||||
}
|
||||
return reporterv2.NewReportEventReceiver(tenantConfig.GetConfigObj(), reportID, submitData)
|
||||
@@ -81,7 +81,8 @@ func getReporter(ctx context.Context, tenantConfig cautils.ITenantConfig, report
|
||||
return reporterv2.NewReportMock("", "")
|
||||
}
|
||||
var message string
|
||||
if !fwScan {
|
||||
|
||||
if !fwScan && scanInfo.ScanType != cautils.ScanTypeWorkload {
|
||||
message = "Kubescape does not submit scan results when scanning controls"
|
||||
}
|
||||
|
||||
|
||||
+20
-8
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger/helpers"
|
||||
"github.com/kubescape/k8s-interface/k8sinterface"
|
||||
"github.com/kubescape/k8s-interface/workloadinterface"
|
||||
"github.com/kubescape/kubescape/v2/core/cautils"
|
||||
"github.com/kubescape/kubescape/v2/core/cautils/getter"
|
||||
"github.com/kubescape/kubescape/v2/core/pkg/hostsensorutils"
|
||||
@@ -94,7 +95,7 @@ func getInterfaces(ctx context.Context, scanInfo *cautils.ScanInfo) componentInt
|
||||
// ================== setup reporter & printer objects ======================================
|
||||
|
||||
// reporting behavior - setup reporter
|
||||
reportHandler := getReporter(ctx, tenantConfig, scanInfo.ScanID, scanInfo.Submit, scanInfo.FrameworkScan, scanInfo.GetScanningContext())
|
||||
reportHandler := getReporter(ctx, tenantConfig, scanInfo.ScanID, scanInfo.Submit, scanInfo.FrameworkScan, *scanInfo)
|
||||
|
||||
// setup printers
|
||||
outputPrinters := GetOutputPrinters(scanInfo, ctx)
|
||||
@@ -193,7 +194,6 @@ func (ks *Kubescape) Scan(ctx context.Context, scanInfo *cautils.ScanInfo) (*res
|
||||
}
|
||||
|
||||
// ======================== prioritization ===================
|
||||
scanInfo.ScanType = cautils.ScanTypeRepo
|
||||
if scanInfo.PrintAttackTree || isPrioritizationScanType(scanInfo.ScanType) {
|
||||
_, spanPrioritization := otel.Tracer("").Start(ctxOpa, "prioritization")
|
||||
if priotizationHandler, err := resourcesprioritization.NewResourcesPrioritizationHandler(ctxOpa, scanInfo.Getters.AttackTracksGetter, scanInfo.PrintAttackTree); err != nil {
|
||||
@@ -207,7 +207,7 @@ func (ks *Kubescape) Scan(ctx context.Context, scanInfo *cautils.ScanInfo) (*res
|
||||
spanPrioritization.End()
|
||||
}
|
||||
|
||||
if scanInfo.ScanImages && len(scanData.ResourceIDToImageMap) > 0 {
|
||||
if scanInfo.ScanImages {
|
||||
scanImages(scanInfo, scanData, ctx, resultsHandling)
|
||||
}
|
||||
// ========================= results handling =====================
|
||||
@@ -221,17 +221,29 @@ func (ks *Kubescape) Scan(ctx context.Context, scanInfo *cautils.ScanInfo) (*res
|
||||
}
|
||||
|
||||
func scanImages(scanInfo *cautils.ScanInfo, scanData *cautils.OPASessionObj, ctx context.Context, resultsHandling *resultshandling.ResultsHandler) {
|
||||
logger.L().Ctx(ctx).Info("Scanning images")
|
||||
logger.L().Info("Scanning images")
|
||||
|
||||
dbCfg, _ := imagescan.NewDefaultDBConfig()
|
||||
svc := imagescan.NewScanService(dbCfg)
|
||||
|
||||
for _, imgs := range scanData.ResourceIDToImageMap {
|
||||
for _, img := range imgs {
|
||||
scanSingleImage(ctx, img, svc, resultsHandling, *scanInfo)
|
||||
if scanInfo.ScanType == cautils.ScanTypeWorkload {
|
||||
wlObj := workloadinterface.NewWorkloadObj(scanData.ScannedWorkload.GetObject())
|
||||
scanSingleWorkload(wlObj, ctx, svc, resultsHandling, scanInfo)
|
||||
} else {
|
||||
for _, workload := range scanData.AllResources {
|
||||
wlObj := workloadinterface.NewWorkloadObj(workload.GetObject())
|
||||
scanSingleWorkload(wlObj, ctx, svc, resultsHandling, scanInfo)
|
||||
}
|
||||
}
|
||||
logger.L().Ctx(ctx).Success("Finished scanning images")
|
||||
|
||||
logger.L().Success("Finished scanning images")
|
||||
}
|
||||
|
||||
func scanSingleWorkload(wlObj *workloadinterface.Workload, ctx context.Context, svc imagescan.Service, resultsHandling *resultshandling.ResultsHandler, scanInfo *cautils.ScanInfo) {
|
||||
containers, _ := wlObj.GetContainers()
|
||||
for _, container := range containers {
|
||||
scanSingleImage(ctx, container.Image, svc, resultsHandling, *scanInfo)
|
||||
}
|
||||
}
|
||||
|
||||
func scanSingleImage(ctx context.Context, img string, svc imagescan.Service, resultsHandling *resultshandling.ResultsHandler, scanInfo cautils.ScanInfo) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -32,13 +32,12 @@ func NewFileResourceHandler(_ context.Context, inputPatterns []string, workloadI
|
||||
}
|
||||
}
|
||||
|
||||
func (fileHandler *FileResourceHandler) GetResources(ctx context.Context, sessionObj *cautils.OPASessionObj, _ *identifiers.PortalDesignator, progressListener opaprocessor.IJobProgressNotificationClient, scanInfo cautils.ScanInfo) (cautils.K8SResources, map[string]workloadinterface.IMetadata, cautils.KSResources, map[string]bool, map[string][]string, error) {
|
||||
func (fileHandler *FileResourceHandler) GetResources(ctx context.Context, sessionObj *cautils.OPASessionObj, _ *identifiers.PortalDesignator, progressListener opaprocessor.IJobProgressNotificationClient, scanInfo cautils.ScanInfo) (cautils.K8SResources, map[string]workloadinterface.IMetadata, cautils.KSResources, map[string]bool, error) {
|
||||
allResources := map[string]workloadinterface.IMetadata{}
|
||||
ksResources := cautils.KSResources{}
|
||||
resourceIDToImages := map[string][]string{}
|
||||
|
||||
if len(fileHandler.inputPatterns) == 0 {
|
||||
return nil, nil, nil, nil, nil, fmt.Errorf("missing input")
|
||||
return nil, nil, nil, nil, fmt.Errorf("missing input")
|
||||
}
|
||||
|
||||
logger.L().Info("Accessing local objects")
|
||||
@@ -56,29 +55,13 @@ func (fileHandler *FileResourceHandler) GetResources(ctx context.Context, sessio
|
||||
} else {
|
||||
workloadIDToSource, workloads, err = getResourcesFromPath(ctx, fileHandler.inputPatterns[path])
|
||||
if err != nil {
|
||||
return nil, allResources, nil, nil, nil, err
|
||||
return nil, allResources, nil, nil, err
|
||||
}
|
||||
}
|
||||
if len(workloads) == 0 {
|
||||
logger.L().Debug("path ignored because contains only a non-kubernetes file", helpers.String("path", fileHandler.inputPatterns[path]))
|
||||
}
|
||||
|
||||
if scanInfo.ScanImages {
|
||||
for i := range workloads {
|
||||
wlObj := workloadinterface.NewWorkloadObj(workloads[i].GetObject())
|
||||
containers, err := wlObj.GetContainers()
|
||||
if err != nil {
|
||||
|
||||
}
|
||||
for _, container := range containers {
|
||||
if _, ok := resourceIDToImages[workloads[i].GetID()]; !ok {
|
||||
resourceIDToImages[workloads[i].GetID()] = []string{}
|
||||
}
|
||||
resourceIDToImages[workloads[i].GetID()] = append(resourceIDToImages[workloads[i].GetID()], container.Image)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for k, v := range workloadIDToSource {
|
||||
sessionObj.ResourceSource[k] = v
|
||||
}
|
||||
@@ -90,7 +73,7 @@ func (fileHandler *FileResourceHandler) GetResources(ctx context.Context, sessio
|
||||
// locate input workload in the mapped resources - if not found or not a valid workload, return error
|
||||
inputWorkload, err := findWorkloadToScan(mappedResources, fileHandler.workloadIdentifier)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, nil, err
|
||||
return nil, nil, nil, nil, err
|
||||
}
|
||||
sessionObj.ScannedWorkload = inputWorkload
|
||||
|
||||
@@ -117,7 +100,113 @@ func (fileHandler *FileResourceHandler) GetResources(ctx context.Context, sessio
|
||||
cautils.StopSpinner()
|
||||
logger.L().Success("Done accessing local objects")
|
||||
|
||||
return k8sResources, allResources, ksResources, excludedRulesMap, resourceIDToImages, nil
|
||||
return k8sResources, allResources, ksResources, excludedRulesMap, nil
|
||||
}
|
||||
|
||||
func getWorkloadFromHelmChart(ctx context.Context, helmPath, workloadPath string) (map[string]reporthandling.Source, []workloadinterface.IMetadata, error) {
|
||||
clonedRepo, err := cloneGitRepo(&helmPath)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if clonedRepo != "" {
|
||||
defer os.RemoveAll(clonedRepo)
|
||||
}
|
||||
|
||||
helmSourceToWorkloads, helmSourceToChartName := cautils.LoadResourcesFromHelmCharts(ctx, helmPath)
|
||||
|
||||
wlSource, _ := helmSourceToWorkloads[workloadPath]
|
||||
|
||||
// Get repo root
|
||||
repoRoot, gitRepo := extractGitRepo(helmPath)
|
||||
|
||||
helmChartName := helmSourceToChartName[workloadPath]
|
||||
|
||||
relSource, err := filepath.Rel(repoRoot, helmPath)
|
||||
if err == nil {
|
||||
helmPath = relSource
|
||||
}
|
||||
|
||||
var lastCommit reporthandling.LastCommit
|
||||
if gitRepo != nil {
|
||||
commitInfo, _ := gitRepo.GetFileLastCommit(helmPath)
|
||||
if commitInfo != nil {
|
||||
lastCommit = reporthandling.LastCommit{
|
||||
Hash: commitInfo.SHA,
|
||||
Date: commitInfo.Author.Date,
|
||||
CommitterName: commitInfo.Author.Name,
|
||||
CommitterEmail: commitInfo.Author.Email,
|
||||
Message: commitInfo.Message,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
workloadSource := reporthandling.Source{
|
||||
RelativePath: helmPath,
|
||||
FileType: reporthandling.SourceTypeHelmChart,
|
||||
HelmChartName: helmChartName,
|
||||
LastCommit: lastCommit,
|
||||
}
|
||||
workloadIDToSource := make(map[string]reporthandling.Source, 0)
|
||||
workloadIDToSource[wlSource[0].GetID()] = workloadSource
|
||||
|
||||
workloads := []workloadinterface.IMetadata{}
|
||||
workloads = append(workloads, wlSource...)
|
||||
|
||||
return workloadIDToSource, workloads, nil
|
||||
|
||||
}
|
||||
|
||||
func getWorkloadFromHelmChart(ctx context.Context, helmPath, workloadPath string) (map[string]reporthandling.Source, []workloadinterface.IMetadata, error) {
|
||||
clonedRepo, err := cloneGitRepo(&helmPath)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if clonedRepo != "" {
|
||||
defer os.RemoveAll(clonedRepo)
|
||||
}
|
||||
|
||||
helmSourceToWorkloads, helmSourceToChartName := cautils.LoadResourcesFromHelmCharts(ctx, helmPath)
|
||||
|
||||
wlSource, _ := helmSourceToWorkloads[workloadPath]
|
||||
|
||||
// Get repo root
|
||||
repoRoot, gitRepo := extractGitRepo(helmPath)
|
||||
|
||||
helmChartName := helmSourceToChartName[workloadPath]
|
||||
|
||||
relSource, err := filepath.Rel(repoRoot, helmPath)
|
||||
if err == nil {
|
||||
helmPath = relSource
|
||||
}
|
||||
|
||||
var lastCommit reporthandling.LastCommit
|
||||
if gitRepo != nil {
|
||||
commitInfo, _ := gitRepo.GetFileLastCommit(helmPath)
|
||||
if commitInfo != nil {
|
||||
lastCommit = reporthandling.LastCommit{
|
||||
Hash: commitInfo.SHA,
|
||||
Date: commitInfo.Author.Date,
|
||||
CommitterName: commitInfo.Author.Name,
|
||||
CommitterEmail: commitInfo.Author.Email,
|
||||
Message: commitInfo.Message,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
workloadSource := reporthandling.Source{
|
||||
RelativePath: helmPath,
|
||||
FileType: reporthandling.SourceTypeHelmChart,
|
||||
HelmChartName: helmChartName,
|
||||
LastCommit: lastCommit,
|
||||
}
|
||||
workloadIDToSource := make(map[string]reporthandling.Source, 0)
|
||||
workloadIDToSource[wlSource[0].GetID()] = workloadSource
|
||||
|
||||
workloads := []workloadinterface.IMetadata{}
|
||||
workloads = append(workloads, wlSource...)
|
||||
|
||||
return workloadIDToSource, workloads, nil
|
||||
|
||||
}
|
||||
|
||||
func getResourcesFromPath(ctx context.Context, path string) (map[string]reporthandling.Source, []workloadinterface.IMetadata, error) {
|
||||
|
||||
@@ -29,7 +29,7 @@ func CollectResources(ctx context.Context, rsrcHandler IResourceHandler, policyI
|
||||
setCloudMetadata(opaSessionObj)
|
||||
}
|
||||
|
||||
resourcesMap, allResources, ksResources, excludedRulesMap, resourceIDToImages, err := rsrcHandler.GetResources(ctx, opaSessionObj, &policyIdentifier[0].Designators, progressListener, scanInfo)
|
||||
resourcesMap, allResources, ksResources, excludedRulesMap, err := rsrcHandler.GetResources(ctx, opaSessionObj, &policyIdentifier[0].Designators, progressListener, scanInfo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -38,7 +38,6 @@ func CollectResources(ctx context.Context, rsrcHandler IResourceHandler, policyI
|
||||
opaSessionObj.AllResources = allResources
|
||||
opaSessionObj.KubescapeResource = ksResources
|
||||
opaSessionObj.ExcludedRules = excludedRulesMap
|
||||
opaSessionObj.ResourceIDToImageMap = resourceIDToImages
|
||||
|
||||
if (opaSessionObj.K8SResources == nil || len(opaSessionObj.K8SResources) == 0) && (opaSessionObj.KubescapeResource == nil || len(opaSessionObj.KubescapeResource) == 0) {
|
||||
return fmt.Errorf("empty list of resources")
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
)
|
||||
|
||||
type IResourceHandler interface {
|
||||
GetResources(context.Context, *cautils.OPASessionObj, *identifiers.PortalDesignator, opaprocessor.IJobProgressNotificationClient, cautils.ScanInfo) (cautils.K8SResources, map[string]workloadinterface.IMetadata, cautils.KSResources, map[string]bool, map[string][]string, error)
|
||||
GetResources(context.Context, *cautils.OPASessionObj, *identifiers.PortalDesignator, opaprocessor.IJobProgressNotificationClient, cautils.ScanInfo) (cautils.K8SResources, map[string]workloadinterface.IMetadata, cautils.KSResources, map[string]bool, error)
|
||||
GetClusterAPIServerInfo(ctx context.Context) *version.Info
|
||||
GetWorkloadParentKind(workloadinterface.IWorkload) string
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/armosec/armoapi-go/identifiers"
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger/helpers"
|
||||
"github.com/kubescape/kubescape/v2/core/cautils"
|
||||
@@ -20,15 +21,12 @@ import (
|
||||
"github.com/kubescape/k8s-interface/k8sinterface"
|
||||
"github.com/kubescape/k8s-interface/workloadinterface"
|
||||
|
||||
"github.com/armosec/armoapi-go/identifiers"
|
||||
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
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)
|
||||
@@ -60,7 +58,7 @@ func NewK8sResourceHandler(k8s *k8sinterface.KubernetesApi, fieldSelector IField
|
||||
}
|
||||
}
|
||||
|
||||
func (k8sHandler *K8sResourceHandler) GetResources(ctx context.Context, sessionObj *cautils.OPASessionObj, designator *identifiers.PortalDesignator, progressListener opaprocessor.IJobProgressNotificationClient, scanInfo cautils.ScanInfo) (cautils.K8SResources, map[string]workloadinterface.IMetadata, cautils.KSResources, map[string]bool, map[string][]string, error) {
|
||||
func (k8sHandler *K8sResourceHandler) GetResources(ctx context.Context, sessionObj *cautils.OPASessionObj, designator *identifiers.PortalDesignator, progressListener opaprocessor.IJobProgressNotificationClient, scanInfo cautils.ScanInfo) (cautils.K8SResources, map[string]workloadinterface.IMetadata, cautils.KSResources, map[string]bool, error) {
|
||||
// get k8s resources
|
||||
logger.L().Info("Accessing Kubernetes objects")
|
||||
|
||||
@@ -68,7 +66,7 @@ func (k8sHandler *K8sResourceHandler) GetResources(ctx context.Context, sessionO
|
||||
|
||||
workload, err := k8sHandler.findWorkloadToScan(k8sHandler.workloadIdentifier)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, nil, err
|
||||
return nil, nil, nil, nil, err
|
||||
}
|
||||
sessionObj.ScannedWorkload = workload
|
||||
|
||||
@@ -78,28 +76,14 @@ 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)
|
||||
_, namespace, labels := identifiers.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)
|
||||
if err != nil {
|
||||
cautils.StopSpinner()
|
||||
return k8sResourcesMap, allResources, ksResourceMap, nil, nil, err
|
||||
}
|
||||
|
||||
resourceIDToImages := make(map[string][]string, 0)
|
||||
if scanInfo.ScanImages {
|
||||
for _, workload := range allResources {
|
||||
wlObj := workloadinterface.NewWorkloadObj(workload.GetObject())
|
||||
containers, _ := wlObj.GetContainers()
|
||||
for _, container := range containers {
|
||||
resourceIDToImages[workload.GetID()] = append(resourceIDToImages[workload.GetID()], container.Image)
|
||||
}
|
||||
}
|
||||
return k8sResourcesMap, allResources, ksResourceMap, nil, err
|
||||
}
|
||||
|
||||
// add workload to k8s resources map (for single workload scan)
|
||||
@@ -174,7 +158,7 @@ func (k8sHandler *K8sResourceHandler) GetResources(ctx context.Context, sessionO
|
||||
}
|
||||
}
|
||||
|
||||
return k8sResourcesMap, allResources, ksResourceMap, excludedRulesMap, resourceIDToImages, nil
|
||||
return k8sResourcesMap, allResources, ksResourceMap, excludedRulesMap, nil
|
||||
}
|
||||
|
||||
func (k8sHandler *K8sResourceHandler) findWorkloadToScan(workloadIdentifier *cautils.WorkloadIdentifier) (workloadinterface.IWorkload, error) {
|
||||
@@ -194,7 +178,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)
|
||||
}
|
||||
@@ -327,7 +315,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) (cautils.K8SResources, map[string]workloadinterface.IMetadata, error) {
|
||||
k8sResources := queryableResources.ToK8sResourceMap()
|
||||
allResources := map[string]workloadinterface.IMetadata{}
|
||||
|
||||
@@ -335,7 +323,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, nil, qr.FieldSelectors)
|
||||
if err != nil {
|
||||
if !strings.Contains(err.Error(), "the server could not find the requested resource") {
|
||||
// handle error
|
||||
@@ -379,7 +367,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{}
|
||||
@@ -397,21 +385,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...)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -127,6 +127,10 @@ func (pp *PrettyPrinter) ActionPrint(_ context.Context, opaSessionObj *cautils.O
|
||||
}
|
||||
}
|
||||
|
||||
if pp.scanType == cautils.ScanTypeWorkload {
|
||||
cautils.InfoDisplay(pp.writer, "Workload: %s/%s/%s\n", opaSessionObj.ScannedWorkload.GetNamespace(), opaSessionObj.ScannedWorkload.GetKind(), opaSessionObj.ScannedWorkload.GetName())
|
||||
}
|
||||
|
||||
pp.mainPrinter.PrintConfigurationsScanning(&opaSessionObj.Report.SummaryDetails, sortedControlIDs)
|
||||
|
||||
// When writing to Stdout, we aren’t really writing to an output file,
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ func (cp *ClusterPrinter) PrintCategoriesTables(writer io.Writer, summaryDetails
|
||||
|
||||
categoriesToCategoryControls := mapCategoryToSummary(summaryDetails.ListControls(), mapClusterControlsToCategories)
|
||||
|
||||
for _, id := range categoriesDisplayOrder {
|
||||
for _, id := range clusterCategoriesDisplayOrder {
|
||||
categoryControl, ok := categoriesToCategoryControls[id]
|
||||
if !ok {
|
||||
continue
|
||||
|
||||
+10
-1
@@ -30,7 +30,7 @@ const (
|
||||
nodeEscapeCategoryID = "Cat-9"
|
||||
)
|
||||
|
||||
var categoriesDisplayOrder = []string{
|
||||
var clusterCategoriesDisplayOrder = []string{
|
||||
controlPlaneCategoryID,
|
||||
accessControlCategoryID,
|
||||
secretsCategoryID,
|
||||
@@ -38,6 +38,15 @@ var categoriesDisplayOrder = []string{
|
||||
workloadsCategoryID,
|
||||
}
|
||||
|
||||
var workloadCategoriesDisplayOrder = []string{
|
||||
supplyChainCategoryID,
|
||||
resourceManagementCategoryID,
|
||||
storageCategoryID,
|
||||
secretsCategoryID,
|
||||
networkCategoryID,
|
||||
nodeEscapeCategoryID,
|
||||
}
|
||||
|
||||
var mapCategoryToType = map[string]CategoryType{
|
||||
controlPlaneCategoryID: TypeStatus,
|
||||
accessControlCategoryID: TypeCounting,
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@ func (rp *RepoPrinter) PrintCategoriesTables(writer io.Writer, summaryDetails *r
|
||||
|
||||
categoriesToCategoryControls := mapCategoryToSummary(summaryDetails.ListControls(), mapClusterControlsToCategories)
|
||||
|
||||
for _, id := range categoriesDisplayOrder {
|
||||
for _, id := range clusterCategoriesDisplayOrder {
|
||||
categoryControl, ok := categoriesToCategoryControls[id]
|
||||
if !ok {
|
||||
continue
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ func (wp *WorkloadPrinter) PrintCategoriesTables(writer io.Writer, summaryDetail
|
||||
|
||||
categoriesToCategoryControls := mapCategoryToSummary(summaryDetails.ListControls(), mapWorkloadControlsToCategories)
|
||||
|
||||
for _, id := range categoriesDisplayOrder {
|
||||
for _, id := range workloadCategoriesDisplayOrder {
|
||||
categoryControl, ok := categoriesToCategoryControls[id]
|
||||
if !ok {
|
||||
continue
|
||||
|
||||
@@ -32,7 +32,7 @@ func (wp *WorkloadPrinter) printImageScanningSummary(summary *imageprinter.Image
|
||||
printImageScanningSummary(wp.writer, *summary, false)
|
||||
|
||||
for _, img := range summary.Images {
|
||||
cautils.InfoTextDisplay(wp.writer, fmt.Sprintf("Receive full report by running: 'kubescape scan image %s\n", img))
|
||||
cautils.SimpleDisplay(wp.writer, fmt.Sprintf("Receive full report by running: 'kubescape scan image %s'\n", img))
|
||||
}
|
||||
|
||||
cautils.InfoTextDisplay(wp.writer, "\n")
|
||||
|
||||
Reference in New Issue
Block a user