Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Checker: Add time range to report #422

Merged
merged 10 commits into from
Aug 17, 2023
16 changes: 4 additions & 12 deletions cmd/csaf_checker/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import (
"errors"
"fmt"
"net/http"
"time"

"github.com/csaf-poc/csaf_distribution/v2/internal/filter"
"github.com/csaf-poc/csaf_distribution/v2/internal/models"
Expand Down Expand Up @@ -49,7 +48,7 @@ type config struct {
Config string `short:"c" long:"config" description:"Path to config TOML file" value-name:"TOML-FILE" toml:"-"`

clientCerts []tls.Certificate
ageAccept func(time.Time) bool
ageAccept *models.TimeRange
ignorePattern filter.PatternMatcher
}

Expand Down Expand Up @@ -156,14 +155,6 @@ func (cfg *config) prepareCertificates() error {
return nil
}

// acceptYears returns a filter that accepts advisories from the last years.
func acceptYears(years uint) func(time.Time) bool {
good := time.Now().AddDate(-int(years), 0, 0)
return func(t time.Time) bool {
return !t.Before(good)
}
}

// prepareTimeRangeFilter sets up the filter in which time range
// advisory should be considered for checking.
func (cfg *config) prepareTimeRangeFilter() error {
Expand All @@ -172,10 +163,11 @@ func (cfg *config) prepareTimeRangeFilter() error {
return errors.New(`"timerange" and "years" are both configured: only one allowed`)

case cfg.Years != nil:
cfg.ageAccept = acceptYears(*cfg.Years)
years := models.NYears(*cfg.Years)
cfg.ageAccept = &years

case cfg.Range != nil:
cfg.ageAccept = cfg.Range.Contains
cfg.ageAccept = cfg.Range
}
return nil
}
13 changes: 7 additions & 6 deletions cmd/csaf_checker/processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,8 +241,9 @@ func (p *processor) clean() {
func (p *processor) run(domains []string) (*Report, error) {

report := Report{
Date: ReportTime{Time: time.Now().UTC()},
Version: util.SemVersion,
Date: ReportTime{Time: time.Now().UTC()},
Version: util.SemVersion,
TimeRange: p.cfg.ageAccept,
}

for _, d := range domains {
Expand Down Expand Up @@ -545,8 +546,8 @@ func (p *processor) rolieFeedEntries(feed string) ([]csaf.AdvisoryFile, error) {
rfeed.Entries(func(entry *csaf.Entry) {

// Filter if we have date checking.
if p.cfg.ageAccept != nil {
if pub := time.Time(entry.Published); !pub.IsZero() && !p.cfg.ageAccept(pub) {
if accept := p.cfg.ageAccept; accept != nil {
if pub := time.Time(entry.Published); !pub.IsZero() && !accept.Contains(pub) {
return
}
}
Expand Down Expand Up @@ -666,7 +667,7 @@ func (p *processor) integrity(
if m := yearFromURL.FindStringSubmatch(u); m != nil {
year, _ := strconv.Atoi(m[1])
// Check if we are in checking time interval.
if p.cfg.ageAccept != nil && !p.cfg.ageAccept(
if accept := p.cfg.ageAccept; accept != nil && !accept.Contains(
time.Date(
year, 12, 31, // Assume last day of year.
23, 59, 59, 0, // 23:59:59
Expand Down Expand Up @@ -972,7 +973,7 @@ func (p *processor) checkChanges(base string, mask whereType) error {
return nil, nil, err
}
// Apply date range filtering.
if p.cfg.ageAccept != nil && !p.cfg.ageAccept(t) {
if accept := p.cfg.ageAccept; accept != nil && !accept.Contains(t) {
continue
}
path := r[pathColumn]
Expand Down
8 changes: 5 additions & 3 deletions cmd/csaf_checker/report.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"time"

"github.com/csaf-poc/csaf_distribution/v2/csaf"
"github.com/csaf-poc/csaf_distribution/v2/internal/models"
)

// MessageType is the kind of the message.
Expand Down Expand Up @@ -60,9 +61,10 @@ type ReportTime struct{ time.Time }

// Report is the overall report.
type Report struct {
Domains []*Domain `json:"domains,omitempty"`
Version string `json:"version,omitempty"`
Date ReportTime `json:"date,omitempty"`
Domains []*Domain `json:"domains,omitempty"`
Version string `json:"version,omitempty"`
Date ReportTime `json:"date,omitempty"`
TimeRange *models.TimeRange `json:"timerange,omitempty"`
}

// MarshalText implements the encoding.TextMarshaller interface.
Expand Down
22 changes: 20 additions & 2 deletions cmd/csaf_checker/tmpl/report.html
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,26 @@ <h2>{{ .Name }}{{ if .HasErrors }} (failed){{ end }}</h2>
{{ end }}

<footer>
Date of run: <time datetime="{{.Date.Format "2006-01-02T15:04:05Z"}}">{{ .Date.Local.Format "Monday, 02 Jan 2006 15:04:05 MST" }}</time>
csaf_checker v<span class="version">{{ .Version }}</span>
<fieldset>
<legend>Runtime</legend>
<table>
<tr>
<td><strong>Date of run:</strong></td>
<td><time datetime="{{ .Date.Format "2006-01-02T15:04:05Z"}}">{{ .Date.Local.Format "Monday, 02 Jan 2006 15:04:05 MST" }}</time></td>
</tr>
{{ if .TimeRange }}{{ with .TimeRange }}
<tr>
<td><strong>Time range:</strong></td>
<td><time datetime="{{ (index . 0).Format "2006-01-02T15:04:05Z"}}">{{ (index . 0).Local.Format "Monday, 02 Jan 2006 15:04:05 MST" }}</time> -
<time datetime="{{ (index . 1).Format "2006-01-02T15:04:05Z"}}">{{ (index . 1).Local.Format "Monday, 02 Jan 2006 15:04:05 MST" }}</time></td>
</tr>
{{ end }}{{ end }}
<tr>
<td><strong>Version:</strong></td>
<td>csaf_checker v<span class="version">{{ .Version }}</span></td>
</tr>
</table>
</fieldset>
</footer>
</body>
</html>
3 changes: 2 additions & 1 deletion docs/csaf_checker.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
Usage:
csaf_checker [OPTIONS] domain...

Application Options:
bernhardreiter marked this conversation as resolved.
Show resolved Hide resolved
Application Options:
-o, --output=REPORT-FILE File name of the generated report
-f, --format=[json|html] Format of report (default: json)
Expand Down Expand Up @@ -104,7 +105,7 @@ of regular expressions to match their URLs by using the `ignorepattern`
option.

E.g. `-i='.*white.*' -i='*.red.*'` will ignore files which URLs contain
the sub strings **white** or **red**.
the sub strings **white** or **red**.
In the config file this has to be noted as:
```
ignorepattern = [".*white.*", ".*red.*"]
Expand Down
19 changes: 18 additions & 1 deletion internal/models/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
package models

import (
"encoding/json"
"fmt"
"strings"
"time"
Expand All @@ -27,10 +28,17 @@ func NewTimeInterval(a, b time.Time) TimeRange {
return TimeRange{a, b}
}

// NYears returns a time interval spanning the last years.
func NYears(years uint) TimeRange {
now := time.Now()
start := now.AddDate(-int(years), 0, 0)
return NewTimeInterval(start, now)
}

// guessDate tries to guess an RFC 3339 date time from a given string.
func guessDate(s string) (time.Time, bool) {
for _, layout := range []string{
"2006-01-02T15:04:05Z07:00",
time.RFC3339,
"2006-01-02T15:04:05",
"2006-01-02T15:04",
"2006-01-02T15",
Expand All @@ -50,6 +58,15 @@ func (tr *TimeRange) UnmarshalText(text []byte) error {
return tr.UnmarshalFlag(string(text))
}

// MarshalJSON implements [encoding/json.Marshaler].
func (tr TimeRange) MarshalJSON() ([]byte, error) {
s := []string{
tr[0].Format(time.RFC3339),
tr[1].Format(time.RFC3339),
}
return json.Marshal(s)
}

// UnmarshalFlag implements [go-flags/Unmarshaler].
func (tr *TimeRange) UnmarshalFlag(s string) error {
s = strings.TrimSpace(s)
Expand Down
Loading