From a943de4ba9f44e252d79f5e3ad9363ddd82cfecd Mon Sep 17 00:00:00 2001 From: MaineK00n Date: Wed, 3 Apr 2024 14:24:21 +0900 Subject: [PATCH] feat(fetcher/redhat): fetch extras, supplementary, els advisories --- commands/fetch-redhat.go | 2 +- fetcher/redhat/redhat.go | 137 +++++++++++++++++++++++++++------------ 2 files changed, 95 insertions(+), 44 deletions(-) diff --git a/commands/fetch-redhat.go b/commands/fetch-redhat.go index 79fd4183..5dc401f6 100644 --- a/commands/fetch-redhat.go +++ b/commands/fetch-redhat.go @@ -85,7 +85,7 @@ func fetchRedHat(_ *cobra.Command, args []string) (err error) { } roots := make([]redhat.Root, 0, len(m)) - for _, k := range []string{fmt.Sprintf("rhel-%s.oval.xml.bz2", v), fmt.Sprintf("com.redhat.rhsa-RHEL%s.xml", v)} { + for _, k := range []string{fmt.Sprintf("rhel-%s.oval.xml.bz2", v), fmt.Sprintf("rhel-%s-extras.oval.xml.bz2", v), fmt.Sprintf("rhel-%s-supplementary.oval.xml.bz2", v), fmt.Sprintf("rhel-%s-els.oval.xml.bz2", v), fmt.Sprintf("com.redhat.rhsa-RHEL%s.xml", v), fmt.Sprintf("com.redhat.rhsa-RHEL%s-ELS.xml", v)} { roots = append(roots, m[k]) } diff --git a/fetcher/redhat/redhat.go b/fetcher/redhat/redhat.go index 51822179..dabdbe09 100644 --- a/fetcher/redhat/redhat.go +++ b/fetcher/redhat/redhat.go @@ -19,25 +19,79 @@ import ( // FetchFiles fetch OVAL from RedHat func FetchFiles(versions []string) (map[string][]util.FetchResult, error) { results := map[string][]util.FetchResult{} - vs := make([]string, 0, len(versions)) for _, v := range versions { - n, err := strconv.Atoi(v) - if err != nil { - log15.Warn("Skip unknown redhat.", "version", v) - continue - } - - if n < 5 { + switch v { + case "1", "2", "3": log15.Warn("Skip redhat because no vulnerability information provided.", "version", v) - continue - } + case "4": + rs, err := fetchOVALv1([]string{fmt.Sprintf("com.redhat.rhsa-RHEL%s.xml", v)}) + if err != nil { + return nil, xerrors.Errorf("Failed to fetch OVALv1. err: %w", err) + } + results[v] = rs + case "5": + rs, err := fetchOVALv1([]string{fmt.Sprintf("com.redhat.rhsa-RHEL%s.xml", v), fmt.Sprintf("com.redhat.rhsa-RHEL%s-ELS.xml", v)}) + if err != nil { + return nil, xerrors.Errorf("Failed to fetch OVALv1. err: %w", err) + } + results[v] = rs + case "6": + rs, err := fetchOVALv1([]string{fmt.Sprintf("com.redhat.rhsa-RHEL%s.xml", v)}) + if err != nil { + return nil, xerrors.Errorf("Failed to fetch OVALv1. err: %w", err) + } + results[v] = rs + + rs, err = fetchOVALv2([]string{v, fmt.Sprintf("%s-extras", v), fmt.Sprintf("%s-supplementary", v), fmt.Sprintf("%s-els", v)}) + if err != nil { + return nil, xerrors.Errorf("Failed to fetch OVALv2. err: %w", err) + } + results[v] = append(results[v], rs...) + case "7": + rs, err := fetchOVALv1([]string{fmt.Sprintf("com.redhat.rhsa-RHEL%s.xml", v)}) + if err != nil { + return nil, xerrors.Errorf("Failed to fetch OVALv1. err: %w", err) + } + results[v] = rs + + rs, err = fetchOVALv2([]string{v, fmt.Sprintf("%s-extras", v), fmt.Sprintf("%s-supplementary", v)}) + if err != nil { + return nil, xerrors.Errorf("Failed to fetch OVALv2. err: %w", err) + } + results[v] = append(results[v], rs...) + case "8", "9": + rs, err := fetchOVALv1([]string{fmt.Sprintf("com.redhat.rhsa-RHEL%s.xml", v)}) + if err != nil { + return nil, xerrors.Errorf("Failed to fetch OVALv1. err: %w", err) + } + results[v] = rs + + rs, err = fetchOVALv2([]string{v}) + if err != nil { + return nil, xerrors.Errorf("Failed to fetch OVALv2. err: %w", err) + } + results[v] = append(results[v], rs...) + default: + if _, err := strconv.Atoi(v); err != nil { + log15.Warn("Skip unknown redhat.", "version", v) + break + } - vs = append(vs, v) + rs, err := fetchOVALv2([]string{v}) + if err != nil { + return nil, xerrors.Errorf("Failed to fetch OVALv2. err: %w", err) + } + results[v] = rs + } } - if len(vs) == 0 { + + if len(results) == 0 { return nil, xerrors.New("There are no versions to fetch") } + return results, nil +} +func fetchOVALv1(names []string) ([]util.FetchResult, error) { log15.Info("Fetching... ", "URL", "https://access.redhat.com/security/data/archive/oval_v1_20230706.tar.gz") resp, err := http.Get("https://access.redhat.com/security/data/archive/oval_v1_20230706.tar.gz") if err != nil { @@ -54,6 +108,8 @@ func FetchFiles(versions []string) (map[string][]util.FetchResult, error) { } defer gr.Close() + results := make([]util.FetchResult, 0, len(names)) + tr := tar.NewReader(gr) for { hdr, err := tr.Next() @@ -64,42 +120,37 @@ func FetchFiles(versions []string) (map[string][]util.FetchResult, error) { return nil, xerrors.Errorf("Failed to next tar reader. err: %w", err) } - v := strings.TrimSuffix(strings.TrimPrefix(hdr.Name, "com.redhat.rhsa-RHEL"), ".xml") - if slices.Contains(vs, v) { - bs, err := io.ReadAll(tr) - if err != nil { - return nil, xerrors.Errorf("Failed to read all com.redhat.rhsa-RHEL%s.xml. err: %w", v, err) - } - results[v] = append(results[v], util.FetchResult{ - Target: v, - URL: fmt.Sprintf("https://access.redhat.com/security/data/archive/oval_v1_20230706.tar.gz/com.redhat.rhsa-RHEL%s.xml", v), - Body: bs, - }) + if !slices.Contains(names, hdr.Name) { + continue } - } - reqs := make([]util.FetchRequest, 0, len(vs)) - for _, v := range vs { - if v != "5" { - reqs = append(reqs, util.FetchRequest{ - Target: v, - URL: fmt.Sprintf("https://access.redhat.com/security/data/oval/v2/RHEL%s/rhel-%s.oval.xml.bz2", v, v), - MIMEType: util.MIMETypeBzip2, - }) - } - } - if len(reqs) > 0 { - rs, err := util.FetchFeedFiles(reqs) + bs, err := io.ReadAll(tr) if err != nil { - return nil, xerrors.Errorf("Failed to fetch. err: %w", err) - } - for _, r := range rs { - results[r.Target] = append(results[r.Target], r) + return nil, xerrors.Errorf("Failed to read all %s. err: %w", hdr.Name, err) } + results = append(results, util.FetchResult{ + Target: strings.TrimSuffix(strings.TrimPrefix(hdr.Name, "com.redhat.rhsa-RHEL"), ".xml"), + URL: fmt.Sprintf("https://access.redhat.com/security/data/archive/oval_v1_20230706.tar.gz/%s", hdr.Name), + Body: bs, + }) } - if len(results) == 0 { - return nil, xerrors.New("There are no versions to fetch") - } return results, nil } + +func fetchOVALv2(names []string) ([]util.FetchResult, error) { + reqs := make([]util.FetchRequest, 0, len(names)) + for _, n := range names { + reqs = append(reqs, util.FetchRequest{ + Target: n, + URL: fmt.Sprintf("https://access.redhat.com/security/data/oval/v2/RHEL%s/rhel-%s.oval.xml.bz2", n[0:1], n), + MIMEType: util.MIMETypeBzip2, + }) + } + + rs, err := util.FetchFeedFiles(reqs) + if err != nil { + return nil, xerrors.Errorf("Failed to fetch. err: %w", err) + } + return rs, nil +}