github.com/khulnasoft-lab/tunnel-db@v0.0.0-20231117205118-74e1113bd007/pkg/vulnsrc/alpine/alpine.go (about) 1 package alpine 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "io" 7 "path/filepath" 8 "strings" 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 alpineDir = "alpine" 21 ) 22 23 var ( 24 platformFormat = "alpine %s" 25 26 source = types.DataSource{ 27 ID: vulnerability.Alpine, 28 Name: "Alpine Secdb", 29 URL: "https://secdb.alpinelinux.org/", 30 } 31 ) 32 33 type VulnSrc struct { 34 dbc db.Operation 35 } 36 37 func NewVulnSrc() VulnSrc { 38 return VulnSrc{ 39 dbc: db.Config{}, 40 } 41 } 42 43 func (vs VulnSrc) Name() types.SourceID { 44 return source.ID 45 } 46 47 func (vs VulnSrc) Update(dir string) error { 48 rootDir := filepath.Join(dir, "vuln-list", alpineDir) 49 var advisories []advisory 50 err := utils.FileWalk(rootDir, func(r io.Reader, path string) error { 51 var advisory advisory 52 if err := json.NewDecoder(r).Decode(&advisory); err != nil { 53 return xerrors.Errorf("failed to decode Alpine advisory: %w", err) 54 } 55 advisories = append(advisories, advisory) 56 return nil 57 }) 58 if err != nil { 59 return xerrors.Errorf("error in Alpine walk: %w", err) 60 } 61 62 if err = vs.save(advisories); err != nil { 63 return xerrors.Errorf("error in Alpine save: %w", err) 64 } 65 66 return nil 67 } 68 69 func (vs VulnSrc) save(advisories []advisory) error { 70 err := vs.dbc.BatchUpdate(func(tx *bolt.Tx) error { 71 for _, adv := range advisories { 72 version := strings.TrimPrefix(adv.Distroversion, "v") 73 platformName := fmt.Sprintf(platformFormat, version) 74 if err := vs.dbc.PutDataSource(tx, platformName, source); err != nil { 75 return xerrors.Errorf("failed to put data source: %w", err) 76 } 77 if err := vs.saveSecFixes(tx, platformName, adv.PkgName, adv.Secfixes); err != nil { 78 return err 79 } 80 } 81 return nil 82 }) 83 if err != nil { 84 return xerrors.Errorf("error in db batch update: %w", err) 85 } 86 return nil 87 } 88 89 func (vs VulnSrc) saveSecFixes(tx *bolt.Tx, platform, pkgName string, secfixes map[string][]string) error { 90 for fixedVersion, vulnIDs := range secfixes { 91 advisory := types.Advisory{ 92 FixedVersion: fixedVersion, 93 } 94 for _, vulnID := range vulnIDs { 95 // See https://gitlab.alpinelinux.org/alpine/infra/docker/secdb/-/issues/3 96 // e.g. CVE-2017-2616 (+ regression fix) 97 ids := strings.Fields(vulnID) 98 for _, cveID := range ids { 99 cveID = strings.ReplaceAll(cveID, "CVE_", "CVE-") 100 if !strings.HasPrefix(cveID, "CVE-") { 101 continue 102 } 103 if err := vs.dbc.PutAdvisoryDetail(tx, cveID, pkgName, []string{platform}, advisory); err != nil { 104 return xerrors.Errorf("failed to save Alpine advisory: %w", err) 105 } 106 107 // for optimization 108 if err := vs.dbc.PutVulnerabilityID(tx, cveID); err != nil { 109 return xerrors.Errorf("failed to save the vulnerability ID: %w", err) 110 } 111 } 112 } 113 } 114 return nil 115 } 116 117 func (vs VulnSrc) Get(release, pkgName string) ([]types.Advisory, error) { 118 bucket := fmt.Sprintf(platformFormat, release) 119 advisories, err := vs.dbc.GetAdvisories(bucket, pkgName) 120 if err != nil { 121 return nil, xerrors.Errorf("failed to get Alpine advisories: %w", err) 122 } 123 return advisories, nil 124 }