Skip to content

Commit

Permalink
internal/config: fix CR issues
Browse files Browse the repository at this point in the history
  • Loading branch information
seilagamo committed Jul 23, 2024
1 parent da0900e commit ec468c8
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 84 deletions.
2 changes: 2 additions & 0 deletions cmd/lava/internal/help/helpdoc.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,8 @@ The exclusion rules support the following filters:
and the checktype options.
- summary: regular expression that matches the summary of the
vulnerability.
- expiration: is the date on which the exclusion becomes inactive.
The format is YYYY/MM/DD.
A finding is excluded if it matches all the filters of an exclusion
rule.
Expand Down
11 changes: 5 additions & 6 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ type Exclusion struct {
// the vulnerability.
Summary string `yaml:"summary"`

// Expiration is the maximum date until the exclusion is considered.
// ExpirationDate is the date on which the exclusion becomes inactive.
// The format is YYYY/MM/DD.
ExpirationDate ExpirationDate `yaml:"expiration"`

Expand All @@ -413,12 +413,12 @@ type ExpirationDate struct {
}

// parseExpirationDate converts a string into an [ExpirationDate] value.
func parseExpirationDate(expirationDate string) (ExpirationDate, error) {
result, err := time.Parse(ExpirationDateLayout, expirationDate)
func parseExpirationDate(date string) (ExpirationDate, error) {
t, err := time.Parse(ExpirationDateLayout, date)
if err != nil {
return ExpirationDate{}, fmt.Errorf("%w: %w", ErrInvalidExpirationDate, err)
}
return ExpirationDate{result}, nil
return ExpirationDate{Time: t}, nil
}

// UnmarshalText decodes an [ExpirationDate] text into an [ExpirationDate]
Expand All @@ -433,8 +433,7 @@ func (ed *ExpirationDate) UnmarshalText(text []byte) error {
return nil
}

// MarshalText encodes an [ExpirationDate] as text. It returns error
// if the date is invalid.
// MarshalText encodes an [ExpirationDate] value as text.
func (ed ExpirationDate) MarshalText() (text []byte, err error) {
return []byte(ed.String()), nil
}
Expand Down
75 changes: 31 additions & 44 deletions internal/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import (
agentconfig "github.com/adevinta/vulcan-agent/config"
types "github.com/adevinta/vulcan-types"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
)

func TestParse(t *testing.T) {
Expand Down Expand Up @@ -237,7 +236,7 @@ func TestParse(t *testing.T) {
wantErrRegexp: regexp.MustCompile(`level string ".*": unknown name`),
},
{
name: "valid expiration data",
name: "valid expiration date",
file: "testdata/valid_expiration_date.yaml",
want: Config{
LavaVersion: "v1.0.0",
Expand All @@ -257,14 +256,14 @@ func TestParse(t *testing.T) {
{
Summary: "Secret Leaked in Git Repository",
Description: "Ignore test certificates.",
ExpirationDate: parseED("2024/07/05"),
ExpirationDate: mustParseExpDate("2024/07/05"),
},
},
},
},
},
{
name: "invalid expiration data",
name: "invalid expiration date",
file: "testdata/invalid_expiration_date.yaml",
want: Config{},
wantErr: ErrInvalidExpirationDate,
Expand Down Expand Up @@ -294,8 +293,7 @@ func TestParse(t *testing.T) {
t.Errorf("unexpected error: %v", err)
}
}
opt := cmpopts.EquateComparable(ExpirationDate{})
if diff := cmp.Diff(tt.want, got, opt); diff != "" {
if diff := cmp.Diff(tt.want, got); diff != "" {
t.Errorf("configs mismatch (-want +got):\n%v", diff)
}
})
Expand Down Expand Up @@ -415,27 +413,27 @@ func ptr[V any](v V) *V {

func TestParseExpirationDate(t *testing.T) {
tests := []struct {
name string
dateString string
want ExpirationDate
wantErr error
name string
date string
want ExpirationDate
wantErr error
}{
{
name: "valid date",
dateString: "2024/07/05",
want: parseED("2024/07/05"),
wantErr: nil,
name: "valid date",
date: "2024/07/05",
want: mustParseExpDate("2024/07/05"),
wantErr: nil,
},
{
name: "invalid date",
dateString: "2024-07-05",
want: ExpirationDate{},
wantErr: ErrInvalidExpirationDate,
name: "invalid date",
date: "2024-07-05",
want: ExpirationDate{},
wantErr: ErrInvalidExpirationDate,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := parseExpirationDate(tt.dateString)
got, err := parseExpirationDate(tt.date)
if !errors.Is(err, tt.wantErr) {
t.Errorf("unexpected error: want: %v, got: %v", tt.wantErr, err)
}
Expand All @@ -447,33 +445,22 @@ func TestParseExpirationDate(t *testing.T) {
}

func TestExpirationDate_MarshalText(t *testing.T) {
tests := []struct {
name string
date ExpirationDate
want string
wantErr error
}{
{
name: "valid date",
date: parseED("2024/07/05"),
want: "2024/07/05",
wantErr: nil,
},
date := mustParseExpDate("2024/07/05")
want := "2024/07/05"

got, err := date.MarshalText()
if err != nil {
t.Errorf("unexpected error: want: %v, got: %v", nil, err)
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := tt.date.MarshalText()
if !errors.Is(err, tt.wantErr) {
t.Errorf("unexpected error: want: %v, got: %v", tt.wantErr, err)
}
if string(got) != tt.want {
t.Errorf("unexpected expiration date string: want: %v, got: %v", tt.want, string(got))
}
})
if string(got) != want {
t.Errorf("unexpected expiration date string: want: %s, got: %s", want, got)
}
}

func parseED(expirationDate string) ExpirationDate {
result, _ := time.Parse(ExpirationDateLayout, expirationDate)
return ExpirationDate{result}
func mustParseExpDate(date string) ExpirationDate {
t, err := time.Parse(ExpirationDateLayout, date)
if err != nil {
panic(err)
}
return ExpirationDate{Time: t}
}
25 changes: 6 additions & 19 deletions internal/report/report.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,10 @@ type Writer struct {
minSeverity config.Severity
showSeverity config.Severity
exclusions []config.Exclusion
timeProvider TimeProvider
}

// TimeProvider provides a time server.
type TimeProvider interface {
Now() time.Time
}

type realTime struct{}

func (realTime) Now() time.Time {
return time.Now()
}
// timeNow is set by tests to mock the current time.
var timeNow = time.Now

// NewWriter creates a new instance of a report writer.
func NewWriter(cfg config.ReportConfig) (Writer, error) {
Expand Down Expand Up @@ -80,7 +71,6 @@ func NewWriter(cfg config.ReportConfig) (Writer, error) {
minSeverity: cfg.Severity,
showSeverity: showSeverity,
exclusions: cfg.Exclusions,
timeProvider: realTime{},
}, nil
}

Expand Down Expand Up @@ -152,6 +142,10 @@ func (writer Writer) parseReport(er engine.Report) ([]vulnerability, error) {
// excluded based on the [Writer] configuration and the affected target.
func (writer Writer) isExcluded(v report.Vulnerability, target string) (bool, error) {
for _, excl := range writer.exclusions {
if !excl.ExpirationDate.IsZero() && excl.ExpirationDate.Before(timeNow()) {
continue
}

if excl.Fingerprint != "" && v.Fingerprint != excl.Fingerprint {
continue
}
Expand Down Expand Up @@ -189,13 +183,6 @@ func (writer Writer) isExcluded(v report.Vulnerability, target string) (bool, er
continue
}
}

if !excl.ExpirationDate.IsZero() {
now := writer.timeProvider.Now()
if excl.ExpirationDate.Before(now) {
continue
}
}
return true, nil
}
return false, nil
Expand Down
31 changes: 16 additions & 15 deletions internal/report/report_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -413,13 +413,6 @@ func TestWriter_parseReport(t *testing.T) {
}
}

type mockTime struct{}

func (mt mockTime) Now() time.Time {
testTime, _ := time.Parse(time.RFC3339, "2024-01-02T15:04:05Z")
return testTime
}

func TestWriter_isExcluded(t *testing.T) {
tests := []struct {
name string
Expand Down Expand Up @@ -640,7 +633,7 @@ func TestWriter_isExcluded(t *testing.T) {
wantNilErr: true,
},
{
name: "exclude by summary not expired",
name: "active exclusion",
vulnerability: vreport.Vulnerability{
Summary: "Vulnerability Summary 1",
Score: 6.7,
Expand All @@ -651,15 +644,15 @@ func TestWriter_isExcluded(t *testing.T) {
{
Summary: "Summary 1",
Description: "Excluded vulnerabilities Summary 1",
ExpirationDate: parseED("2024/05/06"),
ExpirationDate: mustParseExpDate("2024/05/06"),
},
},
},
want: true,
wantNilErr: true,
},
{
name: "exclusion expired",
name: "expired exclusion",
vulnerability: vreport.Vulnerability{
Summary: "Vulnerability Summary 1",
Score: 6.7,
Expand All @@ -670,7 +663,7 @@ func TestWriter_isExcluded(t *testing.T) {
{
Summary: "Summary 1",
Description: "Excluded vulnerabilities Summary 1",
ExpirationDate: parseED("2023/05/06"),
ExpirationDate: mustParseExpDate("2023/05/06"),
},
},
},
Expand All @@ -680,8 +673,13 @@ func TestWriter_isExcluded(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
oldTimeNow := timeNow
defer func() { timeNow = oldTimeNow }()
timeNow = func() time.Time {
tn, _ := time.Parse(time.RFC3339, "2024-01-02T15:04:05Z")
return tn
}
w, err := NewWriter(tt.rConfig)
w.timeProvider = mockTime{}
if err != nil {
t.Fatalf("unable to create a report writer: %v", err)
}
Expand Down Expand Up @@ -1506,7 +1504,10 @@ func ptr[V any](v V) *V {
return &v
}

func parseED(expirationDate string) config.ExpirationDate {
result, _ := time.Parse(config.ExpirationDateLayout, expirationDate)
return config.ExpirationDate{Time: result}
func mustParseExpDate(date string) config.ExpirationDate {
t, err := time.Parse(config.ExpirationDateLayout, date)
if err != nil {
panic(err)
}
return config.ExpirationDate{Time: t}
}

0 comments on commit ec468c8

Please sign in to comment.