// FetchUpdate fetches vulnerability updates from the Debian Security Tracker. func (fetcher *DebianFetcher) FetchUpdate(datastore database.Datastore) (resp updater.FetcherResponse, err error) { log.Info("fetching Debian vulnerabilities") // Download JSON. r, err := http.Get(url) if err != nil { log.Errorf("could not download Debian's update: %s", err) io.Copy(ioutil.Discard, r.Body) return resp, cerrors.ErrCouldNotDownload } defer r.Body.Close() r.Close = true // Get the SHA-1 of the latest update's JSON data latestHash, err := datastore.GetKeyValue(updaterFlag) if err != nil { return resp, err } // Parse the JSON. resp, err = buildResponse(r.Body, latestHash) if err != nil { return resp, err } return resp, nil }
func (f *fetcher) FetchUpdate(db database.Datastore) (resp updater.FetcherResponse, err error) { log.Info("fetching Alpine vulnerabilities") // Pull the master branch. var commit string commit, err = f.pullRepository() if err != nil { return } // Ask the database for the latest commit we successfully applied. var dbCommit string dbCommit, err = db.GetKeyValue(updaterFlag) if err != nil { return } // Set the updaterFlag to equal the commit processed. resp.FlagName = updaterFlag resp.FlagValue = commit // Short-circuit if there have been no updates. if commit == dbCommit { log.Debug("no alpine update") return } var namespaces []string namespaces, err = detectNamespaces(f.repositoryLocalPath) // Append any changed vulnerabilities to the response. for _, namespace := range namespaces { var vulns []database.Vulnerability var note string vulns, note, err = parseVulnsFromNamespace(f.repositoryLocalPath, namespace) if err != nil { return } if note != "" { resp.Notes = append(resp.Notes, note) } resp.Vulnerabilities = append(resp.Vulnerabilities, vulns...) } return }
func getLastUpdate(datastore database.Datastore) (time.Time, bool, error) { lastUpdateTSS, err := datastore.GetKeyValue(flagName) if err != nil { return time.Time{}, false, err } if lastUpdateTSS == "" { // This is the first update. return time.Time{}, true, nil } lastUpdateTS, err := strconv.ParseInt(lastUpdateTSS, 10, 64) if err != nil { return time.Time{}, false, err } return time.Unix(lastUpdateTS, 0).UTC(), false, nil }
// FetchUpdate gets vulnerability updates from the Red Hat OVAL definitions. func (f *RHELFetcher) FetchUpdate(datastore database.Datastore) (resp updater.FetcherResponse, err error) { log.Info("fetching Red Hat vulnerabilities") // Get the first RHSA we have to manage. flagValue, err := datastore.GetKeyValue(updaterFlag) if err != nil { return resp, err } firstRHSA, err := strconv.Atoi(flagValue) if firstRHSA == 0 || err != nil { firstRHSA = firstRHEL5RHSA } // Fetch the update list. r, err := http.Get(ovalURI) if err != nil { log.Errorf("could not download RHEL's update list: %s", err) return resp, cerrors.ErrCouldNotDownload } // Get the list of RHSAs that we have to process. var rhsaList []int scanner := bufio.NewScanner(r.Body) for scanner.Scan() { line := scanner.Text() r := rhsaRegexp.FindStringSubmatch(line) if len(r) == 2 { rhsaNo, _ := strconv.Atoi(r[1]) if rhsaNo > firstRHSA { rhsaList = append(rhsaList, rhsaNo) } } } for _, rhsa := range rhsaList { // Download the RHSA's XML file. r, err := http.Get(ovalURI + rhsaFilePrefix + strconv.Itoa(rhsa) + ".xml") if err != nil { log.Errorf("could not download RHEL's update file: %s", err) return resp, cerrors.ErrCouldNotDownload } // Parse the XML. vs, err := parseRHSA(r.Body) if err != nil { return resp, err } // Collect vulnerabilities. for _, v := range vs { resp.Vulnerabilities = append(resp.Vulnerabilities, v) } } // Set the flag if we found anything. if len(rhsaList) > 0 { resp.FlagName = updaterFlag resp.FlagValue = strconv.Itoa(rhsaList[len(rhsaList)-1]) } else { log.Debug("no Red Hat update.") } return resp, nil }
// FetchUpdate gets vulnerability updates from the Ubuntu CVE Tracker. func (fetcher *UbuntuFetcher) FetchUpdate(datastore database.Datastore) (resp updater.FetcherResponse, err error) { log.Info("fetching Ubuntu vulnerabilities") // Check to see if the repository does not already exist. if _, pathExists := os.Stat(fetcher.repositoryLocalPath); fetcher.repositoryLocalPath == "" || os.IsNotExist(pathExists) { // Create a temporary folder and download the repository. p, err := ioutil.TempDir(os.TempDir(), "ubuntu-cve-tracker") if err != nil { return resp, ErrFilesystem } // bzr wants an empty target directory. fetcher.repositoryLocalPath = p + "/repository" // Create the new repository. err = createRepository(fetcher.repositoryLocalPath) if err != nil { return resp, err } } else { // Update the repository that's already on disk. err = updateRepository(fetcher.repositoryLocalPath) if err != nil { return resp, err } } // Get revision number. revisionNumber, err := getRevisionNumber(fetcher.repositoryLocalPath) if err != nil { return resp, err } // Get the latest revision number we successfully applied in the database. dbRevisionNumber, err := datastore.GetKeyValue("ubuntuUpdater") if err != nil { return resp, err } // Get the list of vulnerabilities that we have to update. modifiedCVE, err := collectModifiedVulnerabilities(revisionNumber, dbRevisionNumber, fetcher.repositoryLocalPath) if err != nil { return resp, err } notes := make(map[string]struct{}) for cvePath := range modifiedCVE { // Open the CVE file. file, err := os.Open(fetcher.repositoryLocalPath + "/" + cvePath) if err != nil { // This can happen when a file is modified and then moved in another // commit. continue } // Parse the vulnerability. v, unknownReleases, err := parseUbuntuCVE(file) if err != nil { return resp, err } // Add the vulnerability to the response. resp.Vulnerabilities = append(resp.Vulnerabilities, v) // Store any unknown releases as notes. for k := range unknownReleases { note := fmt.Sprintf("Ubuntu %s is not mapped to any version number (eg. trusty->14.04). Please update me.", k) notes[note] = struct{}{} // If we encountered unknown Ubuntu release, we don't want the revision // number to be considered as managed. dbRevisionNumberInt, _ := strconv.Atoi(dbRevisionNumber) revisionNumber = dbRevisionNumberInt } // Close the file manually. // // We do that instead of using defer because defer works on a function-level scope. // We would open many files and close them all at once at the end of the function, // which could lead to exceed fs.file-max. file.Close() } // Add flag and notes. resp.FlagName = updaterFlag resp.FlagValue = strconv.Itoa(revisionNumber) for note := range notes { resp.Notes = append(resp.Notes, note) } return }
// FetchUpdate gets vulnerability updates from the Ubuntu CVE Tracker. func (fetcher *UbuntuFetcher) FetchUpdate(datastore database.Datastore) (resp updater.FetcherResponse, err error) { log.Info("fetching Ubuntu vulnerabilities") // Pull the bzr repository. if err = fetcher.pullRepository(); err != nil { return resp, err } // Get revision number. revisionNumber, err := getRevisionNumber(fetcher.repositoryLocalPath) if err != nil { return resp, err } // Get the latest revision number we successfully applied in the database. dbRevisionNumber, err := datastore.GetKeyValue("ubuntuUpdater") if err != nil { return resp, err } // Get the list of vulnerabilities that we have to update. modifiedCVE, err := collectModifiedVulnerabilities(revisionNumber, dbRevisionNumber, fetcher.repositoryLocalPath) if err != nil { return resp, err } notes := make(map[string]struct{}) for cvePath := range modifiedCVE { // Open the CVE file. file, err := os.Open(fetcher.repositoryLocalPath + "/" + cvePath) if err != nil { // This can happen when a file is modified and then moved in another // commit. continue } // Parse the vulnerability. v, unknownReleases, err := parseUbuntuCVE(file) if err != nil { return resp, err } // Add the vulnerability to the response. resp.Vulnerabilities = append(resp.Vulnerabilities, v) // Store any unknown releases as notes. for k := range unknownReleases { note := fmt.Sprintf("Ubuntu %s is not mapped to any version number (eg. trusty->14.04). Please update me.", k) notes[note] = struct{}{} // If we encountered unknown Ubuntu release, we don't want the revision // number to be considered as managed. dbRevisionNumberInt, _ := strconv.Atoi(dbRevisionNumber) revisionNumber = dbRevisionNumberInt } // Close the file manually. // // We do that instead of using defer because defer works on a function-level scope. // We would open many files and close them all at once at the end of the function, // which could lead to exceed fs.file-max. file.Close() } // Add flag and notes. resp.FlagName = updaterFlag resp.FlagValue = strconv.Itoa(revisionNumber) for note := range notes { resp.Notes = append(resp.Notes, note) } return }