format v2

This commit is contained in:
David Wertenteil
2022-04-07 13:54:49 +03:00
parent 2a7c20ea94
commit bd9e44382e
4 changed files with 82 additions and 51 deletions
@@ -18,7 +18,6 @@ const (
columnCounterExclude = iota
columnCounterAll = iota
columnRiskScore = iota
columnInfo = iota
_rowLen = iota
)
@@ -40,30 +39,23 @@ func generateRow(controlSummary reportsummary.IControlSummary, infoToPrintInfo [
row[columnCounterFailed] = fmt.Sprintf("%d", controlSummary.NumberOfResources().Failed())
row[columnCounterExclude] = fmt.Sprintf("%d", controlSummary.NumberOfResources().Excluded())
row[columnCounterAll] = fmt.Sprintf("%d", controlSummary.NumberOfResources().All())
row[columnRiskScore] = getRiskScoreColumn(controlSummary)
row[columnInfo] = getInfoColumn(controlSummary, infoToPrintInfo)
row[columnRiskScore] = getRiskScoreColumn(controlSummary, infoToPrintInfo)
return row
}
func getInfoColumn(controlSummary reportsummary.IControlSummary, infoToPrintInfo []infoStars) string {
if !controlSummary.GetStatus().IsSkipped() {
return ""
}
if controlSummary.GetStatus().IsSkipped() {
for i := range infoToPrintInfo {
if infoToPrintInfo[i].info == controlSummary.GetStatus().Info() {
return infoToPrintInfo[i].stars
}
for i := range infoToPrintInfo {
if infoToPrintInfo[i].info == controlSummary.GetStatus().Info() {
return infoToPrintInfo[i].stars
}
}
return ""
}
func getRiskScoreColumn(controlSummary reportsummary.IControlSummary) string {
func getRiskScoreColumn(controlSummary reportsummary.IControlSummary, infoToPrintInfo []infoStars) string {
if controlSummary.GetStatus().IsSkipped() {
return string(controlSummary.GetStatus().Status())
return fmt.Sprintf("%s%s", controlSummary.GetStatus().Status(), getInfoColumn(controlSummary, infoToPrintInfo))
}
return fmt.Sprintf("%d", cautils.Float32ToInt(controlSummary.GetScore())) + "%"
}
@@ -111,7 +103,6 @@ func getControlTableHeaders() []string {
headers[columnCounterAll] = "ALL RESOURCES"
headers[columnSeverity] = "SEVERITY"
headers[columnRiskScore] = "% RISK-SCORE"
headers[columnInfo] = "INFO"
return headers
}
@@ -123,6 +114,5 @@ func getColumnsAlignments() []int {
alignments[columnCounterAll] = tablewriter.ALIGN_CENTER
alignments[columnSeverity] = tablewriter.ALIGN_LEFT
alignments[columnRiskScore] = tablewriter.ALIGN_CENTER
alignments[columnRiskScore] = tablewriter.ALIGN_CENTER
return alignments
}
@@ -30,13 +30,15 @@ func NewPrettyPrinter(verboseMode bool, formatVersion string) *PrettyPrinter {
}
func (prettyPrinter *PrettyPrinter) ActionPrint(opaSessionObj *cautils.OPASessionObj) {
fmt.Fprintf(prettyPrinter.writer, "\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n")
sortedControlNames := getSortedControlsNames(opaSessionObj.Report.SummaryDetails.Controls) // ListControls().All())
if prettyPrinter.verboseMode {
if prettyPrinter.formatVersion == "v1" {
prettyPrinter.printResults(&opaSessionObj.Report.SummaryDetails.Controls, opaSessionObj.AllResources, sortedControlNames)
} else if prettyPrinter.formatVersion == "v2" {
prettyPrinter.resourceTable(opaSessionObj.ResourcesResult, opaSessionObj.AllResources)
prettyPrinter.resourceTable(opaSessionObj)
}
}
prettyPrinter.printSummaryTable(&opaSessionObj.Report.SummaryDetails, sortedControlNames)
@@ -176,12 +178,13 @@ func generateFooter(summaryDetails *reportsummary.SummaryDetails) []string {
row[columnCounterAll] = fmt.Sprintf("%d", summaryDetails.NumberOfResources().All())
row[columnSeverity] = " "
row[columnRiskScore] = fmt.Sprintf("%.2f%s", summaryDetails.Score, "%")
row[columnInfo] = " "
return row
}
func (prettyPrinter *PrettyPrinter) printSummaryTable(summaryDetails *reportsummary.SummaryDetails, sortedControlNames [][]string) {
cautils.InfoTextDisplay(prettyPrinter.writer, "\n"+controlListSummary(summaryDetails)+"\n\n")
summaryTable := tablewriter.NewWriter(prettyPrinter.writer)
summaryTable.SetAutoWrapText(false)
summaryTable.SetHeader(getControlTableHeaders())
@@ -237,3 +240,7 @@ func frameworksScoresToString(frameworks []reportsummary.IFrameworkSummary) stri
func getControlLink(controlID string) string {
return fmt.Sprintf("https://hub.armo.cloud/docs/%s", strings.ToLower(controlID))
}
func controlListSummary(summaryDetails *reportsummary.SummaryDetails) string {
return fmt.Sprintf("Controls: %d (Failed: %d, Excluded: %d, Skipped: %d)", summaryDetails.NumberOfControls().All(), summaryDetails.NumberOfControls().Failed(), summaryDetails.NumberOfControls().Excluded(), summaryDetails.NumberOfControls().Skipped())
}
@@ -5,58 +5,80 @@ import (
"sort"
"strings"
"github.com/armosec/k8s-interface/workloadinterface"
"github.com/armosec/kubescape/core/cautils"
"github.com/armosec/opa-utils/reporthandling/results/v1/reportsummary"
"github.com/armosec/opa-utils/reporthandling/results/v1/resourcesresults"
"github.com/olekukonko/tablewriter"
)
func (prettyPrinter *PrettyPrinter) resourceTable(results map[string]resourcesresults.Result, allResources map[string]workloadinterface.IMetadata) {
const (
resourceColumnSeverity = iota
resourceColumnName = iota
resourceColumnURL = iota
resourceColumnPath = iota
_resourceRowLen = iota
)
summaryTable := tablewriter.NewWriter(prettyPrinter.writer)
summaryTable.SetAutoWrapText(true)
summaryTable.SetAutoMergeCells(true)
summaryTable.SetHeader(generateResourceHeader())
summaryTable.SetHeaderLine(true)
summaryTable.SetRowLine(true)
// summaryTable.SetFooter([]string{"", "", "Total", "", "$146.93"})
// For control scan framework will be nil
data := Matrix{}
for i := range results {
resource, ok := allResources[i]
func (prettyPrinter *PrettyPrinter) resourceTable(opaSessionObj *cautils.OPASessionObj) {
for resourceID, result := range opaSessionObj.ResourcesResult {
if !result.GetStatus(nil).IsFailed() {
continue
}
resource, ok := opaSessionObj.AllResources[resourceID]
if !ok {
continue
}
s := results[i]
if raw := generateResourceRows(resource, s.ListControls(), prettyPrinter.verboseMode); len(raw) > 0 {
fmt.Fprintf(prettyPrinter.writer, "\n#######################################################################################################\n")
if source, ok := opaSessionObj.ResourceSource[resourceID]; ok {
fmt.Fprintf(prettyPrinter.writer, "Source: %s\n", source)
}
fmt.Fprintf(prettyPrinter.writer, "%s/%s, Name: %s", resource.GetApiVersion(), resource.GetKind(), resource.GetName())
if resource.GetNamespace() != "" {
fmt.Fprintf(prettyPrinter.writer, ", Namespace: %s", resource.GetNamespace())
}
fmt.Fprintf(prettyPrinter.writer, "\n\n")
summaryTable := tablewriter.NewWriter(prettyPrinter.writer)
summaryTable.SetAutoWrapText(true)
summaryTable.SetAutoMergeCells(true)
summaryTable.SetHeader(generateResourceHeader())
summaryTable.SetHeaderLine(true)
summaryTable.SetRowLine(true)
data := Matrix{}
if raw := generateResourceRows(result.ListControls(), &opaSessionObj.Report.SummaryDetails); len(raw) > 0 {
data = append(data, raw...)
}
// For control scan framework will be nil
sort.Sort(data)
summaryTable.AppendBulk(data)
summaryTable.Render()
}
sort.Sort(data)
summaryTable.AppendBulk(data)
summaryTable.Render()
}
func generateResourceRows(resource workloadinterface.IMetadata, controls []resourcesresults.ResourceAssociatedControl, verboseMode bool) [][]string {
func generateResourceRows(controls []resourcesresults.ResourceAssociatedControl, summaryDetails *reportsummary.SummaryDetails) [][]string {
rows := [][]string{}
for i := range controls {
row := make([]string, _resourceRowLen)
if controls[i].GetName() == "" {
continue
}
row := []string{}
if !verboseMode && controls[i].GetStatus(nil).IsPassed() {
if !controls[i].GetStatus(nil).IsFailed() {
continue
}
row = append(row, fmt.Sprintf("%s\nhttps://hub.armo.cloud/docs/%s", controls[i].GetName(), strings.ToLower(controls[i].GetID())))
row = append(row, resource.GetNamespace())
paths := failedPathsToString(&controls[i])
row[resourceColumnURL] = fmt.Sprintf("https://hub.armo.cloud/docs/%s", strings.ToLower(controls[i].GetID()))
row[resourceColumnPath] = strings.Join(failedPathsToString(&controls[i]), "\n")
row[resourceColumnName] = controls[i].GetName()
if c := summaryDetails.Controls.GetControl(reportsummary.EControlCriteriaName, controls[i].GetName()); c != nil {
row[resourceColumnSeverity] = getSeverityColumn(c)
}
row = append(row, fmt.Sprintf("%s/%s\n%s", resource.GetKind(), resource.GetName(), strings.Join(paths, ";\n")))
row = append(row, string(controls[i].GetStatus(nil).Status()))
rows = append(rows, row)
}
@@ -64,7 +86,12 @@ func generateResourceRows(resource workloadinterface.IMetadata, controls []resou
}
func generateResourceHeader() []string {
return []string{"Control", "Namespace", "Kind/Name", "Statues"}
headers := make([]string, _resourceRowLen)
headers[resourceColumnSeverity] = "Severity"
headers[resourceColumnName] = "Control Name"
headers[resourceColumnURL] = "Docs"
headers[resourceColumnPath] = "Assistant Remediation"
return headers
}
type Matrix [][]string
@@ -92,6 +92,8 @@ func (report *ReportEventReceiver) GetURL() string {
u.Scheme = "https"
u.Host = getter.GetArmoAPIConnector().GetFrontendURL()
q := u.Query()
if report.customerAdminEMail != "" || report.token == "" { // data has been submitted
u.Path = fmt.Sprintf("configuration-scanning/%s", report.clusterName)
} else {
@@ -99,9 +101,14 @@ func (report *ReportEventReceiver) GetURL() string {
q := u.Query()
q.Add("invitationToken", report.token)
q.Add("customerGUID", report.customerGUID)
u.RawQuery = q.Encode()
}
q.Add("utm_source", "GitHub")
q.Add("utm_medium", "CLI")
q.Add("utm_campaign", "Submit")
u.RawQuery = q.Encode()
return u.String()
}