From cf4317b5f67e222f03ec74ba5faa8da74aaf397a Mon Sep 17 00:00:00 2001 From: alegrey91 Date: Thu, 17 Feb 2022 18:16:29 +0100 Subject: [PATCH 1/2] feat(resulthandling): add support for pdf format output --- clihandler/cmd/scan.go | 2 +- go.mod | 5 + go.sum | 10 + resultshandling/printer/printresults.go | 1 + resultshandling/printer/v2/pdf.go | 246 +++++++++++++++++++++ resultshandling/printer/v2/pdf/logo.png | Bin 0 -> 54270 bytes resultshandling/printer/v2/printresults.go | 2 + 7 files changed, 265 insertions(+), 1 deletion(-) create mode 100644 resultshandling/printer/v2/pdf.go create mode 100644 resultshandling/printer/v2/pdf/logo.png diff --git a/clihandler/cmd/scan.go b/clihandler/cmd/scan.go index cdb62449..b2861228 100644 --- a/clihandler/cmd/scan.go +++ b/clihandler/cmd/scan.go @@ -48,7 +48,7 @@ func init() { scanCmd.PersistentFlags().StringVar(&scanInfo.UseArtifactsFrom, "use-artifacts-from", "", "Load artifacts from local directory. If not used will download them") scanCmd.PersistentFlags().StringVarP(&scanInfo.ExcludedNamespaces, "exclude-namespaces", "e", "", "Namespaces to exclude from scanning. Recommended: kube-system,kube-public") scanCmd.PersistentFlags().Uint16VarP(&scanInfo.FailThreshold, "fail-threshold", "t", 100, "Failure threshold is the percent above which the command fails and returns exit code 1") - scanCmd.PersistentFlags().StringVarP(&scanInfo.Format, "format", "f", "pretty-printer", `Output format. Supported formats: "pretty-printer"/"json"/"junit"/"prometheus"`) + scanCmd.PersistentFlags().StringVarP(&scanInfo.Format, "format", "f", "pretty-printer", `Output format. Supported formats: "pretty-printer","json","junit","prometheus","pdf"`) scanCmd.PersistentFlags().StringVar(&scanInfo.IncludeNamespaces, "include-namespaces", "", "scan specific namespaces. e.g: --include-namespaces ns-a,ns-b") scanCmd.PersistentFlags().BoolVarP(&scanInfo.Local, "keep-local", "", false, "If you do not want your Kubescape results reported to Armo backend. Use this flag if you ran with the '--submit' flag in the past and you do not want to submit your current scan results") scanCmd.PersistentFlags().StringVarP(&scanInfo.Output, "output", "o", "", "Output file. Print output to file and not stdout") diff --git a/go.mod b/go.mod index 35cdc24c..ca9009c0 100644 --- a/go.mod +++ b/go.mod @@ -14,6 +14,7 @@ require ( github.com/fatih/color v1.13.0 github.com/francoispqt/gojay v1.2.13 github.com/gofrs/uuid v4.1.0+incompatible + github.com/johnfercher/maroto v0.34.0 github.com/mattn/go-isatty v0.0.14 github.com/olekukonko/tablewriter v0.0.5 github.com/open-policy-agent/opa v0.33.1 @@ -50,6 +51,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/sso v1.8.0 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.13.0 // indirect github.com/aws/smithy-go v1.9.1 // indirect + github.com/boombuler/barcode v1.0.0 // indirect github.com/coreos/go-oidc v2.2.1+incompatible // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/docker/docker v20.10.9+incompatible // indirect @@ -66,12 +68,14 @@ require ( 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/google/uuid v1.1.2 // indirect github.com/googleapis/gax-go/v2 v2.0.5 // 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 github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/json-iterator/go v1.1.11 // indirect + github.com/jung-kurt/gofpdf v1.4.2 // indirect github.com/mattn/go-colorable v0.1.9 // indirect github.com/mattn/go-runewidth v0.0.9 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect @@ -82,6 +86,7 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect 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/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 diff --git a/go.sum b/go.sum index c1d4f78f..6c8dffcb 100644 --- a/go.sum +++ b/go.sum @@ -141,6 +141,7 @@ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kB github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/boombuler/barcode v1.0.0 h1:s1TvRnXwL2xJRaccrdcBQMZxq6X7DvsMogtmJeHDdrc= github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= github.com/briandowns/spinner v1.18.0 h1:SJs0maNOs4FqhBwiJ3Gr7Z1D39/rukIVGQvpNZVHVcM= @@ -362,6 +363,7 @@ 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/googleapis/gax-go v2.0.0+incompatible h1:j0GKcs05QVmm7yesiZq2+9cxHkNK9YM6zKx4D2qucQU= github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= @@ -416,6 +418,8 @@ github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9Y github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +github.com/johnfercher/maroto v0.34.0 h1:kmqlO280WbjzeaPn8HtqUE3gooauVwqO/3cmrBtCL4A= +github.com/johnfercher/maroto v0.34.0/go.mod h1:UeLY7evCe2Au8KwHFzaSGffKGADEZK+u6O8C74mdudM= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= @@ -431,6 +435,8 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= +github.com/jung-kurt/gofpdf v1.4.2 h1:3u2ojTwxPPu3ysIOc5iTwcECpvkFCAe2RJ/tQrvfLi0= +github.com/jung-kurt/gofpdf v1.4.2/go.mod h1:rZsO0wEsunjT/L9stF3fJjYbAHgqNYuQB4B8FWvBck0= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= @@ -573,6 +579,7 @@ github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6L github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +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= @@ -636,6 +643,8 @@ github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -742,6 +751,7 @@ golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6 h1:QE6XYQK6naiK1EPAe1g/ILLxN golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190507092727-e4e5bf290fec/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20200119044424-58c23975cae1/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= diff --git a/resultshandling/printer/printresults.go b/resultshandling/printer/printresults.go index 1ac75455..30aaf302 100644 --- a/resultshandling/printer/printresults.go +++ b/resultshandling/printer/printresults.go @@ -15,6 +15,7 @@ const ( JsonFormat string = "json" JunitResultFormat string = "junit" PrometheusFormat string = "prometheus" + PdfFormat string = "pdf" ) type IPrinter interface { diff --git a/resultshandling/printer/v2/pdf.go b/resultshandling/printer/v2/pdf.go new file mode 100644 index 00000000..d594b4e6 --- /dev/null +++ b/resultshandling/printer/v2/pdf.go @@ -0,0 +1,246 @@ +package v2 + +import ( + _ "embed" + b64 "encoding/base64" + "fmt" + "os" + "path/filepath" + "sort" + "strings" + "time" + + "github.com/armosec/kubescape/cautils" + "github.com/armosec/kubescape/resultshandling/printer" + "github.com/armosec/opa-utils/reporthandling/results/v1/reportsummary" + "github.com/johnfercher/maroto/pkg/color" + "github.com/johnfercher/maroto/pkg/consts" + "github.com/johnfercher/maroto/pkg/pdf" + "github.com/johnfercher/maroto/pkg/props" +) + +const ( + pdfOutputFile = "report" + pdfOutputExt = ".pdf" +) + +var ( + //go:embed pdf/logo.png + kubescapeLogo []byte +) + +type PdfPrinter struct { + writer *os.File + sortedControlNames []string +} + +func NewPdfPrinter() *PdfPrinter { + return &PdfPrinter{} +} + +func (pdfPrinter *PdfPrinter) SetWriter(outputFile string) { + // Ensure to have an available output file, otherwise create it. + if outputFile == "" { + outputFile = pdfOutputFile + } + // Ensure to have the right file extension. + if filepath.Ext(strings.TrimSpace(outputFile)) != pdfOutputExt { + outputFile = outputFile + pdfOutputExt + } + pdfPrinter.writer = printer.GetWriter(outputFile) +} + +func (pdfPrinter *PdfPrinter) Score(score float32) { + fmt.Fprintf(os.Stderr, "\nOverall risk-score (0- Excellent, 100- All failed): %d\n", int(score)) +} + +func (pdfPrinter *PdfPrinter) ActionPrint(opaSessionObj *cautils.OPASessionObj) { + pdfPrinter.sortedControlNames = getSortedControlsNames(opaSessionObj.Report.SummaryDetails.Controls) + + m := pdf.NewMaroto(consts.Portrait, consts.A4) + pdfPrinter.printHeader(m) + pdfPrinter.printFramework(m, opaSessionObj.Report.SummaryDetails.ListFrameworks().All()) + pdfPrinter.printTable(m, &opaSessionObj.Report.SummaryDetails) + pdfPrinter.printFinalResult(m, &opaSessionObj.Report.SummaryDetails) + + // Extrat output buffer. + outBuff, err := m.Output() + if err != nil { + fmt.Println("Could not save PDF:", err) + os.Exit(1) + } + pdfPrinter.writer.Write(outBuff.Bytes()) +} + +// Print Kubescape logo and report date. +func (pdfPrinter *PdfPrinter) printHeader(m pdf.Maroto) { + // Retrieve current time (we need it for the report timestamp). + t := time.Now() + // Enconde PNG into Base64 to embed it into the pdf. + kubescapeLogoEnc := b64.StdEncoding.EncodeToString(kubescapeLogo) + + m.SetPageMargins(10, 15, 10) + m.Row(40, func() { + //m.Text(fmt.Sprintf("Security Assessment"), props.Text{ + // Align: consts.Center, + // Size: 24, + // Family: consts.Arial, + // Style: consts.Bold, + //}) + _ = m.Base64Image(kubescapeLogoEnc, consts.Png, props.Rect{ + Center: true, + Percent: 100, + }) + }) + m.Row(6, func() { + m.Text(fmt.Sprintf("Report date: %d-%02d-%02dT%02d:%02d:%02d", + t.Year(), + t.Month(), + t.Day(), + t.Hour(), + t.Minute(), + t.Second()), props.Text{ + Align: consts.Left, + Size: 6.0, + Style: consts.Bold, + Family: consts.Arial, + }) + }) + m.Line(1) +} + +// 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(fmt.Sprintf(p), props.Text{ + Align: consts.Center, + Size: 8, + Family: consts.Arial, + Style: consts.Bold, + }) + }) +} + +// 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"} + + controls := make([][]string, len(pdfPrinter.sortedControlNames)) + for i := range controls { + controls[i] = make([]string, len(headers)) + } + for i := 0; i < len(pdfPrinter.sortedControlNames); i++ { + controls[i] = generateRow(summaryDetails.Controls.GetControl(reportsummary.EControlCriteriaName, pdfPrinter.sortedControlNames[i])) + } + + m.TableList(headers, controls, props.TableList{ + HeaderProp: props.TableListContent{ + Family: consts.Arial, + Style: consts.Bold, + Size: 8.0, + }, + ContentProp: props.TableListContent{ + Family: consts.Courier, + Style: consts.Normal, + Size: 8.0, + }, + Align: consts.Center, + AlternatedBackground: &color.Color{ + Red: 224, + Green: 224, + Blue: 224, + }, + HeaderContentSpace: 2.0, + Line: false, + }) + m.Line(1) + m.Row(2, func(){}) +} + +// Add final results. +func (pdfPrinter *PdfPrinter) printFinalResult(m pdf.Maroto, summaryDetails *reportsummary.SummaryDetails) { + m.Row(5, func() { + m.Col(3, func() { + m.Text("Resource summary", props.Text{ + Align: consts.Left, + Size: 8.0, + Style: consts.Bold, + Family: consts.Arial, + }) + }) + m.Col(2, func() { + m.Text(fmt.Sprintf("%d", summaryDetails.NumberOfResources().Failed()), props.Text{ + Align: consts.Left, + Size: 8.0, + Style: consts.Bold, + Family: consts.Arial, + }) + }) + m.Col(2, func() { + m.Text(fmt.Sprintf("%d", summaryDetails.NumberOfResources().Excluded()), props.Text{ + Align: consts.Left, + Size: 8.0, + Style: consts.Bold, + Family: consts.Arial, + }) + }) + m.Col(2, func() { + m.Text(fmt.Sprintf("%d", summaryDetails.NumberOfResources().All()), props.Text{ + Align: consts.Left, + Size: 8.0, + Style: consts.Bold, + Family: consts.Arial, + }) + }) + m.Col(2, func() { + m.Text(fmt.Sprintf("%.2f%s", summaryDetails.Score, "%"), props.Text{ + Align: consts.Left, + Size: 8.0, + Style: consts.Bold, + Family: consts.Arial, + }) + }) + }) +} + +// 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/pdf/logo.png b/resultshandling/printer/v2/pdf/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..cfa8ffc1a75c7f9774b6105cc50f752d7f94eec4 GIT binary patch literal 54270 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 literal 0 HcmV?d00001 diff --git a/resultshandling/printer/v2/printresults.go b/resultshandling/printer/v2/printresults.go index 04b0aa28..8dcda6c4 100644 --- a/resultshandling/printer/v2/printresults.go +++ b/resultshandling/printer/v2/printresults.go @@ -15,6 +15,8 @@ func GetPrinter(printFormat string, verboseMode bool) printer.IPrinter { return NewJunitPrinter() // case printer.PrometheusFormat: // return NewPrometheusPrinter(verboseMode) + case printer.PdfFormat: + return NewPdfPrinter() default: return resourcemapping.NewPrettyPrinter(verboseMode) } From 5f2e5c6f4ec232b03928eb8b1c5492e54e3a5772 Mon Sep 17 00:00:00 2001 From: alegrey91 Date: Thu, 17 Feb 2022 18:17:12 +0100 Subject: [PATCH 2/2] docs: describe support for pdf format output --- README.md | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ebaa5320..3d6ce3bb 100644 --- a/README.md +++ b/README.md @@ -96,12 +96,12 @@ Set-ExecutionPolicy RemoteSigned -scope CurrentUser | `--include-namespaces` | Scan all namespaces | Scan specific namespaces | | | `-s`/`--silent` | Display progress messages | Silent progress messages | | | `-t`/`--fail-threshold` | `100` (do not fail) | fail command (return exit code 1) if result is above threshold | `0` -> `100` | -| `-f`/`--format` | `pretty-printer` | Output format | `pretty-printer`/`json`/`junit`/`prometheus` | +| `-f`/`--format` | `pretty-printer` | Output format | `pretty-printer`/`json`/`junit`/`prometheus`/`pdf` | | `-o`/`--output` | print to stdout | Save scan result in file | | -| `--use-from` | | Load local framework object from specified path. If not used will download latest | +| `--use-from` | | Load local framework object from specified path. If not used will download latest || | `--use-artifacts-from` | | Load artifacts (frameworks, control-config, exceptions) from local directory. If not used will download them | | | `--use-default` | `false` | Load local framework object from default path. If not used will download latest | `true`/`false` | -| `--exceptions` | | Path to an exceptions obj, [examples](examples/exceptions/README.md). Default will download exceptions from Kubescape SaaS | +| `--exceptions` | | Path to an exceptions obj, [examples](examples/exceptions/README.md). Default will download exceptions from Kubescape SaaS || | `--controls-config` | | Path to a controls-config obj. If not set will download controls-config from ARMO management portal | | | `--submit` | `false` | If set, Kubescape will 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 sent | `true`/`false` | | `--keep-local` | `false` | Kubescape will not send scan results to Armo management portal. Use this flag if you ran with the `--submit` flag in the past and you do not want to submit your current scan results | `true`/`false` | @@ -173,7 +173,14 @@ kubescape scan --format json --output results.json kubescape scan --format junit --output results.xml ``` +#### Output in `pdf` format + +``` +kubescape scan --format pdf --output results.pdf +``` + #### Output in `prometheus` metrics format - Contributed by [@Joibel](https://github.com/Joibel) + ``` kubescape scan --format prometheus ```