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

     1  package predicate
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"io"
     7  	"time"
     8  
     9  	"github.com/package-url/packageurl-go"
    10  	"golang.org/x/xerrors"
    11  
    12  	"github.com/devseccon/trivy/pkg/clock"
    13  	"github.com/devseccon/trivy/pkg/types"
    14  )
    15  
    16  // CosignVulnPredicate represents the Cosign Vulnerability Scan Record.
    17  // CosignVulnPredicate is based on structures in the Cosign repository.
    18  // We defined them ourselves to reduce our dependence on the repository.
    19  // cf. https://github.com/sigstore/cosign/blob/e0547cff64f98585a837a524ff77ff6b47ff5609/pkg/cosign/attestation/attestation.go#L45-L50
    20  type CosignVulnPredicate struct {
    21  	Invocation Invocation `json:"invocation"`
    22  	Scanner    Scanner    `json:"scanner"`
    23  	Metadata   Metadata   `json:"metadata"`
    24  }
    25  
    26  type Invocation struct {
    27  	Parameters interface{} `json:"parameters"`
    28  	URI        string      `json:"uri"`
    29  	EventID    string      `json:"event_id"`
    30  	BuilderID  string      `json:"builder.id"`
    31  }
    32  
    33  type DB struct {
    34  	URI     string `json:"uri"`
    35  	Version string `json:"version"`
    36  }
    37  
    38  type Scanner struct {
    39  	URI     string       `json:"uri"`
    40  	Version string       `json:"version"`
    41  	DB      DB           `json:"db"`
    42  	Result  types.Report `json:"result"`
    43  }
    44  
    45  type Metadata struct {
    46  	ScanStartedOn  time.Time `json:"scanStartedOn"`
    47  	ScanFinishedOn time.Time `json:"scanFinishedOn"`
    48  }
    49  
    50  type VulnWriter struct {
    51  	output  io.Writer
    52  	version string
    53  }
    54  
    55  func NewVulnWriter(output io.Writer, version string) VulnWriter {
    56  	return VulnWriter{
    57  		output:  output,
    58  		version: version,
    59  	}
    60  }
    61  
    62  func (w VulnWriter) Write(report types.Report) error {
    63  
    64  	predicate := CosignVulnPredicate{}
    65  
    66  	purl := packageurl.NewPackageURL("github", "aquasecurity", "trivy", w.version, nil, "")
    67  	predicate.Scanner = Scanner{
    68  		URI:     purl.ToString(),
    69  		Version: w.version,
    70  		Result:  report,
    71  	}
    72  
    73  	now := clock.Now()
    74  	predicate.Metadata = Metadata{
    75  		ScanStartedOn:  now,
    76  		ScanFinishedOn: now,
    77  	}
    78  
    79  	output, err := json.MarshalIndent(predicate, "", "  ")
    80  	if err != nil {
    81  		return xerrors.Errorf("failed to marshal cosign vulnerability predicate: %w", err)
    82  	}
    83  
    84  	if _, err = fmt.Fprint(w.output, string(output)); err != nil {
    85  		return xerrors.Errorf("failed to write cosign vulnerability predicate: %w", err)
    86  	}
    87  	return nil
    88  
    89  }