From 3d90cac427e52a6470f112746fa86a595ffe8717 Mon Sep 17 00:00:00 2001 From: Jimmy Zelinskie Date: Wed, 14 Dec 2016 17:01:38 -0500 Subject: [PATCH] alpine: add support for v3.4 YAML schema --- updater/fetchers/alpine/alpine.go | 73 ++++- updater/fetchers/alpine/alpine_test.go | 34 ++- .../testdata/{main.yaml => v33_main.yaml} | 0 .../fetchers/alpine/testdata/v34_main.yaml | 251 ++++++++++++++++++ 4 files changed, 344 insertions(+), 14 deletions(-) rename updater/fetchers/alpine/testdata/{main.yaml => v33_main.yaml} (100%) create mode 100644 updater/fetchers/alpine/testdata/v34_main.yaml diff --git a/updater/fetchers/alpine/alpine.go b/updater/fetchers/alpine/alpine.go index 0a074a57..7705a3d7 100644 --- a/updater/fetchers/alpine/alpine.go +++ b/updater/fetchers/alpine/alpine.go @@ -92,12 +92,19 @@ func (f *fetcher) FetchUpdate(db database.Datastore) (resp updater.FetcherRespon if err != nil { return } + log.Debug(namespace) var vulns []database.Vulnerability - vulns, err = parseYAML(file) + switch namespace { + case "v3.3": + vulns, err = parse33YAML(file) + case "v3.4": + vulns, err = parse34YAML(file) + } if err != nil { return } + resp.Vulnerabilities = append(resp.Vulnerabilities, vulns...) file.Close() } @@ -111,7 +118,7 @@ func (f *fetcher) pullRepository() (commit string, err error) { return "", ErrFilesystem } - if out, err := utils.Exec(f.repositoryLocalPath, "git", "pull"); err != nil { + if out, err := utils.Exec(f.repositoryLocalPath, "git", "clone", secdbGitURL, "."); err != nil { f.Clean() log.Errorf("could not pull alpine-secdb repository: %s. output: %s", err, out) return "", cerrors.ErrCouldNotDownload @@ -133,7 +140,7 @@ func (f *fetcher) Clean() { } } -type secdbFile struct { +type secdb33File struct { Distro string `yaml:"distroversion"` Packages []struct { Pkg struct { @@ -144,14 +151,14 @@ type secdbFile struct { } `yaml:"packages"` } -func parseYAML(r io.Reader) (vulns []database.Vulnerability, err error) { +func parse33YAML(r io.Reader) (vulns []database.Vulnerability, err error) { var rBytes []byte rBytes, err = ioutil.ReadAll(r) if err != nil { return } - var file secdbFile + var file secdb33File err = yaml.Unmarshal(rBytes, &file) if err != nil { return @@ -166,6 +173,7 @@ func parseYAML(r io.Reader) (vulns []database.Vulnerability, err error) { } var vuln database.Vulnerability + vuln.Severity = types.Unknown vuln.Name = fix vuln.Link = nvdURLPrefix + fix vuln.FixedIn = []database.FeatureVersion{ @@ -177,10 +185,63 @@ func parseYAML(r io.Reader) (vulns []database.Vulnerability, err error) { Version: version, }, } - vulns = append(vulns, vuln) } } return } + +type secdb34File struct { + Distro string `yaml:"distroversion"` + Packages []struct { + Pkg struct { + Name string `yaml:"name"` + Fixes map[string][]string `yaml:"secfixes"` + } `yaml:"pkg"` + } `yaml:"packages"` +} + +func parse34YAML(r io.Reader) (vulns []database.Vulnerability, err error) { + var rBytes []byte + rBytes, err = ioutil.ReadAll(r) + if err != nil { + return + } + + var file secdb34File + err = yaml.Unmarshal(rBytes, &file) + if err != nil { + return + } + + for _, pack := range file.Packages { + pkg := pack.Pkg + for versionStr, vulnStrs := range pkg.Fixes { + version, err := types.NewVersion(versionStr) + if err != nil { + log.Warningf("could not parse package version '%s': %s. skipping", versionStr, err.Error()) + continue + } + + for _, vulnStr := range vulnStrs { + var vuln database.Vulnerability + vuln.Severity = types.Unknown + vuln.Name = vulnStr + vuln.Link = nvdURLPrefix + vulnStr + vuln.FixedIn = []database.FeatureVersion{ + { + Feature: database.Feature{ + Namespace: database.Namespace{Name: "alpine:" + file.Distro}, + Name: pkg.Name, + }, + Version: version, + }, + } + vulns = append(vulns, vuln) + } + } + } + + return +} diff --git a/updater/fetchers/alpine/alpine_test.go b/updater/fetchers/alpine/alpine_test.go index b4d61655..4588d97e 100644 --- a/updater/fetchers/alpine/alpine_test.go +++ b/updater/fetchers/alpine/alpine_test.go @@ -23,20 +23,38 @@ import ( "github.com/stretchr/testify/assert" ) -func TestAlpineYAMLParsing(t *testing.T) { +func TestAlpine33YAMLParsing(t *testing.T) { _, filename, _, _ := runtime.Caller(0) path := filepath.Join(filepath.Dir(filename)) - testData, _ := os.Open(path + "/testdata/main.yaml") + testData, _ := os.Open(path + "/testdata/v33_main.yaml") defer testData.Close() - vulns, err := parseYAML(testData) + vulns, err := parse33YAML(testData) if err != nil { assert.Nil(t, err) } - assert.Equal(t, len(vulns), 15) - assert.Equal(t, vulns[0].Name, "CVE-2016-2147") - assert.Equal(t, vulns[0].FixedIn[0].Feature.Namespace.Name, "alpine:v3.3") - assert.Equal(t, vulns[0].FixedIn[0].Feature.Name, "busybox") - assert.Equal(t, vulns[0].Link, "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-2147") + assert.Equal(t, 15, len(vulns)) + assert.Equal(t, "CVE-2016-2147", vulns[0].Name) + assert.Equal(t, "alpine:v3.3", vulns[0].FixedIn[0].Feature.Namespace.Name) + assert.Equal(t, "busybox", vulns[0].FixedIn[0].Feature.Name) + assert.Equal(t, "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-2147", vulns[0].Link) +} + +func TestAlpine34YAMLParsing(t *testing.T) { + _, filename, _, _ := runtime.Caller(0) + path := filepath.Join(filepath.Dir(filename)) + + testData, _ := os.Open(path + "/testdata/v34_main.yaml") + defer testData.Close() + + vulns, err := parse34YAML(testData) + if err != nil { + assert.Nil(t, err) + } + assert.Equal(t, 105, len(vulns)) + assert.Equal(t, "CVE-2016-5387", vulns[0].Name) + assert.Equal(t, "alpine:v3.4", vulns[0].FixedIn[0].Feature.Namespace.Name) + assert.Equal(t, "apache2", vulns[0].FixedIn[0].Feature.Name) + assert.Equal(t, "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-5387", vulns[0].Link) } diff --git a/updater/fetchers/alpine/testdata/main.yaml b/updater/fetchers/alpine/testdata/v33_main.yaml similarity index 100% rename from updater/fetchers/alpine/testdata/main.yaml rename to updater/fetchers/alpine/testdata/v33_main.yaml diff --git a/updater/fetchers/alpine/testdata/v34_main.yaml b/updater/fetchers/alpine/testdata/v34_main.yaml new file mode 100644 index 00000000..325977eb --- /dev/null +++ b/updater/fetchers/alpine/testdata/v34_main.yaml @@ -0,0 +1,251 @@ +--- +distroversion: v3.4 +reponame: main +archs: + - x86_64 + - x86 + - armhf +urlprefix: http://dl-cdn.alpinelinux.org/alpine +apkurl: "{{urlprefix}}/{{distroversion}}/{{reponame}}/{{arch}}/{{pkg.name}}-{{pkg.ver}}.apk" +packages: + - pkg: + name: apache2 + secfixes: + 2.4.23-r1: + - CVE-2016-5387 + - pkg: + name: busybox + secfixes: + 1.24.2-r0: + - CVE-2016-2147 + - CVE-2016-2148 + - pkg: + name: bzip2 + secfixes: + 1.0.6-r5: + - CVE-2016-3189 + - pkg: + name: c-ares + secfixes: + 1.12.0-r0: + - CVE-2016-5180 + - pkg: + name: collectd + secfixes: + 5.5.2-r0: + - CVE-2016-6254 + - pkg: + name: curl + secfixes: + 7.51.0: + - CVE-2016-8615 + - CVE-2016-8616 + - CVE-2016-8617 + - CVE-2016-8618 + - CVE-2016-8619 + - CVE-2016-8620 + - CVE-2016-8621 + - CVE-2016-8622 + - CVE-2016-8623 + - CVE-2016-8624 + - CVE-2016-8625 + 7.50.3-r0: + - CVE-2016-7167 + 7.50.2-r0: + - CVE-2016-7141 + 7.50.1-r0: + - CVE-2016-5419 + - CVE-2016-5420 + - CVE-2016-5421 + 7.36.0-r0: + - CVE-2014-0138 + - CVE-2014-0139 + - pkg: + name: expat + secfixes: + 2.1.1-r1: + - CVE-2016-0718 + 2.1.1-r2: + - CVE-2016-4472 + - pkg: + name: flex + secfixes: + 2.6.1-r0: + - CVE-2016-6354 + - pkg: + name: gd + secfixes: + 2.2.1-r0: + - CVE-2016-3074 + 2.2.2-r0: + - CVE-2015-8874 + - CVE-2016-5767 + 2.2.3-r0: + - CVE-2016-5766 + - CVE-2016-6128 + - CVE-2016-6132 + - CVE-2016-6207 + - CVE-2016-6214 + 2.2.3-r1: + - CVE-2016-7568 + - pkg: + name: giflib + secfixes: + 5.1.4-r0: + - CVE-2016-3977 + - pkg: + name: guile + secfixes: + 2.0.11-r3: + - CVE-2016-8605 + - CVE-2016-8606 + - pkg: + name: icu + secfixes: + 57.1-r1: + - CVE-2016-6293 + - pkg: + name: imagemagick + secfixes: + 6.9.5.3: + - CVE-2016-5010 + - CVE-2016-5687 + - CVE-2016-5688 + - CVE-2016-5689 + - CVE-2016-5690 + - CVE-2016-5691 + - CVE-2016-5841 + - CVE-2016-5842 + - CVE-2016-6491 + 6.9.5.9-r1: + - CVE-2016-7799 + - CVE-2016-7906 + - pkg: + name: jq + secfixes: + 1.5-r1: + - CVE-2015-8863 + - pkg: + name: krb5 + secfixes: + 1.14-r1: + - CVE-2015-8629 + - CVE-2015-8630 + - CVE-2015-8631 + 1.14-r2: + - CVE-2016-3119 + 1.14.3-r0: + - CVE-2016-3120 + - pkg: + name: libarchive + secfixes: + 3.2.0-r0: + - CVE-2016-1541 + 3.2.1-r0: + - CVE-2015-8934 + - CVE-2016-4300 + - CVE-2016-4302 + - CVE-2016-4809 + - CVE-2016-5844 + - CVE-2016-6250 + - pkg: + name: libbsd + secfixes: + 0.8.2: + - CVE-2016-2090 + - pkg: + name: libidn + secfixes: + 1.33-r0: + - CVE-2015-8948 + - CVE-2016-6261 + - CVE-2016-6262 + - CVE-2016-6263 + - pkg: + name: libssh2 + secfixes: + 1.7.0-r0: + - CVE-2016-0787 + - pkg: + name: openjpeg + secfixes: + 2.1.2-r0: + - CVE-2016-7445 + - pkg: + name: openssh + secfixes: + 7.2_p2-r1: + - CVE-2016-6210 + 7.2_p2-r2: + - CVE-2016-6515 + - pkg: + name: openssl + secfixes: + 1.0.2h-r0: + - CVE-2016-2107 + - CVE-2016-2105 + - CVE-2016-2106 + - CVE-2016-2109 + - CVE-2016-2176 + 1.0.2h-r1: + - CVE-2016-2177 + - CVE-2016-2178 + 1.0.2h-r2: + - CVE-2016-2180 + 1.0.2h-r3: + - CVE-2016-2179 + - CVE-2016-2182 + - CVE-2016-6302 + - CVE-2016-6303 + 1.0.2h-r4: + - CVE-2016-2181 + 1.0.2i-r0: + - CVE-2016-2183 + - CVE-2016-6304 + - CVE-2016-6306 + - pkg: + name: pcre + secfixes: + 8.38-r1: + - CVE-2016-1283 + - CVE-2016-3191 + - pkg: + name: py-django + secfixes: + 1.8.16-r0: + - CVE-2016-9013 + - CVE-2016-9014 + - pkg: + name: tar + secfixes: + 1.29-r1: + - CVE-2016-6321 + - pkg: + name: wget + secfixes: + 1.17.1-r1: + - CVE-2016-4971 + - pkg: + name: wpa_supplicant + secfixes: + 2.5-r3: + - CVE-2016-4476 + - CVE-2016-4477 + - pkg: + name: xen + secfixes: + 4.6.3-r1: + - CVE-2016-6258 XSA-182 + - CVE-2016-6259 XSA-183 + - CVE-2016-5403 XSA-184 + 4.6.3-r2: + - CVE-2016-7092 XSA-185 + - CVE-2016-7093 XSA-186 + - CVE-2016-7094 XSA-187 + 4.6.3-r3: + - CVE-2016-7777 XSA-190 + - pkg: + name: zabbix + secfixes: + 3.0.4-r0: + - ZBX-11023