github.com/khulnasoft-lab/tunnel-db@v0.0.0-20231117205118-74e1113bd007/pkg/vulnsrc/chainguard/chainguard.go (about) 1 package chainguard 2 3 import ( 4 "encoding/json" 5 "io" 6 "path/filepath" 7 "strings" 8 9 bolt "go.etcd.io/bbolt" 10 "golang.org/x/xerrors" 11 12 "github.com/khulnasoft-lab/tunnel-db/pkg/db" 13 "github.com/khulnasoft-lab/tunnel-db/pkg/types" 14 "github.com/khulnasoft-lab/tunnel-db/pkg/utils" 15 "github.com/khulnasoft-lab/tunnel-db/pkg/vulnsrc/vulnerability" 16 ) 17 18 const ( 19 chainguardDir = "chainguard" 20 distroName = "chainguard" 21 ) 22 23 var ( 24 source = types.DataSource{ 25 ID: vulnerability.Chainguard, 26 Name: "Chainguard Security Data", 27 URL: "https://packages.cgr.dev/chainguard/security.json", 28 } 29 ) 30 31 type VulnSrc struct { 32 dbc db.Operation 33 } 34 35 func NewVulnSrc() VulnSrc { 36 return VulnSrc{ 37 dbc: db.Config{}, 38 } 39 } 40 41 func (vs VulnSrc) Name() types.SourceID { 42 return source.ID 43 } 44 45 func (vs VulnSrc) Update(dir string) error { 46 rootDir := filepath.Join(dir, "vuln-list", chainguardDir) 47 var advisories []advisory 48 err := utils.FileWalk(rootDir, func(r io.Reader, path string) error { 49 var advisory advisory 50 if err := json.NewDecoder(r).Decode(&advisory); err != nil { 51 return xerrors.Errorf("failed to decode Chainguard advisory: %w", err) 52 } 53 advisories = append(advisories, advisory) 54 return nil 55 }) 56 if err != nil { 57 return xerrors.Errorf("error in Chainguard walk: %w", err) 58 } 59 60 if err = vs.save(advisories); err != nil { 61 return xerrors.Errorf("error in Chainguard save: %w", err) 62 } 63 64 return nil 65 } 66 67 func (vs VulnSrc) save(advisories []advisory) error { 68 err := vs.dbc.BatchUpdate(func(tx *bolt.Tx) error { 69 for _, adv := range advisories { 70 bucket := distroName 71 if err := vs.dbc.PutDataSource(tx, bucket, source); err != nil { 72 return xerrors.Errorf("failed to put data source: %w", err) 73 } 74 if err := vs.saveSecFixes(tx, distroName, adv.PkgName, adv.Secfixes); err != nil { 75 return err 76 } 77 } 78 return nil 79 }) 80 if err != nil { 81 return xerrors.Errorf("error in db batch update: %w", err) 82 } 83 return nil 84 } 85 86 func (vs VulnSrc) saveSecFixes(tx *bolt.Tx, platform, pkgName string, secfixes map[string][]string) error { 87 for fixedVersion, vulnIDs := range secfixes { 88 advisory := types.Advisory{ 89 FixedVersion: fixedVersion, 90 } 91 92 for _, vulnID := range vulnIDs { 93 if !strings.HasPrefix(vulnID, "CVE-") { 94 continue 95 } 96 97 if err := vs.dbc.PutAdvisoryDetail(tx, vulnID, pkgName, []string{platform}, advisory); err != nil { 98 return xerrors.Errorf("failed to save Chainguard advisory: %w", err) 99 } 100 101 // for optimization 102 if err := vs.dbc.PutVulnerabilityID(tx, vulnID); err != nil { 103 return xerrors.Errorf("failed to save the vulnerability ID: %w", err) 104 } 105 } 106 } 107 108 return nil 109 } 110 111 func (vs VulnSrc) Get(_, pkgName string) ([]types.Advisory, error) { 112 bucket := distroName 113 advisories, err := vs.dbc.GetAdvisories(bucket, pkgName) 114 if err != nil { 115 return nil, xerrors.Errorf("failed to get Chainguard advisories: %w", err) 116 } 117 return advisories, nil 118 }