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  }