mirror of
https://github.com/kubescape/kubescape.git
synced 2026-04-15 06:58:11 +00:00
add silent flag
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
+23
-1
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
+7
-6
@@ -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{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
+30
-31
@@ -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()
|
||||
|
||||
+11
-11
@@ -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 // <namespace>:[<WorkloadSummery>]
|
||||
WorkloadSummary map[string][]WorkloadSummary // <namespace>:[<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)
|
||||
}
|
||||
|
||||
+14
-14
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user