github.com/devseccon/trivy@v0.47.1-0.20231123133102-bd902a0bd996/pkg/compliance/report/report.go (about)

     1  package report
     2  
     3  import (
     4  	"io"
     5  
     6  	"golang.org/x/xerrors"
     7  
     8  	defsecTypes "github.com/aquasecurity/defsec/pkg/types"
     9  	dbTypes "github.com/aquasecurity/trivy-db/pkg/types"
    10  	"github.com/devseccon/trivy/pkg/compliance/spec"
    11  	"github.com/devseccon/trivy/pkg/types"
    12  )
    13  
    14  const (
    15  	allReport     = "all"
    16  	summaryReport = "summary"
    17  )
    18  
    19  type Option struct {
    20  	Format        types.Format
    21  	Report        string
    22  	Output        io.Writer
    23  	Severities    []dbTypes.Severity
    24  	ColumnHeading []string
    25  }
    26  
    27  // ComplianceReport represents a kubernetes scan report
    28  type ComplianceReport struct {
    29  	ID               string
    30  	Title            string
    31  	Description      string
    32  	Version          string
    33  	RelatedResources []string
    34  	Results          []*ControlCheckResult
    35  }
    36  
    37  type ControlCheckResult struct {
    38  	ID            string
    39  	Name          string
    40  	Description   string
    41  	DefaultStatus defsecTypes.ControlStatus `json:",omitempty"`
    42  	Severity      string
    43  	Results       types.Results
    44  }
    45  
    46  // SummaryReport represents a kubernetes scan report with consolidated findings
    47  type SummaryReport struct {
    48  	SchemaVersion   int `json:",omitempty"`
    49  	ID              string
    50  	Title           string
    51  	SummaryControls []ControlCheckSummary `json:",omitempty"`
    52  }
    53  
    54  type ControlCheckSummary struct {
    55  	ID        string
    56  	Name      string
    57  	Severity  string
    58  	TotalFail *int `json:",omitempty"`
    59  }
    60  
    61  // Writer defines the result write operation
    62  type Writer interface {
    63  	Write(ComplianceReport) error
    64  }
    65  
    66  // Write writes the results in the give format
    67  func Write(report *ComplianceReport, option Option) error {
    68  	switch option.Format {
    69  	case types.FormatJSON:
    70  		jwriter := JSONWriter{
    71  			Output: option.Output,
    72  			Report: option.Report,
    73  		}
    74  		return jwriter.Write(report)
    75  	case types.FormatTable:
    76  		if !report.empty() {
    77  			complianceWriter := &TableWriter{
    78  				Output:     option.Output,
    79  				Report:     option.Report,
    80  				Severities: option.Severities,
    81  			}
    82  			err := complianceWriter.Write(report)
    83  			if err != nil {
    84  				return err
    85  			}
    86  		}
    87  		return nil
    88  	default:
    89  		return xerrors.Errorf(`unknown format %q. Use "json" or "table"`, option.Format)
    90  	}
    91  }
    92  
    93  func (r ComplianceReport) empty() bool {
    94  	return len(r.Results) == 0
    95  }
    96  
    97  // buildControlCheckResults create compliance results data
    98  func buildControlCheckResults(checksMap map[string]types.Results, controls []defsecTypes.Control) []*ControlCheckResult {
    99  	var complianceResults []*ControlCheckResult
   100  	for _, control := range controls {
   101  		var results types.Results
   102  		for _, c := range control.Checks {
   103  			results = append(results, checksMap[c.ID]...)
   104  		}
   105  		complianceResults = append(complianceResults, &ControlCheckResult{
   106  			Name:          control.Name,
   107  			ID:            control.ID,
   108  			Description:   control.Description,
   109  			Severity:      string(control.Severity),
   110  			DefaultStatus: control.DefaultStatus,
   111  			Results:       results,
   112  		})
   113  	}
   114  	return complianceResults
   115  }
   116  
   117  // buildComplianceReportResults create compliance results data
   118  func buildComplianceReportResults(checksMap map[string]types.Results, s defsecTypes.Spec) *ComplianceReport {
   119  	controlCheckResult := buildControlCheckResults(checksMap, s.Controls)
   120  	return &ComplianceReport{
   121  		ID:               s.ID,
   122  		Title:            s.Title,
   123  		Description:      s.Description,
   124  		Version:          s.Version,
   125  		RelatedResources: s.RelatedResources,
   126  		Results:          controlCheckResult,
   127  	}
   128  }
   129  
   130  func BuildComplianceReport(scanResults []types.Results, cs spec.ComplianceSpec) (*ComplianceReport, error) {
   131  	// aggregate checks by ID
   132  	aggregateChecksByID := spec.AggregateAllChecksBySpecID(scanResults, cs)
   133  
   134  	// build compliance report results
   135  	return buildComplianceReportResults(aggregateChecksByID, cs.Spec), nil
   136  }