From 92449bf564ca256263db0b185746553e7d0b3c96 Mon Sep 17 00:00:00 2001 From: David Wertenteil Date: Tue, 29 Aug 2023 09:50:22 +0300 Subject: [PATCH] core(cmd): adding corrections to cmd (#1357) * adding corrections to cmd Signed-off-by: David Wertenteil * remove decorative line Signed-off-by: David Wertenteil * wip: changed results indicator Signed-off-by: David Wertenteil * replace status test with icons Signed-off-by: David Wertenteil * print workloads in a different line Signed-off-by: David Wertenteil * update display Signed-off-by: David Wertenteil * deprecate commands Signed-off-by: David Wertenteil * removed unused functions Signed-off-by: David Wertenteil * fixed tests Signed-off-by: David Wertenteil * update cloud provider detection Signed-off-by: David Wertenteil * rename column name Signed-off-by: David Wertenteil --------- Signed-off-by: David Wertenteil --- cmd/delete/delete.go | 28 --- cmd/fix/fix.go | 2 +- cmd/root.go | 24 +- cmd/scan/scan.go | 8 +- cmd/submit/results.go | 124 --------- cmd/submit/submit.go | 45 ---- cmd/update/update.go | 7 +- cmd/version/version.go | 5 +- core/cautils/datastructuresmethods.go | 45 ++-- core/cautils/datastructuresmethods_test.go | 236 +++++++++++++++++- core/cautils/scaninfo.go | 5 +- core/cautils/scaninfo_test.go | 35 +++ core/core/submit.go | 36 --- core/meta/ksinterface.go | 4 - .../handlepullresources_test.go | 148 ++--------- .../resourcehandler/handlerpullresources.go | 61 +---- core/pkg/resourcehandler/k8sresources.go | 2 +- .../printer/v2/prettyprinter/clusterscan.go | 5 +- .../printer/v2/prettyprinter/reposcan.go | 5 +- .../configurationprinter/categorytable.go | 32 +-- .../categorytable_test.go | 28 +-- .../configurationprinter/workloadscan.go | 13 - .../configurationprinter/workloadscan_test.go | 91 +------ .../tableprinter/imageprinter/utils.go | 2 +- .../tableprinter/imageprinter/utils_test.go | 2 +- .../prettyprinter/tableprinter/utils/utils.go | 20 +- .../printer/v2/prettyprinter/utils.go | 14 +- core/pkg/resultshandling/printer/v2/utils.go | 6 +- .../reporter/v2/reporteventreceiver.go | 4 +- go.mod | 2 +- go.sum | 4 +- httphandler/go.mod | 2 +- httphandler/go.sum | 4 +- 33 files changed, 412 insertions(+), 637 deletions(-) delete mode 100644 cmd/delete/delete.go delete mode 100644 cmd/submit/results.go delete mode 100644 cmd/submit/submit.go delete mode 100644 core/core/submit.go diff --git a/cmd/delete/delete.go b/cmd/delete/delete.go deleted file mode 100644 index 0904ce5b..00000000 --- a/cmd/delete/delete.go +++ /dev/null @@ -1,28 +0,0 @@ -package delete - -import ( - "github.com/kubescape/kubescape/v2/core/meta" - v1 "github.com/kubescape/kubescape/v2/core/meta/datastructures/v1" - "github.com/spf13/cobra" -) - -func GetDeleteCmd(ks meta.IKubescape) *cobra.Command { - var deleteInfo v1.Delete - - var deleteCmd = &cobra.Command{ - Use: "delete ", - Short: "Delete configurations in Kubescape SaaS version", - Long: ``, - Run: func(cmd *cobra.Command, args []string) { - }, - } - deleteCmd.PersistentFlags().StringVarP(&deleteInfo.AccountID, "account", "", "", "Kubescape SaaS account ID. Default will load account ID from cache") - deleteCmd.PersistentFlags().MarkDeprecated("client-id", "Client ID is no longer supported. Feel free to contact the Kubescape maintainers for more information.") - deleteCmd.PersistentFlags().MarkDeprecated("secret-key", "Secret Key is no longer supported. Feel free to contact the Kubescape maintainers for more information.") - deleteCmd.AddCommand(&cobra.Command{ - Use: "exceptions", - Deprecated: "Contact Kubescape maintainers for more information.", - }) - - return deleteCmd -} diff --git a/cmd/fix/fix.go b/cmd/fix/fix.go index 0c91dbac..32a84227 100644 --- a/cmd/fix/fix.go +++ b/cmd/fix/fix.go @@ -27,7 +27,7 @@ func GetFixCmd(ks meta.IKubescape) *cobra.Command { fixCmd := &cobra.Command{ Use: "fix ", - Short: "Fix misconfiguration in files", + Short: "Propose a fix for the misconfiguration found when scanning Kubernetes manifest files", Long: ``, Example: fixCmdExamples, RunE: func(cmd *cobra.Command, args []string) error { diff --git a/cmd/root.go b/cmd/root.go index 877c9f62..9a31069f 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -8,12 +8,10 @@ import ( "github.com/kubescape/go-logger/helpers" "github.com/kubescape/kubescape/v2/cmd/completion" "github.com/kubescape/kubescape/v2/cmd/config" - "github.com/kubescape/kubescape/v2/cmd/delete" "github.com/kubescape/kubescape/v2/cmd/download" "github.com/kubescape/kubescape/v2/cmd/fix" "github.com/kubescape/kubescape/v2/cmd/list" "github.com/kubescape/kubescape/v2/cmd/scan" - "github.com/kubescape/kubescape/v2/cmd/submit" "github.com/kubescape/kubescape/v2/cmd/update" "github.com/kubescape/kubescape/v2/cmd/version" "github.com/kubescape/kubescape/v2/core/cautils" @@ -27,11 +25,11 @@ import ( var rootInfo cautils.RootInfo var ksExamples = fmt.Sprintf(` - # Scan command + # Scan a Kubernetes cluster or YAML files for image vulnerabilities and misconfigurations %[1]s scan - # List supported frameworks - %[1]s list frameworks + # List supported controls + %[1]s list controls # Download artifacts (air-gapped environment support) %[1]s download artifacts @@ -74,23 +72,31 @@ func getRootCmd(ks meta.IKubescape) *cobra.Command { rootCmd.PersistentFlags().StringVarP(&rootInfo.Logger, "logger", "l", helpers.InfoLevel.String(), fmt.Sprintf("Logger level. Supported: %s [$KS_LOGGER]", strings.Join(helpers.SupportedLevels(), "/"))) rootCmd.PersistentFlags().StringVar(&rootInfo.CacheDir, "cache-dir", getter.DefaultLocalStore, "Cache directory [$KS_CACHE_DIR]") - rootCmd.PersistentFlags().BoolVarP(&rootInfo.DisableColor, "disable-color", "", false, "Disable Color output for logging") - rootCmd.PersistentFlags().BoolVarP(&rootInfo.EnableColor, "enable-color", "", false, "Force enable Color output for logging") + rootCmd.PersistentFlags().BoolVarP(&rootInfo.DisableColor, "disable-color", "", false, "Disable color output for logging") + rootCmd.PersistentFlags().BoolVarP(&rootInfo.EnableColor, "enable-color", "", false, "Force enable color output for logging") cobra.OnInitialize(initLogger, initLoggerLevel, initEnvironment, initCacheDir) // Supported commands rootCmd.AddCommand(scan.GetScanCommand(ks)) rootCmd.AddCommand(download.GetDownloadCmd(ks)) - rootCmd.AddCommand(delete.GetDeleteCmd(ks)) rootCmd.AddCommand(list.GetListCmd(ks)) - rootCmd.AddCommand(submit.GetSubmitCmd(ks)) rootCmd.AddCommand(completion.GetCompletionCmd()) rootCmd.AddCommand(version.GetVersionCmd()) rootCmd.AddCommand(config.GetConfigCmd(ks)) rootCmd.AddCommand(update.GetUpdateCmd()) rootCmd.AddCommand(fix.GetFixCmd(ks)) + // deprecated commands + rootCmd.AddCommand(&cobra.Command{ + Use: "submit", + Deprecated: "This command is deprecated. Contact Kubescape maintainers for more information.", + }) + rootCmd.AddCommand(&cobra.Command{ + Use: "delete", + Deprecated: "This command is deprecated. Contact Kubescape maintainers for more information.", + }) + return rootCmd } diff --git a/cmd/scan/scan.go b/cmd/scan/scan.go index 8157f645..19034e39 100644 --- a/cmd/scan/scan.go +++ b/cmd/scan/scan.go @@ -17,14 +17,14 @@ import ( var scanCmdExamples = fmt.Sprintf(` Scan command is for scanning an existing cluster or kubernetes manifest files based on pre-defined frameworks - # Scan current cluster with all frameworks + # Scan current cluster %[1]s scan - # Scan kubernetes YAML manifest files + # Scan kubernetes manifest files %[1]s scan . # Scan and save the results in the JSON format - %[1]s scan --format json --output results.json --format-version=v2 + %[1]s scan --format json --output results.json # Display all resources %[1]s scan --verbose @@ -39,7 +39,7 @@ func GetScanCommand(ks meta.IKubescape) *cobra.Command { // scanCmd represents the scan command scanCmd := &cobra.Command{ Use: "scan", - Short: "Scan the current running cluster or yaml files", + Short: "Scan a Kubernetes cluster or YAML files for image vulnerabilities and misconfigurations", Long: `The action you want to perform`, Example: scanCmdExamples, Args: func(cmd *cobra.Command, args []string) error { diff --git a/cmd/submit/results.go b/cmd/submit/results.go deleted file mode 100644 index b7c2418d..00000000 --- a/cmd/submit/results.go +++ /dev/null @@ -1,124 +0,0 @@ -package submit - -import ( - "context" - "encoding/json" - "fmt" - "os" - - "github.com/google/uuid" - "github.com/kubescape/kubescape/v2/core/cautils" - "github.com/kubescape/kubescape/v2/core/cautils/getter" - reporthandlingv2 "github.com/kubescape/opa-utils/reporthandling/v2" - - logger "github.com/kubescape/go-logger" - "github.com/kubescape/k8s-interface/k8sinterface" - "github.com/kubescape/k8s-interface/workloadinterface" - "github.com/kubescape/kubescape/v2/core/meta" - "github.com/kubescape/kubescape/v2/core/meta/cliinterfaces" - v1 "github.com/kubescape/kubescape/v2/core/meta/datastructures/v1" - reporterv2 "github.com/kubescape/kubescape/v2/core/pkg/resultshandling/reporter/v2" - - "github.com/spf13/cobra" -) - -var formatVersion string - -type ResultsObject struct { - filePath string - customerGUID string - clusterName string -} - -func NewResultsObject(customerGUID, clusterName, filePath string) *ResultsObject { - return &ResultsObject{ - filePath: filePath, - customerGUID: customerGUID, - clusterName: clusterName, - } -} - -func (resultsObject *ResultsObject) SetResourcesReport() (*reporthandlingv2.PostureReport, error) { - // load framework results from json file - report, err := loadResultsFromFile(resultsObject.filePath) - if err != nil { - return nil, err - } - return report, nil -} - -func (resultsObject *ResultsObject) ListAllResources() (map[string]workloadinterface.IMetadata, error) { - return map[string]workloadinterface.IMetadata{}, nil -} - -func getResultsCmd(ks meta.IKubescape, submitInfo *v1.Submit) *cobra.Command { - var resultsCmd = &cobra.Command{ - Use: fmt.Sprintf("results \nExample:\n$ %[1]s submit results path/to/results.json --format-version v2", cautils.ExecName()), - Short: "Submit a pre scanned results file. The file must be in json format", - Long: ``, - RunE: func(cmd *cobra.Command, args []string) error { - - if err := flagValidationSubmit(submitInfo); err != nil { - return err - } - - if len(args) == 0 { - return fmt.Errorf("missing results file") - } - - k8s := getKubernetesApi() - - // get config - clusterConfig := getTenantConfig(submitInfo.AccountID, "", "", k8s) - resultsObjects := NewResultsObject(clusterConfig.GetAccountID(), clusterConfig.GetContextName(), args[0]) - - r := reporterv2.NewReportEventReceiver(clusterConfig, uuid.NewString(), reporterv2.SubmitContextScan) - - submitInterfaces := cliinterfaces.SubmitInterfaces{ - ClusterConfig: clusterConfig, - SubmitObjects: resultsObjects, - Reporter: r, - } - - if err := ks.Submit(context.TODO(), submitInterfaces); err != nil { - logger.L().Fatal(err.Error()) - } - return nil - }, - } - resultsCmd.PersistentFlags().StringVar(&formatVersion, "format-version", "v2", "Output object can be different between versions, this is for maintaining backward and forward compatibility. Supported:'v1'/'v2'") - - return resultsCmd -} -func loadResultsFromFile(filePath string) (*reporthandlingv2.PostureReport, error) { - report := &reporthandlingv2.PostureReport{} - f, err := os.ReadFile(filePath) - if err != nil { - return nil, err - } - if err = json.Unmarshal(f, report); err != nil { - return report, fmt.Errorf("failed to unmarshal results file: %s, make sure you run kubescape with '--format=json --format-version=v2'", err.Error()) - } - return report, nil -} - -// getKubernetesApi -func getKubernetesApi() *k8sinterface.KubernetesApi { - if !k8sinterface.IsConnectedToCluster() { - return nil - } - return k8sinterface.NewKubernetesApi() -} -func getTenantConfig(accountID, clusterName string, customClusterName string, k8s *k8sinterface.KubernetesApi) cautils.ITenantConfig { - if !k8sinterface.IsConnectedToCluster() || k8s == nil { - return cautils.NewLocalConfig(getter.GetKSCloudAPIConnector(), accountID, clusterName, customClusterName) - } - return cautils.NewClusterConfig(k8s, getter.GetKSCloudAPIConnector(), accountID, clusterName, customClusterName) -} - -// Check if the flag entered are valid -func flagValidationSubmit(submitInfo *v1.Submit) error { - - // Validate the user's credentials - return cautils.ValidateAccountID(submitInfo.AccountID) -} diff --git a/cmd/submit/submit.go b/cmd/submit/submit.go deleted file mode 100644 index 83a58d44..00000000 --- a/cmd/submit/submit.go +++ /dev/null @@ -1,45 +0,0 @@ -package submit - -import ( - "fmt" - - "github.com/kubescape/kubescape/v2/core/cautils" - "github.com/kubescape/kubescape/v2/core/meta" - metav1 "github.com/kubescape/kubescape/v2/core/meta/datastructures/v1" - "github.com/spf13/cobra" -) - -var submitCmdExamples = fmt.Sprintf(` -# Submit Kubescape scan results file -%[1]s submit results - -`, cautils.ExecName()) - -func GetSubmitCmd(ks meta.IKubescape) *cobra.Command { - var submitInfo metav1.Submit - - submitCmd := &cobra.Command{ - Use: "submit ", - Short: "Submit an object to the Kubescape SaaS version", - Long: ``, - Example: submitCmdExamples, - Run: func(cmd *cobra.Command, args []string) { - }, - } - submitCmd.PersistentFlags().StringVarP(&submitInfo.AccountID, "account", "", "", "Kubescape SaaS account ID. Default will load account ID from cache") - submitCmd.PersistentFlags().MarkDeprecated("client-id", "Client ID is no longer supported. Feel free to contact the Kubescape maintainers for more information.") - submitCmd.PersistentFlags().MarkDeprecated("secret-key", "Secret Key is no longer supported. Feel free to contact the Kubescape maintainers for more information.") - - submitCmd.AddCommand(getResultsCmd(ks, &submitInfo)) - - // deprecated commands - submitCmd.AddCommand(&cobra.Command{ - Use: "exceptions", - Deprecated: "Contact Kubescape maintainers for more information.", - }) - submitCmd.AddCommand(&cobra.Command{ - Use: "rbac", - Deprecated: "Contact Kubescape maintainers for more information.", - }) - return submitCmd -} diff --git a/cmd/update/update.go b/cmd/update/update.go index fe373a0d..48b61737 100644 --- a/cmd/update/update.go +++ b/cmd/update/update.go @@ -8,6 +8,7 @@ import ( "fmt" logger "github.com/kubescape/go-logger" + "github.com/kubescape/go-logger/helpers" "github.com/kubescape/kubescape/v2/core/cautils" "github.com/spf13/cobra" ) @@ -24,16 +25,16 @@ var updateCmdExamples = fmt.Sprintf(` func GetUpdateCmd() *cobra.Command { updateCmd := &cobra.Command{ Use: "update", - Short: "Update your version", + Short: "Update to latest release version", Long: ``, Example: updateCmdExamples, RunE: func(_ *cobra.Command, args []string) error { //Checking the user's version of kubescape to the latest release if cautils.BuildNumber == cautils.LatestReleaseVersion { //your version == latest version - logger.L().Info(("You are in the latest version")) + logger.L().Info(("Nothing to update, you are running the latest version"), helpers.String("Version", cautils.BuildNumber)) } else { - fmt.Printf("please refer to our installation docs in the following link: %s", installationLink) + fmt.Printf("Please refer to our installation docs in the following link: %s", installationLink) } return nil }, diff --git a/cmd/version/version.go b/cmd/version/version.go index 311888e3..dd4259a6 100644 --- a/cmd/version/version.go +++ b/cmd/version/version.go @@ -5,6 +5,7 @@ import ( "fmt" "os" + "github.com/kubescape/go-logger" "github.com/kubescape/kubescape/v2/core/cautils" "github.com/spf13/cobra" ) @@ -19,10 +20,10 @@ func GetVersionCmd() *cobra.Command { v := cautils.NewIVersionCheckHandler(ctx) v.CheckLatestVersion(ctx, cautils.NewVersionCheckRequest(cautils.BuildNumber, "", "", "version")) fmt.Fprintf(os.Stdout, - "Your current version is: %s [git enabled in build: %t]\n", + "Your current version is: %s\n", cautils.BuildNumber, - isGitEnabled(), ) + logger.L().Debug(fmt.Sprintf("git enabled in build: %t", isGitEnabled())) return nil }, } diff --git a/core/cautils/datastructuresmethods.go b/core/cautils/datastructuresmethods.go index 61dda263..82b563e0 100644 --- a/core/cautils/datastructuresmethods.go +++ b/core/cautils/datastructuresmethods.go @@ -5,7 +5,6 @@ import ( "github.com/armosec/utils-go/boolutils" cloudsupport "github.com/kubescape/k8s-interface/cloudsupport/v1" - "github.com/kubescape/k8s-interface/k8sinterface" "github.com/kubescape/opa-utils/reporthandling" "github.com/kubescape/opa-utils/reporthandling/apis" ) @@ -89,58 +88,50 @@ func isRuleKubescapeVersionCompatible(attributes map[string]interface{}, version return true } -func getCloudType(scanInfo *ScanInfo) (bool, reporthandling.ScanningScopeType) { +func getCloudProvider(scanInfo *ScanInfo) reporthandling.ScanningScopeType { if cloudsupport.IsAKS() { - return true, reporthandling.ScopeCloudAKS + return reporthandling.ScopeCloudAKS } - if cloudsupport.IsEKS(k8sinterface.GetConfig()) { - return true, reporthandling.ScopeCloudEKS + if cloudsupport.IsEKS() { + return reporthandling.ScopeCloudEKS } - if cloudsupport.IsGKE(k8sinterface.GetConfig()) { - return true, reporthandling.ScopeCloudGKE + if cloudsupport.IsGKE() { + return reporthandling.ScopeCloudGKE } - return false, "" + return "" } func GetScanningScope(scanInfo *ScanInfo) reporthandling.ScanningScopeType { - var result reporthandling.ScanningScopeType switch scanInfo.GetScanningContext() { case ContextCluster: - isCloud, cloudType := getCloudType(scanInfo) - if isCloud { - result = cloudType - } else { - result = reporthandling.ScopeCluster + if cloudProvider := getCloudProvider(scanInfo); cloudProvider != "" { + return cloudProvider } + return reporthandling.ScopeCluster default: - result = reporthandling.ScopeFile + return reporthandling.ScopeFile } - - return result } func isScanningScopeMatchToControlScope(scanScope reporthandling.ScanningScopeType, controlScope reporthandling.ScanningScopeType) bool { - result := false switch controlScope { case reporthandling.ScopeFile: - result = (reporthandling.ScopeFile == scanScope) + return reporthandling.ScopeFile == scanScope case reporthandling.ScopeCluster: - result = (reporthandling.ScopeCluster == scanScope) || (reporthandling.ScopeCloud == scanScope) || (reporthandling.ScopeCloudAKS == scanScope) || (reporthandling.ScopeCloudEKS == scanScope) || (reporthandling.ScopeCloudGKE == scanScope) + return reporthandling.ScopeCluster == scanScope || reporthandling.ScopeCloud == scanScope || reporthandling.ScopeCloudAKS == scanScope || reporthandling.ScopeCloudEKS == scanScope || reporthandling.ScopeCloudGKE == scanScope case reporthandling.ScopeCloud: - result = (reporthandling.ScopeCloud == scanScope) || (reporthandling.ScopeCloudAKS == scanScope) || (reporthandling.ScopeCloudEKS == scanScope) || (reporthandling.ScopeCloudGKE == scanScope) + return reporthandling.ScopeCloud == scanScope || reporthandling.ScopeCloudAKS == scanScope || reporthandling.ScopeCloudEKS == scanScope || reporthandling.ScopeCloudGKE == scanScope case reporthandling.ScopeCloudAKS: - result = (reporthandling.ScopeCloudAKS == scanScope) + return reporthandling.ScopeCloudAKS == scanScope case reporthandling.ScopeCloudEKS: - result = (reporthandling.ScopeCloudEKS == scanScope) + return reporthandling.ScopeCloudEKS == scanScope case reporthandling.ScopeCloudGKE: - result = (reporthandling.ScopeCloudGKE == scanScope) + return reporthandling.ScopeCloudGKE == scanScope default: - result = true + return true } - - return result } func isControlFitToScanScope(control reporthandling.Control, scanScopeMatches reporthandling.ScanningScopeType) bool { diff --git a/core/cautils/datastructuresmethods_test.go b/core/cautils/datastructuresmethods_test.go index a19107d8..11126bc5 100644 --- a/core/cautils/datastructuresmethods_test.go +++ b/core/cautils/datastructuresmethods_test.go @@ -4,8 +4,8 @@ import ( "fmt" "testing" + "github.com/armosec/armoapi-go/armotypes" "github.com/kubescape/opa-utils/reporthandling" - "github.com/stretchr/testify/assert" ) @@ -79,7 +79,6 @@ func TestIsControlFitToScanScope(t *testing.T) { scanInfo: &ScanInfo{}, Control: reporthandling.Control{ ScanningScope: &reporthandling.ScanningScope{ - Matches: []reporthandling.ScanningScopeType{ reporthandling.ScopeCloudEKS, }, @@ -99,6 +98,237 @@ func TestIsControlFitToScanScope(t *testing.T) { expected_res: false, }} for i := range tests { - assert.Equal(t, isControlFitToScanScope(tests[i].Control, GetScanningScope(tests[i].scanInfo)), tests[i].expected_res, fmt.Sprintf("tests_true index %d", i)) + assert.Equal(t, tests[i].expected_res, isControlFitToScanScope(tests[i].Control, GetScanningScope(tests[i].scanInfo)), fmt.Sprintf("tests_true index %d", i)) + } +} + +func TestIsScanningScopeMatchToControlScope(t *testing.T) { + tests := []struct { + scanScope reporthandling.ScanningScopeType + controlScope reporthandling.ScanningScopeType + expected bool + }{ + { + scanScope: reporthandling.ScopeFile, + controlScope: reporthandling.ScopeFile, + expected: true, + }, + { + scanScope: ScopeCluster, + controlScope: ScopeCluster, + expected: true, + }, + { + scanScope: reporthandling.ScopeCloud, + controlScope: reporthandling.ScopeCloud, + expected: true, + }, + { + scanScope: reporthandling.ScopeCloudAKS, + controlScope: reporthandling.ScopeCloudAKS, + expected: true, + }, + { + scanScope: reporthandling.ScopeCloudEKS, + controlScope: reporthandling.ScopeCloudEKS, + expected: true, + }, + { + scanScope: reporthandling.ScopeCloudGKE, + controlScope: reporthandling.ScopeCloudGKE, + expected: true, + }, + { + scanScope: ScopeCluster, + controlScope: reporthandling.ScopeCloud, + expected: false, + }, + { + scanScope: reporthandling.ScopeCloud, + controlScope: ScopeCluster, + expected: true, + }, + { + scanScope: reporthandling.ScopeCloudAKS, + controlScope: ScopeCluster, + expected: true, + }, + { + scanScope: reporthandling.ScopeCloudEKS, + controlScope: ScopeCluster, + expected: true, + }, + { + scanScope: reporthandling.ScopeCloudGKE, + controlScope: ScopeCluster, + expected: true, + }, + { + scanScope: reporthandling.ScopeCloud, + controlScope: reporthandling.ScopeCloudAKS, + expected: false, + }, + { + scanScope: reporthandling.ScopeCloudAKS, + controlScope: reporthandling.ScopeCloud, + expected: true, + }, + { + scanScope: reporthandling.ScopeCloudEKS, + controlScope: reporthandling.ScopeCloud, + expected: true, + }, + { + scanScope: reporthandling.ScopeCloudGKE, + controlScope: reporthandling.ScopeCloud, + expected: true, + }, + { + scanScope: ScopeCluster, + controlScope: reporthandling.ScopeCloudAKS, + expected: false, + }, + { + scanScope: ScopeCluster, + controlScope: reporthandling.ScopeCloudEKS, + expected: false, + }, + { + scanScope: ScopeCluster, + controlScope: reporthandling.ScopeCloudGKE, + expected: false, + }, + { + scanScope: reporthandling.ScopeFile, + controlScope: ScopeCluster, + expected: false, + }, + { + scanScope: reporthandling.ScopeFile, + controlScope: reporthandling.ScopeCloud, + expected: false, + }, + { + scanScope: reporthandling.ScopeFile, + controlScope: reporthandling.ScopeCloudAKS, + expected: false, + }, + { + scanScope: reporthandling.ScopeFile, + controlScope: reporthandling.ScopeCloudEKS, + expected: false, + }, + { + scanScope: reporthandling.ScopeFile, + controlScope: reporthandling.ScopeCloudGKE, + expected: false, + }, + { + scanScope: reporthandling.ScopeCloud, + controlScope: reporthandling.ScopeCloudEKS, + expected: false, + }, + { + scanScope: reporthandling.ScopeCloud, + controlScope: reporthandling.ScopeCloudGKE, + expected: false, + }, + { + scanScope: reporthandling.ScopeCloudAKS, + controlScope: reporthandling.ScopeCloudEKS, + expected: false, + }, + { + scanScope: reporthandling.ScopeCloudAKS, + controlScope: reporthandling.ScopeCloudGKE, + expected: false, + }, + { + scanScope: reporthandling.ScopeCloudEKS, + controlScope: reporthandling.ScopeCloudAKS, + expected: false, + }, + { + scanScope: reporthandling.ScopeCloudEKS, + controlScope: reporthandling.ScopeCloudGKE, + expected: false, + }, + { + scanScope: reporthandling.ScopeCloudGKE, + controlScope: reporthandling.ScopeCloudAKS, + expected: false, + }, + { + scanScope: reporthandling.ScopeCloudGKE, + controlScope: reporthandling.ScopeCloudEKS, + expected: false, + }, + } + + for _, test := range tests { + result := isScanningScopeMatchToControlScope(test.scanScope, test.controlScope) + assert.Equal(t, test.expected, result, fmt.Sprintf("scanScope: %v, controlScope: %v", test.scanScope, test.controlScope)) + } +} + +func TestIsFrameworkFitToScanScope(t *testing.T) { + tests := []struct { + name string + framework reporthandling.Framework + scanScopeMatch reporthandling.ScanningScopeType + want bool + }{ + { + name: "Framework with nil ScanningScope should return true", + framework: reporthandling.Framework{ + PortalBase: armotypes.PortalBase{ + Name: "test-framework", + }, + }, + scanScopeMatch: reporthandling.ScopeFile, + want: true, + }, + { + name: "Framework with empty ScanningScope.Matches should return true", + framework: reporthandling.Framework{ + PortalBase: armotypes.PortalBase{ + Name: "test-framework", + }, ScanningScope: &reporthandling.ScanningScope{}, + }, + scanScopeMatch: reporthandling.ScopeFile, + want: true, + }, + { + name: "Framework with matching ScanningScope.Matches should return true", + framework: reporthandling.Framework{ + PortalBase: armotypes.PortalBase{ + Name: "test-framework", + }, ScanningScope: &reporthandling.ScanningScope{ + Matches: []reporthandling.ScanningScopeType{reporthandling.ScopeFile}, + }, + }, + scanScopeMatch: reporthandling.ScopeFile, + want: true, + }, + { + name: "Framework with non-matching ScanningScope.Matches should return false", + framework: reporthandling.Framework{ + PortalBase: armotypes.PortalBase{ + Name: "test-framework", + }, ScanningScope: &reporthandling.ScanningScope{ + Matches: []reporthandling.ScanningScopeType{reporthandling.ScopeCluster}, + }, + }, + scanScopeMatch: reporthandling.ScopeFile, + want: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := isFrameworkFitToScanScope(tt.framework, tt.scanScopeMatch); got != tt.want { + t.Errorf("isFrameworkFitToScanScope() = %v, want %v", got, tt.want) + } + }) } } diff --git a/core/cautils/scaninfo.go b/core/cautils/scaninfo.go index 1c463786..c9034e80 100644 --- a/core/cautils/scaninfo.go +++ b/core/cautils/scaninfo.go @@ -296,11 +296,10 @@ func scanInfoToScanMetadata(ctx context.Context, scanInfo *ScanInfo) *reporthand } func (scanInfo *ScanInfo) GetScanningContext() ScanningContext { - input := "" if len(scanInfo.InputPatterns) > 0 { - input = scanInfo.InputPatterns[0] + return GetScanningContext(scanInfo.InputPatterns[0]) } - return GetScanningContext(input) + return GetScanningContext("") } // GetScanningContext get scanning context from the input param diff --git a/core/cautils/scaninfo_test.go b/core/cautils/scaninfo_test.go index 6137689b..e998bf19 100644 --- a/core/cautils/scaninfo_test.go +++ b/core/cautils/scaninfo_test.go @@ -2,6 +2,8 @@ package cautils import ( "context" + "os" + "path/filepath" "testing" reporthandlingv2 "github.com/kubescape/opa-utils/reporthandling/v2" @@ -37,12 +39,18 @@ func TestSetContextMetadata(t *testing.T) { } func TestGetHostname(t *testing.T) { + // Test that the hostname is not empty assert.NotEqual(t, "", getHostname()) } func TestGetScanningContext(t *testing.T) { + // Test with empty input assert.Equal(t, ContextCluster, GetScanningContext("")) + + // Test with Git URL input assert.Equal(t, ContextGitURL, GetScanningContext("https://github.com/kubescape/kubescape")) + + // TODO: Add more tests with other input types } func TestScanInfoFormats(t *testing.T) { @@ -71,3 +79,30 @@ func TestScanInfoFormats(t *testing.T) { }) } } + +func TestGetScanningContextWithFile(t *testing.T) { + // Test with a file + dir, err := os.MkdirTemp("", "example") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(dir) + + filePath := filepath.Join(dir, "file.txt") + if _, err := os.Create(filePath); err != nil { + t.Fatal(err) + } + + assert.Equal(t, ContextFile, GetScanningContext(filePath)) +} + +func TestGetScanningContextWithDir(t *testing.T) { + // Test with a directory + dir, err := os.MkdirTemp("", "example") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(dir) + + assert.Equal(t, ContextDir, GetScanningContext(dir)) +} diff --git a/core/core/submit.go b/core/core/submit.go deleted file mode 100644 index 06994e78..00000000 --- a/core/core/submit.go +++ /dev/null @@ -1,36 +0,0 @@ -package core - -import ( - "context" - - "github.com/kubescape/kubescape/v2/core/cautils" - "github.com/kubescape/kubescape/v2/core/meta/cliinterfaces" - - logger "github.com/kubescape/go-logger" -) - -func (ks *Kubescape) Submit(ctx context.Context, submitInterfaces cliinterfaces.SubmitInterfaces) error { - - // list resources - report, err := submitInterfaces.SubmitObjects.SetResourcesReport() - if err != nil { - return err - } - allresources, err := submitInterfaces.SubmitObjects.ListAllResources() - if err != nil { - return err - } - // report - o := &cautils.OPASessionObj{ - Report: report, - AllResources: allresources, - Metadata: &report.Metadata, - } - if err := submitInterfaces.Reporter.Submit(ctx, o); err != nil { - return err - } - logger.L().Success("Data has been submitted successfully") - submitInterfaces.Reporter.DisplayMessage() - - return nil -} diff --git a/core/meta/ksinterface.go b/core/meta/ksinterface.go index 96a6643e..8d8c9736 100644 --- a/core/meta/ksinterface.go +++ b/core/meta/ksinterface.go @@ -4,7 +4,6 @@ import ( "context" "github.com/kubescape/kubescape/v2/core/cautils" - "github.com/kubescape/kubescape/v2/core/meta/cliinterfaces" metav1 "github.com/kubescape/kubescape/v2/core/meta/datastructures/v1" "github.com/kubescape/kubescape/v2/core/pkg/resultshandling" ) @@ -16,9 +15,6 @@ type IKubescape interface { List(ctx context.Context, listPolicies *metav1.ListPolicies) error // TODO - return list response Download(ctx context.Context, downloadInfo *metav1.DownloadInfo) error // TODO - return downloaded policies - // submit - Submit(ctx context.Context, submitInterfaces cliinterfaces.SubmitInterfaces) error // TODO - func should receive object - // config SetCachedConfig(setConfig *metav1.SetConfig) error ViewCachedConfig(viewConfig *metav1.ViewConfig) error diff --git a/core/pkg/resourcehandler/handlepullresources_test.go b/core/pkg/resourcehandler/handlepullresources_test.go index ec01144b..e1789628 100644 --- a/core/pkg/resourcehandler/handlepullresources_test.go +++ b/core/pkg/resourcehandler/handlepullresources_test.go @@ -11,13 +11,13 @@ import ( "github.com/kubescape/opa-utils/reporthandling/apis" helpersv1 "github.com/kubescape/opa-utils/reporthandling/helpers/v1" - reporthandlingv2 "github.com/kubescape/opa-utils/reporthandling/v2" reportv2 "github.com/kubescape/opa-utils/reporthandling/v2" "github.com/stretchr/testify/assert" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/version" "k8s.io/client-go/dynamic/fake" fakeclientset "k8s.io/client-go/kubernetes/fake" + "k8s.io/client-go/rest" clientcmdapi "k8s.io/client-go/tools/clientcmd/api" ) @@ -49,7 +49,7 @@ func Test_getCloudMetadata(t *testing.T) { name: "Test_getCloudMetadata - GitVersion: GKE", args: args{ opaSessionObj: &cautils.OPASessionObj{ - Report: &reporthandlingv2.PostureReport{ + Report: &reportv2.PostureReport{ ClusterAPIServerInfo: &version.Info{ GitVersion: "v1.25.4-gke.1600", }, @@ -60,25 +60,14 @@ func Test_getCloudMetadata(t *testing.T) { }, want: helpersv1.NewGKEMetadata(""), }, - { - name: "Test_getCloudMetadata_context_GKE", - args: args{ - opaSessionObj: &cautils.OPASessionObj{ - Report: &reporthandlingv2.PostureReport{ - ClusterAPIServerInfo: nil, - }, - }, - kubeConfig: kubeConfig, - context: "gke_xxx-xx-0000_us-central1-c_xxxx-1", - }, - want: helpersv1.NewGKEMetadata(""), - }, { name: "Test_getCloudMetadata_context_EKS", args: args{ opaSessionObj: &cautils.OPASessionObj{ - Report: &reporthandlingv2.PostureReport{ - ClusterAPIServerInfo: nil, + Report: &reportv2.PostureReport{ + ClusterAPIServerInfo: &version.Info{ + GitVersion: "v1.25.4-eks.1600", + }, }, }, kubeConfig: kubeConfig, @@ -90,8 +79,10 @@ func Test_getCloudMetadata(t *testing.T) { name: "Test_getCloudMetadata_context_AKS", args: args{ opaSessionObj: &cautils.OPASessionObj{ - Report: &reporthandlingv2.PostureReport{ - ClusterAPIServerInfo: nil, + Report: &reportv2.PostureReport{ + ClusterAPIServerInfo: &version.Info{ + GitVersion: "v1", + }, }, }, kubeConfig: kubeConfig, @@ -100,10 +91,15 @@ func Test_getCloudMetadata(t *testing.T) { want: helpersv1.NewAKSMetadata(""), }, } + k8sinterface.K8SConfig = &rest.Config{} for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { k8sinterface.SetClusterContextName(tt.args.context) - got := getCloudMetadata(tt.args.opaSessionObj, tt.args.kubeConfig) + k8sinterface.SetClientConfigAPI(tt.args.kubeConfig) + k8sinterface.SetK8SGitServerVersion(tt.args.opaSessionObj.Report.ClusterAPIServerInfo.GitVersion) + k8sinterface.SetConnectedToCluster(true) + + got := getCloudMetadata(tt.args.opaSessionObj) if got == nil { t.Errorf("getCloudMetadata() = %v, want %v", got, tt.want.Provider()) return @@ -113,112 +109,10 @@ func Test_getCloudMetadata(t *testing.T) { } }) } + k8sinterface.SetClusterContextName("") + k8sinterface.SetClientConfigAPI(nil) } -func Test_isGKE(t *testing.T) { - type args struct { - config *clientcmdapi.Config - context string - } - tests := []struct { - name string - args args - want bool - }{ - { - name: "Test_isGKE", - args: args{ - config: getKubeConfigMock(), - context: "gke_xxx-xx-0000_us-central1-c_xxxx-1", - }, - want: true, - }, - } - for _, tt := range tests { - - t.Run(tt.name, func(t *testing.T) { - // set context - k8sinterface.SetClusterContextName(tt.args.context) - if got := isGKE(tt.args.config); got != tt.want { - t.Errorf("isGKE() = %v, want %v", got, tt.want) - } - }) - } -} - -func Test_isEKS(t *testing.T) { - type args struct { - config *clientcmdapi.Config - context string - } - tests := []struct { - name string - args args - want bool - }{ - { - name: "Test_isEKS", - args: args{ - config: getKubeConfigMock(), - context: "arn:aws:eks:eu-west-1:xxx:cluster/xxxx", - }, - want: true, - }, - } - for _, tt := range tests { - - t.Run(tt.name, func(t *testing.T) { - // set context - k8sinterface.SetClusterContextName(tt.args.context) - if got := isEKS(tt.args.config); got != tt.want { - t.Errorf("isEKS() = %v, want %v", got, tt.want) - } - }) - } -} - -func Test_isAKS(t *testing.T) { - type args struct { - config *clientcmdapi.Config - context string - } - tests := []struct { - name string - args args - want bool - }{ - { - name: "Test_isAKS", - args: args{ - config: getKubeConfigMock(), - context: "xxxx-2", - }, - want: true, - }, - } - for _, tt := range tests { - - t.Run(tt.name, func(t *testing.T) { - // set context - k8sinterface.SetClusterContextName(tt.args.context) - if got := isAKS(tt.args.config); got != tt.want { - t.Errorf("isAKS() = %v, want %v", got, tt.want) - } - }) - } -} - -/* unused for now. -type iResourceHandlerMock struct{} - -func (*iResourceHandlerMock) GetResources(*cautils.OPASessionObj, *identifiers.PortalDesignator) (*cautils.K8SResources, map[string]workloadinterface.IMetadata, *cautils.KSResources, error) { - return nil, nil, nil, nil -} -func (*iResourceHandlerMock) GetClusterAPIServerInfo() *version.Info { - return nil -} -*/ - // https://github.com/kubescape/kubescape/pull/1004 // Cluster named .*eks.* config without a cloudconfig panics whereas we just want to scan a file func getResourceHandlerMock() *K8sResourceHandler { @@ -237,12 +131,12 @@ func getResourceHandlerMock() *K8sResourceHandler { func Test_CollectResources(t *testing.T) { resourceHandler := getResourceHandlerMock() objSession := &cautils.OPASessionObj{ - Metadata: &reporthandlingv2.Metadata{ - ScanMetadata: reporthandlingv2.ScanMetadata{ + Metadata: &reportv2.Metadata{ + ScanMetadata: reportv2.ScanMetadata{ ScanningTarget: reportv2.Cluster, }, }, - Report: &reporthandlingv2.PostureReport{ + Report: &reportv2.PostureReport{ ClusterAPIServerInfo: nil, }, } diff --git a/core/pkg/resourcehandler/handlerpullresources.go b/core/pkg/resourcehandler/handlerpullresources.go index 0de09fd9..df13b4ea 100644 --- a/core/pkg/resourcehandler/handlerpullresources.go +++ b/core/pkg/resourcehandler/handlerpullresources.go @@ -3,11 +3,9 @@ package resourcehandler import ( "context" "fmt" - "strings" logger "github.com/kubescape/go-logger" "github.com/kubescape/go-logger/helpers" - "github.com/kubescape/k8s-interface/cloudsupport" cloudsupportv1 "github.com/kubescape/k8s-interface/cloudsupport/v1" "github.com/kubescape/k8s-interface/k8sinterface" "github.com/kubescape/kubescape/v2/core/cautils" @@ -16,7 +14,6 @@ import ( helpersv1 "github.com/kubescape/opa-utils/reporthandling/helpers/v1" reportv2 "github.com/kubescape/opa-utils/reporthandling/v2" "go.opentelemetry.io/otel" - clientcmdapi "k8s.io/client-go/tools/clientcmd/api" ) func CollectResources(ctx context.Context, rsrcHandler IResourceHandler, policyIdentifier []cautils.PolicyIdentifier, opaSessionObj *cautils.OPASessionObj, progressListener opaprocessor.IJobProgressNotificationClient, scanInfo *cautils.ScanInfo) error { @@ -47,7 +44,7 @@ func CollectResources(ctx context.Context, rsrcHandler IResourceHandler, policyI } func setCloudMetadata(opaSessionObj *cautils.OPASessionObj) { - iCloudMetadata := getCloudMetadata(opaSessionObj, k8sinterface.GetConfig()) + iCloudMetadata := getCloudMetadata(opaSessionObj) if iCloudMetadata == nil { return } @@ -67,53 +64,15 @@ func setCloudMetadata(opaSessionObj *cautils.OPASessionObj) { // 1. Get cloud provider from API server git version (EKS, GKE) // 2. Get cloud provider from kubeconfig by parsing the cluster context (EKS, GKE) // 3. Get cloud provider from kubeconfig by parsing the server URL (AKS) -func getCloudMetadata(opaSessionObj *cautils.OPASessionObj, config *clientcmdapi.Config) apis.ICloudParser { - - if config == nil { +func getCloudMetadata(opaSessionObj *cautils.OPASessionObj) apis.ICloudParser { + switch cloudsupportv1.GetCloudProvider() { + case cloudsupportv1.AKS: + return helpersv1.NewAKSMetadata(k8sinterface.GetContextName()) + case cloudsupportv1.EKS: + return helpersv1.NewEKSMetadata(k8sinterface.GetContextName()) + case cloudsupportv1.GKE: + return helpersv1.NewGKEMetadata(k8sinterface.GetContextName()) + default: return nil } - - var provider string - - // attempting to get cloud provider from API server git version - if opaSessionObj.Report.ClusterAPIServerInfo != nil { - provider = cloudsupport.GetCloudProvider(opaSessionObj.Report.ClusterAPIServerInfo.GitVersion) - } - - if provider == cloudsupportv1.AKS || isAKS(config) { - return helpersv1.NewAKSMetadata(k8sinterface.GetContextName()) - } - if provider == cloudsupportv1.EKS || isEKS(config) { - return helpersv1.NewEKSMetadata(k8sinterface.GetContextName()) - } - if provider == cloudsupportv1.GKE || isGKE(config) { - return helpersv1.NewGKEMetadata(k8sinterface.GetContextName()) - } - - return nil -} - -// check if the server is AKS. e.g. https://XXX.XX.XXX.azmk8s.io:443 -func isAKS(config *clientcmdapi.Config) bool { - const serverIdentifierAKS = "azmk8s.io" - if cluster, ok := config.Clusters[k8sinterface.GetContextName()]; ok { - return strings.Contains(cluster.Server, serverIdentifierAKS) - } - return false -} - -// check if the server is EKS. e.g. arn:aws:eks:eu-west-1:xxx:cluster/xxxx -func isEKS(config *clientcmdapi.Config) bool { - if context, ok := config.Contexts[k8sinterface.GetContextName()]; ok { - return strings.Contains(context.Cluster, cloudsupportv1.EKS) - } - return false -} - -// check if the server is GKE. e.g. gke_xxx-xx-0000_us-central1-c_xxxx-1 -func isGKE(config *clientcmdapi.Config) bool { - if context, ok := config.Contexts[k8sinterface.GetContextName()]; ok { - return strings.Contains(context.Cluster, cloudsupportv1.GKE) - } - return false } diff --git a/core/pkg/resourcehandler/k8sresources.go b/core/pkg/resourcehandler/k8sresources.go index 23bbc7f7..0e88feb7 100644 --- a/core/pkg/resourcehandler/k8sresources.go +++ b/core/pkg/resourcehandler/k8sresources.go @@ -189,7 +189,7 @@ func (k8sHandler *K8sResourceHandler) findScanObjectResource(resource *objectsen } func (k8sHandler *K8sResourceHandler) collectCloudResources(ctx context.Context, sessionObj *cautils.OPASessionObj, allResources map[string]workloadinterface.IMetadata, externalResourceMap cautils.ExternalResources, cloudResources []string, progressListener opaprocessor.IJobProgressNotificationClient) error { - provider := cloudsupport.GetCloudProvider(k8sHandler.clusterName) + provider := cloudsupport.GetCloudProvider() if provider == "" { return fmt.Errorf("failed to get cloud provider, cluster: %s", k8sHandler.clusterName) } diff --git a/core/pkg/resultshandling/printer/v2/prettyprinter/clusterscan.go b/core/pkg/resultshandling/printer/v2/prettyprinter/clusterscan.go index 7786b689..629212ae 100644 --- a/core/pkg/resultshandling/printer/v2/prettyprinter/clusterscan.go +++ b/core/pkg/resultshandling/printer/v2/prettyprinter/clusterscan.go @@ -59,7 +59,7 @@ func (cp *ClusterPrinter) printTopWorkloads(topWorkloadsByScore []reporthandling cautils.InfoTextDisplay(cp.writer, txt) - cautils.SimpleDisplay(cp.writer, fmt.Sprintf("%s\n\n", strings.Repeat("─", len(txt)))) + cautils.SimpleDisplay(cp.writer, fmt.Sprintf("%s\n", strings.Repeat("─", len(txt)))) cautils.SimpleDisplay(cp.writer, highStakesWlsText) @@ -67,7 +67,8 @@ func (cp *ClusterPrinter) printTopWorkloads(topWorkloadsByScore []reporthandling ns := wl.GetNamespace() name := wl.GetName() kind := wl.GetKind() - cautils.SimpleDisplay(cp.writer, fmt.Sprintf("%d. namespace: %s, name: %s, kind: %s - '%s'\n", i+1, ns, name, kind, getCallToActionString(cp.getWorkloadScanCommand(ns, kind, name)))) + cautils.SimpleDisplay(cp.writer, fmt.Sprintf("%d. namespace: %s, name: %s, kind: %s\n", i+1, ns, name, kind)) + cautils.SimpleDisplay(cp.writer, fmt.Sprintf(" '%s'\n", getCallToActionString(cp.getWorkloadScanCommand(ns, kind, name)))) } cautils.InfoTextDisplay(cp.writer, "\n") diff --git a/core/pkg/resultshandling/printer/v2/prettyprinter/reposcan.go b/core/pkg/resultshandling/printer/v2/prettyprinter/reposcan.go index 0348d30f..dacaadc8 100644 --- a/core/pkg/resultshandling/printer/v2/prettyprinter/reposcan.go +++ b/core/pkg/resultshandling/printer/v2/prettyprinter/reposcan.go @@ -58,7 +58,7 @@ func (rp *RepoPrinter) printTopWorkloads(topWorkloadsByScore []reporthandling.IR txt := getTopWorkloadsTitle(len(topWorkloadsByScore)) cautils.InfoTextDisplay(rp.writer, txt) - cautils.SimpleDisplay(rp.writer, fmt.Sprintf("%s\n\n", strings.Repeat("─", len(txt)))) + cautils.SimpleDisplay(rp.writer, fmt.Sprintf("%s\n", strings.Repeat("─", len(txt)))) cautils.SimpleDisplay(rp.writer, highStakesWlsText) @@ -67,7 +67,8 @@ func (rp *RepoPrinter) printTopWorkloads(topWorkloadsByScore []reporthandling.IR name := wl.GetName() kind := wl.GetKind() cmdPrefix := getWorkloadPrefixForCmd(ns, kind, name) - cautils.SimpleDisplay(rp.writer, fmt.Sprintf("%d. %s - '%s'\n", i+1, cmdPrefix, getCallToActionString(rp.getWorkloadScanCommand(ns, kind, name, *wl.GetSource())))) + cautils.SimpleDisplay(rp.writer, fmt.Sprintf("%d. %s\n", i+1, cmdPrefix)) + cautils.SimpleDisplay(rp.writer, fmt.Sprintf(" %s\n", getCallToActionString(rp.getWorkloadScanCommand(ns, kind, name, *wl.GetSource())))) } cautils.InfoTextDisplay(rp.writer, "\n") diff --git a/core/pkg/resultshandling/printer/v2/prettyprinter/tableprinter/configurationprinter/categorytable.go b/core/pkg/resultshandling/printer/v2/prettyprinter/tableprinter/configurationprinter/categorytable.go index 46bacad7..9ded6a5e 100644 --- a/core/pkg/resultshandling/printer/v2/prettyprinter/tableprinter/configurationprinter/categorytable.go +++ b/core/pkg/resultshandling/printer/v2/prettyprinter/tableprinter/configurationprinter/categorytable.go @@ -1,12 +1,10 @@ package configurationprinter import ( - "fmt" "io" "github.com/kubescape/kubescape/v2/core/cautils" "github.com/kubescape/kubescape/v2/core/pkg/resultshandling/printer/v2/prettyprinter/tableprinter/utils" - "github.com/kubescape/opa-utils/reporthandling/apis" "github.com/kubescape/opa-utils/reporthandling/results/v1/reportsummary" "github.com/olekukonko/tablewriter" ) @@ -15,7 +13,7 @@ const ( docsPrefix = "https://hub.armosec.io/docs" scanControlPrefix = "$ kubescape scan control" controlNameHeader = "CONTROL NAME" - statusHeader = "STATUS" + statusHeader = "" docsHeader = "DOCS" resourcesHeader = "RESOURCES" runHeader = "VIEW DETAILS" @@ -31,8 +29,8 @@ func initCategoryTableData(categoryType CategoryType) ([]string, []int) { func getCategoryStatusTypeHeaders() []string { headers := make([]string, 3) - headers[0] = controlNameHeader - headers[1] = statusHeader + headers[0] = statusHeader + headers[1] = controlNameHeader headers[2] = docsHeader return headers @@ -48,7 +46,7 @@ func getCategoryCountingTypeHeaders() []string { } func getStatusTypeAlignments() []int { - return []int{tablewriter.ALIGN_LEFT, tablewriter.ALIGN_CENTER, tablewriter.ALIGN_CENTER} + return []int{tablewriter.ALIGN_CENTER, tablewriter.ALIGN_LEFT, tablewriter.ALIGN_CENTER} } func getCountingTypeAlignments() []int { @@ -66,14 +64,14 @@ func generateCategoryStatusRow(controlSummary reportsummary.IControlSummary, inf rows := make([]string, 3) - rows[0] = controlSummary.GetName() - if len(controlSummary.GetName()) > 50 { - rows[0] = controlSummary.GetName()[:50] + "..." - } else { - rows[0] = controlSummary.GetName() - } + rows[0] = utils.GetStatusIcon(controlSummary.GetStatus().Status()) - rows[1] = utils.GetStatusColor(controlSummary.GetStatus().Status())(getStatus(status, controlSummary, infoToPrintInfo)) + rows[1] = controlSummary.GetName() + if len(controlSummary.GetName()) > 50 { + rows[1] = controlSummary.GetName()[:50] + "..." + } else { + rows[1] = controlSummary.GetName() + } rows[2] = getDocsForControl(controlSummary) @@ -81,14 +79,6 @@ func generateCategoryStatusRow(controlSummary reportsummary.IControlSummary, inf } -func getStatus(status apis.IStatus, controlSummary reportsummary.IControlSummary, infoToPrintInfo []utils.InfoStars) string { - // skipped is shown as action required - if status.IsSkipped() { - return fmt.Sprintf("%s %s", "action required", GetInfoColumn(controlSummary, infoToPrintInfo)) - } - return string(controlSummary.GetStatus().Status()) -} - func getCategoryTableWriter(writer io.Writer, headers []string, columnAligments []int) *tablewriter.Table { table := tablewriter.NewWriter(writer) table.SetHeader(headers) diff --git a/core/pkg/resultshandling/printer/v2/prettyprinter/tableprinter/configurationprinter/categorytable_test.go b/core/pkg/resultshandling/printer/v2/prettyprinter/tableprinter/configurationprinter/categorytable_test.go index aea317d2..6d4b69df 100644 --- a/core/pkg/resultshandling/printer/v2/prettyprinter/tableprinter/configurationprinter/categorytable_test.go +++ b/core/pkg/resultshandling/printer/v2/prettyprinter/tableprinter/configurationprinter/categorytable_test.go @@ -27,8 +27,8 @@ func TestInitCategoryTableData(t *testing.T) { { name: "Test2", categoryType: TypeStatus, - expectedHeaders: []string{"CONTROL NAME", "STATUS", "DOCS"}, - expectedAlignments: []int{tablewriter.ALIGN_LEFT, tablewriter.ALIGN_CENTER, tablewriter.ALIGN_CENTER}, + expectedHeaders: []string{"", "CONTROL NAME", "DOCS"}, + expectedAlignments: []int{tablewriter.ALIGN_CENTER, tablewriter.ALIGN_LEFT, tablewriter.ALIGN_CENTER}, }, } for _, tt := range tests { @@ -53,12 +53,12 @@ func TestGetCategoryStatusTypeHeaders(t *testing.T) { t.Errorf("Expected 3 headers, got %d", len(headers)) } - if headers[0] != controlNameHeader { - t.Errorf("Expected %s, got %s", controlNameHeader, headers[0]) + if headers[0] != statusHeader { + t.Errorf("Expected %s, got %s", statusHeader, headers[0]) } - if headers[1] != statusHeader { - t.Errorf("Expected %s, got %s", statusHeader, headers[1]) + if headers[1] != controlNameHeader { + t.Errorf("Expected %s, got %s", controlNameHeader, headers[1]) } if headers[2] != docsHeader { @@ -93,12 +93,12 @@ func TestGetStatusTypeAlignments(t *testing.T) { t.Errorf("Expected 3 alignments, got %d", len(alignments)) } - if alignments[0] != tablewriter.ALIGN_LEFT { - t.Errorf("Expected %d, got %d", tablewriter.ALIGN_LEFT, alignments[0]) + if alignments[0] != tablewriter.ALIGN_CENTER { + t.Errorf("Expected %d, got %d", tablewriter.ALIGN_CENTER, alignments[0]) } - if alignments[1] != tablewriter.ALIGN_CENTER { - t.Errorf("Expected %d, got %d", tablewriter.ALIGN_CENTER, alignments[1]) + if alignments[1] != tablewriter.ALIGN_LEFT { + t.Errorf("Expected %d, got %d", tablewriter.ALIGN_LEFT, alignments[1]) } if alignments[2] != tablewriter.ALIGN_CENTER { @@ -140,7 +140,7 @@ func TestGenerateCategoryStatusRow(t *testing.T) { Status: apis.StatusFailed, ControlID: "ctrlID", }, - expectedRows: []string{"test", "failed", "https://hub.armosec.io/docs/ctrlid"}, + expectedRows: []string{"❌", "test", "https://hub.armosec.io/docs/ctrlid"}, }, { name: "skipped control", @@ -152,7 +152,7 @@ func TestGenerateCategoryStatusRow(t *testing.T) { }, ControlID: "ctrlID", }, - expectedRows: []string{"test", "action required *", "https://hub.armosec.io/docs/ctrlid"}, + expectedRows: []string{"⚠️", "test", "https://hub.armosec.io/docs/ctrlid"}, infoToPrintInfo: []utils.InfoStars{ { Info: "testInfo", @@ -167,7 +167,7 @@ func TestGenerateCategoryStatusRow(t *testing.T) { Status: apis.StatusPassed, ControlID: "ctrlID", }, - expectedRows: []string{"test", "passed", "https://hub.armosec.io/docs/ctrlid"}, + expectedRows: []string{"✅", "test", "https://hub.armosec.io/docs/ctrlid"}, }, { name: "big name", @@ -176,7 +176,7 @@ func TestGenerateCategoryStatusRow(t *testing.T) { Status: apis.StatusFailed, ControlID: "ctrlID", }, - expectedRows: []string{"testtesttesttesttesttesttesttesttesttesttesttestte...", "failed", "https://hub.armosec.io/docs/ctrlid"}, + expectedRows: []string{"❌", "testtesttesttesttesttesttesttesttesttesttesttestte...", "https://hub.armosec.io/docs/ctrlid"}, }, } diff --git a/core/pkg/resultshandling/printer/v2/prettyprinter/tableprinter/configurationprinter/workloadscan.go b/core/pkg/resultshandling/printer/v2/prettyprinter/tableprinter/configurationprinter/workloadscan.go index fe6596e0..35cee54b 100644 --- a/core/pkg/resultshandling/printer/v2/prettyprinter/tableprinter/configurationprinter/workloadscan.go +++ b/core/pkg/resultshandling/printer/v2/prettyprinter/tableprinter/configurationprinter/workloadscan.go @@ -60,16 +60,3 @@ func (wp *WorkloadPrinter) renderSingleCategoryTable(categoryName string, catego func (wp *WorkloadPrinter) initCategoryTableData() ([]string, []int) { return getCategoryStatusTypeHeaders(), getStatusTypeAlignments() } - -func (wp *WorkloadPrinter) generateCountingCategoryRow(controlSummary reportsummary.IControlSummary, infoToPrintInfo []utils.InfoStars) []string { - - row := make([]string, 3) - - row[0] = controlSummary.GetName() - - row[1] = getStatus(controlSummary.GetStatus(), controlSummary, infoToPrintInfo) - - row[2] = getDocsForControl(controlSummary) - - return row -} diff --git a/core/pkg/resultshandling/printer/v2/prettyprinter/tableprinter/configurationprinter/workloadscan_test.go b/core/pkg/resultshandling/printer/v2/prettyprinter/tableprinter/configurationprinter/workloadscan_test.go index 37d99304..ccf10deb 100644 --- a/core/pkg/resultshandling/printer/v2/prettyprinter/tableprinter/configurationprinter/workloadscan_test.go +++ b/core/pkg/resultshandling/printer/v2/prettyprinter/tableprinter/configurationprinter/workloadscan_test.go @@ -1,20 +1,15 @@ package configurationprinter import ( - "reflect" "testing" - "github.com/kubescape/kubescape/v2/core/pkg/resultshandling/printer/v2/prettyprinter/tableprinter/utils" - "github.com/kubescape/opa-utils/reporthandling/apis" - "github.com/kubescape/opa-utils/reporthandling/results/v1/reportsummary" "github.com/olekukonko/tablewriter" - "github.com/stretchr/testify/assert" ) func TestWorkloadScan_InitCategoryTableData(t *testing.T) { - expectedHeader := []string{"CONTROL NAME", "STATUS", "DOCS"} - expectedAlign := []int{tablewriter.ALIGN_LEFT, tablewriter.ALIGN_CENTER, tablewriter.ALIGN_CENTER} + expectedHeader := []string{"", "CONTROL NAME", "DOCS"} + expectedAlign := []int{tablewriter.ALIGN_CENTER, tablewriter.ALIGN_LEFT, tablewriter.ALIGN_CENTER} workloadPrinter := NewWorkloadPrinter() @@ -33,85 +28,3 @@ func TestWorkloadScan_InitCategoryTableData(t *testing.T) { } } - -func TestWorkloadScan_GenerateCountingCategoryRow(t *testing.T) { - tests := []struct { - name string - controlSummary reportsummary.IControlSummary - infoToPrint []utils.InfoStars - expectedRows []string - }{ - { - name: "1 failed control", - controlSummary: &reportsummary.ControlSummary{ - StatusInfo: apis.StatusInfo{ - InnerStatus: apis.StatusFailed, - }, - ControlID: "ctrl1", - Name: "ctrl1", - StatusCounters: reportsummary.StatusCounters{ - FailedResources: 1, - }, - }, - expectedRows: []string{"ctrl1", "failed", "https://hub.armosec.io/docs/ctrl1"}, - }, - { - name: "multiple failed controls", - controlSummary: &reportsummary.ControlSummary{ - StatusInfo: apis.StatusInfo{ - InnerStatus: apis.StatusFailed, - }, - ControlID: "ctrl1", - Name: "ctrl1", - StatusCounters: reportsummary.StatusCounters{ - FailedResources: 5, - }, - }, - expectedRows: []string{"ctrl1", "failed", "https://hub.armosec.io/docs/ctrl1"}, - }, - { - name: "no failed controls", - controlSummary: &reportsummary.ControlSummary{ - StatusInfo: apis.StatusInfo{ - InnerStatus: apis.StatusPassed, - }, - ControlID: "ctrl1", - Name: "ctrl1", - StatusCounters: reportsummary.StatusCounters{ - FailedResources: 0, - }, - }, - expectedRows: []string{"ctrl1", "passed", "https://hub.armosec.io/docs/ctrl1"}, - }, - { - name: "action required", - infoToPrint: []utils.InfoStars{ - { - Info: "action required", - Stars: "*", - }, - }, - controlSummary: &reportsummary.ControlSummary{ - ControlID: "ctrl1", - StatusInfo: apis.StatusInfo{ - InnerStatus: apis.StatusSkipped, - InnerInfo: "action required", - }, - Name: "ctrl1", - StatusCounters: reportsummary.StatusCounters{ - SkippedResources: 1, - }, - }, - expectedRows: []string{"ctrl1", "action required *", "https://hub.armosec.io/docs/ctrl1"}, - }, - } - - workloadPrinter := NewWorkloadPrinter() - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - row := workloadPrinter.generateCountingCategoryRow(tt.controlSummary, tt.infoToPrint) - assert.True(t, reflect.DeepEqual(row, tt.expectedRows)) - }) - } -} diff --git a/core/pkg/resultshandling/printer/v2/prettyprinter/tableprinter/imageprinter/utils.go b/core/pkg/resultshandling/printer/v2/prettyprinter/tableprinter/imageprinter/utils.go index e14cd397..e9fed4aa 100644 --- a/core/pkg/resultshandling/printer/v2/prettyprinter/tableprinter/imageprinter/utils.go +++ b/core/pkg/resultshandling/printer/v2/prettyprinter/tableprinter/imageprinter/utils.go @@ -64,7 +64,7 @@ func generateRow(cve CVE) []string { func getImageScanningHeaders() []string { headers := make([]string, 5) headers[imageColumnSeverity] = "SEVERITY" - headers[imageColumnName] = "NAME" + headers[imageColumnName] = "VULNERABILITY" headers[imageColumnComponent] = "COMPONENT" headers[imageColumnVersion] = "VERSION" headers[imageColumnFixedIn] = "FIXED IN" diff --git a/core/pkg/resultshandling/printer/v2/prettyprinter/tableprinter/imageprinter/utils_test.go b/core/pkg/resultshandling/printer/v2/prettyprinter/tableprinter/imageprinter/utils_test.go index ecb92e0c..c23b9424 100644 --- a/core/pkg/resultshandling/printer/v2/prettyprinter/tableprinter/imageprinter/utils_test.go +++ b/core/pkg/resultshandling/printer/v2/prettyprinter/tableprinter/imageprinter/utils_test.go @@ -140,7 +140,7 @@ func TestGenerateRow(t *testing.T) { func TestGetImageScanningHeaders(t *testing.T) { headers := getImageScanningHeaders() - expectedHeaders := []string{"SEVERITY", "NAME", "COMPONENT", "VERSION", "FIXED IN"} + expectedHeaders := []string{"SEVERITY", "VULNERABILITY", "COMPONENT", "VERSION", "FIXED IN"} for i := range headers { if headers[i] != expectedHeaders[i] { diff --git a/core/pkg/resultshandling/printer/v2/prettyprinter/tableprinter/utils/utils.go b/core/pkg/resultshandling/printer/v2/prettyprinter/tableprinter/utils/utils.go index 2513f216..4d24dc4f 100644 --- a/core/pkg/resultshandling/printer/v2/prettyprinter/tableprinter/utils/utils.go +++ b/core/pkg/resultshandling/printer/v2/prettyprinter/tableprinter/utils/utils.go @@ -125,18 +125,16 @@ func GetStatusColor(status apis.ScanningStatus) func(...string) string { } } -func getColor(controlSeverity int) func(...string) string { - switch controlSeverity { - case apis.SeverityCritical: - return gchalk.WithAnsi256(1).Bold - case apis.SeverityHigh: - return gchalk.WithAnsi256(196).Bold - case apis.SeverityMedium: - return gchalk.WithAnsi256(166).Bold - case apis.SeverityLow: - return gchalk.WithAnsi256(220).Bold +func GetStatusIcon(status apis.ScanningStatus) string { + switch status { + case apis.StatusPassed: + return "✅" + case apis.StatusFailed: + return "❌" + case apis.StatusSkipped: + return "⚠️" default: - return gchalk.WithAnsi256(16).Bold + return "⚠️" } } diff --git a/core/pkg/resultshandling/printer/v2/prettyprinter/utils.go b/core/pkg/resultshandling/printer/v2/prettyprinter/utils.go index b81b6165..c52adaac 100644 --- a/core/pkg/resultshandling/printer/v2/prettyprinter/utils.go +++ b/core/pkg/resultshandling/printer/v2/prettyprinter/utils.go @@ -203,11 +203,15 @@ func printImageScanningSummary(writer *os.File, summary imageprinter.ImageScanSu }) if len(summary.CVEs) == 0 { - cautils.InfoTextDisplay(writer, "Vulnerability summary - no vulnerabilities were found!\n\n") + txt := "Vulnerability summary - no vulnerabilities were found!" + cautils.InfoTextDisplay(writer, txt+"\n") + cautils.SimpleDisplay(writer, strings.Repeat("─", len(txt))+"\n") return } - cautils.InfoTextDisplay(writer, "Vulnerability summary - %d vulnerabilities found:\n", len(summary.CVEs)) + txt := fmt.Sprintf("Vulnerability summary - %d vulnerabilities found:", len(summary.CVEs)) + cautils.InfoTextDisplay(writer, txt+"\n") + cautils.SimpleDisplay(writer, strings.Repeat("─", len(txt))+"\n") if len(summary.Images) == 1 { cautils.SimpleDisplay(writer, "Image: %s\n", summary.Images[0]) @@ -238,7 +242,7 @@ func printNextSteps(writer *os.File, nextSteps []string, addLine bool) { txt := "What now?" cautils.InfoTextDisplay(writer, fmt.Sprintf("%s\n", txt)) - cautils.SimpleDisplay(writer, fmt.Sprintf("%s\n\n", strings.Repeat("─", len(txt)))) + cautils.SimpleDisplay(writer, fmt.Sprintf("%s\n", strings.Repeat("─", len(txt)))) for _, ns := range nextSteps { cautils.SimpleDisplay(writer, "* "+ns+"\n") @@ -252,7 +256,7 @@ func printComplianceScore(writer *os.File, frameworks []reportsummary.IFramework txt := "Compliance Score" cautils.InfoTextDisplay(writer, fmt.Sprintf("%s\n", txt)) - cautils.SimpleDisplay(writer, fmt.Sprintf("%s\n\n", strings.Repeat("─", len(txt)))) + cautils.SimpleDisplay(writer, fmt.Sprintf("%s\n", strings.Repeat("─", len(txt)))) cautils.SimpleDisplay(writer, "The compliance score is calculated by multiplying control failures by the number of failures against supported compliance frameworks. Remediate controls, or configure your cluster baseline with exceptions, to improve this score.\n\n") @@ -260,7 +264,7 @@ func printComplianceScore(writer *os.File, frameworks []reportsummary.IFramework cautils.SimpleDisplay(writer, "* %s: %s", fw.GetName(), gchalk.WithYellow().Bold(fmt.Sprintf("%.2f%%\n", fw.GetComplianceScore()))) } - cautils.SimpleDisplay(writer, fmt.Sprintf("\nView a full compliance report by running %s or %s\n", getCallToActionString("'$ kubescape scan framework nsa'"), getCallToActionString("'$ kubescape scan framework mitre'"))) + cautils.SimpleDisplay(writer, fmt.Sprintf("\nView a full compliance report by running %s or %s\n", getCallToActionString("'$ kubescape scan framework nsa'"), getCallToActionString("'$ kubescape scan framework mitre'"))) cautils.InfoTextDisplay(writer, "\n") } diff --git a/core/pkg/resultshandling/printer/v2/utils.go b/core/pkg/resultshandling/printer/v2/utils.go index 9e241286..c03fa409 100644 --- a/core/pkg/resultshandling/printer/v2/utils.go +++ b/core/pkg/resultshandling/printer/v2/utils.go @@ -14,6 +14,8 @@ import ( reporthandlingv2 "github.com/kubescape/opa-utils/reporthandling/v2" ) +const indicator = "†" + // finalizeV2Report finalize the results objects by copying data from map to lists func FinalizeResults(data *cautils.OPASessionObj) *reporthandlingv2.PostureReport { report := reporthandlingv2.PostureReport{ @@ -57,7 +59,7 @@ type infoStars struct { func mapInfoToPrintInfo(controls reportsummary.ControlSummaries) []infoStars { infoToPrintInfo := []infoStars{} infoToPrintInfoMap := map[string]interface{}{} - starCount := "*" + starCount := indicator for _, control := range controls { if control.GetStatus().IsSkipped() && control.GetStatus().Info() != "" { if _, ok := infoToPrintInfoMap[control.GetStatus().Info()]; !ok { @@ -65,7 +67,7 @@ func mapInfoToPrintInfo(controls reportsummary.ControlSummaries) []infoStars { info: control.GetStatus().Info(), stars: starCount, }) - starCount += "*" + starCount += indicator infoToPrintInfoMap[control.GetStatus().Info()] = nil } } diff --git a/core/pkg/resultshandling/reporter/v2/reporteventreceiver.go b/core/pkg/resultshandling/reporter/v2/reporteventreceiver.go index 636030c3..daa2fcde 100644 --- a/core/pkg/resultshandling/reporter/v2/reporteventreceiver.go +++ b/core/pkg/resultshandling/reporter/v2/reporteventreceiver.go @@ -259,7 +259,7 @@ func (report *ReportEventReceiver) sendReport(host string, postureReport *report } func (report *ReportEventReceiver) setMessage(message string) { - report.message = "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + message + report.message = message } func (report *ReportEventReceiver) DisplayMessage() { @@ -271,6 +271,6 @@ func (report *ReportEventReceiver) DisplayMessage() { cautils.SimpleDisplay(os.Stderr, strings.Repeat("─", len(txt))) - cautils.SimpleDisplay(os.Stderr, fmt.Sprintf("\n\n%s\n\n", report.message)) + cautils.SimpleDisplay(os.Stderr, fmt.Sprintf("\n%s\n\n", report.message)) } } diff --git a/go.mod b/go.mod index d3f01c13..4ac27d42 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,7 @@ require ( github.com/kubescape/backend v0.0.0-20230820141235-28748e7aad2a github.com/kubescape/go-git-url v0.0.25 github.com/kubescape/go-logger v0.0.20 - github.com/kubescape/k8s-interface v0.0.138 + github.com/kubescape/k8s-interface v0.0.141 github.com/kubescape/opa-utils v0.0.267 github.com/kubescape/rbac-utils v0.0.21-0.20230806101615-07e36f555520 github.com/kubescape/regolibrary v1.0.291-rc.0 diff --git a/go.sum b/go.sum index 06f7f6cc..7a3335ab 100644 --- a/go.sum +++ b/go.sum @@ -1292,8 +1292,8 @@ github.com/kubescape/go-git-url v0.0.25 h1:i7SSSC1+1m/Dg+4LV3erp0YklnWj1Z0cVlRxC github.com/kubescape/go-git-url v0.0.25/go.mod h1:IbVT7Wsxlghsa+YxI5KOx4k9VQJaa3z0kTaQz5D3nKM= github.com/kubescape/go-logger v0.0.20 h1:ZU3T6Za7maCiChdoTrqpD6TI11DGJwd9xU/TFtRlMOI= github.com/kubescape/go-logger v0.0.20/go.mod h1:BAWhQMYc/gnC5wMtPvc9Z4VXFqykFFMaXaPkq0+txBY= -github.com/kubescape/k8s-interface v0.0.138 h1:JjqLExOQiV1iG6jDLVQ/KpPzH8T9U7jQOtpUe5frF2o= -github.com/kubescape/k8s-interface v0.0.138/go.mod h1:5sz+5Cjvo98lTbTVDiDA4MmlXxeHSVMW/wR0V3hV4K8= +github.com/kubescape/k8s-interface v0.0.141 h1:CQcK3PZsSeDFVmlvyHya48NJihGe7Qc+3kEWsmc4KnA= +github.com/kubescape/k8s-interface v0.0.141/go.mod h1:5sz+5Cjvo98lTbTVDiDA4MmlXxeHSVMW/wR0V3hV4K8= github.com/kubescape/opa-utils v0.0.267 h1:qzINBGsVOTKeLAIj1YfaYdV93FsSRriWdiN0JXJwD/o= github.com/kubescape/opa-utils v0.0.267/go.mod h1:95JkuIOfClgLc+DyGb2mDvefRW0STkZe4L2z6AaZJlQ= github.com/kubescape/rbac-utils v0.0.21-0.20230806101615-07e36f555520 h1:SqlwF8G+oFazeYmZQKoPczLEflBQpwpHCU8DoLLyfj8= diff --git a/httphandler/go.mod b/httphandler/go.mod index 99d2c5b2..6a8a6757 100644 --- a/httphandler/go.mod +++ b/httphandler/go.mod @@ -11,7 +11,7 @@ require ( github.com/gorilla/mux v1.8.0 github.com/gorilla/schema v1.2.0 github.com/kubescape/go-logger v0.0.20 - github.com/kubescape/k8s-interface v0.0.138 + github.com/kubescape/k8s-interface v0.0.141 github.com/kubescape/kubescape/v2 v2.0.0-00010101000000-000000000000 github.com/kubescape/opa-utils v0.0.267 github.com/stretchr/testify v1.8.4 diff --git a/httphandler/go.sum b/httphandler/go.sum index 4b105eb6..4545c856 100644 --- a/httphandler/go.sum +++ b/httphandler/go.sum @@ -1296,8 +1296,8 @@ github.com/kubescape/go-git-url v0.0.25 h1:i7SSSC1+1m/Dg+4LV3erp0YklnWj1Z0cVlRxC github.com/kubescape/go-git-url v0.0.25/go.mod h1:IbVT7Wsxlghsa+YxI5KOx4k9VQJaa3z0kTaQz5D3nKM= github.com/kubescape/go-logger v0.0.20 h1:ZU3T6Za7maCiChdoTrqpD6TI11DGJwd9xU/TFtRlMOI= github.com/kubescape/go-logger v0.0.20/go.mod h1:BAWhQMYc/gnC5wMtPvc9Z4VXFqykFFMaXaPkq0+txBY= -github.com/kubescape/k8s-interface v0.0.138 h1:JjqLExOQiV1iG6jDLVQ/KpPzH8T9U7jQOtpUe5frF2o= -github.com/kubescape/k8s-interface v0.0.138/go.mod h1:5sz+5Cjvo98lTbTVDiDA4MmlXxeHSVMW/wR0V3hV4K8= +github.com/kubescape/k8s-interface v0.0.141 h1:CQcK3PZsSeDFVmlvyHya48NJihGe7Qc+3kEWsmc4KnA= +github.com/kubescape/k8s-interface v0.0.141/go.mod h1:5sz+5Cjvo98lTbTVDiDA4MmlXxeHSVMW/wR0V3hV4K8= github.com/kubescape/opa-utils v0.0.267 h1:qzINBGsVOTKeLAIj1YfaYdV93FsSRriWdiN0JXJwD/o= github.com/kubescape/opa-utils v0.0.267/go.mod h1:95JkuIOfClgLc+DyGb2mDvefRW0STkZe4L2z6AaZJlQ= github.com/kubescape/rbac-utils v0.0.21-0.20230806101615-07e36f555520 h1:SqlwF8G+oFazeYmZQKoPczLEflBQpwpHCU8DoLLyfj8=