mirror of
https://github.com/kubescape/kubescape.git
synced 2026-04-15 06:58:11 +00:00
json v2 support
This commit is contained in:
@@ -150,7 +150,7 @@ kubescape scan --verbose
|
||||
|
||||
#### Output in `json` format
|
||||
```
|
||||
kubescape scan --format json --output results.json
|
||||
kubescape scan --format json --format-version v2 --output results.json
|
||||
```
|
||||
|
||||
#### Output in `junit xml` format
|
||||
|
||||
+1
-1
@@ -68,7 +68,7 @@ type ScanInfo struct {
|
||||
VerboseMode bool // Display all of the input resources and not only failed resources
|
||||
Format string // Format results (table, json, junit ...)
|
||||
Output string // Store results in an output file, Output file name
|
||||
OutputVersion string // Output object can be differnet between versions, this is for testing and backward compatibility
|
||||
FormatVersion string // Output object can be differnet between versions, this is for testing and backward compatibility
|
||||
ExcludedNamespaces string // used for host sensor namespace
|
||||
IncludeNamespaces string // DEPRECATED?
|
||||
InputPatterns []string // Yaml files input patterns
|
||||
|
||||
@@ -79,12 +79,12 @@ func init() {
|
||||
scanCmd.PersistentFlags().BoolVarP(&scanInfo.Silent, "silent", "s", false, "Silent progress messages")
|
||||
scanCmd.PersistentFlags().BoolVarP(&scanInfo.Submit, "submit", "", false, "Send the scan results to Armo management portal where 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 default the results are not submitted")
|
||||
scanCmd.PersistentFlags().StringVar(&scanInfo.HostSensorYamlPath, "host-scan-yaml", "", "Override default host sensor DaemonSet. Use this flag cautiously")
|
||||
scanCmd.PersistentFlags().StringVar(&scanInfo.OutputVersion, "output-version", "v1", "Output object can be differnet between versions, this is for testing and backward compatibility")
|
||||
scanCmd.PersistentFlags().StringVar(&scanInfo.FormatVersion, "format-version", "v1", "Output object can be differnet between versions, this is for testing and backward compatibility")
|
||||
|
||||
// hidden flags
|
||||
scanCmd.PersistentFlags().MarkHidden("host-scan-yaml") // this flag should be used very cautiously. We prefer users will not use it at all unless the DaemoSet can not run pods on the nodes
|
||||
scanCmd.PersistentFlags().MarkHidden("silent") // this flag should be deprecated since we added the --logger support
|
||||
scanCmd.PersistentFlags().MarkHidden("output-version") // meant for testing different output approaches and not for common use
|
||||
scanCmd.PersistentFlags().MarkHidden("format-version") // meant for testing different output approaches and not for common use
|
||||
|
||||
hostF := scanCmd.PersistentFlags().VarPF(&scanInfo.HostSensorEnabled, "enable-host-scan", "", "Deploy ARMO K8s host-sensor daemonset in the scanned cluster. Deleting it right after we collecting the data. Required to collect valueable data from cluster nodes for certain controls. Yaml file: https://raw.githubusercontent.com/armosec/kubescape/master/hostsensorutils/hostsensor.yaml")
|
||||
hostF.NoOptDefVal = "true"
|
||||
|
||||
@@ -83,7 +83,7 @@ func getInterfaces(scanInfo *cautils.ScanInfo) componentInterfaces {
|
||||
reportHandler := getReporter(tenantConfig, scanInfo.Submit)
|
||||
|
||||
// setup printer
|
||||
printerHandler := resultshandling.NewPrinter(scanInfo.Format, scanInfo.OutputVersion, scanInfo.VerboseMode)
|
||||
printerHandler := resultshandling.NewPrinter(scanInfo.Format, scanInfo.FormatVersion, scanInfo.VerboseMode)
|
||||
printerHandler.SetWriter(scanInfo.Output)
|
||||
|
||||
// ================== return interface ======================================
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/armosec/kubescape/cautils"
|
||||
"github.com/armosec/kubescape/cautils/logger"
|
||||
"github.com/armosec/kubescape/resultshandling/printer"
|
||||
)
|
||||
|
||||
type JsonPrinter struct {
|
||||
writer *os.File
|
||||
}
|
||||
|
||||
func NewJsonPrinter() *JsonPrinter {
|
||||
return &JsonPrinter{}
|
||||
}
|
||||
|
||||
func (jsonPrinter *JsonPrinter) SetWriter(outputFile string) {
|
||||
jsonPrinter.writer = printer.GetWriter(outputFile)
|
||||
}
|
||||
|
||||
func (jsonPrinter *JsonPrinter) Score(score float32) {
|
||||
fmt.Fprintf(os.Stderr, "\nOverall risk-score (0- Excellent, 100- All failed): %d\n", int(score))
|
||||
}
|
||||
|
||||
func (jsonPrinter *JsonPrinter) ActionPrint(opaSessionObj *cautils.OPASessionObj) {
|
||||
finalizeJson(opaSessionObj)
|
||||
r, err := json.Marshal(opaSessionObj.Report)
|
||||
if err != nil {
|
||||
logger.L().Fatal("failed to Marshal posture report object")
|
||||
}
|
||||
jsonPrinter.writer.Write(r)
|
||||
}
|
||||
@@ -103,10 +103,6 @@ func (junitPrinter *JunitPrinter) Score(score float32) {
|
||||
fmt.Fprintf(os.Stderr, "\nOverall risk-score (0- Excellent, 100- All failed): %d\n", int(score))
|
||||
}
|
||||
|
||||
func (junitPrinter *JunitPrinter) FinalizeData(opaSessionObj *cautils.OPASessionObj) {
|
||||
finalizeReport(opaSessionObj)
|
||||
}
|
||||
|
||||
func (junitPrinter *JunitPrinter) ActionPrint(opaSessionObj *cautils.OPASessionObj) {
|
||||
junitResult := testsSuites(opaSessionObj)
|
||||
postureReportStr, err := xml.Marshal(junitResult)
|
||||
|
||||
@@ -17,24 +17,27 @@ import (
|
||||
)
|
||||
|
||||
type PrettyPrinter struct {
|
||||
outputVersion string
|
||||
formatVersion string
|
||||
writer *os.File
|
||||
verboseMode bool
|
||||
sortedControlNames []string
|
||||
}
|
||||
|
||||
func NewPrettyPrinter(verboseMode bool, outputVersion string) *PrettyPrinter {
|
||||
func NewPrettyPrinter(verboseMode bool, formatVersion string) *PrettyPrinter {
|
||||
return &PrettyPrinter{
|
||||
verboseMode: verboseMode,
|
||||
outputVersion: outputVersion,
|
||||
formatVersion: formatVersion,
|
||||
}
|
||||
}
|
||||
|
||||
func (prettyPrinter *PrettyPrinter) ActionPrint(opaSessionObj *cautils.OPASessionObj) {
|
||||
prettyPrinter.sortedControlNames = getSortedControlsNames(opaSessionObj.Report.SummaryDetails.Controls) // ListControls().All())
|
||||
|
||||
prettyPrinter.resourceTable(opaSessionObj.ResourcesResult, opaSessionObj.AllResources)
|
||||
prettyPrinter.printResults(&opaSessionObj.Report.SummaryDetails.Controls, opaSessionObj.AllResources)
|
||||
if prettyPrinter.formatVersion == "v1" {
|
||||
prettyPrinter.resourceTable(opaSessionObj.ResourcesResult, opaSessionObj.AllResources)
|
||||
} else if prettyPrinter.formatVersion == "v2" {
|
||||
prettyPrinter.printResults(&opaSessionObj.Report.SummaryDetails.Controls, opaSessionObj.AllResources)
|
||||
}
|
||||
prettyPrinter.printSummaryTable(&opaSessionObj.Report.SummaryDetails)
|
||||
|
||||
}
|
||||
@@ -47,10 +50,6 @@ func (prettyPrinter *PrettyPrinter) Score(score float32) {
|
||||
}
|
||||
|
||||
func (prettyPrinter *PrettyPrinter) printResults(controls *reportsummary.ControlSummaries, allResources map[string]workloadinterface.IMetadata) {
|
||||
if prettyPrinter.outputVersion != "v1" {
|
||||
return
|
||||
}
|
||||
|
||||
for i := 0; i < len(prettyPrinter.sortedControlNames); i++ {
|
||||
|
||||
controlSummary := controls.GetControl(reportsummary.EControlCriteriaName, prettyPrinter.sortedControlNames[i]) // summaryDetails.Controls ListControls().All() Controls.GetControl(ca)
|
||||
|
||||
@@ -11,9 +11,7 @@ import (
|
||||
)
|
||||
|
||||
func (prettyPrinter *PrettyPrinter) resourceTable(results map[string]resourcesresults.Result, allResources map[string]workloadinterface.IMetadata) {
|
||||
if prettyPrinter.outputVersion != "v2" {
|
||||
return
|
||||
}
|
||||
|
||||
summaryTable := tablewriter.NewWriter(prettyPrinter.writer)
|
||||
summaryTable.SetAutoWrapText(true)
|
||||
summaryTable.SetAutoMergeCells(true)
|
||||
|
||||
@@ -3,22 +3,22 @@ package v2
|
||||
import (
|
||||
"github.com/armosec/k8s-interface/workloadinterface"
|
||||
"github.com/armosec/kubescape/cautils"
|
||||
"github.com/armosec/kubescape/cautils/logger"
|
||||
"github.com/armosec/kubescape/cautils/logger/helpers"
|
||||
"github.com/armosec/opa-utils/reporthandling"
|
||||
"github.com/armosec/opa-utils/reporthandling/results/v1/resourcesresults"
|
||||
)
|
||||
|
||||
// finalizeV2Report finalize the results objects by copying data from map to lists
|
||||
func finalizeReport(opaSessionObj *cautils.OPASessionObj) {
|
||||
func finalizeJson(opaSessionObj *cautils.OPASessionObj) {
|
||||
if len(opaSessionObj.Report.Results) == 0 {
|
||||
opaSessionObj.Report.Results = make([]resourcesresults.Result, len(opaSessionObj.ResourcesResult))
|
||||
finalizeResults(opaSessionObj.Report.Results, opaSessionObj.ResourcesResult)
|
||||
opaSessionObj.ResourcesResult = nil
|
||||
}
|
||||
|
||||
if len(opaSessionObj.Report.Resources) == 0 {
|
||||
opaSessionObj.Report.Resources = make([]reporthandling.Resource, len(opaSessionObj.AllResources))
|
||||
finalizeResources(opaSessionObj.Report.Resources, opaSessionObj.AllResources)
|
||||
opaSessionObj.AllResources = nil
|
||||
finalizeResources(opaSessionObj.Report.Resources, opaSessionObj.Report.Results, opaSessionObj.AllResources)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -30,15 +30,22 @@ func finalizeResults(results []resourcesresults.Result, resourcesResult map[stri
|
||||
}
|
||||
}
|
||||
|
||||
func finalizeResources(resources []reporthandling.Resource, allResources map[string]workloadinterface.IMetadata) {
|
||||
func finalizeResources(resources []reporthandling.Resource, results []resourcesresults.Result, allResources map[string]workloadinterface.IMetadata) {
|
||||
index := 0
|
||||
for resourceID := range allResources {
|
||||
if obj, ok := allResources[resourceID]; ok {
|
||||
for i := range results {
|
||||
if obj, ok := allResources[results[i].ResourceID]; ok {
|
||||
r := *reporthandling.NewResource(obj.GetObject())
|
||||
r.ResourceID = resourceID
|
||||
r.ResourceID = results[i].ResourceID
|
||||
resources[index] = r
|
||||
}
|
||||
|
||||
index++
|
||||
}
|
||||
}
|
||||
|
||||
func logOUtputFile(fileName string) {
|
||||
if fileName != "/dev/stdout" && fileName != "/dev/stderr" {
|
||||
logger.L().Success("Scan results saved", helpers.String("filename", fileName))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -53,11 +53,16 @@ func CalculatePostureScore(postureReport *reporthandling.PostureReport) float32
|
||||
return (float32(len(allResources)) - float32(len(failedResources))) / float32(len(allResources))
|
||||
}
|
||||
|
||||
func NewPrinter(printFormat, outputVersion string, verboseMode bool) printer.IPrinter {
|
||||
func NewPrinter(printFormat, formatVersion string, verboseMode bool) printer.IPrinter {
|
||||
|
||||
switch printFormat {
|
||||
case printer.JsonFormat:
|
||||
return printerv1.NewJsonPrinter()
|
||||
switch formatVersion {
|
||||
case "v2":
|
||||
return printerv2.NewJsonPrinter()
|
||||
default:
|
||||
return printerv1.NewJsonPrinter()
|
||||
}
|
||||
case printer.JunitResultFormat:
|
||||
return printerv2.NewJunitPrinter(verboseMode)
|
||||
case printer.PrometheusFormat:
|
||||
@@ -65,6 +70,6 @@ func NewPrinter(printFormat, outputVersion string, verboseMode bool) printer.IPr
|
||||
case printer.PdfFormat:
|
||||
return printerv2.NewPdfPrinter()
|
||||
default:
|
||||
return printerv2.NewPrettyPrinter(verboseMode, outputVersion)
|
||||
return printerv2.NewPrettyPrinter(verboseMode, formatVersion)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user