cmd/report2cve,internal/report: refactor
Logic for cmd/report2cve is moved to internal/report.
Change-Id: Iaa087765fc2ee7528e3a818651a9a81bfed469cf
Reviewed-on: https://go-review.googlesource.com/c/vuln/+/373002
Trust: Julie Qiu <julie@golang.org>
Run-TryBot: Julie Qiu <julie@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
diff --git a/srv/cmd/report2cve/main.go b/srv/cmd/report2cve/main.go
index fec35d7..55c99b6 100644
--- a/srv/cmd/report2cve/main.go
+++ b/srv/cmd/report2cve/main.go
@@ -8,150 +8,21 @@
import (
"encoding/json"
- "errors"
"fmt"
- "io/ioutil"
+ "log"
"os"
- "strings"
- "golang.org/x/vuln/srv/internal/cveschema"
- "golang.org/x/vuln/srv/internal/derrors"
"golang.org/x/vuln/srv/internal/report"
- "gopkg.in/yaml.v2"
)
-func fromReport(r *report.Report) (_ *cveschema.CVE, err error) {
- defer derrors.Wrap(&err, "fromReport(r)")
- if r.CVE != "" || len(r.CVEs) > 0 {
- return nil, errors.New("report has CVE ID is wrong section (should be in cve_metadata for self-issued CVEs)")
- }
- if r.CVEMetadata == nil {
- return nil, errors.New("report missing cve_metadata section")
- }
- if r.CVEMetadata.ID == "" {
- return nil, errors.New("report missing CVE ID")
- }
-
- c := &cveschema.CVE{
- DataType: "CVE",
- DataFormat: "MITRE",
- DataVersion: "4.0",
- Metadata: cveschema.Metadata{
- ID: r.CVEMetadata.ID,
- Assigner: "security@golang.org",
- State: cveschema.StatePublic,
- },
-
- Description: cveschema.Description{
- Data: []cveschema.LangString{
- {
- Lang: "eng",
- Value: strings.TrimSuffix(r.CVEMetadata.Description, "\n"),
- },
- },
- },
-
- ProblemType: cveschema.ProblemType{
- Data: []cveschema.ProblemTypeDataItem{
- {
- Description: []cveschema.LangString{
- {
- Lang: "eng",
- Value: r.CVEMetadata.CWE,
- },
- },
- },
- },
- },
-
- Affects: cveschema.Affects{
- Vendor: cveschema.Vendor{
- Data: []cveschema.VendorDataItem{
- {
- VendorName: "n/a", // ???
- Product: cveschema.Product{
- Data: []cveschema.ProductDataItem{
- {
- ProductName: r.Package,
- Version: versionToVersion(r.Versions),
- },
- },
- },
- },
- },
- },
- },
- }
-
- for _, additional := range r.AdditionalPackages {
- c.Affects.Vendor.Data = append(c.Affects.Vendor.Data, cveschema.VendorDataItem{
- VendorName: "n/a",
- Product: cveschema.Product{
- Data: []cveschema.ProductDataItem{
- {
- ProductName: additional.Package,
- Version: versionToVersion(additional.Versions),
- },
- },
- },
- })
- }
-
- if r.Links.PR != "" {
- c.References.Data = append(c.References.Data, cveschema.Reference{URL: r.Links.PR})
- }
- if r.Links.Commit != "" {
- c.References.Data = append(c.References.Data, cveschema.Reference{URL: r.Links.Commit})
- }
- for _, url := range r.Links.Context {
- c.References.Data = append(c.References.Data, cveschema.Reference{URL: url})
- }
-
- return c, nil
-}
-
-func versionToVersion(versions []report.VersionRange) cveschema.VersionData {
- vd := cveschema.VersionData{}
- for _, vr := range versions {
- if vr.Introduced != "" {
- vd.Data = append(vd.Data, cveschema.VersionDataItem{
- VersionValue: vr.Introduced,
- VersionAffected: ">=",
- })
- }
- if vr.Fixed != "" {
- vd.Data = append(vd.Data, cveschema.VersionDataItem{
- VersionValue: vr.Fixed,
- VersionAffected: "<",
- })
- }
- }
- return vd
-}
-
func main() {
if len(os.Args) != 2 {
fmt.Fprint(os.Stderr, "usage: report2cve report.yaml")
os.Exit(1)
}
-
- reportPath := os.Args[1]
- b, err := ioutil.ReadFile(reportPath)
+ cve, err := report.ToCVE(os.Args[1])
if err != nil {
- fmt.Fprintf(os.Stderr, "failed to read %q: %s\n", reportPath, err)
- os.Exit(1)
- }
-
- var r report.Report
- if err = yaml.UnmarshalStrict(b, &r); err != nil {
- fmt.Fprintf(os.Stderr, "failed to parse %q: %s\n", reportPath, err)
- os.Exit(1)
- }
-
- cve, err := fromReport(&r)
- if err != nil {
- fmt.Fprintf(os.Stderr, "failed to generate CVE: %s\n", err)
- os.Exit(1)
+ log.Fatal(err)
}
// We need to use an encoder so that it doesn't escape angle
diff --git a/srv/internal/report/cve.go b/srv/internal/report/cve.go
new file mode 100644
index 0000000..94e32f0
--- /dev/null
+++ b/srv/internal/report/cve.go
@@ -0,0 +1,136 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package report
+
+import (
+ "errors"
+ "fmt"
+ "io/ioutil"
+ "strings"
+
+ "golang.org/x/vuln/srv/internal/cveschema"
+ "golang.org/x/vuln/srv/internal/derrors"
+ "gopkg.in/yaml.v2"
+)
+
+func ToCVE(reportPath string) (_ *cveschema.CVE, err error) {
+ defer derrors.Wrap(&err, "report.ToCVE(%q)", reportPath)
+
+ b, err := ioutil.ReadFile(reportPath)
+ if err != nil {
+ return nil, fmt.Errorf("ioutil.ReadFile(%q): %v", reportPath, err)
+ }
+
+ var r Report
+ if err = yaml.UnmarshalStrict(b, &r); err != nil {
+ return nil, fmt.Errorf("yaml.Unmarshal:: %v", err)
+ }
+
+ if r.CVE != "" || len(r.CVEs) > 0 {
+ return nil, errors.New("report has CVE ID is wrong section (should be in cve_metadata for self-issued CVEs)")
+ }
+ if r.CVEMetadata == nil {
+ return nil, errors.New("report missing cve_metadata section")
+ }
+ if r.CVEMetadata.ID == "" {
+ return nil, errors.New("report missing CVE ID")
+ }
+
+ c := &cveschema.CVE{
+ DataType: "CVE",
+ DataFormat: "MITRE",
+ DataVersion: "4.0",
+ Metadata: cveschema.Metadata{
+ ID: r.CVEMetadata.ID,
+ Assigner: "security@golang.org",
+ State: cveschema.StatePublic,
+ },
+
+ Description: cveschema.Description{
+ Data: []cveschema.LangString{
+ {
+ Lang: "eng",
+ Value: strings.TrimSuffix(r.CVEMetadata.Description, "\n"),
+ },
+ },
+ },
+
+ ProblemType: cveschema.ProblemType{
+ Data: []cveschema.ProblemTypeDataItem{
+ {
+ Description: []cveschema.LangString{
+ {
+ Lang: "eng",
+ Value: r.CVEMetadata.CWE,
+ },
+ },
+ },
+ },
+ },
+
+ Affects: cveschema.Affects{
+ Vendor: cveschema.Vendor{
+ Data: []cveschema.VendorDataItem{
+ {
+ VendorName: "n/a", // ???
+ Product: cveschema.Product{
+ Data: []cveschema.ProductDataItem{
+ {
+ ProductName: r.Package,
+ Version: versionToVersion(r.Versions),
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ }
+
+ for _, additional := range r.AdditionalPackages {
+ c.Affects.Vendor.Data = append(c.Affects.Vendor.Data, cveschema.VendorDataItem{
+ VendorName: "n/a",
+ Product: cveschema.Product{
+ Data: []cveschema.ProductDataItem{
+ {
+ ProductName: additional.Package,
+ Version: versionToVersion(additional.Versions),
+ },
+ },
+ },
+ })
+ }
+
+ if r.Links.PR != "" {
+ c.References.Data = append(c.References.Data, cveschema.Reference{URL: r.Links.PR})
+ }
+ if r.Links.Commit != "" {
+ c.References.Data = append(c.References.Data, cveschema.Reference{URL: r.Links.Commit})
+ }
+ for _, url := range r.Links.Context {
+ c.References.Data = append(c.References.Data, cveschema.Reference{URL: url})
+ }
+
+ return c, nil
+}
+
+func versionToVersion(versions []VersionRange) cveschema.VersionData {
+ vd := cveschema.VersionData{}
+ for _, vr := range versions {
+ if vr.Introduced != "" {
+ vd.Data = append(vd.Data, cveschema.VersionDataItem{
+ VersionValue: vr.Introduced,
+ VersionAffected: ">=",
+ })
+ }
+ if vr.Fixed != "" {
+ vd.Data = append(vd.Data, cveschema.VersionDataItem{
+ VersionValue: vr.Fixed,
+ VersionAffected: "<",
+ })
+ }
+ }
+ return vd
+}