diff --git a/cautils/armotypes/portaltypesutils.go b/cautils/armotypes/portaltypesutils.go index a7b875e8..7e517beb 100644 --- a/cautils/armotypes/portaltypesutils.go +++ b/cautils/armotypes/portaltypesutils.go @@ -1,7 +1,5 @@ package armotypes -import "github.com/golang/glog" - var IgnoreLabels = []string{AttributeCluster, AttributeNamespace} // DigestPortalDesignator - get cluster namespace and labels from designator @@ -12,7 +10,6 @@ func DigestPortalDesignator(designator *PortalDesignator) (string, string, map[s // case DesignatorWlid: TODO // case DesignatorWildWlid: TODO default: - glog.Warningf("in 'digestPortalDesignator' designator type: '%v' not yet supported. please contact Armo team", designator.DesignatorType) } return "", "", nil } diff --git a/cautils/display.go b/cautils/display.go index b7cc0181..4f92d625 100644 --- a/cautils/display.go +++ b/cautils/display.go @@ -10,6 +10,16 @@ import ( "github.com/mattn/go-isatty" ) +var silent = false + +func SetSilentMode(s bool) { + silent = s +} + +func IsSilent() bool { + return silent +} + var FailureDisplay = color.New(color.Bold, color.FgHiRed).FprintfFunc() var FailureTextDisplay = color.New(color.Faint, color.FgHiRed).FprintfFunc() var InfoDisplay = color.New(color.Bold, color.FgHiYellow).FprintfFunc() @@ -20,19 +30,31 @@ var DescriptionDisplay = color.New(color.Faint, color.FgWhite).FprintfFunc() var Spinner *spinner.Spinner +func ScanStartDisplay() { + if !IsSilent() { + InfoDisplay(os.Stdout, "ARMO security scanner starting\n") + } +} + func SuccessTextDisplay(str string) { + if IsSilent() { + return + } SuccessDisplay(os.Stdout, "[success] ") SimpleDisplay(os.Stdout, fmt.Sprintf("%s\n", str)) } func ProgressTextDisplay(str string) { + if IsSilent() { + return + } InfoDisplay(os.Stdout, "[progress] ") SimpleDisplay(os.Stdout, fmt.Sprintf("%s\n", str)) } func StartSpinner() { - if isatty.IsTerminal(os.Stdout.Fd()) { + if isatty.IsTerminal(os.Stdout.Fd()) && !IsSilent() { Spinner = spinner.New(spinner.CharSets[7], 100*time.Millisecond) // Build our new spinner Spinner.Start() } diff --git a/cautils/opapolicy/datastructures.go b/cautils/opapolicy/datastructures.go index 4c9a25a0..ac73aef6 100644 --- a/cautils/opapolicy/datastructures.go +++ b/cautils/opapolicy/datastructures.go @@ -150,9 +150,9 @@ type PolicyIdentifier struct { } type ScanInfo struct { - PolicyIdentifier PolicyIdentifier `json:"policyIdentifier"` - Output string `json:"output"` - ExcludedNamespaces string `json:"excludedNamespaces"` - Input []string `json:"input"` - Silent bool `json:"silent"` + PolicyIdentifier PolicyIdentifier + Output string + ExcludedNamespaces string + InputPatterns []string + Silent bool } diff --git a/cmd/framework.go b/cmd/framework.go index 27b4b6b9..0803a09d 100644 --- a/cmd/framework.go +++ b/cmd/framework.go @@ -18,6 +18,8 @@ import ( ) var scanInfo opapolicy.ScanInfo +var supportedFrameworks = []string{"nsa", "mitre"} +var isSilent bool type CLIHandler struct { policyHandler *policyhandler.PolicyHandler @@ -42,22 +44,22 @@ var frameworkCmd = &cobra.Command{ scanInfo.PolicyIdentifier = opapolicy.PolicyIdentifier{} scanInfo.PolicyIdentifier.Kind = opapolicy.KindFramework scanInfo.PolicyIdentifier.Name = args[0] - scanInfo.Input = args[1:] + scanInfo.InputPatterns = args[1:] + cautils.SetSilentMode(scanInfo.Silent) CliSetup() }, } func isValidFramework(framework string) bool { - return framework == "nsa" || framework != "mitre" + return cautils.StringInSlice(supportedFrameworks, framework) != cautils.ValueNotFound } func init() { scanCmd.AddCommand(frameworkCmd) scanInfo = opapolicy.ScanInfo{} - frameworkCmd.Flags().StringVarP(&scanInfo.ExcludedNamespaces, "excluded-namespaces", "e", "", "namespaces to exclude from check") + frameworkCmd.Flags().StringVarP(&scanInfo.ExcludedNamespaces, "exclude-namespaces", "e", "", "namespaces to exclude from check") frameworkCmd.Flags().StringVarP(&scanInfo.Output, "output", "o", "pretty-printer", "output format") frameworkCmd.Flags().BoolVarP(&scanInfo.Silent, "silent", "s", false, "silent output") - } func processYamlInput(yamls string) { @@ -106,8 +108,7 @@ func NewCLIHandler(policyHandler *policyhandler.PolicyHandler) *CLIHandler { } func (clihandler *CLIHandler) Scan() error { - cautils.InfoDisplay(os.Stdout, "ARMO security scanner starting\n") - + cautils.ScanStartDisplay() policyNotification := &opapolicy.PolicyNotification{ NotificationType: opapolicy.TypeExecPostureScan, Rules: []opapolicy.PolicyIdentifier{ diff --git a/opaprocessor/processorhandler.go b/opaprocessor/processorhandler.go index b3fc2bda..a49118a8 100644 --- a/opaprocessor/processorhandler.go +++ b/opaprocessor/processorhandler.go @@ -56,7 +56,6 @@ func (opap *OPAProcessor) ProcessRulesListenner() { } func (opap *OPAProcessor) ProcessRulesHandler(opaSessionObj *cautils.OPASessionObj) error { - glog.Infof(fmt.Sprintf("Starting 'ProcessRulesHandler'. reportID: %s", opaSessionObj.PostureReport.ReportID)) cautils.ProgressTextDisplay(fmt.Sprintf("Scanning cluster %s", cautils.ClusterName)) cautils.StartSpinner() frameworkReports := []opapolicy.FrameworkReport{} @@ -99,7 +98,6 @@ func (opap *OPAProcessor) ProcessRulesHandler(opaSessionObj *cautils.OPASessionO opaSessionObj.PostureReport.FrameworkReports = frameworkReports opaSessionObj.PostureReport.ReportGenerationTime = time.Now().UTC() - glog.Infof(fmt.Sprintf("Done 'ProcessRulesHandler'. reportID: %s", opaSessionObj.PostureReport.ReportID)) cautils.StopSpinner() cautils.SuccessTextDisplay(fmt.Sprintf("Done scanning cluster %s", cautils.ClusterName)) return errs diff --git a/policyhandler/handlenotification.go b/policyhandler/handlenotification.go index 0f0c2c00..fa868188 100644 --- a/policyhandler/handlenotification.go +++ b/policyhandler/handlenotification.go @@ -27,13 +27,11 @@ func NewPolicyHandler(processPolicy *chan *cautils.OPASessionObj, k8s *k8sinterf } func (policyHandler *PolicyHandler) HandleNotificationRequest(notification *opapolicy.PolicyNotification, excludedNamespaces string) error { - glog.Infof("Processing notification. reportID: %s", notification.ReportID) opaSessionObj := cautils.NewOPASessionObj(nil, nil) // validate notification // TODO // get policies - glog.Infof(fmt.Sprintf("Getting %d policies from backend. reportID: %s", len(notification.Rules), notification.ReportID)) cautils.ProgressTextDisplay("Downloading framework definitions") frameworks, err := policyHandler.GetPoliciesFromBackend(notification) if err != nil { @@ -51,8 +49,6 @@ func (policyHandler *PolicyHandler) HandleNotificationRequest(notification *opap // get k8s resources cautils.ProgressTextDisplay("Accessing Kubernetes objects") - glog.Infof(fmt.Sprintf("Getting kubernetes objects. reportID: %s", notification.ReportID)) - k8sResources, err := policyHandler.getK8sResources(frameworks, ¬ification.Designators, excludedNamespaces) if err != nil || len(*k8sResources) == 0 { glog.Error(err) diff --git a/printer/printresults.go b/printer/printresults.go index 199ca2ea..6f273024 100644 --- a/printer/printresults.go +++ b/printer/printresults.go @@ -33,7 +33,7 @@ type Printer struct { func NewPrinter(opaSessionObj *chan *cautils.OPASessionObj, printerType string) *Printer { return &Printer{ opaSessionObj: opaSessionObj, - summary: NewSummery(), + summary: NewSummary(), printerType: printerType, } } @@ -42,9 +42,8 @@ func (printer *Printer) ActionPrint() { for { opaSessionObj := <-*printer.opaSessionObj - if printer.printerType == PrettyPrinter { - printer.SummerySetup(opaSessionObj.PostureReport) + printer.SummarySetup(opaSessionObj.PostureReport) printer.PrintResults() printer.PrintSummaryTable() } else if printer.printerType == JsonPrinter { @@ -66,7 +65,7 @@ func (printer *Printer) ActionPrint() { os.Exit(1) } os.Stdout.Write(postureReportStr) - } else { + } else if !cautils.IsSilent() { fmt.Println("unknown output printer") os.Exit(1) } @@ -77,19 +76,19 @@ func (printer *Printer) ActionPrint() { } } -func (printer *Printer) SummerySetup(postureReport *opapolicy.PostureReport) { +func (printer *Printer) SummarySetup(postureReport *opapolicy.PostureReport) { for _, fr := range postureReport.FrameworkReports { for _, cr := range fr.ControlReports { if len(cr.RuleReports) == 0 { continue } - workloadsSummery := listResultSummery(cr.RuleReports) - mapResources := groupByNamespace(workloadsSummery) + workloadsSummary := listResultSummary(cr.RuleReports) + mapResources := groupByNamespace(workloadsSummary) - printer.summary[cr.Name] = ControlSummery{ + printer.summary[cr.Name] = ControlSummary{ TotalResources: cr.GetNumberOfResources(), - TotalFailed: len(workloadsSummery), - WorkloadSummery: mapResources, + TotalFailed: len(workloadsSummary), + WorkloadSummary: mapResources, Description: cr.Description, Remediation: cr.Remediation, } @@ -101,46 +100,46 @@ func (printer *Printer) SummerySetup(postureReport *opapolicy.PostureReport) { func (printer *Printer) PrintResults() { for i := 0; i < len(printer.sortedControlNames); i++ { - controlSummery := printer.summary[printer.sortedControlNames[i]] - printer.printTitle(printer.sortedControlNames[i], &controlSummery) - printer.printResult(printer.sortedControlNames[i], &controlSummery) + controlSummary := printer.summary[printer.sortedControlNames[i]] + printer.printTitle(printer.sortedControlNames[i], &controlSummary) + printer.printResult(printer.sortedControlNames[i], &controlSummary) if printer.summary[printer.sortedControlNames[i]].TotalResources > 0 { - printer.printSummery(printer.sortedControlNames[i], &controlSummery) + printer.printSummary(printer.sortedControlNames[i], &controlSummary) } } } -func (print *Printer) printSummery(controlName string, controlSummery *ControlSummery) { +func (print *Printer) printSummary(controlName string, controlSummary *ControlSummary) { cautils.SimpleDisplay(os.Stdout, "Summary - ") - cautils.SuccessDisplay(os.Stdout, "Passed:%v ", controlSummery.TotalResources-controlSummery.TotalFailed) - cautils.FailureDisplay(os.Stdout, "Failed:%v ", controlSummery.TotalFailed) - cautils.InfoDisplay(os.Stdout, "Total:%v\n", controlSummery.TotalResources) - if controlSummery.TotalFailed > 0 { - cautils.DescriptionDisplay(os.Stdout, "Remediation: %v\n", controlSummery.Remediation) + cautils.SuccessDisplay(os.Stdout, "Passed:%v ", controlSummary.TotalResources-controlSummary.TotalFailed) + cautils.FailureDisplay(os.Stdout, "Failed:%v ", controlSummary.TotalFailed) + cautils.InfoDisplay(os.Stdout, "Total:%v\n", controlSummary.TotalResources) + if controlSummary.TotalFailed > 0 { + cautils.DescriptionDisplay(os.Stdout, "Remediation: %v\n", controlSummary.Remediation) } cautils.DescriptionDisplay(os.Stdout, "\n") } -func (printer *Printer) printTitle(controlName string, controlSummery *ControlSummery) { +func (printer *Printer) printTitle(controlName string, controlSummary *ControlSummary) { cautils.InfoDisplay(os.Stdout, "[control: %s] ", controlName) - if controlSummery.TotalResources == 0 { + if controlSummary.TotalResources == 0 { cautils.InfoDisplay(os.Stdout, "resources not found %v\n", emoji.ConfusedFace) - } else if controlSummery.TotalFailed == 0 { + } else if controlSummary.TotalFailed == 0 { cautils.SuccessDisplay(os.Stdout, "passed %v\n", emoji.ThumbsUp) } else { cautils.FailureDisplay(os.Stdout, "failed %v\n", emoji.SadButRelievedFace) } - cautils.DescriptionDisplay(os.Stdout, "Description: %s\n", controlSummery.Description) + cautils.DescriptionDisplay(os.Stdout, "Description: %s\n", controlSummary.Description) } -func (printer *Printer) printResult(controlName string, controlSummery *ControlSummery) { +func (printer *Printer) printResult(controlName string, controlSummary *ControlSummary) { indent := INDENT - for ns, rsc := range controlSummery.WorkloadSummery { + for ns, rsc := range controlSummary.WorkloadSummary { preIndent := indent if ns != "" { cautils.SimpleDisplay(os.Stdout, "%sNamespace %s\n", indent, ns) @@ -156,7 +155,7 @@ func (printer *Printer) printResult(controlName string, controlSummery *ControlS } -func generateRow(control string, cs ControlSummery) []string { +func generateRow(control string, cs ControlSummary) []string { row := []string{control} row = append(row, cs.ToSlice()...) row = append(row, fmt.Sprintf("%d%s", percentage(cs.TotalResources, cs.TotalFailed), "%")) @@ -195,10 +194,10 @@ func (printer *Printer) PrintSummaryTable() { sumFailed := 0 for i := 0; i < len(printer.sortedControlNames); i++ { - controlSummery := printer.summary[printer.sortedControlNames[i]] - summaryTable.Append(generateRow(printer.sortedControlNames[i], controlSummery)) - sumFailed += controlSummery.TotalFailed - sumTotal += controlSummery.TotalResources + controlSummary := printer.summary[printer.sortedControlNames[i]] + summaryTable.Append(generateRow(printer.sortedControlNames[i], controlSummary)) + sumFailed += controlSummary.TotalFailed + sumTotal += controlSummary.TotalResources } summaryTable.SetFooter(generateFooter(len(printer.summary), sumFailed, sumTotal)) summaryTable.Render() diff --git a/printer/summary.go b/printer/summary.go index 3a2eebbc..6c567830 100644 --- a/printer/summary.go +++ b/printer/summary.go @@ -4,34 +4,34 @@ import ( "fmt" ) -type Summary map[string]ControlSummery +type Summary map[string]ControlSummary -func NewSummery() Summary { - return make(map[string]ControlSummery) +func NewSummary() Summary { + return make(map[string]ControlSummary) } -type ControlSummery struct { +type ControlSummary struct { TotalResources int TotalFailed int Description string Remediation string - WorkloadSummery map[string][]WorkloadSummery // :[] + WorkloadSummary map[string][]WorkloadSummary // :[] } -type WorkloadSummery struct { +type WorkloadSummary struct { Kind string Name string Namespace string Group string } -func (controlSummery *ControlSummery) ToSlice() []string { +func (controlSummary *ControlSummary) ToSlice() []string { s := []string{} - s = append(s, fmt.Sprintf("%d", controlSummery.TotalFailed)) - s = append(s, fmt.Sprintf("%d", controlSummery.TotalResources)) + s = append(s, fmt.Sprintf("%d", controlSummary.TotalFailed)) + s = append(s, fmt.Sprintf("%d", controlSummary.TotalResources)) return s } -func (workloadSummery *WorkloadSummery) ToString() string { - return fmt.Sprintf("/%s/%s/%s/%s", workloadSummery.Group, workloadSummery.Namespace, workloadSummery.Kind, workloadSummery.Name) +func (workloadSummary *WorkloadSummary) ToString() string { + return fmt.Sprintf("/%s/%s/%s/%s", workloadSummary.Group, workloadSummary.Namespace, workloadSummary.Kind, workloadSummary.Name) } diff --git a/printer/summeryhelpers.go b/printer/summeryhelpers.go index 91bccc23..7a02bd3a 100644 --- a/printer/summeryhelpers.go +++ b/printer/summeryhelpers.go @@ -7,26 +7,26 @@ import ( "kube-escape/cautils/opapolicy" ) -// Group workloads by namespace - return {"namespace": <[]WorkloadSummery>} -func groupByNamespace(resources []WorkloadSummery) map[string][]WorkloadSummery { - mapResources := make(map[string][]WorkloadSummery) +// Group workloads by namespace - return {"namespace": <[]WorkloadSummary>} +func groupByNamespace(resources []WorkloadSummary) map[string][]WorkloadSummary { + mapResources := make(map[string][]WorkloadSummary) for i := range resources { if r, ok := mapResources[resources[i].Namespace]; ok { r = append(r, resources[i]) mapResources[resources[i].Namespace] = r } else { - mapResources[resources[i].Namespace] = []WorkloadSummery{resources[i]} + mapResources[resources[i].Namespace] = []WorkloadSummary{resources[i]} } } return mapResources } -func listResultSummery(ruleReports []opapolicy.RuleReport) []WorkloadSummery { - workloadsSummery := []WorkloadSummery{} +func listResultSummary(ruleReports []opapolicy.RuleReport) []WorkloadSummary { + workloadsSummary := []WorkloadSummary{} track := map[string]bool{} for c := range ruleReports { for _, ruleReport := range ruleReports[c].RuleResponses { - resource, err := ruleResultSummery(ruleReport.AlertObject) + resource, err := ruleResultSummary(ruleReport.AlertObject) if err != nil { fmt.Println(err.Error()) continue @@ -36,18 +36,18 @@ func listResultSummery(ruleReports []opapolicy.RuleReport) []WorkloadSummery { for i := range resource { if ok := track[resource[i].ToString()]; !ok { track[resource[i].ToString()] = true - workloadsSummery = append(workloadsSummery, resource[i]) + workloadsSummary = append(workloadsSummary, resource[i]) } } } } - return workloadsSummery + return workloadsSummary } -func ruleResultSummery(obj opapolicy.AlertObject) ([]WorkloadSummery, error) { - resource := []WorkloadSummery{} +func ruleResultSummary(obj opapolicy.AlertObject) ([]WorkloadSummary, error) { + resource := []WorkloadSummary{} for i := range obj.K8SApiObjects { - r, err := newWorkloadSummery(obj.K8SApiObjects[i]) + r, err := newWorkloadSummary(obj.K8SApiObjects[i]) if err != nil { return resource, err } @@ -57,8 +57,8 @@ func ruleResultSummery(obj opapolicy.AlertObject) ([]WorkloadSummery, error) { return resource, nil } -func newWorkloadSummery(obj map[string]interface{}) (*WorkloadSummery, error) { - r := &WorkloadSummery{} +func newWorkloadSummary(obj map[string]interface{}) (*WorkloadSummary, error) { + r := &WorkloadSummary{} workload := k8sinterface.NewWorkloadObj(obj) if workload == nil {