1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
|
package fetcher
import (
"encoding/json"
"errors"
"fmt"
"time"
"github.com/spf13/viper"
"github.com/knqyf263/gost/models"
"github.com/knqyf263/gost/util"
)
// ListAllRedhatCves returns the list of all CVEs from RedHat API
// https://access.redhat.com/documentation/en-us/red_hat_security_data_api/0.1/html-single/red_hat_security_data_api/#list_all_cves
func ListAllRedhatCves(before, after string, wait int) (entries []models.RedhatEntry, err error) {
for page := 1; ; page++ {
url := fmt.Sprintf("https://access.redhat.com/labs/securitydataapi/cve.json?page=%d&after=%s", page, after)
if before != "" {
url += fmt.Sprintf("&before=%s", before)
}
body, err := util.FetchURL(url, "")
if err != nil {
return entries, fmt.Errorf("Failed to fetch RedHat CVEs list: %v, url: %s", err, url)
}
entryList := []models.RedhatEntry{}
if err = json.Unmarshal(body, &entryList); err != nil {
return nil, err
}
if len(entryList) == 0 {
break
}
entries = append(entries, entryList...)
time.Sleep(time.Duration(wait) * time.Second)
}
return entries, nil
}
// GetRedhatCveDetailURL returns CVE detail URL.
func GetRedhatCveDetailURL(cveID string) (url string) {
return fmt.Sprintf("https://access.redhat.com/labs/securitydataapi/cve/%s.json", cveID)
}
// RetrieveRedhatCveDetails returns full CVE details from RedHat API
// https://access.redhat.com/documentation/en-us/red_hat_security_data_api/0.1/html-single/red_hat_security_data_api/#retrieve_a_cve
func RetrieveRedhatCveDetails(urls []string) (cves []models.RedhatCVEJSON, err error) {
cveJSONs, err := util.FetchConcurrently(urls, viper.GetInt("threads"), viper.GetInt("wait"))
if err != nil {
return cves, fmt.Errorf("Failed to fetch cve data from RedHat. err: %s", err)
}
for _, cveJSON := range cveJSONs {
var cve models.RedhatCVEJSON
if err = json.Unmarshal(cveJSON, &cve); err != nil {
return nil, err
}
switch cve.TempAffectedRelease.(type) {
case []interface{}:
var ar models.RedhatCVEJSONAffectedReleaseArray
if err = json.Unmarshal(cveJSON, &ar); err != nil {
return nil, fmt.Errorf("Unknown affected_release type err: %s", err)
}
cve.AffectedRelease = ar.AffectedRelease
case map[string]interface{}:
var ar models.RedhatCVEJSONAffectedReleaseObject
if err = json.Unmarshal(cveJSON, &ar); err != nil {
return nil, fmt.Errorf("Unknown affected_release type err: %s", err)
}
cve.AffectedRelease = []models.RedhatAffectedRelease{ar.AffectedRelease}
case nil:
default:
return nil, errors.New("Unknown affected_release type")
}
switch cve.TempPackageState.(type) {
case []interface{}:
var ps models.RedhatCVEJSONPackageStateArray
if err = json.Unmarshal(cveJSON, &ps); err != nil {
return nil, fmt.Errorf("Unknown package_state type err: %s", err)
}
cve.PackageState = ps.PackageState
case map[string]interface{}:
var ps models.RedhatCVEJSONPackageStateObject
if err = json.Unmarshal(cveJSON, &ps); err != nil {
return nil, fmt.Errorf("Unknown package_state type err: %s", err)
}
cve.PackageState = []models.RedhatPackageState{ps.PackageState}
case nil:
default:
return nil, errors.New("Unknown package_state type")
}
cves = append(cves, cve)
}
return cves, nil
}
|