github.com/khulnasoft-lab/tunnel-db@v0.0.0-20231117205118-74e1113bd007/pkg/vulnsrc/photon/photon.go (about)

     1  package photon
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"io"
     7  	"log"
     8  	"path/filepath"
     9  
    10  	bolt "go.etcd.io/bbolt"
    11  	"golang.org/x/xerrors"
    12  
    13  	"github.com/khulnasoft-lab/tunnel-db/pkg/db"
    14  	"github.com/khulnasoft-lab/tunnel-db/pkg/types"
    15  	"github.com/khulnasoft-lab/tunnel-db/pkg/utils"
    16  	"github.com/khulnasoft-lab/tunnel-db/pkg/vulnsrc/vulnerability"
    17  )
    18  
    19  const (
    20  	photonDir      = "photon"
    21  	platformFormat = "Photon OS %s"
    22  )
    23  
    24  var source = types.DataSource{
    25  	ID:   vulnerability.Photon,
    26  	Name: "Photon OS CVE metadata",
    27  	URL:  "https://packages.vmware.com/photon/photon_cve_metadata/",
    28  }
    29  
    30  type VulnSrc struct {
    31  	dbc db.Operation
    32  }
    33  
    34  func NewVulnSrc() VulnSrc {
    35  	return VulnSrc{
    36  		dbc: db.Config{},
    37  	}
    38  }
    39  
    40  func (vs VulnSrc) Name() types.SourceID {
    41  	return source.ID
    42  }
    43  
    44  func (vs VulnSrc) Update(dir string) error {
    45  	rootDir := filepath.Join(dir, "vuln-list", photonDir)
    46  
    47  	var cves []PhotonCVE
    48  	err := utils.FileWalk(rootDir, func(r io.Reader, path string) error {
    49  		var cve PhotonCVE
    50  		if err := json.NewDecoder(r).Decode(&cve); err != nil {
    51  			return xerrors.Errorf("failed to decode Photon JSON: %w", err)
    52  		}
    53  		cves = append(cves, cve)
    54  
    55  		return nil
    56  	})
    57  	if err != nil {
    58  		return xerrors.Errorf("error in Photon walk: %w", err)
    59  	}
    60  
    61  	if err = vs.save(cves); err != nil {
    62  		return xerrors.Errorf("unable to save Photon advisories: %w", err)
    63  	}
    64  
    65  	return nil
    66  }
    67  
    68  func (vs VulnSrc) save(cves []PhotonCVE) error {
    69  	log.Println("Saving Photon DB")
    70  	err := vs.dbc.BatchUpdate(func(tx *bolt.Tx) error {
    71  		return vs.commit(tx, cves)
    72  	})
    73  	if err != nil {
    74  		return xerrors.Errorf("error in batch update: %w", err)
    75  	}
    76  
    77  	return nil
    78  }
    79  
    80  func (vs VulnSrc) commit(tx *bolt.Tx, cves []PhotonCVE) error {
    81  	for _, cve := range cves {
    82  		platformName := fmt.Sprintf(platformFormat, cve.OSVersion)
    83  		if err := vs.dbc.PutDataSource(tx, platformName, source); err != nil {
    84  			return xerrors.Errorf("failed to put data source: %w", err)
    85  		}
    86  
    87  		advisory := types.Advisory{
    88  			FixedVersion: cve.ResVer,
    89  		}
    90  		if err := vs.dbc.PutAdvisoryDetail(tx, cve.CveID, cve.Pkg, []string{platformName}, advisory); err != nil {
    91  			return xerrors.Errorf("failed to save Photon advisory: %w", err)
    92  		}
    93  
    94  		vuln := types.VulnerabilityDetail{
    95  			// Photon uses CVSS Version 3.X
    96  			CvssScoreV3: cve.CveScore,
    97  		}
    98  		if err := vs.dbc.PutVulnerabilityDetail(tx, cve.CveID, source.ID, vuln); err != nil {
    99  			return xerrors.Errorf("failed to save Photon vulnerability detail: %w", err)
   100  		}
   101  
   102  		// for optimization
   103  		if err := vs.dbc.PutVulnerabilityID(tx, cve.CveID); err != nil {
   104  			return xerrors.Errorf("failed to save the vulnerability ID: %w", err)
   105  		}
   106  	}
   107  	return nil
   108  }
   109  
   110  func (vs VulnSrc) Get(release string, pkgName string) ([]types.Advisory, error) {
   111  	bucket := fmt.Sprintf(platformFormat, release)
   112  	advisories, err := vs.dbc.GetAdvisories(bucket, pkgName)
   113  	if err != nil {
   114  		return nil, xerrors.Errorf("failed to get Photon advisories: %w", err)
   115  	}
   116  	return advisories, nil
   117  }