From 155349dac0265b4c317577108164e5d6cdf294a5 Mon Sep 17 00:00:00 2001 From: dwertent Date: Wed, 23 Feb 2022 15:54:59 +0200 Subject: [PATCH 1/6] adding resource table --- hostsensorutils/hostsensordeploy.go | 2 +- resultshandling/printer/v2/controltable.go | 36 +++ resultshandling/printer/v2/pdf.go | 48 +--- .../v2/{controlmapping => }/prettyprinter.go | 43 +--- .../v2/resourcemapping/prettyprinter.go | 215 ------------------ resultshandling/printer/v2/resourcetable.go | 93 ++++++++ .../v2/{controlmapping => }/summeryhelpers.go | 2 +- resultshandling/results.go | 3 +- 8 files changed, 143 insertions(+), 299 deletions(-) create mode 100644 resultshandling/printer/v2/controltable.go rename resultshandling/printer/v2/{controlmapping => }/prettyprinter.go (85%) delete mode 100644 resultshandling/printer/v2/resourcemapping/prettyprinter.go create mode 100644 resultshandling/printer/v2/resourcetable.go rename resultshandling/printer/v2/{controlmapping => }/summeryhelpers.go (99%) diff --git a/hostsensorutils/hostsensordeploy.go b/hostsensorutils/hostsensordeploy.go index ca919dd8..0fd080c3 100644 --- a/hostsensorutils/hostsensordeploy.go +++ b/hostsensorutils/hostsensordeploy.go @@ -151,7 +151,7 @@ func (hsh *HostSensorHandler) checkPodForEachNode() error { hsh.podListLock.RLock() podsMap := hsh.HostSensorPodNames hsh.podListLock.RUnlock() - return fmt.Errorf("host-sensor pods number (%d) differ than nodes number (%d) after deadline exceded. We will take data only from the pods below: %v", + return fmt.Errorf("host-sensor pods number (%d) differ than nodes number (%d) after deadline exceeded. Kubescape will take data only from the pods below: %v", podsNum, len(nodesList.Items), podsMap) } time.Sleep(100 * time.Millisecond) diff --git a/resultshandling/printer/v2/controltable.go b/resultshandling/printer/v2/controltable.go new file mode 100644 index 00000000..ea26300b --- /dev/null +++ b/resultshandling/printer/v2/controltable.go @@ -0,0 +1,36 @@ +package v2 + +import ( + "fmt" + "sort" + + "github.com/armosec/opa-utils/reporthandling/results/v1/reportsummary" +) + +func generateRow(controlSummary reportsummary.IControlSummary) []string { + row := []string{controlSummary.GetName()} + row = append(row, fmt.Sprintf("%d", controlSummary.NumberOfResources().Failed())) + row = append(row, fmt.Sprintf("%d", controlSummary.NumberOfResources().Excluded())) + row = append(row, fmt.Sprintf("%d", controlSummary.NumberOfResources().All())) + + if !controlSummary.GetStatus().IsSkipped() { + row = append(row, fmt.Sprintf("%d", int(controlSummary.GetScore()))+"%") + } else { + row = append(row, "skipped") + } + return row +} + +func getSortedControlsNames(controls reportsummary.ControlSummaries) []string { + controlNames := make([]string, 0, len(controls)) + for k := range controls { + c := controls[k] + controlNames = append(controlNames, c.GetName()) + } + sort.Strings(controlNames) + return controlNames +} + +func getControlTableHeaders() []string { + return []string{"CONTROL NAME", "FAILED RESOURCES", "EXCLUDED RESOURCES", "ALL RESOURCES", "% RISK-SCORE"} +} diff --git a/resultshandling/printer/v2/pdf.go b/resultshandling/printer/v2/pdf.go index 4504a541..449fbacd 100644 --- a/resultshandling/printer/v2/pdf.go +++ b/resultshandling/printer/v2/pdf.go @@ -6,7 +6,6 @@ import ( "fmt" "os" "path/filepath" - "sort" "strings" "time" @@ -111,21 +110,8 @@ func (pdfPrinter *PdfPrinter) printHeader(m pdf.Maroto) { // Print pdf frameworks after pdf header. func (pdfPrinter *PdfPrinter) printFramework(m pdf.Maroto, frameworks []reportsummary.IPolicies) { - var p string - if len(frameworks) == 1 { - if frameworks[0].GetName() != "" { - p = fmt.Sprintf("FRAMEWORK %s\n", frameworks[0].GetName()) - } - } else if len(frameworks) > 1 { - p = "FRAMEWORKS: " - i := 0 - for ; i < len(frameworks)-1; i++ { - p += fmt.Sprintf("%s (risk: %.2f), ", frameworks[i].GetName(), frameworks[i].GetScore()) - } - p += fmt.Sprintf("%s (risk: %.2f)\n", frameworks[i].GetName(), frameworks[i].GetScore()) - } m.Row(10, func() { - m.Text(p, props.Text{ + m.Text(frameworksScoresToString(frameworks), props.Text{ Align: consts.Center, Size: 8, Family: consts.Arial, @@ -136,8 +122,7 @@ func (pdfPrinter *PdfPrinter) printFramework(m pdf.Maroto, frameworks []reportsu // Create pdf table func (pdfPrinter *PdfPrinter) printTable(m pdf.Maroto, summaryDetails *reportsummary.SummaryDetails) { - headers := []string{"CONTROL NAME", "FAILED RESOURCES", "EXCLUDED RESOURCES", "ALL RESOURCES", "% RISK-SCORE"} - + headers := getControlTableHeaders() controls := make([][]string, len(pdfPrinter.sortedControlNames)) for i := range controls { controls[i] = make([]string, len(headers)) @@ -215,32 +200,3 @@ func (pdfPrinter *PdfPrinter) printFinalResult(m pdf.Maroto, summaryDetails *rep }) }) } - -// Return sorted control names. -func getSortedControlsNames(controls reportsummary.ControlSummaries) []string { - controlNames := make([]string, 0, len(controls)) - for k := range controls { - c := controls[k] - controlNames = append(controlNames, c.GetName()) - } - sort.Strings(controlNames) - return controlNames -} - -// Generate rows to be appended to the table. -func generateRow(controlSummary reportsummary.IControlSummary) []string { - // We use ReplaceAll because some control name - // has a too long name that unformat the pdf view. - controlName := strings.ReplaceAll(controlSummary.GetName(), "-", " ") - row := []string{controlName} - row = append(row, fmt.Sprintf("%d", controlSummary.NumberOfResources().Failed())) - row = append(row, fmt.Sprintf("%d", controlSummary.NumberOfResources().Excluded())) - row = append(row, fmt.Sprintf("%d", controlSummary.NumberOfResources().All())) - - if !controlSummary.GetStatus().IsSkipped() { - row = append(row, fmt.Sprintf("%d", int(controlSummary.GetScore()))+"%") - } else { - row = append(row, "skipped") - } - return row -} diff --git a/resultshandling/printer/v2/controlmapping/prettyprinter.go b/resultshandling/printer/v2/prettyprinter.go similarity index 85% rename from resultshandling/printer/v2/controlmapping/prettyprinter.go rename to resultshandling/printer/v2/prettyprinter.go index dec73734..b380e680 100644 --- a/resultshandling/printer/v2/controlmapping/prettyprinter.go +++ b/resultshandling/printer/v2/prettyprinter.go @@ -1,4 +1,4 @@ -package controlmapping +package v2 import ( "fmt" @@ -31,6 +31,7 @@ func NewPrettyPrinter(verboseMode bool) *PrettyPrinter { 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) prettyPrinter.printSummaryTable(&opaSessionObj.Report.SummaryDetails) @@ -152,25 +153,6 @@ func generateRelatedObjectsStr(workload WorkloadSummary) string { } return relatedStr } - -func generateRow(controlSummary reportsummary.IControlSummary) []string { - row := []string{controlSummary.GetName()} - row = append(row, fmt.Sprintf("%d", controlSummary.NumberOfResources().Failed())) - row = append(row, fmt.Sprintf("%d", controlSummary.NumberOfResources().Excluded())) - row = append(row, fmt.Sprintf("%d", controlSummary.NumberOfResources().All())) - - if !controlSummary.GetStatus().IsSkipped() { - row = append(row, fmt.Sprintf("%d", int(controlSummary.GetScore()))+"%") - } else { - row = append(row, "skipped") - } - return row -} - -func generateHeader() []string { - return []string{"Control Name", "Failed Resources", "Excluded Resources", "All Resources", "% risk-score"} -} - func generateFooter(summaryDetails *reportsummary.SummaryDetails) []string { // Control name | # failed resources | all resources | % success row := []string{} @@ -184,11 +166,11 @@ func generateFooter(summaryDetails *reportsummary.SummaryDetails) []string { } func (prettyPrinter *PrettyPrinter) printSummaryTable(summaryDetails *reportsummary.SummaryDetails) { // For control scan framework will be nil - prettyPrinter.printFramework(summaryDetails.ListFrameworks().All()) + cautils.InfoTextDisplay(prettyPrinter.writer, frameworksScoresToString(summaryDetails.ListFrameworks().All())) summaryTable := tablewriter.NewWriter(prettyPrinter.writer) summaryTable.SetAutoWrapText(false) - summaryTable.SetHeader(generateHeader()) + summaryTable.SetHeader(getControlTableHeaders()) summaryTable.SetHeaderLine(true) alignments := []int{tablewriter.ALIGN_LEFT, tablewriter.ALIGN_CENTER, tablewriter.ALIGN_CENTER, tablewriter.ALIGN_CENTER, tablewriter.ALIGN_CENTER} summaryTable.SetColumnAlignment(alignments) @@ -203,10 +185,11 @@ func (prettyPrinter *PrettyPrinter) printSummaryTable(summaryDetails *reportsumm summaryTable.Render() } -func (prettyPrinter *PrettyPrinter) printFramework(frameworks []reportsummary.IPolicies) { +func frameworksScoresToString(frameworks []reportsummary.IPolicies) string { if len(frameworks) == 1 { if frameworks[0].GetName() != "" { - cautils.InfoTextDisplay(prettyPrinter.writer, fmt.Sprintf("FRAMEWORK %s\n", frameworks[0].GetName())) + return fmt.Sprintf("FRAMEWORK %s\n", frameworks[0].GetName()) + // cautils.InfoTextDisplay(prettyPrinter.writer, )) } } else if len(frameworks) > 1 { p := "FRAMEWORKS: " @@ -215,17 +198,9 @@ func (prettyPrinter *PrettyPrinter) printFramework(frameworks []reportsummary.IP p += fmt.Sprintf("%s (risk: %.2f), ", frameworks[i].GetName(), frameworks[i].GetScore()) } p += fmt.Sprintf("%s (risk: %.2f)\n", frameworks[i].GetName(), frameworks[i].GetScore()) - cautils.InfoTextDisplay(prettyPrinter.writer, p) + return p } -} -func getSortedControlsNames(controls reportsummary.ControlSummaries) []string { - controlNames := make([]string, 0, len(controls)) - for k := range controls { - c := controls[k] - controlNames = append(controlNames, c.GetName()) - } - sort.Strings(controlNames) - return controlNames + return "" } // func getSortedControlsNames(controls []reportsummary.IPolicies) []string { diff --git a/resultshandling/printer/v2/resourcemapping/prettyprinter.go b/resultshandling/printer/v2/resourcemapping/prettyprinter.go deleted file mode 100644 index 49b29002..00000000 --- a/resultshandling/printer/v2/resourcemapping/prettyprinter.go +++ /dev/null @@ -1,215 +0,0 @@ -package resourcemapping - -import ( - "fmt" - "os" - "strings" - - "github.com/armosec/kubescape/cautils" - "github.com/armosec/kubescape/resultshandling/printer" - "github.com/armosec/opa-utils/reporthandling/results/v1/resourcesresults" - "github.com/olekukonko/tablewriter" -) - -type PrettyPrinter struct { - writer *os.File - verboseMode bool -} - -func NewPrettyPrinter(verboseMode bool) *PrettyPrinter { - return &PrettyPrinter{ - verboseMode: verboseMode, - } -} - -func (prettyPrinter *PrettyPrinter) printResourceTable(results []resourcesresults.Result) { - - summaryTable := tablewriter.NewWriter(prettyPrinter.writer) - summaryTable.SetAutoWrapText(true) - summaryTable.SetAutoMergeCells(false) - // summaryTable.SetCenterSeparator("=") - // summaryTable.SetRowSeparator("*") - // summaryTable. - summaryTable.SetHeader(generateResourceHeader()) - summaryTable.SetHeaderLine(true) - - // For control scan framework will be nil - for i := range results { - // status := result.GetStatus(nil).Status() - resourceID := results[i].GetResourceID() - control := results[i].ListControls() - if raw := generateResourceRow(resourceID, control, prettyPrinter.verboseMode); len(raw) > 0 { - summaryTable.Append(raw) - } - } - - // alignments := []int{tablewriter.ALIGN_LEFT, tablewriter.ALIGN_CENTER, tablewriter.ALIGN_CENTER, tablewriter.ALIGN_CENTER, tablewriter.ALIGN_CENTER} - // summaryTable.SetColumnAlignment(alignments) - - // for i := 0; i < len(prettyPrinter.sortedControlNames); i++ { - // controlSummary := prettyPrinter.summary[prettyPrinter.sortedControlNames[i]] - // summaryTable.Append(generateRow(prettyPrinter.sortedControlNames[i], controlSummary)) - // } - - // summaryTable.SetFooter(generateFooter(prettyPrinter)) - - summaryTable.Render() -} - -func (prettyPrinter *PrettyPrinter) ActionPrint(opaSessionObj *cautils.OPASessionObj) { - - prettyPrinter.printResourceTable(opaSessionObj.Report.Results) - // var overallRiskScore float32 = 0 - // for _, frameworkReport := range opaSessionObj.PostureReport.FrameworkReports { - // frameworkNames = append(frameworkNames, frameworkReport.Name) - // frameworkScores = append(frameworkScores, frameworkReport.Score) - // failedResources = reporthandling.GetUniqueResourcesIDs(append(failedResources, frameworkReport.ListResourcesIDs().GetFailedResources()...)) - // warningResources = reporthandling.GetUniqueResourcesIDs(append(warningResources, frameworkReport.ListResourcesIDs().GetWarningResources()...)) - // allResources = reporthandling.GetUniqueResourcesIDs(append(allResources, frameworkReport.ListResourcesIDs().GetAllResources()...)) - // prettyPrinter.summarySetup(frameworkReport, opaSessionObj.AllResources) - // overallRiskScore += frameworkReport.Score - // } - - // overallRiskScore /= float32(len(opaSessionObj.PostureReport.FrameworkReports)) - - // prettyPrinter.frameworkSummary = ResultSummary{ - // RiskScore: overallRiskScore, - // TotalResources: len(allResources), - // TotalFailed: len(failedResources), - // TotalWarning: len(warningResources), - // } - - // prettyPrinter.printResults() - // prettyPrinter.printSummaryTable(frameworkNames, frameworkScores) - -} - -func (prettyPrinter *PrettyPrinter) SetWriter(outputFile string) { - prettyPrinter.writer = printer.GetWriter(outputFile) -} - -func (prettyPrinter *PrettyPrinter) FinalizeData(opaSessionObj *cautils.OPASessionObj) { - // finalizeReport(opaSessionObj) -} -func (prettyPrinter *PrettyPrinter) Score(score float32) { -} - -// func (prettyPrinter *PrettyPrinter) printSummary(controlName string, controlSummary *ResultSummary) { -// // cautils.SimpleDisplay(prettyPrinter.writer, "Summary - ") -// // cautils.SuccessDisplay(prettyPrinter.writer, "Passed:%v ", controlSummary.TotalResources-controlSummary.TotalFailed-controlSummary.TotalWarning) -// // cautils.WarningDisplay(prettyPrinter.writer, "Excluded:%v ", controlSummary.TotalWarning) -// // cautils.FailureDisplay(prettyPrinter.writer, "Failed:%v ", controlSummary.TotalFailed) -// // cautils.InfoDisplay(prettyPrinter.writer, "Total:%v\n", controlSummary.TotalResources) -// // if controlSummary.TotalFailed > 0 { -// // cautils.DescriptionDisplay(prettyPrinter.writer, "Remediation: %v\n", controlSummary.Remediation) -// // } -// // cautils.DescriptionDisplay(prettyPrinter.writer, "\n") - -// } - -func generateResourceRow(resourceID string, controls []resourcesresults.ResourceAssociatedControl, verboseMode bool) []string { - row := []string{} - - controlsNames := []string{} - statuses := []string{} - - for i := range controls { - if !verboseMode && controls[i].GetStatus(nil).IsPassed() { - continue - } - if controls[i].GetName() == "" { - continue - } - controlsNames = append(controlsNames, controls[i].GetName()) - statuses = append(statuses, string(controls[i].GetStatus(nil).Status())) - } - - splitted := strings.Split(resourceID, "/") - if len(splitted) < 5 || len(controlsNames) == 0 { - return row - } - - row = append(row, splitted[3]) - row = append(row, splitted[4]) - row = append(row, splitted[2]) - - row = append(row, strings.Join(controlsNames, "\n")) - row = append(row, strings.Join(statuses, "\n")) - - return row -} - -// func generateRow(control string, cs ResultSummary) []string { -// row := []string{control} -// row = append(row, cs.ToSlice()...) -// if cs.TotalResources != 0 { -// row = append(row, fmt.Sprintf("%d", int(cs.RiskScore))+"%") -// } else { -// row = append(row, "skipped") -// } -// return row -// } - -func generateResourceHeader() []string { - return []string{"Kind", "Name", "Namespace", "Controls", "Statues"} -} -func generateHeader() []string { - return []string{"Control Name", "Failed Resources", "Excluded Resources", "All Resources", "% risk-score"} -} - -func generateFooter(prettyPrinter *PrettyPrinter) []string { - // Control name | # failed resources | all resources | % success - row := []string{} - // row = append(row, "Resource Summary") //fmt.Sprintf(""%d", numControlers")) - // row = append(row, fmt.Sprintf("%d", prettyPrinter.frameworkSummary.TotalFailed)) - // row = append(row, fmt.Sprintf("%d", prettyPrinter.frameworkSummary.TotalWarning)) - // row = append(row, fmt.Sprintf("%d", prettyPrinter.frameworkSummary.TotalResources)) - // row = append(row, fmt.Sprintf("%.2f%s", prettyPrinter.frameworkSummary.RiskScore, "%")) - - return row -} -func (prettyPrinter *PrettyPrinter) printSummaryTable(frameworksNames []string, frameworkScores []float32) { - // For control scan framework will be nil - prettyPrinter.printFramework(frameworksNames, frameworkScores) - - summaryTable := tablewriter.NewWriter(prettyPrinter.writer) - // summaryTable.SetAutoWrapText(false) - // summaryTable.SetHeader(generateHeader()) - // summaryTable.SetHeaderLine(true) - // alignments := []int{tablewriter.ALIGN_LEFT, tablewriter.ALIGN_CENTER, tablewriter.ALIGN_CENTER, tablewriter.ALIGN_CENTER, tablewriter.ALIGN_CENTER} - // summaryTable.SetColumnAlignment(alignments) - - // for i := 0; i < len(prettyPrinter.sortedControlNames); i++ { - // controlSummary := prettyPrinter.summary[prettyPrinter.sortedControlNames[i]] - // summaryTable.Append(generateRow(prettyPrinter.sortedControlNames[i], controlSummary)) - // } - - // summaryTable.SetFooter(generateFooter(prettyPrinter)) - - summaryTable.Render() -} - -func (prettyPrinter *PrettyPrinter) printFramework(frameworksNames []string, frameworkScores []float32) { - if len(frameworksNames) == 1 { - cautils.InfoTextDisplay(prettyPrinter.writer, fmt.Sprintf("FRAMEWORK %s\n", frameworksNames[0])) - } else if len(frameworksNames) > 1 { - p := "FRAMEWORKS: " - for i := 0; i < len(frameworksNames)-1; i++ { - p += fmt.Sprintf("%s (risk: %.2f), ", frameworksNames[i], frameworkScores[i]) - } - p += fmt.Sprintf("%s (risk: %.2f)\n", frameworksNames[len(frameworksNames)-1], frameworkScores[len(frameworkScores)-1]) - cautils.InfoTextDisplay(prettyPrinter.writer, p) - } -} - -// func (prettyPrinter *PrettyPrinter) getSortedControlsNames() []string { -// controlNames := make([]string, 0, len(prettyPrinter.summary)) -// for k := range prettyPrinter.summary { -// controlNames = append(controlNames, k) -// } -// sort.Strings(controlNames) -// return controlNames -// } -// func getControlURL(controlID string) string { -// return fmt.Sprintf("https://hub.armo.cloud/docs/%s", strings.ToLower(controlID)) -// } diff --git a/resultshandling/printer/v2/resourcetable.go b/resultshandling/printer/v2/resourcetable.go new file mode 100644 index 00000000..bfaaa15e --- /dev/null +++ b/resultshandling/printer/v2/resourcetable.go @@ -0,0 +1,93 @@ +package v2 + +import ( + "fmt" + "strings" + + "github.com/armosec/k8s-interface/workloadinterface" + "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) { + + 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 := [][]string{} + for i := range results { + resource, ok := allResources[i] + if !ok { + continue + } + s := results[i] + if raw := generateResourceRows(resource, s.ListControls(), prettyPrinter.verboseMode); len(raw) > 0 { + data = append(data, raw...) + } + } + sortTable(data) + summaryTable.AppendBulk(data) + + summaryTable.Render() +} + +func generateResourceRows(resource workloadinterface.IMetadata, controls []resourcesresults.ResourceAssociatedControl, verboseMode bool) [][]string { + rows := [][]string{} + + for i := range controls { + + if controls[i].GetName() == "" { + continue + } + row := []string{} + + if !verboseMode && controls[i].GetStatus(nil).IsPassed() { + 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()) + var paths []string + for j := range controls[i].ResourceAssociatedRules { + for k := range controls[i].ResourceAssociatedRules[j].Paths { + if p := controls[i].ResourceAssociatedRules[j].Paths[k].FailedPath; p != "" { + paths = append(paths, p) + } + if p := controls[i].ResourceAssociatedRules[j].Paths[k].FixPath.Path; p != "" { + v := controls[i].ResourceAssociatedRules[j].Paths[k].FixPath.Value + paths = append(paths, fmt.Sprintf("%s=%s", p, v)) + } + } + } + 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) + } + + return rows +} + +func generateResourceHeader() []string { + return []string{"Control", "Namespace", "Kind/Name", "Statues"} +} + +func sortTable(data [][]string) { + + for j := len(data[0]) - 1; j >= 0; j-- { + for k := 0; k < len(data)-2; { + if data[k][j] > data[k+1][j] { + tmp := data[k] + data[k] = data[k+1] + data[k+1] = tmp + k = 0 + } else { + k++ + } + } + } +} diff --git a/resultshandling/printer/v2/controlmapping/summeryhelpers.go b/resultshandling/printer/v2/summeryhelpers.go similarity index 99% rename from resultshandling/printer/v2/controlmapping/summeryhelpers.go rename to resultshandling/printer/v2/summeryhelpers.go index cc606f8a..09d0f2e8 100644 --- a/resultshandling/printer/v2/controlmapping/summeryhelpers.go +++ b/resultshandling/printer/v2/summeryhelpers.go @@ -1,4 +1,4 @@ -package controlmapping +package v2 import ( "github.com/armosec/k8s-interface/k8sinterface" diff --git a/resultshandling/results.go b/resultshandling/results.go index 86662250..1736a9f8 100644 --- a/resultshandling/results.go +++ b/resultshandling/results.go @@ -6,7 +6,6 @@ import ( "github.com/armosec/kubescape/resultshandling/printer" printerv1 "github.com/armosec/kubescape/resultshandling/printer/v1" printerv2 "github.com/armosec/kubescape/resultshandling/printer/v2" - "github.com/armosec/kubescape/resultshandling/printer/v2/controlmapping" "github.com/armosec/kubescape/resultshandling/reporter" "github.com/armosec/opa-utils/reporthandling" @@ -66,6 +65,6 @@ func NewPrinter(printFormat string, verboseMode bool) printer.IPrinter { case printer.PdfFormat: return printerv2.NewPdfPrinter() default: - return controlmapping.NewPrettyPrinter(verboseMode) + return printerv2.NewPrettyPrinter(verboseMode) } } From d5fcbe842fc62943c68c44ee2b341f2430e7341f Mon Sep 17 00:00:00 2001 From: dwertent Date: Thu, 24 Feb 2022 09:50:12 +0200 Subject: [PATCH 2/6] adding autocompletion --- clihandler/cmd/completion.go | 43 ++++++++++++++++++++++++++++++++++++ go.sum | 9 +++++--- 2 files changed, 49 insertions(+), 3 deletions(-) create mode 100644 clihandler/cmd/completion.go diff --git a/clihandler/cmd/completion.go b/clihandler/cmd/completion.go new file mode 100644 index 00000000..7613441f --- /dev/null +++ b/clihandler/cmd/completion.go @@ -0,0 +1,43 @@ +package cmd + +import ( + "os" + "strings" + + "github.com/spf13/cobra" +) + +var completionCmdExamples = ` + + # Enable BASH shell autocompletion + echo 'source <(kubescape completion bash)' >> ~/.bashrc + + # Enable ZSH shell autocompletion + echo 'source <(kubectl completion zsh)' >> "${fpath[1]}/_kubectl" + +` +var completionCmd = &cobra.Command{ + Use: "completion [bash|zsh|fish|powershell]", + Short: "Generate autocompletion script", + Long: "To load completions", + Example: completionCmdExamples, + DisableFlagsInUseLine: true, + ValidArgs: []string{"bash", "zsh", "fish", "powershell"}, + Args: cobra.ExactValidArgs(1), + Run: func(cmd *cobra.Command, args []string) { + switch strings.ToLower(args[0]) { + case "bash": + cmd.Root().GenBashCompletion(os.Stdout) + case "zsh": + cmd.Root().GenZshCompletion(os.Stdout) + case "fish": + cmd.Root().GenFishCompletion(os.Stdout, true) + case "powershell": + cmd.Root().GenPowerShellCompletionWithDesc(os.Stdout) + } + }, +} + +func init() { + rootCmd.AddCommand(completionCmd) +} diff --git a/go.sum b/go.sum index 6c8dffcb..99dfc09a 100644 --- a/go.sum +++ b/go.sum @@ -85,8 +85,9 @@ github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmV github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armosec/armoapi-go v0.0.2/go.mod h1:vIK17yoKbJRQyZXWWLe3AqfqCRITxW8qmSkApyq5xFs= github.com/armosec/armoapi-go v0.0.23/go.mod h1:iaVVGyc23QGGzAdv4n+szGQg3Rbpixn9yQTU3qWRpaw= -github.com/armosec/armoapi-go v0.0.49 h1:b3gvZ5YB5DSEfk8pt7x0705b4Pcuahd3wI/ZmGYmB3Y= github.com/armosec/armoapi-go v0.0.49/go.mod h1:iaVVGyc23QGGzAdv4n+szGQg3Rbpixn9yQTU3qWRpaw= +github.com/armosec/armoapi-go v0.0.54 h1:8PjT7qpvt5YsR0OxRRoQ891IOaWThlTJvVgRVReBBLA= +github.com/armosec/armoapi-go v0.0.54/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.50/go.mod h1:vHxGWqD/uh6+GQb9Sqv7OGMs+Rvc2dsFVc0XtgRh1ZU= @@ -363,8 +364,9 @@ github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go v2.0.0+incompatible h1:j0GKcs05QVmm7yesiZq2+9cxHkNK9YM6zKx4D2qucQU= github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg= @@ -947,8 +949,9 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= From 36b384036266d9fc7b4851d003a422d9f5037604 Mon Sep 17 00:00:00 2001 From: dwertent Date: Thu, 24 Feb 2022 12:09:47 +0200 Subject: [PATCH 3/6] support host sensor from local file --- cautils/scaninfo.go | 3 ++- clihandler/cmd/root.go | 3 ++- clihandler/cmd/scan.go | 5 ++++- clihandler/initcliutils.go | 8 ++++---- hostsensorutils/hostsensordeploy.go | 19 ++++++++++++++++++- 5 files changed, 30 insertions(+), 8 deletions(-) diff --git a/cautils/scaninfo.go b/cautils/scaninfo.go index de242233..0030fc36 100644 --- a/cautils/scaninfo.go +++ b/cautils/scaninfo.go @@ -70,7 +70,8 @@ type ScanInfo struct { Silent bool // Silent mode - Do not print progress logs FailThreshold uint16 // Failure score threshold Submit bool // Submit results to Armo BE - HostSensor BoolPtrFlag // Deploy ARMO K8s host sensor to collect data from certain controls + HostSensorEnabled BoolPtrFlag // Deploy ARMO K8s host sensor to collect data from certain controls + HostSensorYamlPath string // Path to hostsensor file Local bool // Do not submit results Account string // account ID Logger string // logger level diff --git a/clihandler/cmd/root.go b/clihandler/cmd/root.go index 96245611..8fc1d615 100644 --- a/clihandler/cmd/root.go +++ b/clihandler/cmd/root.go @@ -35,13 +35,14 @@ var rootCmd = &cobra.Command{ Use: "kubescape", Version: cautils.BuildNumber, Short: "Kubescape is a tool for testing Kubernetes security posture", - Long: `Kubescape is a tool for testing Kubernetes security posture based on NSA \ MITRE ATT&CK® and other frameworks specifications`, + Long: `Based on NSA \ MITRE ATT&CK® and other frameworks specifications`, Example: ksExamples, } func Execute() { rootCmd.Execute() } + func init() { cobra.OnInitialize(initLogger, initLoggerLevel, initEnvironment, initCacheDir) diff --git a/clihandler/cmd/scan.go b/clihandler/cmd/scan.go index b2861228..ef1587d2 100644 --- a/clihandler/cmd/scan.go +++ b/clihandler/cmd/scan.go @@ -58,7 +58,10 @@ 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") - hostF := scanCmd.PersistentFlags().VarPF(&scanInfo.HostSensor, "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") + scanCmd.PersistentFlags().StringVar(&scanInfo.HostSensorYamlPath, "host-scan-yaml", "", "Override default host sensor DaemonSet. Use this flag cautiously") + scanCmd.PersistentFlags().MarkHidden("host-scan-yaml") + + 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") hostF.NoOptDefVal = "true" hostF.DefValue = "false, for no TTY in stdin" diff --git a/clihandler/initcliutils.go b/clihandler/initcliutils.go index 1a364ea1..a466690d 100644 --- a/clihandler/initcliutils.go +++ b/clihandler/initcliutils.go @@ -74,12 +74,12 @@ func getHostSensorHandler(scanInfo *cautils.ScanInfo, k8s *k8sinterface.Kubernet hasHostSensorControls := true // we need to determined which controls needs host sensor - if scanInfo.HostSensor.Get() == nil && hasHostSensorControls { - scanInfo.HostSensor.SetBool(askUserForHostSensor()) + if scanInfo.HostSensorEnabled.Get() == nil && hasHostSensorControls { + scanInfo.HostSensorEnabled.SetBool(askUserForHostSensor()) logger.L().Warning("Kubernetes cluster nodes scanning is disabled. This is required to collect valuable data for certain controls. You can enable it using the --enable-host-scan flag") } - if hostSensorVal := scanInfo.HostSensor.Get(); hostSensorVal != nil && *hostSensorVal { - hostSensorHandler, err := hostsensorutils.NewHostSensorHandler(k8s) + if hostSensorVal := scanInfo.HostSensorEnabled.Get(); hostSensorVal != nil && *hostSensorVal { + hostSensorHandler, err := hostsensorutils.NewHostSensorHandler(k8s, scanInfo.HostSensorYamlPath) if err != nil { logger.L().Warning(fmt.Sprintf("failed to create host sensor: %s", err.Error())) return &hostsensorutils.HostSensorHandlerMock{} diff --git a/hostsensorutils/hostsensordeploy.go b/hostsensorutils/hostsensordeploy.go index 0fd080c3..efe6adf0 100644 --- a/hostsensorutils/hostsensordeploy.go +++ b/hostsensorutils/hostsensordeploy.go @@ -4,6 +4,7 @@ import ( _ "embed" "fmt" "io" + "os" "strings" "sync" "time" @@ -37,11 +38,18 @@ type HostSensorHandler struct { gracePeriod int64 } -func NewHostSensorHandler(k8sObj *k8sinterface.KubernetesApi) (*HostSensorHandler, error) { +func NewHostSensorHandler(k8sObj *k8sinterface.KubernetesApi, hostSensorYAMLFile string) (*HostSensorHandler, error) { if k8sObj == nil { return nil, fmt.Errorf("nil k8s interface received") } + if hostSensorYAMLFile != "" { + d, err := loadHostSensorFromFile(hostSensorYAMLFile) + if err != nil { + return nil, fmt.Errorf("failed to load host-scan yaml file, reason: %s", err.Error()) + } + hostSensorYAML = d + } hsh := &HostSensorHandler{ k8sObj: k8sObj, HostSensorPodNames: map[string]string{}, @@ -249,3 +257,12 @@ func (hsh *HostSensorHandler) GetNamespace() string { } return hsh.DaemonSet.Namespace } + +func loadHostSensorFromFile(hostSensorYAMLFile string) (string, error) { + dat, err := os.ReadFile(hostSensorYAMLFile) + if err != nil { + return "", err + } + // TODO - Add file validation + return string(dat), err +} From 8694a929cf271cd7be52d79da952bc260011119e Mon Sep 17 00:00:00 2001 From: dwertent Date: Thu, 24 Feb 2022 13:57:33 +0200 Subject: [PATCH 4/6] support output versions --- README.md | 5 ++- cautils/scaninfo.go | 1 + clihandler/cmd/framework.go | 11 +------ clihandler/cmd/scan.go | 35 ++++++++++++++++++--- clihandler/initcli.go | 2 +- resultshandling/printer/v2/prettyprinter.go | 17 +++++++--- resultshandling/printer/v2/resourcetable.go | 4 ++- resultshandling/results.go | 4 +-- 8 files changed, 54 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 309e161e..06e4cab8 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,8 @@ Want to contribute? Want to discuss something? Have an issue? # Options and examples +[Kubescape docs](https://hub.armo.cloud/docs) + ## Playground * [Kubescape playground](https://www.katacoda.com/pathaksaiyam/scenarios/kubescape) @@ -65,9 +67,10 @@ Want to contribute? Want to discuss something? Have an issue? * [Overview](https://youtu.be/wdBkt_0Qhbg) * [How To Secure Kubernetes Clusters With Kubescape And Armo](https://youtu.be/ZATGiDIDBQk) -* [Scanning Kubernetes YAML files](https://youtu.be/Ox6DaR7_4ZI) +* [Scan Kubernetes YAML files](https://youtu.be/Ox6DaR7_4ZI) * [Scan Kubescape on an air-gapped environment (offline support)](https://youtu.be/IGXL9s37smM) * [Managing exceptions in the Kubescape SaaS version](https://youtu.be/OzpvxGmCR80) +* [Configure and run customized frameworks](https://youtu.be/12Sanq_rEhs) ## Install on Windows diff --git a/cautils/scaninfo.go b/cautils/scaninfo.go index 0030fc36..9bef29b3 100644 --- a/cautils/scaninfo.go +++ b/cautils/scaninfo.go @@ -64,6 +64,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 ExcludedNamespaces string // used for host sensor namespace IncludeNamespaces string // DEPRECATED? InputPatterns []string // Yaml files input patterns diff --git a/clihandler/cmd/framework.go b/clihandler/cmd/framework.go index f06c9c80..ad978473 100644 --- a/clihandler/cmd/framework.go +++ b/clihandler/cmd/framework.go @@ -16,7 +16,7 @@ import ( var ( frameworkExample = ` # Scan all frameworks and submit the results - kubescape scan --submit + kubescape scan framework all --submit # Scan the NSA framework kubescape scan framework nsa @@ -30,15 +30,6 @@ var ( # Scan kubernetes YAML manifest files kubescape scan framework nsa *.yaml - # Scan and save the results in the JSON format - kubescape scan --format json --output results.json - - # Save scan results in JSON format - kubescape scan --format json --output results.json - - # Display all resources - kubescape scan --verbose - Run 'kubescape list frameworks' for the list of supported frameworks ` ) diff --git a/clihandler/cmd/scan.go b/clihandler/cmd/scan.go index ef1587d2..55e7ead1 100644 --- a/clihandler/cmd/scan.go +++ b/clihandler/cmd/scan.go @@ -8,11 +8,32 @@ import ( var scanInfo cautils.ScanInfo +var scanCmdExamples = ` + Scan command is for scanning an existing cluster or kubernetes manifest files based on pre-defind frameworks + + # Scan current cluster with all frameworks + kubescape scan --submit --enable-host-scan + + # Scan kubernetes YAML manifest files + kubescape scan *.yaml + + # Scan and save the results in the JSON format + kubescape scan --format json --output results.json + + # Display all resources + kubescape scan --verbose + + # Scan different clusters from the kubectl context + kubescape scan --kube-context + +` + // scanCmd represents the scan command var scanCmd = &cobra.Command{ - Use: "scan [command]", - Short: "Scan the current running cluster or yaml files", - Long: `The action you want to perform`, + Use: "scan", + Short: "Scan the current running cluster or yaml files", + Long: `The action you want to perform`, + Example: scanCmdExamples, Args: func(cmd *cobra.Command, args []string) error { if len(args) > 0 { if args[0] != "framework" && args[0] != "control" { @@ -57,9 +78,13 @@ func init() { scanCmd.PersistentFlags().StringSliceVar(&scanInfo.UseFrom, "use-from", nil, "Load local policy object from specified path. If not used will download latest") 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().MarkHidden("host-scan-yaml") + scanCmd.PersistentFlags().StringVar(&scanInfo.OutputVersion, "output-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 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") hostF.NoOptDefVal = "true" diff --git a/clihandler/initcli.go b/clihandler/initcli.go index a0dab3c3..0a96a51f 100644 --- a/clihandler/initcli.go +++ b/clihandler/initcli.go @@ -83,7 +83,7 @@ func getInterfaces(scanInfo *cautils.ScanInfo) componentInterfaces { reportHandler := getReporter(tenantConfig, scanInfo.Submit) // setup printer - printerHandler := resultshandling.NewPrinter(scanInfo.Format, scanInfo.VerboseMode) + printerHandler := resultshandling.NewPrinter(scanInfo.Format, scanInfo.OutputVersion, scanInfo.VerboseMode) printerHandler.SetWriter(scanInfo.Output) // ================== return interface ====================================== diff --git a/resultshandling/printer/v2/prettyprinter.go b/resultshandling/printer/v2/prettyprinter.go index b380e680..75e7053b 100644 --- a/resultshandling/printer/v2/prettyprinter.go +++ b/resultshandling/printer/v2/prettyprinter.go @@ -17,21 +17,23 @@ import ( ) type PrettyPrinter struct { + outputVersion string writer *os.File verboseMode bool sortedControlNames []string } -func NewPrettyPrinter(verboseMode bool) *PrettyPrinter { +func NewPrettyPrinter(verboseMode bool, outputVersion string) *PrettyPrinter { return &PrettyPrinter{ - verboseMode: verboseMode, + verboseMode: verboseMode, + outputVersion: outputVersion, } } func (prettyPrinter *PrettyPrinter) ActionPrint(opaSessionObj *cautils.OPASessionObj) { prettyPrinter.sortedControlNames = getSortedControlsNames(opaSessionObj.Report.SummaryDetails.Controls) // ListControls().All()) - // prettyPrinter.resourceTable(opaSessionObj.ResourcesResult, opaSessionObj.AllResources) + prettyPrinter.resourceTable(opaSessionObj.ResourcesResult, opaSessionObj.AllResources) prettyPrinter.printResults(&opaSessionObj.Report.SummaryDetails.Controls, opaSessionObj.AllResources) prettyPrinter.printSummaryTable(&opaSessionObj.Report.SummaryDetails) @@ -45,6 +47,10 @@ 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) @@ -165,8 +171,6 @@ func generateFooter(summaryDetails *reportsummary.SummaryDetails) []string { return row } func (prettyPrinter *PrettyPrinter) printSummaryTable(summaryDetails *reportsummary.SummaryDetails) { - // For control scan framework will be nil - cautils.InfoTextDisplay(prettyPrinter.writer, frameworksScoresToString(summaryDetails.ListFrameworks().All())) summaryTable := tablewriter.NewWriter(prettyPrinter.writer) summaryTable.SetAutoWrapText(false) @@ -183,6 +187,9 @@ func (prettyPrinter *PrettyPrinter) printSummaryTable(summaryDetails *reportsumm // summaryTable.SetFooter(generateFooter()) summaryTable.Render() + + // For control scan framework will be nil + cautils.InfoTextDisplay(prettyPrinter.writer, frameworksScoresToString(summaryDetails.ListFrameworks().All())) } func frameworksScoresToString(frameworks []reportsummary.IPolicies) string { diff --git a/resultshandling/printer/v2/resourcetable.go b/resultshandling/printer/v2/resourcetable.go index bfaaa15e..cc291e8e 100644 --- a/resultshandling/printer/v2/resourcetable.go +++ b/resultshandling/printer/v2/resourcetable.go @@ -10,7 +10,9 @@ 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) diff --git a/resultshandling/results.go b/resultshandling/results.go index 1736a9f8..f6f4917d 100644 --- a/resultshandling/results.go +++ b/resultshandling/results.go @@ -53,7 +53,7 @@ func CalculatePostureScore(postureReport *reporthandling.PostureReport) float32 return (float32(len(allResources)) - float32(len(failedResources))) / float32(len(allResources)) } -func NewPrinter(printFormat string, verboseMode bool) printer.IPrinter { +func NewPrinter(printFormat, outputVersion string, verboseMode bool) printer.IPrinter { switch printFormat { case printer.JsonFormat: @@ -65,6 +65,6 @@ func NewPrinter(printFormat string, verboseMode bool) printer.IPrinter { case printer.PdfFormat: return printerv2.NewPdfPrinter() default: - return printerv2.NewPrettyPrinter(verboseMode) + return printerv2.NewPrettyPrinter(verboseMode, outputVersion) } } From dc172a147645ce31d0774ea40c097730392f1137 Mon Sep 17 00:00:00 2001 From: dwertent Date: Thu, 24 Feb 2022 18:22:29 +0200 Subject: [PATCH 5/6] fixed help message --- cautils/scaninfo.go | 6 ++++-- cautils/versioncheck.go | 6 +++--- clihandler/cmd/root.go | 19 +++++++++---------- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/cautils/scaninfo.go b/cautils/scaninfo.go index 9bef29b3..7f21ff3d 100644 --- a/cautils/scaninfo.go +++ b/cautils/scaninfo.go @@ -53,6 +53,10 @@ func (bpf *BoolPtrFlag) Set(val string) error { return nil } +type RootInfo struct { + Logger string // logger level + CacheDir string // cached dir +} type ScanInfo struct { Getters PolicyIdentifier []reporthandling.PolicyIdentifier @@ -75,8 +79,6 @@ type ScanInfo struct { HostSensorYamlPath string // Path to hostsensor file Local bool // Do not submit results Account string // account ID - Logger string // logger level - CacheDir string // cached dir KubeContext string // context name FrameworkScan bool // false if scanning control ScanAll bool // true if scan all frameworks diff --git a/cautils/versioncheck.go b/cautils/versioncheck.go index b53bced7..83385df1 100644 --- a/cautils/versioncheck.go +++ b/cautils/versioncheck.go @@ -98,7 +98,7 @@ func (v *VersionCheckHandler) CheckLatestVersion(versionData *VersionCheckReques if latestVersion.ClientUpdate != "" { if BuildNumber != "" && BuildNumber < latestVersion.ClientUpdate { - logger.L().Warning(warningMessage(latestVersion.Client, latestVersion.ClientUpdate)) + logger.L().Warning(warningMessage(latestVersion.ClientUpdate)) } } @@ -133,6 +133,6 @@ func (v *VersionCheckHandler) getLatestVersion(versionData *VersionCheckRequest) return vResp, nil } -func warningMessage(kind, release string) string { - return fmt.Sprintf("'%s' is not updated to the latest release: '%s'", kind, release) +func warningMessage(release string) string { + return fmt.Sprintf("current version '%s' is not updated to the latest release: '%s'", BuildNumber, release) } diff --git a/clihandler/cmd/root.go b/clihandler/cmd/root.go index 8fc1d615..8c3dff7c 100644 --- a/clihandler/cmd/root.go +++ b/clihandler/cmd/root.go @@ -1,7 +1,6 @@ package cmd import ( - "flag" "fmt" "os" "strings" @@ -14,6 +13,7 @@ import ( ) var armoBEURLs = "" +var rootInfo cautils.RootInfo const envFlagUsage = "Send report results to specific URL. Format:,,.\n\t\tExample:report.armo.cloud,api.armo.cloud,portal.armo.cloud" @@ -44,14 +44,13 @@ func Execute() { } func init() { + cobra.OnInitialize(initLogger, initLoggerLevel, initEnvironment, initCacheDir) - flag.CommandLine.StringVar(&armoBEURLs, "environment", "", envFlagUsage) rootCmd.PersistentFlags().StringVar(&armoBEURLs, "environment", "", envFlagUsage) rootCmd.PersistentFlags().MarkHidden("environment") - rootCmd.PersistentFlags().StringVarP(&scanInfo.Logger, "logger", "l", helpers.InfoLevel.String(), fmt.Sprintf("Logger level. Supported: %s [$KS_LOGGER]", strings.Join(helpers.SupportedLevels(), "/"))) - rootCmd.PersistentFlags().StringVar(&scanInfo.CacheDir, "cache-dir", getter.DefaultLocalStore, "Cache directory [$KS_CACHE_DIR]") - flag.Parse() + rootCmd.PersistentFlags().StringVarP(&rootInfo.Logger, "logger", "l", helpers.InfoLevel.String(), fmt.Sprintf("Logger level. Supported: %s [$KS_LOGGER]", strings.Join(helpers.SupportedLevels(), "/"))) + rootCmd.PersistentFlags().StringVar(&rootInfo.CacheDir, "cache-dir", getter.DefaultLocalStore, "Cache directory [$KS_CACHE_DIR]") } func initLogger() { @@ -60,18 +59,18 @@ func initLogger() { } } func initLoggerLevel() { - if scanInfo.Logger != helpers.InfoLevel.String() { + if rootInfo.Logger != helpers.InfoLevel.String() { } else if l := os.Getenv("KS_LOGGER"); l != "" { - scanInfo.Logger = l + rootInfo.Logger = l } - if err := logger.L().SetLevel(scanInfo.Logger); err != nil { + if err := logger.L().SetLevel(rootInfo.Logger); err != nil { logger.L().Fatal(fmt.Sprintf("supported levels: %s", strings.Join(helpers.SupportedLevels(), "/")), helpers.Error(err)) } } func initCacheDir() { - if scanInfo.CacheDir != getter.DefaultLocalStore { - getter.DefaultLocalStore = scanInfo.CacheDir + if rootInfo.CacheDir != getter.DefaultLocalStore { + getter.DefaultLocalStore = rootInfo.CacheDir } else if cacheDir := os.Getenv("KS_CACHE_DIR"); cacheDir != "" { getter.DefaultLocalStore = cacheDir } else { From db95da37424aa2ff16e1a153374be4a43e1655db Mon Sep 17 00:00:00 2001 From: dwertent Date: Thu, 24 Feb 2022 18:43:29 +0200 Subject: [PATCH 6/6] udpate packages --- go.mod | 19 +++++++------ go.sum | 85 +++++++++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 82 insertions(+), 22 deletions(-) diff --git a/go.mod b/go.mod index 9988151e..5a61d8ea 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,8 @@ module github.com/armosec/kubescape go 1.17 require ( - github.com/armosec/armoapi-go v0.0.54 - github.com/armosec/k8s-interface v0.0.60 + github.com/armosec/armoapi-go v0.0.57 + github.com/armosec/k8s-interface v0.0.63 github.com/armosec/opa-utils v0.0.110 github.com/armosec/rbac-utils v0.0.14 github.com/armosec/utils-go v0.0.3 @@ -29,7 +29,8 @@ require ( ) require ( - cloud.google.com/go v0.81.0 // indirect + cloud.google.com/go v0.97.0 // indirect + cloud.google.com/go/container v1.0.0 // indirect github.com/Azure/go-autorest v14.2.0+incompatible // indirect github.com/Azure/go-autorest/autorest v0.11.18 // indirect github.com/Azure/go-autorest/autorest/adal v0.9.13 // indirect @@ -61,14 +62,13 @@ require ( github.com/go-gota/gota v0.12.0 // indirect github.com/go-logr/logr v0.4.0 // indirect github.com/gobwas/glob v0.2.3 // indirect - github.com/gofrs/uuid v4.1.0+incompatible // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/glog v1.0.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/google/go-cmp v0.5.6 // indirect github.com/google/gofuzz v1.1.0 // indirect - github.com/googleapis/gax-go/v2 v2.0.5 // indirect + github.com/googleapis/gax-go/v2 v2.1.1 // indirect github.com/googleapis/gnostic v0.5.5 // indirect github.com/imdario/mergo v0.3.12 // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect @@ -86,7 +86,6 @@ require ( github.com/pquerna/cachecontrol v0.1.0 // indirect github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 // indirect github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58 // indirect - github.com/satori/go.uuid v1.2.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect @@ -97,15 +96,15 @@ require ( golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 // indirect golang.org/x/net v0.0.0-20210825183410-e898025ed96a // indirect golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1 // indirect - golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf // indirect + golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359 // indirect golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d // indirect golang.org/x/text v0.3.7 // indirect golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect gonum.org/v1/gonum v0.9.1 // indirect - google.golang.org/api v0.44.0 // indirect + google.golang.org/api v0.59.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c // indirect - google.golang.org/grpc v1.38.0 // indirect + google.golang.org/genproto v0.0.0-20211027162914-98a5263abeca // indirect + google.golang.org/grpc v1.40.0 // indirect google.golang.org/protobuf v1.27.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/square/go-jose.v2 v2.6.0 // indirect diff --git a/go.sum b/go.sum index 99dfc09a..56b612fa 100644 --- a/go.sum +++ b/go.sum @@ -19,14 +19,23 @@ cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKP cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= -cloud.google.com/go v0.81.0 h1:at8Tk2zUz63cLPR0JPWm5vp77pEZmzxEQBEfRKn1VV8= cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= +cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= +cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= +cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= +cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= +cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= +cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= +cloud.google.com/go v0.97.0 h1:3DXvAyifywvq64LfkKaMOmkWPS1CikIQdMe2lY9vxU8= +cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/container v1.0.0 h1:k3IMcHEEJR4pQmj4/gNeUuA4azhW7i2RPX8xGhyneZw= +cloud.google.com/go/container v1.0.0/go.mod h1:EQLhTDFhzVXTX6TmjfNqa3/ikbCzjGlZcGY67exUnlY= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= @@ -86,13 +95,13 @@ github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj github.com/armosec/armoapi-go v0.0.2/go.mod h1:vIK17yoKbJRQyZXWWLe3AqfqCRITxW8qmSkApyq5xFs= github.com/armosec/armoapi-go v0.0.23/go.mod h1:iaVVGyc23QGGzAdv4n+szGQg3Rbpixn9yQTU3qWRpaw= github.com/armosec/armoapi-go v0.0.49/go.mod h1:iaVVGyc23QGGzAdv4n+szGQg3Rbpixn9yQTU3qWRpaw= -github.com/armosec/armoapi-go v0.0.54 h1:8PjT7qpvt5YsR0OxRRoQ891IOaWThlTJvVgRVReBBLA= -github.com/armosec/armoapi-go v0.0.54/go.mod h1:iaVVGyc23QGGzAdv4n+szGQg3Rbpixn9yQTU3qWRpaw= +github.com/armosec/armoapi-go v0.0.57 h1:uAYohbzo+ZXZ4FR9R0i6181susGllWI4auUXQQhKQdQ= +github.com/armosec/armoapi-go v0.0.57/go.mod h1:U/Axd+D5N00x9Ekr7t+5HXqLCMO+98NfJSVAggqJftI= 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.50/go.mod h1:vHxGWqD/uh6+GQb9Sqv7OGMs+Rvc2dsFVc0XtgRh1ZU= -github.com/armosec/k8s-interface v0.0.60 h1:jTCiO15QQbHVuxFQ928rp4srf1rQoUzeybfcbv/cuss= -github.com/armosec/k8s-interface v0.0.60/go.mod h1:g0jv/fG+VqpT5ivO6D2gJcJ/w68BiffDz+PcU9YFbL4= +github.com/armosec/k8s-interface v0.0.63 h1:RuMqsYcneVUD7HJkMVxjc8N6bpWd6rhJ5K85USMq1Sg= +github.com/armosec/k8s-interface v0.0.63/go.mod h1:vwprS8qn/iowd5yf0JHpqDsLA5I8W2muqX9AxKhkb0Q= github.com/armosec/opa-utils v0.0.64/go.mod h1:6tQP8UDq2EvEfSqh8vrUdr/9QVSCG4sJfju1SXQOn4c= github.com/armosec/opa-utils v0.0.110 h1:qncGcbnYjiGULP3yK+4geRNNpRoWqKXQL+Xg+iXc1cM= github.com/armosec/opa-utils v0.0.110/go.mod h1:Wc1P4gkB6UQeGW8I76zCuitGGl15Omp0bKw7N0tR9dk= @@ -165,6 +174,7 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= @@ -216,6 +226,7 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ= github.com/evanphx/json-patch v4.11.0+incompatible h1:glyUF9yIYtMHzn8xaKw5rMhdWcwsYV8dZHIq5567/xs= @@ -277,7 +288,6 @@ github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/gofrs/uuid v4.1.0+incompatible h1:sIa2eCvUTwgjbqXrPLfNwUf9S3i3mpH1O1atV+iL/Wk= github.com/gofrs/uuid v4.1.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= @@ -303,6 +313,7 @@ github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -351,6 +362,7 @@ github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/ github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= @@ -362,6 +374,9 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -371,8 +386,10 @@ github.com/googleapis/gax-go v2.0.0+incompatible h1:j0GKcs05QVmm7yesiZq2+9cxHkNK github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= +github.com/googleapis/gax-go/v2 v2.1.1 h1:dp3bWCh+PPO1zjRRiCSczJav13sBvG4UhNyVTa1KqdU= +github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= github.com/googleapis/gnostic v0.5.5 h1:9fHAtK0uDfpveeqqo1hkEZJcFvYXAiCN3UutL8F9xHw= github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA= @@ -584,7 +601,6 @@ github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58 h1:nlG4Wa5+minh3S9LVFtNoY+GVRiudA2e3EVfcCi3RCA= github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= @@ -833,6 +849,7 @@ golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLd golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -853,6 +870,9 @@ golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1 h1:B333XXssMuKQeBwiNODx4TupZy7bf4sxFZnN2ZOcvUE= golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= @@ -931,13 +951,19 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf h1:2ucpDCmfkl8Bd/FsLtiD653Wf96cW37s+iGx93zsu4k= golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359 h1:2B5p2L5IfGiD7+b9BOoRMC6DgObAVZV+Fsp050NqXik= +golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE= @@ -1020,7 +1046,10 @@ golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1060,8 +1089,17 @@ google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34q google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= -google.golang.org/api v0.44.0 h1:URs6qR1lAxDsqWITsQXI4ZkGiYJ5dHtRNiCpfs2OeKA= google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= +google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= +google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= +google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= +google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= +google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= +google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= +google.golang.org/api v0.59.0 h1:fPfFO7gttlXYo2ALuD3HxJzh8vaF++4youI0BkFL6GE= +google.golang.org/api v0.59.0/go.mod h1:sT2boj7M9YJxZzgeZqXogmhfmRWDtPzT31xkieUbuZU= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1118,8 +1156,26 @@ google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c h1:wtujag7C+4D6KMoulW9YauvK2lgdvCMS260jsqqBXr0= +google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= +google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= +google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210921142501-181ce0d877f6/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211008145708-270636b82663/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211027162914-98a5263abeca h1:+e+aQDO4/c9KaG8PXWHTc6/+Du6kz+BKcXCSnV4SSTE= +google.golang.org/genproto v0.0.0-20211027162914-98a5263abeca/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= @@ -1143,8 +1199,13 @@ google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAG google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.38.0 h1:/9BgsAsa5nWe26HqOlvlgJnqBuktYOLCgjCPqsa56W0= +google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.40.0 h1:AGJ0Ih4mHjSeibYkFGh1dD9KJ/eOtZ93I6hoHhukQ5Q= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=