github.com/devseccon/trivy@v0.47.1-0.20231123133102-bd902a0bd996/pkg/report/writer.go (about) 1 package report 2 3 import ( 4 "io" 5 "strings" 6 "sync" 7 8 "golang.org/x/xerrors" 9 10 cr "github.com/devseccon/trivy/pkg/compliance/report" 11 ftypes "github.com/devseccon/trivy/pkg/fanal/types" 12 "github.com/devseccon/trivy/pkg/flag" 13 "github.com/devseccon/trivy/pkg/log" 14 "github.com/devseccon/trivy/pkg/report/cyclonedx" 15 "github.com/devseccon/trivy/pkg/report/github" 16 "github.com/devseccon/trivy/pkg/report/predicate" 17 "github.com/devseccon/trivy/pkg/report/spdx" 18 "github.com/devseccon/trivy/pkg/report/table" 19 "github.com/devseccon/trivy/pkg/types" 20 ) 21 22 const ( 23 SchemaVersion = 2 24 ) 25 26 // Write writes the result to output, format as passed in argument 27 func Write(report types.Report, option flag.Options) error { 28 output, cleanup, err := option.OutputWriter() 29 if err != nil { 30 return xerrors.Errorf("failed to create a file: %w", err) 31 } 32 defer cleanup() 33 34 // Compliance report 35 if option.Compliance.Spec.ID != "" { 36 return complianceWrite(report, option, output) 37 } 38 39 var writer Writer 40 switch option.Format { 41 case types.FormatTable: 42 writer = &table.Writer{ 43 Output: output, 44 Severities: option.Severities, 45 Tree: option.DependencyTree, 46 ShowMessageOnce: &sync.Once{}, 47 IncludeNonFailures: option.IncludeNonFailures, 48 Trace: option.Trace, 49 LicenseRiskThreshold: option.LicenseRiskThreshold, 50 IgnoredLicenses: option.IgnoredLicenses, 51 } 52 case types.FormatJSON: 53 writer = &JSONWriter{Output: output} 54 case types.FormatGitHub: 55 writer = &github.Writer{ 56 Output: output, 57 Version: option.AppVersion, 58 } 59 case types.FormatCycloneDX: 60 // TODO: support xml format option with cyclonedx writer 61 writer = cyclonedx.NewWriter(output, option.AppVersion) 62 case types.FormatSPDX, types.FormatSPDXJSON: 63 writer = spdx.NewWriter(output, option.AppVersion, option.Format) 64 case types.FormatTemplate: 65 // We keep `sarif.tpl` template working for backward compatibility for a while. 66 if strings.HasPrefix(option.Template, "@") && strings.HasSuffix(option.Template, "sarif.tpl") { 67 log.Logger.Warn("Using `--template sarif.tpl` is deprecated. Please migrate to `--format sarif`. See https://github.com/devseccon/trivy/discussions/1571") 68 writer = &SarifWriter{ 69 Output: output, 70 Version: option.AppVersion, 71 } 72 break 73 } 74 var err error 75 if writer, err = NewTemplateWriter(output, option.Template); err != nil { 76 return xerrors.Errorf("failed to initialize template writer: %w", err) 77 } 78 case types.FormatSarif: 79 target := "" 80 if report.ArtifactType == ftypes.ArtifactFilesystem { 81 target = option.Target 82 } 83 writer = &SarifWriter{ 84 Output: output, 85 Version: option.AppVersion, 86 Target: target, 87 } 88 case types.FormatCosignVuln: 89 writer = predicate.NewVulnWriter(output, option.AppVersion) 90 default: 91 return xerrors.Errorf("unknown format: %v", option.Format) 92 } 93 94 if err := writer.Write(report); err != nil { 95 return xerrors.Errorf("failed to write results: %w", err) 96 } 97 return nil 98 } 99 100 func complianceWrite(report types.Report, opt flag.Options, output io.Writer) error { 101 complianceReport, err := cr.BuildComplianceReport([]types.Results{report.Results}, opt.Compliance) 102 if err != nil { 103 return xerrors.Errorf("compliance report build error: %w", err) 104 } 105 return cr.Write(complianceReport, cr.Option{ 106 Format: opt.Format, 107 Report: opt.ReportFormat, 108 Output: output, 109 Severities: opt.Severities, 110 }) 111 } 112 113 // Writer defines the result write operation 114 type Writer interface { 115 Write(types.Report) error 116 }