From c085aeaa68646f73a86a9c7827f8b87c7b4be61d Mon Sep 17 00:00:00 2001 From: dwertent Date: Mon, 20 Dec 2021 10:53:40 +0200 Subject: [PATCH 1/7] adding control url to results --- resultshandling/printer/prettyprinter.go | 6 +++++- resultshandling/printer/summary.go | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/resultshandling/printer/prettyprinter.go b/resultshandling/printer/prettyprinter.go index 02148df7..4903116b 100644 --- a/resultshandling/printer/prettyprinter.go +++ b/resultshandling/printer/prettyprinter.go @@ -81,6 +81,7 @@ func (printer *PrettyPrinter) summarySetup(fr reporthandling.FrameworkReport, al //controlSummary printer.summary[cr.Name] = ResultSummary{ + ID: cr.ControlID, RiskScore: cr.Score, TotalResources: cr.GetNumberOfResources(), TotalFailed: cr.GetNumberOfFailedResources(), @@ -121,8 +122,11 @@ func (printer *PrettyPrinter) printSummary(controlName string, controlSummary *R } +func getControlURL(controlID string) string { + return fmt.Sprintf("https://hub.armo.cloud/docs/%s", controlID) +} func (printer *PrettyPrinter) printTitle(controlName string, controlSummary *ResultSummary) { - cautils.InfoDisplay(printer.writer, "[control: %s] ", controlName) + cautils.InfoDisplay(printer.writer, "[control: %s - %s] ", controlName, getControlURL(controlSummary.ID)) if controlSummary.TotalResources == 0 { cautils.InfoDisplay(printer.writer, "resources not found %v\n", emoji.ConfusedFace) } else if controlSummary.TotalFailed != 0 { diff --git a/resultshandling/printer/summary.go b/resultshandling/printer/summary.go index 696ad406..d91b2a11 100644 --- a/resultshandling/printer/summary.go +++ b/resultshandling/printer/summary.go @@ -14,6 +14,7 @@ func NewSummary() Summary { } type ResultSummary struct { + ID string RiskScore float32 TotalResources int TotalFailed int From 14d0df3926604af95fdda6c140736f744a5cd506 Mon Sep 17 00:00:00 2001 From: dwertent Date: Mon, 20 Dec 2021 11:11:31 +0200 Subject: [PATCH 2/7] update generated url --- resultshandling/reporter/mockreporter.go | 2 +- resultshandling/reporter/reporteventreceiver.go | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/resultshandling/reporter/mockreporter.go b/resultshandling/reporter/mockreporter.go index 6c4dc6a1..22983fef 100644 --- a/resultshandling/reporter/mockreporter.go +++ b/resultshandling/reporter/mockreporter.go @@ -25,6 +25,6 @@ func (reportMock *ReportMock) SetClusterName(clusterName string) { } func (reportMock *ReportMock) DisplayReportURL() { - message := fmt.Sprintf("\nYou can see the results in a user-friendly UI, choose your preferred compliance framework, check risk results history and trends, manage exceptions, get remediation recommendations and much more by registering here: https://%s\n", getter.GetArmoAPIConnector().GetFrontendURL()) + message := fmt.Sprintf("\nYou can see the results in a user-friendly UI, choose your preferred compliance framework, check risk results history and trends, manage exceptions, get remediation recommendations and much more by registering here: https://%s/cli-signup \n", getter.GetArmoAPIConnector().GetFrontendURL()) cautils.InfoTextDisplay(os.Stdout, fmt.Sprintf("\n%s\n", message)) } diff --git a/resultshandling/reporter/reporteventreceiver.go b/resultshandling/reporter/reporteventreceiver.go index 05ef1fe9..a08e5485 100644 --- a/resultshandling/reporter/reporteventreceiver.go +++ b/resultshandling/reporter/reporteventreceiver.go @@ -116,14 +116,14 @@ func (report *ReportEventReceiver) sendReport(host string, postureReport *report } func (report *ReportEventReceiver) DisplayReportURL() { - message := "You can see the results in a user-friendly UI, choose your preferred compliance framework, check risk results history and trends, manage exceptions, get remediation recommendations and much more by registering here: " + message := "You can see the results in a user-friendly UI, choose your preferred compliance framework, check risk results history and trends, manage exceptions, get remediation recommendations and much more by registering here:" u := url.URL{} u.Scheme = "https" u.Host = getter.GetArmoAPIConnector().GetFrontendURL() if report.customerAdminEMail != "" { - cautils.InfoTextDisplay(os.Stdout, "\n\n"+message+u.String()+"\n\n") + cautils.InfoTextDisplay(os.Stdout, fmt.Sprintf("\n\n%s %s/risk/%s\n\n", message, u.String(), report.clusterName)) return } u.Path = "account/sign-up" @@ -132,5 +132,5 @@ func (report *ReportEventReceiver) DisplayReportURL() { q.Add("customerGUID", report.customerGUID) u.RawQuery = q.Encode() - cautils.InfoTextDisplay(os.Stdout, "\n\n"+message+u.String()+"\n\n") + cautils.InfoTextDisplay(os.Stdout, fmt.Sprintf("\n\n%s %s\n\n", message, u.String())) } From a10c67555da2d780aba6946d402d6af149278081 Mon Sep 17 00:00:00 2001 From: dwertent Date: Mon, 20 Dec 2021 11:14:31 +0200 Subject: [PATCH 3/7] adding spinner when sending reporting --- go.mod | 2 +- go.sum | 4 ++-- resultshandling/reporter/reporteventreceiver.go | 3 +++ 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 4f903f82..2402dc06 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/armosec/opa-utils v0.0.68 github.com/armosec/rbac-utils v0.0.9 github.com/armosec/utils-go v0.0.3 - github.com/briandowns/spinner v1.16.0 + github.com/briandowns/spinner v1.18.0 github.com/enescakir/emoji v1.0.0 github.com/fatih/color v1.13.0 github.com/gofrs/uuid v4.1.0+incompatible diff --git a/go.sum b/go.sum index b12f132f..d42dc8ab 100644 --- a/go.sum +++ b/go.sum @@ -118,8 +118,8 @@ github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqO github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= -github.com/briandowns/spinner v1.16.0 h1:DFmp6hEaIx2QXXuqSJmtfSBSAjRmpGiKG6ip2Wm/yOs= -github.com/briandowns/spinner v1.16.0/go.mod h1:QOuQk7x+EaDASo80FEXwlwiA+j/PPIcX3FScO+3/ZPQ= +github.com/briandowns/spinner v1.18.0 h1:SJs0maNOs4FqhBwiJ3Gr7Z1D39/rukIVGQvpNZVHVcM= +github.com/briandowns/spinner v1.18.0/go.mod h1:QOuQk7x+EaDASo80FEXwlwiA+j/PPIcX3FScO+3/ZPQ= github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= github.com/bytecodealliance/wasmtime-go v0.30.0 h1:WfYpr4WdqInt8m5/HvYinf+HrSEAIhItKIcth+qb1h4= github.com/bytecodealliance/wasmtime-go v0.30.0/go.mod h1:q320gUxqyI8yB+ZqRuaJOEnGkAnHh6WtJjMaT2CW4wI= diff --git a/resultshandling/reporter/reporteventreceiver.go b/resultshandling/reporter/reporteventreceiver.go index a08e5485..979b3b84 100644 --- a/resultshandling/reporter/reporteventreceiver.go +++ b/resultshandling/reporter/reporteventreceiver.go @@ -61,6 +61,9 @@ func (report *ReportEventReceiver) prepareReport(postureReport *reporthandling.P report.initEventReceiverURL() host := hostToString(report.eventReceiverURL, postureReport.ReportID) + cautils.StartSpinner() + defer cautils.StopSpinner() + // send framework results if err := report.sendReport(host, postureReport); err != nil { return err From f57a30898c6ef9f74210bd9889c31a1e5d24f1ba Mon Sep 17 00:00:00 2001 From: dwertent Date: Mon, 20 Dec 2021 13:32:14 +0200 Subject: [PATCH 4/7] print skipped --- resultshandling/printer/prettyprinter.go | 52 ++++++++++++++----- .../reporter/reporteventreceiver.go | 2 +- 2 files changed, 40 insertions(+), 14 deletions(-) diff --git a/resultshandling/printer/prettyprinter.go b/resultshandling/printer/prettyprinter.go index 4903116b..9148358c 100644 --- a/resultshandling/printer/prettyprinter.go +++ b/resultshandling/printer/prettyprinter.go @@ -128,7 +128,7 @@ func getControlURL(controlID string) string { func (printer *PrettyPrinter) printTitle(controlName string, controlSummary *ResultSummary) { cautils.InfoDisplay(printer.writer, "[control: %s - %s] ", controlName, getControlURL(controlSummary.ID)) if controlSummary.TotalResources == 0 { - cautils.InfoDisplay(printer.writer, "resources not found %v\n", emoji.ConfusedFace) + cautils.InfoDisplay(printer.writer, "skipped %v\n", emoji.ConfusedFace) } else if controlSummary.TotalFailed != 0 { cautils.FailureDisplay(printer.writer, "failed %v\n", emoji.SadButRelievedFace) } else if controlSummary.TotalWarning != 0 { @@ -172,6 +172,23 @@ func (printer *PrettyPrinter) printGroupedResources(workloads map[string][]Workl } } +// func (printer *PrettyPrinter) printGroupedResources(workloads map[string][]WorkloadSummary) { +// indent := INDENT +// for ns, rsc := range workloads { +// printer.printGroupedResource(indent, ns, rsc) +// } +// // for ns, rsc := range workloads { +// // if !isKindToBeGrouped(ns) { +// // } +// // } +// // if rsc, ok := workloads["User"]; ok { +// // printer.printGroupedResource(indent, "User", rsc) +// // } +// // if rsc, ok := workloads["Group"]; ok { +// // printer.printGroupedResource(indent, "Group", rsc) +// // } +// } + func (printer *PrettyPrinter) printGroupedResource(indent string, ns string, rsc []WorkloadSummary) { preIndent := indent if isKindToBeGrouped(ns) { @@ -189,6 +206,25 @@ func (printer *PrettyPrinter) printGroupedResource(indent string, ns string, rsc indent = preIndent } +// func (printer *PrettyPrinter) printGroupedResource(indent string, ns string, rsc []WorkloadSummary) { +// preIndent := indent + +// cautils.SimpleDisplay(printer.writer, "%s%s %s\n", indent, rsc[0].groupBy, ns) +// // if isKindToBeGrouped(ns) { +// // cautils.SimpleDisplay(printer.writer, "%s%ss\n", indent, ns) +// // } else if ns != "" { +// // cautils.SimpleDisplay(printer.writer, "%sNamespace %s\n", indent, ns) +// // } +// preIndent2 := indent +// for r := range rsc { +// indent += indent +// relatedObjectsStr := generateRelatedObjectsStr(rsc[r]) +// cautils.SimpleDisplay(printer.writer, fmt.Sprintf("%s%s - %s %s\n", indent, rsc[r].resource.GetKind(), rsc[r].resource.GetName(), relatedObjectsStr)) +// indent = preIndent2 +// } +// indent = preIndent +// } + func generateRelatedObjectsStr(workload WorkloadSummary) string { relatedStr := "" if workload.resource.GetObjectType() == workloadinterface.TypeWorkloadObject { @@ -210,9 +246,9 @@ func generateRow(control string, cs ResultSummary) []string { row := []string{control} row = append(row, cs.ToSlice()...) if cs.TotalResources != 0 { - row = append(row, fmt.Sprintf("%.2f%s", cs.RiskScore, "%")) + row = append(row, fmt.Sprintf("%d", int(cs.RiskScore))+"%") } else { - row = append(row, EmptyPercentage) + row = append(row, "skipped") } return row } @@ -221,16 +257,6 @@ func generateHeader() []string { return []string{"Control Name", "Failed Resources", "Excluded Resources", "All Resources", "% risk-score"} } -func percentage(big, small int) int { - if big == 0 { - if small == 0 { - return 100 - } - return 0 - } - return int(float64(float64(big-small)/float64(big)) * 100) -} - func generateFooter(printer *PrettyPrinter) []string { // Control name | # failed resources | all resources | % success row := []string{} diff --git a/resultshandling/reporter/reporteventreceiver.go b/resultshandling/reporter/reporteventreceiver.go index 979b3b84..fc01232d 100644 --- a/resultshandling/reporter/reporteventreceiver.go +++ b/resultshandling/reporter/reporteventreceiver.go @@ -126,7 +126,7 @@ func (report *ReportEventReceiver) DisplayReportURL() { u.Host = getter.GetArmoAPIConnector().GetFrontendURL() if report.customerAdminEMail != "" { - cautils.InfoTextDisplay(os.Stdout, fmt.Sprintf("\n\n%s %s/risk/%s\n\n", message, u.String(), report.clusterName)) + cautils.InfoTextDisplay(os.Stdout, fmt.Sprintf("\n\n%s %s/risk/%s\n(Account: %s)\n\n", message, u.String(), report.clusterName, report.customerGUID)) return } u.Path = "account/sign-up" From 0ef516d147c72f1173597284c1510c5014ac425d Mon Sep 17 00:00:00 2001 From: dwertent Date: Mon, 20 Dec 2021 18:22:08 +0200 Subject: [PATCH 5/7] support printing sensor and cloud resources --- go.mod | 4 +- go.sum | 9 ++- opaprocessor/processorhandlerutils.go | 2 +- opaprocessor/processorhandlerutils_test.go | 3 + policyhandler/handlenotification.go | 1 - resourcehandler/filesloader.go | 2 +- resourcehandler/k8sresources.go | 4 ++ resultshandling/printer/prettyprinter.go | 72 ++++------------------ resultshandling/printer/printresults.go | 2 - resultshandling/printer/summeryhelpers.go | 45 ++++++++++---- 10 files changed, 62 insertions(+), 82 deletions(-) diff --git a/go.mod b/go.mod index 2402dc06..f73c5e18 100644 --- a/go.mod +++ b/go.mod @@ -4,8 +4,8 @@ go 1.17 require ( github.com/armosec/armoapi-go v0.0.23 - github.com/armosec/k8s-interface v0.0.44 - github.com/armosec/opa-utils v0.0.68 + github.com/armosec/k8s-interface v0.0.46 + github.com/armosec/opa-utils v0.0.72 github.com/armosec/rbac-utils v0.0.9 github.com/armosec/utils-go v0.0.3 github.com/briandowns/spinner v1.18.0 diff --git a/go.sum b/go.sum index d42dc8ab..908604b0 100644 --- a/go.sum +++ b/go.sum @@ -88,12 +88,11 @@ github.com/armosec/armoapi-go v0.0.23 h1:jqoLIWM5CR7DCD9fpFgN0ePqtHvOCoZv/XzCwsU github.com/armosec/armoapi-go v0.0.23/go.mod h1:iaVVGyc23QGGzAdv4n+szGQg3Rbpixn9yQTU3qWRpaw= github.com/armosec/k8s-interface v0.0.8/go.mod h1:xxS+V5QT3gVQTwZyAMMDrYLWGrfKOpiJ7Jfhfa0w9sM= github.com/armosec/k8s-interface v0.0.37/go.mod h1:vHxGWqD/uh6+GQb9Sqv7OGMs+Rvc2dsFVc0XtgRh1ZU= -github.com/armosec/k8s-interface v0.0.43/go.mod h1:vHxGWqD/uh6+GQb9Sqv7OGMs+Rvc2dsFVc0XtgRh1ZU= -github.com/armosec/k8s-interface v0.0.44 h1:UsmVPo0GyyBuTVIP+F8rgHpEaZqQE7sUYjj1DT3kHmc= -github.com/armosec/k8s-interface v0.0.44/go.mod h1:vHxGWqD/uh6+GQb9Sqv7OGMs+Rvc2dsFVc0XtgRh1ZU= +github.com/armosec/k8s-interface v0.0.46 h1:qfCGWtbDCRQg8le2K1OveL94Y3dvGuamHmIJZ61+qqs= +github.com/armosec/k8s-interface v0.0.46/go.mod h1:vHxGWqD/uh6+GQb9Sqv7OGMs+Rvc2dsFVc0XtgRh1ZU= github.com/armosec/opa-utils v0.0.64/go.mod h1:6tQP8UDq2EvEfSqh8vrUdr/9QVSCG4sJfju1SXQOn4c= -github.com/armosec/opa-utils v0.0.68 h1:qsmDjEVPdfJ6+hlSeoBZF5sgeR63HdtPfpVQIg0r1G0= -github.com/armosec/opa-utils v0.0.68/go.mod h1:NVJEQ7695VyylqC7dHw2nD7MHIGJrRIXLgyej1onF64= +github.com/armosec/opa-utils v0.0.72 h1:YaaHIafNwsTD28Adr+PblauChX3YDfnP1LJUmpt3kIU= +github.com/armosec/opa-utils v0.0.72/go.mod h1:+5zC2LGTA5ibp1NDi9niwnA6jYSsE/Pb9M5u4M11dV0= github.com/armosec/rbac-utils v0.0.1/go.mod h1:pQ8CBiij8kSKV7aeZm9FMvtZN28VgA7LZcYyTWimq40= github.com/armosec/rbac-utils v0.0.9 h1:rIOWp4K7BELUNX32ktSjVbb8d/0SpH7W76W6Tf+8rzw= github.com/armosec/rbac-utils v0.0.9/go.mod h1:Ex/IdGWhGv9HZq6Hs8N/ApzCKSIvpNe/ETqDfnuyah0= diff --git a/opaprocessor/processorhandlerutils.go b/opaprocessor/processorhandlerutils.go index 2bdb65e8..beb2c208 100644 --- a/opaprocessor/processorhandlerutils.go +++ b/opaprocessor/processorhandlerutils.go @@ -107,7 +107,7 @@ func isRuleKubescapeVersionCompatible(rule *reporthandling.PolicyRule) bool { } func removeData(obj workloadinterface.IMetadata) { - if !workloadinterface.IsTypeWorkload(obj.GetObject()) { + if !k8sinterface.IsTypeWorkload(obj.GetObject()) { return // remove data only from kubernetes objects } workload := workloadinterface.NewWorkloadObj(obj.GetObject()) diff --git a/opaprocessor/processorhandlerutils_test.go b/opaprocessor/processorhandlerutils_test.go index ac1c74a1..3dc82ee2 100644 --- a/opaprocessor/processorhandlerutils_test.go +++ b/opaprocessor/processorhandlerutils_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/armosec/armoapi-go/armotypes" + "github.com/armosec/k8s-interface/k8sinterface" "github.com/armosec/k8s-interface/workloadinterface" "github.com/armosec/kubescape/cautils" "github.com/armosec/opa-utils/reporthandling" @@ -57,6 +58,8 @@ func TestIsRuleKubescapeVersionCompatible(t *testing.T) { } func TestRemoveData(t *testing.T) { + k8sinterface.InitializeMapResourcesMock() + w := `{"apiVersion":"apps/v1","kind":"Deployment","metadata":{"name":"demoservice-server"},"spec":{"replicas":1,"selector":{"matchLabels":{"app":"demoservice-server"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app":"demoservice-server"}},"spec":{"containers":[{"env":[{"name":"SERVER_PORT","value":"8089"},{"name":"SLEEP_DURATION","value":"1"},{"name":"DEMO_FOLDERS","value":"/app"},{"name":"ARMO_TEST_NAME","value":"auto_attach_deployment"},{"name":"CAA_ENABLE_CRASH_REPORTER","value":"1"}],"image":"quay.io/armosec/demoservice:v25","imagePullPolicy":"IfNotPresent","name":"demoservice","ports":[{"containerPort":8089,"protocol":"TCP"}],"resources":{},"terminationMessagePath":"/dev/termination-log","terminationMessagePolicy":"File"}],"dnsPolicy":"ClusterFirst","restartPolicy":"Always","schedulerName":"default-scheduler","securityContext":{},"terminationGracePeriodSeconds":30}}}}` obj, _ := workloadinterface.NewWorkload([]byte(w)) removeData(obj) diff --git a/policyhandler/handlenotification.go b/policyhandler/handlenotification.go index 2c27bdda..be7cf0ab 100644 --- a/policyhandler/handlenotification.go +++ b/policyhandler/handlenotification.go @@ -59,6 +59,5 @@ func (policyHandler *PolicyHandler) getResources(notification *reporthandling.Po opaSessionObj.K8SResources = resourcesMap opaSessionObj.AllResources = allResources - cautils.SuccessTextDisplay("Let’s start!!!") return nil } diff --git a/resourcehandler/filesloader.go b/resourcehandler/filesloader.go index 28cce904..25cc7e74 100644 --- a/resourcehandler/filesloader.go +++ b/resourcehandler/filesloader.go @@ -125,7 +125,7 @@ func mapResources(workloads []workloadinterface.IMetadata) map[string][]workload continue } - if workloadinterface.IsTypeWorkload(workloads[i].GetObject()) { + if k8sinterface.IsTypeWorkload(workloads[i].GetObject()) { w := workloadinterface.NewWorkloadObj(workloads[i].GetObject()) if groupVersionResource.Group != w.GetGroup() || groupVersionResource.Version != w.GetVersion() { // TODO - print warning diff --git a/resourcehandler/k8sresources.go b/resourcehandler/k8sresources.go index 4bcc499f..888e1a60 100644 --- a/resourcehandler/k8sresources.go +++ b/resourcehandler/k8sresources.go @@ -47,6 +47,8 @@ func (k8sHandler *K8sResourceHandler) GetResources(frameworks []reporthandling.F // get k8s resources cautils.ProgressTextDisplay("Accessing Kubernetes objects") + cautils.StartSpinner() + // build resources map // map resources based on framework required resources: map["/group/version/kind"][] k8sResourcesMap := setResourceMap(frameworks) @@ -69,6 +71,8 @@ func (k8sHandler *K8sResourceHandler) GetResources(frameworks []reporthandling.F cautils.WarningDisplay(os.Stdout, fmt.Sprintf("Warning: %v\n", err.Error())) } + cautils.StopSpinner() + cautils.SuccessTextDisplay("Accessed successfully to Kubernetes objects") return k8sResourcesMap, allResources, nil } diff --git a/resultshandling/printer/prettyprinter.go b/resultshandling/printer/prettyprinter.go index 9148358c..b3a2ca36 100644 --- a/resultshandling/printer/prettyprinter.go +++ b/resultshandling/printer/prettyprinter.go @@ -4,6 +4,7 @@ import ( "fmt" "os" "sort" + "strings" "github.com/armosec/k8s-interface/workloadinterface" "github.com/armosec/kubescape/cautils" @@ -121,10 +122,6 @@ func (printer *PrettyPrinter) printSummary(controlName string, controlSummary *R cautils.DescriptionDisplay(printer.writer, "\n") } - -func getControlURL(controlID string) string { - return fmt.Sprintf("https://hub.armo.cloud/docs/%s", controlID) -} func (printer *PrettyPrinter) printTitle(controlName string, controlSummary *ResultSummary) { cautils.InfoDisplay(printer.writer, "[control: %s - %s] ", controlName, getControlURL(controlSummary.ID)) if controlSummary.TotalResources == 0 { @@ -159,72 +156,25 @@ func (printer *PrettyPrinter) printResources(controlSummary *ResultSummary) { func (printer *PrettyPrinter) printGroupedResources(workloads map[string][]WorkloadSummary) { indent := INDENT - for ns, rsc := range workloads { - if !isKindToBeGrouped(ns) { - printer.printGroupedResource(indent, ns, rsc) - } - } - if rsc, ok := workloads["User"]; ok { - printer.printGroupedResource(indent, "User", rsc) - } - if rsc, ok := workloads["Group"]; ok { - printer.printGroupedResource(indent, "Group", rsc) + for title, rsc := range workloads { + printer.printGroupedResource(indent, title, rsc) } } -// func (printer *PrettyPrinter) printGroupedResources(workloads map[string][]WorkloadSummary) { -// indent := INDENT -// for ns, rsc := range workloads { -// printer.printGroupedResource(indent, ns, rsc) -// } -// // for ns, rsc := range workloads { -// // if !isKindToBeGrouped(ns) { -// // } -// // } -// // if rsc, ok := workloads["User"]; ok { -// // printer.printGroupedResource(indent, "User", rsc) -// // } -// // if rsc, ok := workloads["Group"]; ok { -// // printer.printGroupedResource(indent, "Group", rsc) -// // } -// } - -func (printer *PrettyPrinter) printGroupedResource(indent string, ns string, rsc []WorkloadSummary) { +func (printer *PrettyPrinter) printGroupedResource(indent string, title string, rsc []WorkloadSummary) { preIndent := indent - if isKindToBeGrouped(ns) { - cautils.SimpleDisplay(printer.writer, "%s%ss\n", indent, ns) - } else if ns != "" { - cautils.SimpleDisplay(printer.writer, "%sNamespace %s\n", indent, ns) - } - preIndent2 := indent - for r := range rsc { + if title != "" { + cautils.SimpleDisplay(printer.writer, "%s%s\n", indent, title) indent += indent + } + + for r := range rsc { relatedObjectsStr := generateRelatedObjectsStr(rsc[r]) cautils.SimpleDisplay(printer.writer, fmt.Sprintf("%s%s - %s %s\n", indent, rsc[r].resource.GetKind(), rsc[r].resource.GetName(), relatedObjectsStr)) - indent = preIndent2 } indent = preIndent } -// func (printer *PrettyPrinter) printGroupedResource(indent string, ns string, rsc []WorkloadSummary) { -// preIndent := indent - -// cautils.SimpleDisplay(printer.writer, "%s%s %s\n", indent, rsc[0].groupBy, ns) -// // if isKindToBeGrouped(ns) { -// // cautils.SimpleDisplay(printer.writer, "%s%ss\n", indent, ns) -// // } else if ns != "" { -// // cautils.SimpleDisplay(printer.writer, "%sNamespace %s\n", indent, ns) -// // } -// preIndent2 := indent -// for r := range rsc { -// indent += indent -// relatedObjectsStr := generateRelatedObjectsStr(rsc[r]) -// cautils.SimpleDisplay(printer.writer, fmt.Sprintf("%s%s - %s %s\n", indent, rsc[r].resource.GetKind(), rsc[r].resource.GetName(), relatedObjectsStr)) -// indent = preIndent2 -// } -// indent = preIndent -// } - func generateRelatedObjectsStr(workload WorkloadSummary) string { relatedStr := "" if workload.resource.GetObjectType() == workloadinterface.TypeWorkloadObject { @@ -325,3 +275,7 @@ func getWriter(outputFile string) *os.File { return os.Stdout } + +func getControlURL(controlID string) string { + return fmt.Sprintf("https://hub.armo.cloud/docs/%s", strings.ToLower(controlID)) +} diff --git a/resultshandling/printer/printresults.go b/resultshandling/printer/printresults.go index bd82b4ed..5c4a2746 100644 --- a/resultshandling/printer/printresults.go +++ b/resultshandling/printer/printresults.go @@ -6,8 +6,6 @@ import ( var INDENT = " " -const EmptyPercentage = "NaN" - const ( PrettyFormat string = "pretty-printer" JsonFormat string = "json" diff --git a/resultshandling/printer/summeryhelpers.go b/resultshandling/printer/summeryhelpers.go index a2053278..dee39235 100644 --- a/resultshandling/printer/summeryhelpers.go +++ b/resultshandling/printer/summeryhelpers.go @@ -1,7 +1,9 @@ package printer import ( + "github.com/armosec/k8s-interface/k8sinterface" "github.com/armosec/k8s-interface/workloadinterface" + "github.com/armosec/opa-utils/objectsenvelopes" "github.com/armosec/opa-utils/reporthandling" ) @@ -9,19 +11,40 @@ import ( func groupByNamespaceOrKind(resources []WorkloadSummary, status func(workloadSummary *WorkloadSummary) bool) map[string][]WorkloadSummary { mapResources := make(map[string][]WorkloadSummary) for i := range resources { - if status(&resources[i]) { - if isKindToBeGrouped(resources[i].resource.GetKind()) { - if r, ok := mapResources[resources[i].resource.GetKind()]; ok { - r = append(r, resources[i]) - mapResources[resources[i].resource.GetKind()] = r - } else { - mapResources[resources[i].resource.GetKind()] = []WorkloadSummary{resources[i]} - } - } else if r, ok := mapResources[resources[i].resource.GetNamespace()]; ok { + if !status(&resources[i]) { + continue + } + t := resources[i].resource.GetObjectType() + if t == objectsenvelopes.TypeRegoResponseVectorObject && !isKindToBeGrouped(resources[i].resource.GetKind()) { + t = workloadinterface.TypeWorkloadObject + } + switch t { // TODO - find a better way to defind the groups + case workloadinterface.TypeWorkloadObject: + ns := "" + if resources[i].resource.GetNamespace() != "" { + ns = "Namescape " + resources[i].resource.GetNamespace() + } + if r, ok := mapResources[ns]; ok { r = append(r, resources[i]) - mapResources[resources[i].resource.GetNamespace()] = r + mapResources[ns] = r } else { - mapResources[resources[i].resource.GetNamespace()] = []WorkloadSummary{resources[i]} + mapResources[ns] = []WorkloadSummary{resources[i]} + } + case objectsenvelopes.TypeRegoResponseVectorObject: + group := resources[i].resource.GetKind() + "s" + if r, ok := mapResources[group]; ok { + r = append(r, resources[i]) + mapResources[group] = r + } else { + mapResources[group] = []WorkloadSummary{resources[i]} + } + default: + group, _ := k8sinterface.SplitApiVersion(resources[i].resource.GetApiVersion()) + if r, ok := mapResources[group]; ok { + r = append(r, resources[i]) + mapResources[group] = r + } else { + mapResources[group] = []WorkloadSummary{resources[i]} } } } From 37effda7c5f5d8df4fc10152f4d941e3c502cb19 Mon Sep 17 00:00:00 2001 From: dwertent Date: Tue, 21 Dec 2021 11:04:18 +0200 Subject: [PATCH 6/7] update pkg --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index f73c5e18..72545313 100644 --- a/go.mod +++ b/go.mod @@ -4,8 +4,8 @@ go 1.17 require ( github.com/armosec/armoapi-go v0.0.23 - github.com/armosec/k8s-interface v0.0.46 - github.com/armosec/opa-utils v0.0.72 + github.com/armosec/k8s-interface v0.0.50 + github.com/armosec/opa-utils v0.0.75 github.com/armosec/rbac-utils v0.0.9 github.com/armosec/utils-go v0.0.3 github.com/briandowns/spinner v1.18.0 diff --git a/go.sum b/go.sum index 908604b0..eea11167 100644 --- a/go.sum +++ b/go.sum @@ -88,11 +88,11 @@ github.com/armosec/armoapi-go v0.0.23 h1:jqoLIWM5CR7DCD9fpFgN0ePqtHvOCoZv/XzCwsU github.com/armosec/armoapi-go v0.0.23/go.mod h1:iaVVGyc23QGGzAdv4n+szGQg3Rbpixn9yQTU3qWRpaw= github.com/armosec/k8s-interface v0.0.8/go.mod h1:xxS+V5QT3gVQTwZyAMMDrYLWGrfKOpiJ7Jfhfa0w9sM= github.com/armosec/k8s-interface v0.0.37/go.mod h1:vHxGWqD/uh6+GQb9Sqv7OGMs+Rvc2dsFVc0XtgRh1ZU= -github.com/armosec/k8s-interface v0.0.46 h1:qfCGWtbDCRQg8le2K1OveL94Y3dvGuamHmIJZ61+qqs= -github.com/armosec/k8s-interface v0.0.46/go.mod h1:vHxGWqD/uh6+GQb9Sqv7OGMs+Rvc2dsFVc0XtgRh1ZU= +github.com/armosec/k8s-interface v0.0.50 h1:iLPGI0j85vwKANr9QDAnba4Efjg3DyIJg15jRJdvOnc= +github.com/armosec/k8s-interface v0.0.50/go.mod h1:vHxGWqD/uh6+GQb9Sqv7OGMs+Rvc2dsFVc0XtgRh1ZU= github.com/armosec/opa-utils v0.0.64/go.mod h1:6tQP8UDq2EvEfSqh8vrUdr/9QVSCG4sJfju1SXQOn4c= -github.com/armosec/opa-utils v0.0.72 h1:YaaHIafNwsTD28Adr+PblauChX3YDfnP1LJUmpt3kIU= -github.com/armosec/opa-utils v0.0.72/go.mod h1:+5zC2LGTA5ibp1NDi9niwnA6jYSsE/Pb9M5u4M11dV0= +github.com/armosec/opa-utils v0.0.75 h1:GBI3K18xc3WXJHIorIu4bGNAsfMYHUc1x7zueDz2ZbY= +github.com/armosec/opa-utils v0.0.75/go.mod h1:L7d+uiIIXAZ3LEyKtmEIbMcI1hWgWaXGpn5zVCqzwSU= github.com/armosec/rbac-utils v0.0.1/go.mod h1:pQ8CBiij8kSKV7aeZm9FMvtZN28VgA7LZcYyTWimq40= github.com/armosec/rbac-utils v0.0.9 h1:rIOWp4K7BELUNX32ktSjVbb8d/0SpH7W76W6Tf+8rzw= github.com/armosec/rbac-utils v0.0.9/go.mod h1:Ex/IdGWhGv9HZq6Hs8N/ApzCKSIvpNe/ETqDfnuyah0= From ff7881130fdfb8b31300ef2af95d55447d5af83d Mon Sep 17 00:00:00 2001 From: dwertent Date: Tue, 21 Dec 2021 13:09:31 +0200 Subject: [PATCH 7/7] fixed host sensor issue --- clihandler/initcli.go | 41 +++++++++++++------------ clihandler/initcliutils.go | 3 +- hostsensorutils/hostsensordeploy.go | 3 ++ hostsensorutils/hostsensorgetfrompod.go | 11 +------ 4 files changed, 27 insertions(+), 31 deletions(-) diff --git a/clihandler/initcli.go b/clihandler/initcli.go index b870f364..d8ccf8b1 100644 --- a/clihandler/initcli.go +++ b/clihandler/initcli.go @@ -37,6 +37,18 @@ func getInterfaces(scanInfo *cautils.ScanInfo) componentInterfaces { setSubmitBehavior(scanInfo, tenantConfig) hostSensorHandler := getHostSensorHandler(scanInfo, k8s) + if err := hostSensorHandler.Init(); err != nil { + errMsg := "failed to init host sensor" + if scanInfo.VerboseMode { + errMsg = fmt.Sprintf("%s: %v", errMsg, err) + } + cautils.ErrorDisplay(errMsg) + hostSensorHandler = &hostsensorutils.HostSensorHandlerMock{} + } + // excluding hostsensor namespace + if len(scanInfo.IncludeNamespaces) == 0 && hostSensorHandler.GetNamespace() != "" { + scanInfo.ExcludedNamespaces = fmt.Sprintf("%s,%s", scanInfo.ExcludedNamespaces, hostSensorHandler.GetNamespace()) + } resourceHandler := getResourceHandler(scanInfo, tenantConfig, k8s, hostSensorHandler) @@ -73,28 +85,19 @@ func ScanCliSetup(scanInfo *cautils.ScanInfo) error { interfaces.report.SetClusterName(interfaces.tenantConfig.GetClusterName()) interfaces.report.SetCustomerGUID(interfaces.tenantConfig.GetCustomerGUID()) - if err := interfaces.hostSensorHandler.Init(); err != nil { - errMsg := "failed to init host sensor" - if scanInfo.VerboseMode { - errMsg = fmt.Sprintf("%s: %v", errMsg, err) - } - cautils.ErrorDisplay(errMsg) - } else if len(scanInfo.IncludeNamespaces) == 0 && interfaces.hostSensorHandler.GetNamespace() != "" { - scanInfo.ExcludedNamespaces = fmt.Sprintf("%s,%s", scanInfo.ExcludedNamespaces, interfaces.hostSensorHandler) - defer func() { - if err := interfaces.hostSensorHandler.TearDown(); err != nil { - errMsg := "failed to tear down host sensor" - if scanInfo.VerboseMode { - errMsg = fmt.Sprintf("%s: %v", errMsg, err) - } - cautils.ErrorDisplay(errMsg) - } - }() - } - // set policy getter only after setting the customerGUID setPolicyGetter(scanInfo, interfaces.tenantConfig.GetCustomerGUID()) + defer func() { + if err := interfaces.hostSensorHandler.TearDown(); err != nil { + errMsg := "failed to tear down host sensor" + if scanInfo.VerboseMode { + errMsg = fmt.Sprintf("%s: %v", errMsg, err) + } + cautils.ErrorDisplay(errMsg) + } + }() + // cli handler setup go func() { // policy handler setup diff --git a/clihandler/initcliutils.go b/clihandler/initcliutils.go index 55a35b4e..b7ce4c54 100644 --- a/clihandler/initcliutils.go +++ b/clihandler/initcliutils.go @@ -61,7 +61,7 @@ func getHostSensorHandler(scanInfo *cautils.ScanInfo, k8s *k8sinterface.Kubernet } if hostSensorVal := scanInfo.HostSensor.Get(); hostSensorVal != nil && *hostSensorVal { hostSensorHandler, err := hostsensorutils.NewHostSensorHandler(k8s) - if err != nil { + if err != nil || hostSensorHandler == nil { glog.Errorf("failed to create host sensor: %v", err) return &hostsensorutils.HostSensorHandlerMock{} } @@ -69,7 +69,6 @@ func getHostSensorHandler(scanInfo *cautils.ScanInfo, k8s *k8sinterface.Kubernet } return &hostsensorutils.HostSensorHandlerMock{} } - func getFieldSelector(scanInfo *cautils.ScanInfo) resourcehandler.IFieldSelector { if scanInfo.IncludeNamespaces != "" { return resourcehandler.NewIncludeSelector(scanInfo.IncludeNamespaces) diff --git a/hostsensorutils/hostsensordeploy.go b/hostsensorutils/hostsensordeploy.go index 83a6d020..06e1c008 100644 --- a/hostsensorutils/hostsensordeploy.go +++ b/hostsensorutils/hostsensordeploy.go @@ -201,5 +201,8 @@ func (hsh *HostSensorHandler) TearDown() error { } func (hsh *HostSensorHandler) GetNamespace() string { + if hsh.DaemonSet == nil { + return "" + } return hsh.DaemonSet.Namespace } diff --git a/hostsensorutils/hostsensorgetfrompod.go b/hostsensorutils/hostsensorgetfrompod.go index e6e9f480..aa58aae5 100644 --- a/hostsensorutils/hostsensorgetfrompod.go +++ b/hostsensorutils/hostsensorgetfrompod.go @@ -8,7 +8,6 @@ import ( "github.com/armosec/k8s-interface/k8sinterface" "github.com/armosec/kubescape/cautils" "github.com/armosec/opa-utils/objectsenvelopes/hostsensor" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/yaml" ) @@ -123,7 +122,7 @@ func (hsh *HostSensorHandler) GetOsReleaseFile() ([]hostsensor.HostSensorDataEnv // return list of func (hsh *HostSensorHandler) GetKubeletConfigurations() ([]hostsensor.HostSensorDataEnvelope, error) { // loop over pods and port-forward it to each of them - res, err := hsh.sendAllPodsHTTPGETRequest("/kubeletConfigurations", "") // empty kind, will be overridden + res, err := hsh.sendAllPodsHTTPGETRequest("/kubeletConfigurations", "KubeletConfigurations") // empty kind, will be overridden for resIdx := range res { jsonBytes, err := yaml.YAMLToJSON(res[resIdx].Data) if err != nil { @@ -131,14 +130,6 @@ func (hsh *HostSensorHandler) GetKubeletConfigurations() ([]hostsensor.HostSenso continue } res[resIdx].SetData(jsonBytes) - - kindDet := metav1.TypeMeta{} - if err = json.Unmarshal(jsonBytes, &kindDet); err != nil { - fmt.Printf("In GetKubeletConfigurations failed to Unmarshal GroupVersionKind: %v;\n%v", err, jsonBytes) - continue - } - res[resIdx].SetKind(kindDet.Kind) - res[resIdx].SetApiVersion(k8sinterface.JoinGroupVersion(kindDet.GroupVersionKind().Group, kindDet.GroupVersionKind().Version)) } return res, err }