github.com/khulnasoft-lab/tunnel-db@v0.0.0-20231117205118-74e1113bd007/pkg/vulnsrc/amazon/amazon.go (about) 1 package amazon 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "io" 7 "log" 8 "path/filepath" 9 "strings" 10 11 bolt "go.etcd.io/bbolt" 12 "golang.org/x/xerrors" 13 14 "github.com/khulnasoft-lab/tunnel-db/pkg/db" 15 "github.com/khulnasoft-lab/tunnel-db/pkg/types" 16 "github.com/khulnasoft-lab/tunnel-db/pkg/utils" 17 ustrings "github.com/khulnasoft-lab/tunnel-db/pkg/utils/strings" 18 "github.com/khulnasoft-lab/tunnel-db/pkg/vulnsrc/vulnerability" 19 ) 20 21 const ( 22 amazonDir = "amazon" 23 platformFormat = "amazon linux %s" 24 ) 25 26 var ( 27 targetVersions = []string{"1", "2", "2022", "2023"} 28 29 source = types.DataSource{ 30 ID: vulnerability.Amazon, 31 Name: "Amazon Linux Security Center", 32 URL: "https://alas.aws.amazon.com/", 33 } 34 ) 35 36 type VulnSrc struct { 37 dbc db.Operation 38 advisories map[string][]ALAS 39 } 40 41 // ALAS has detailed data of ALAS 42 type ALAS struct { 43 ID string `json:"id,omitempty"` 44 Title string `json:"title,omitempty"` 45 Severity string `json:"severity,omitempty"` 46 Description string `json:"description,omitempty"` 47 Packages []Package `json:"packages,omitempty"` 48 References []Reference `json:"references,omitempty"` 49 CveIDs []string `json:"cveids,omitempty"` 50 } 51 52 // Package has affected package information 53 type Package struct { 54 Name string `json:"name,omitempty"` 55 Epoch string `json:"epoch,omitempty"` 56 Version string `json:"version,omitempty"` 57 Release string `json:"release,omitempty"` 58 Arch string `json:"arch,omitempty"` 59 } 60 61 // Reference has reference information 62 type Reference struct { 63 Href string `json:"href,omitempty"` 64 } 65 66 func NewVulnSrc() VulnSrc { 67 return VulnSrc{ 68 dbc: db.Config{}, 69 advisories: map[string][]ALAS{}, 70 } 71 } 72 73 func (vs VulnSrc) Name() types.SourceID { 74 return source.ID 75 } 76 77 func (vs VulnSrc) Update(dir string) error { 78 rootDir := filepath.Join(dir, "vuln-list", amazonDir) 79 80 err := utils.FileWalk(rootDir, vs.walkFunc) 81 if err != nil { 82 return xerrors.Errorf("error in Amazon walk: %w", err) 83 } 84 85 if err = vs.save(); err != nil { 86 return xerrors.Errorf("error in Amazon save: %w", err) 87 } 88 89 return nil 90 } 91 92 func (vs *VulnSrc) walkFunc(r io.Reader, path string) error { 93 paths := strings.Split(path, string(filepath.Separator)) 94 if len(paths) < 2 { 95 return nil 96 } 97 version := paths[len(paths)-2] 98 if !ustrings.InSlice(version, targetVersions) { 99 log.Printf("unsupported Amazon version: %s\n", version) 100 return nil 101 } 102 103 var alas ALAS 104 if err := json.NewDecoder(r).Decode(&alas); err != nil { 105 return xerrors.Errorf("failed to decode Amazon JSON: %w", err) 106 } 107 108 vs.advisories[version] = append(vs.advisories[version], alas) 109 return nil 110 } 111 112 func (vs VulnSrc) save() error { 113 log.Println("Saving Amazon DB") 114 err := vs.dbc.BatchUpdate(func(tx *bolt.Tx) error { 115 return vs.commit(tx) 116 }) 117 if err != nil { 118 return xerrors.Errorf("error in batch update: %w", err) 119 } 120 return nil 121 } 122 123 func (vs VulnSrc) commit(tx *bolt.Tx) error { 124 for majorVersion, alasList := range vs.advisories { 125 platformName := fmt.Sprintf(platformFormat, majorVersion) 126 if err := vs.dbc.PutDataSource(tx, platformName, source); err != nil { 127 return xerrors.Errorf("failed to put data source: %w", err) 128 } 129 for _, alas := range alasList { 130 for _, cveID := range alas.CveIDs { 131 for _, pkg := range alas.Packages { 132 advisory := types.Advisory{ 133 FixedVersion: utils.ConstructVersion(pkg.Epoch, pkg.Version, pkg.Release), 134 } 135 if err := vs.dbc.PutAdvisoryDetail(tx, cveID, pkg.Name, []string{platformName}, advisory); err != nil { 136 return xerrors.Errorf("failed to save Amazon advisory: %w", err) 137 } 138 139 var references []string 140 for _, ref := range alas.References { 141 references = append(references, ref.Href) 142 } 143 144 vuln := types.VulnerabilityDetail{ 145 Severity: severityFromPriority(alas.Severity), 146 References: references, 147 Description: alas.Description, 148 Title: "", 149 } 150 if err := vs.dbc.PutVulnerabilityDetail(tx, cveID, source.ID, vuln); err != nil { 151 return xerrors.Errorf("failed to save Amazon vulnerability detail: %w", err) 152 } 153 154 // for optimization 155 if err := vs.dbc.PutVulnerabilityID(tx, cveID); err != nil { 156 return xerrors.Errorf("failed to save the vulnerability ID: %w", err) 157 } 158 } 159 } 160 } 161 } 162 return nil 163 } 164 165 // Get returns a security advisory 166 func (vs VulnSrc) Get(version string, pkgName string) ([]types.Advisory, error) { 167 bucket := fmt.Sprintf(platformFormat, version) 168 advisories, err := vs.dbc.GetAdvisories(bucket, pkgName) 169 if err != nil { 170 return nil, xerrors.Errorf("failed to get Amazon advisories: %w", err) 171 } 172 return advisories, nil 173 } 174 175 func severityFromPriority(priority string) types.Severity { 176 switch priority { 177 case "low": 178 return types.SeverityLow 179 case "medium": 180 return types.SeverityMedium 181 case "important": 182 return types.SeverityHigh 183 case "critical": 184 return types.SeverityCritical 185 default: 186 return types.SeverityUnknown 187 } 188 }