From 465f427a04c2f10bc5163f6bceef13693f7e99e6 Mon Sep 17 00:00:00 2001 From: Paul Duncan Date: Tue, 1 Feb 2022 12:48:15 -0500 Subject: internal/feed: add v2impact, v3impact, and tests --- internal/feed/feed.go | 45 +++-------------------- internal/feed/v2impact.go | 42 +++++++++++++++++++++ internal/feed/v2impact_string.go | 25 +++++++++++++ internal/feed/v2impact_test.go | 79 ++++++++++++++++++++++++++++++++++++++++ internal/feed/v3impact.go | 42 +++++++++++++++++++++ internal/feed/v3impact_string.go | 25 +++++++++++++ internal/feed/v3impact_test.go | 79 ++++++++++++++++++++++++++++++++++++++++ 7 files changed, 297 insertions(+), 40 deletions(-) create mode 100644 internal/feed/v2impact.go create mode 100644 internal/feed/v2impact_string.go create mode 100644 internal/feed/v2impact_test.go create mode 100644 internal/feed/v3impact.go create mode 100644 internal/feed/v3impact_string.go create mode 100644 internal/feed/v3impact_test.go (limited to 'internal/feed') diff --git a/internal/feed/feed.go b/internal/feed/feed.go index b9f7678..9c27fb0 100644 --- a/internal/feed/feed.go +++ b/internal/feed/feed.go @@ -11,9 +11,6 @@ const ( Medium // medium complexity/priv req High // high complexity/priv req - Complete // complete integrity impact - Partial // partial integrity impact - Critical // critical severity CvssVersion31 // CVSS version 3.1 @@ -24,38 +21,6 @@ const ( // TODO: parse cpe -// CVSS integrity/availability impact level -type ImpactLevel int - -// Unmarshal CVSS integrity/availability impact level from JSON. -func (me *ImpactLevel) UnmarshalJSON(b []byte) error { - // decode string, check for error - var s string - if err := json.Unmarshal(b, &s); err != nil { - return err - } - - // check value - switch s { - case "NONE": - *me = None - case "LOW": - *me = Low - case "PARTIAL": - *me = Partial - case "HIGH": - *me = High - case "COMPLETE": - *me = Complete - default: - // return error - return fmt.Errorf("unknown impact level: %s", s) - } - - // return success - return nil -} - // CVSS score type Score float32 @@ -381,10 +346,10 @@ type CvssV3 struct { Scope V3Scope `json:"scope"` // integrity impact - IntegrityImpact ImpactLevel `json:"integrityImpact"` + IntegrityImpact V3Impact `json:"integrityImpact"` // availability impact - AvailabilityImpact ImpactLevel `json:"availabilityImpact"` + AvailabilityImpact V3Impact `json:"availabilityImpact"` // base score BaseScore Score `json:"baseScore"` @@ -417,9 +382,9 @@ type CvssV2 struct { // authentication Authentication Authentication `json:"authentication"` - ConfidentialityImpact ImpactLevel `json:"confidentialityImpact"` - IntegrityImpact ImpactLevel `json:"integrityImpact"` - AvailabilityImpact ImpactLevel `json:"availabilityImpact"` + ConfidentialityImpact V2Impact `json:"confidentialityImpact"` + IntegrityImpact V2Impact `json:"integrityImpact"` + AvailabilityImpact V2Impact `json:"availabilityImpact"` // base score BaseScore Score `json:"baseScore"` diff --git a/internal/feed/v2impact.go b/internal/feed/v2impact.go new file mode 100644 index 0000000..1585e18 --- /dev/null +++ b/internal/feed/v2impact.go @@ -0,0 +1,42 @@ +package feed + +//go:generate stringer -linecomment -type=V2Impact + +import ( + "encoding/json" + "fmt" +) + +// CVSS v2 impact level. +type V2Impact byte + +const ( + V2ImpactNone V2Impact = iota // NONE + V2ImpactPartial // PARTIAL + V2ImpactComplete // COMPLETE +) + +// Unmarshal CVSS v2 impact level from JSON. +func (me *V2Impact) UnmarshalJSON(b []byte) error { + // decode string, check for error + var s string + if err := json.Unmarshal(b, &s); err != nil { + return err + } + + // check value + switch s { + case "NONE": + *me = V2ImpactNone + case "PARTIAL": + *me = V2ImpactPartial + case "COMPLETE": + *me = V2ImpactComplete + default: + // return error + return fmt.Errorf("unknown CVSS v2 impact: %s", s) + } + + // return success + return nil +} diff --git a/internal/feed/v2impact_string.go b/internal/feed/v2impact_string.go new file mode 100644 index 0000000..1dcf21b --- /dev/null +++ b/internal/feed/v2impact_string.go @@ -0,0 +1,25 @@ +// Code generated by "stringer -linecomment -type=V2Impact"; DO NOT EDIT. + +package feed + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[V2ImpactNone-0] + _ = x[V2ImpactPartial-1] + _ = x[V2ImpactComplete-2] +} + +const _V2Impact_name = "NONEPARTIALCOMPLETE" + +var _V2Impact_index = [...]uint8{0, 4, 11, 19} + +func (i V2Impact) String() string { + if i >= V2Impact(len(_V2Impact_index)-1) { + return "V2Impact(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _V2Impact_name[_V2Impact_index[i]:_V2Impact_index[i+1]] +} diff --git a/internal/feed/v2impact_test.go b/internal/feed/v2impact_test.go new file mode 100644 index 0000000..54dc566 --- /dev/null +++ b/internal/feed/v2impact_test.go @@ -0,0 +1,79 @@ +package feed + +import ( + "encoding/json" + "testing" +) + +func TestV2ImpactUnmarshalInvalidData(t *testing.T) { + test := []byte(`{}`) + var val V2Impact + + if err := json.Unmarshal(test, &val); err == nil { + t.Errorf("got \"%s\", exp error", val) + } +} + +func TestV2ImpactUnmarshalUnknown(t *testing.T) { + test := []byte(`"foo"`) + exp := "unknown CVSS v2 impact: foo" + var val V2Impact + + err := json.Unmarshal(test, &val) + if err == nil { + t.Errorf("got \"%s\", exp error", val) + return + } + + if err.Error() != exp { + t.Errorf("got \"%s\", exp \"%s\"", err.Error(), exp) + } +} + +func TestV2ImpactUnmarshalValid(t *testing.T) { + tests := []struct { + val string + exp V2Impact + } { + { "\"NONE\"", V2ImpactNone }, + { "\"PARTIAL\"", V2ImpactPartial }, + { "\"COMPLETE\"", V2ImpactComplete }, + } + + for _, test := range(tests) { + t.Run(test.val, func(t *testing.T) { + var got V2Impact + if err := json.Unmarshal([]byte(test.val), &got); err != nil { + t.Error(err) + return + } + + if got != test.exp { + t.Errorf("got \"%s\", exp \"%s\"", got, test.exp) + } + }) + } +} + +func TestV2ImpactString(t *testing.T) { + tests := []struct { + val V2Impact + exp string + } { + { V2ImpactNone, "NONE" }, + { V2ImpactPartial, "PARTIAL" }, + { V2ImpactComplete, "COMPLETE" }, + + { V2Impact(255), "V2Impact(255)" }, + } + + for _, test := range(tests) { + t.Run(test.exp, func(t *testing.T) { + got := test.val.String() + + if got != test.exp { + t.Errorf("got \"%s\", exp \"%s\"", got, test.exp) + } + }) + } +} diff --git a/internal/feed/v3impact.go b/internal/feed/v3impact.go new file mode 100644 index 0000000..d6c450e --- /dev/null +++ b/internal/feed/v3impact.go @@ -0,0 +1,42 @@ +package feed + +//go:generate stringer -linecomment -type=V3Impact + +import ( + "encoding/json" + "fmt" +) + +// CVSS v3 impact level. +type V3Impact byte + +const ( + V3ImpactNone V3Impact = iota // NONE + V3ImpactLow // LOW + V3ImpactHigh // HIGH +) + +// Unmarshal CVSS v3 impact level from JSON. +func (me *V3Impact) UnmarshalJSON(b []byte) error { + // decode string, check for error + var s string + if err := json.Unmarshal(b, &s); err != nil { + return err + } + + // check value + switch s { + case "NONE": + *me = V3ImpactNone + case "LOW": + *me = V3ImpactLow + case "HIGH": + *me = V3ImpactHigh + default: + // return error + return fmt.Errorf("unknown CVSS v3 impact: %s", s) + } + + // return success + return nil +} diff --git a/internal/feed/v3impact_string.go b/internal/feed/v3impact_string.go new file mode 100644 index 0000000..13c7ee3 --- /dev/null +++ b/internal/feed/v3impact_string.go @@ -0,0 +1,25 @@ +// Code generated by "stringer -linecomment -type=V3Impact"; DO NOT EDIT. + +package feed + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[V3ImpactNone-0] + _ = x[V3ImpactLow-1] + _ = x[V3ImpactHigh-2] +} + +const _V3Impact_name = "NONELOWHIGH" + +var _V3Impact_index = [...]uint8{0, 4, 7, 11} + +func (i V3Impact) String() string { + if i >= V3Impact(len(_V3Impact_index)-1) { + return "V3Impact(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _V3Impact_name[_V3Impact_index[i]:_V3Impact_index[i+1]] +} diff --git a/internal/feed/v3impact_test.go b/internal/feed/v3impact_test.go new file mode 100644 index 0000000..a369f44 --- /dev/null +++ b/internal/feed/v3impact_test.go @@ -0,0 +1,79 @@ +package feed + +import ( + "encoding/json" + "testing" +) + +func TestV3ImpactUnmarshalInvalidData(t *testing.T) { + test := []byte(`{}`) + var val V3Impact + + if err := json.Unmarshal(test, &val); err == nil { + t.Errorf("got \"%s\", exp error", val) + } +} + +func TestV3ImpactUnmarshalUnknown(t *testing.T) { + test := []byte(`"foo"`) + exp := "unknown CVSS v3 impact: foo" + var val V3Impact + + err := json.Unmarshal(test, &val) + if err == nil { + t.Errorf("got \"%s\", exp error", val) + return + } + + if err.Error() != exp { + t.Errorf("got \"%s\", exp \"%s\"", err.Error(), exp) + } +} + +func TestV3ImpactUnmarshalValid(t *testing.T) { + tests := []struct { + val string + exp V3Impact + } { + { "\"NONE\"", V3ImpactNone }, + { "\"LOW\"", V3ImpactLow }, + { "\"HIGH\"", V3ImpactHigh }, + } + + for _, test := range(tests) { + t.Run(test.val, func(t *testing.T) { + var got V3Impact + if err := json.Unmarshal([]byte(test.val), &got); err != nil { + t.Error(err) + return + } + + if got != test.exp { + t.Errorf("got \"%s\", exp \"%s\"", got, test.exp) + } + }) + } +} + +func TestV3ImpactString(t *testing.T) { + tests := []struct { + val V3Impact + exp string + } { + { V3ImpactNone, "NONE" }, + { V3ImpactLow, "LOW" }, + { V3ImpactHigh, "HIGH" }, + + { V3Impact(255), "V3Impact(255)" }, + } + + for _, test := range(tests) { + t.Run(test.exp, func(t *testing.T) { + got := test.val.String() + + if got != test.exp { + t.Errorf("got \"%s\", exp \"%s\"", got, test.exp) + } + }) + } +} -- cgit v1.2.3