Every time in UTC, and every day as YYYY-MM-DD (closes #313)
check / check (push) Failing after 1m25s
check / check (push) Failing after 1m25s
AbuseIPDB's daily count keeps its day as a civil.Date, taken from the UTC clock and written to reputation.json as "YYYY-MM-DD"; it was a time.Time at midnight. Every time read from a state file is converted to UTC, so a time an admin writes with an offset is written back in UTC. TestMainRunsWAF runs sww waf with TZ 14 hours ahead of UTC and checks that the process line, the request line and clients.json are in UTC. SPEC.md states the rule near its start; AGENTS.md makes it an iron rule. Model: opus-5-5
This commit is contained in:
1 parent
f7e3190654
commit
42b99007c8
11 files changed
+256
-22
No files matched your search
+81
-2
@@ -171,9 +171,11 @@ type alertsFile struct {
|
||||
// check refuses the first entry without a field it needs, which would
|
||||
// otherwise be read as something the entry does not say. data is the
|
||||
// file, for a field that may be null or "" but not left out, which the
|
||||
// struct cannot tell apart.
|
||||
// struct cannot tell apart. Its toUTC then converts every time in it to
|
||||
// UTC, since an admin may write a time with an offset.
|
||||
type stateFile interface {
|
||||
check(data []byte) error
|
||||
toUTC()
|
||||
}
|
||||
|
||||
// Load checks that files can be written in Dir, and reads the state files
|
||||
@@ -918,6 +920,80 @@ func missing(i int, field string) error {
|
||||
return fmt.Errorf("entry %d %w %q", i+1, errMissing, field)
|
||||
}
|
||||
|
||||
// toUTC converts every time of each ban to UTC.
|
||||
func (f *bansFile) toUTC() {
|
||||
for i := range f.Bans {
|
||||
ban := &f.Bans[i]
|
||||
convertToUTC(&ban.Start, ban.Expires, ban.Lifted, &ban.Notes.Request.Time)
|
||||
}
|
||||
}
|
||||
|
||||
// toUTC converts every time of each client to UTC.
|
||||
func (f *clientsFile) toUTC() {
|
||||
for i := range f.Clients {
|
||||
client := &f.Clients[i]
|
||||
convertToUTC(&client.Minute.Start, &client.Hour.Start, &client.Day.Start,
|
||||
&client.MinuteBytes.Start, &client.HourBytes.Start,
|
||||
&client.DayBytes.Start, &client.MinuteRefusals.Start,
|
||||
&client.History.FirstSeen, &client.History.LastSeen,
|
||||
&client.History.LookedUp)
|
||||
}
|
||||
}
|
||||
|
||||
// toUTC converts both times of each answer to UTC.
|
||||
func (f *lookupsFile) toUTC() {
|
||||
for i := range f.Lookups {
|
||||
convertToUTC(&f.Lookups[i].Answered, &f.Lookups[i].Used)
|
||||
}
|
||||
}
|
||||
|
||||
// toUTC converts every time of each list, verdict and AbuseIPDB score to
|
||||
// UTC.
|
||||
func (f *reputationFile) toUTC() {
|
||||
for i := range f.Lists {
|
||||
convertToUTC(&f.Lists[i].Tried, &f.Lists[i].Fetched)
|
||||
}
|
||||
|
||||
for i := range f.Verdicts {
|
||||
convertToUTC(&f.Verdicts[i].Fetched)
|
||||
}
|
||||
|
||||
for i := range f.AbuseIPDB.Scores {
|
||||
convertToUTC(&f.AbuseIPDB.Scores[i].Fetched)
|
||||
}
|
||||
}
|
||||
|
||||
// toUTC converts every time of each cooldown, of the hour, of each alert
|
||||
// waiting and of each anomaly counter to UTC.
|
||||
func (f *alertsFile) toUTC() {
|
||||
for i := range f.Cooldowns {
|
||||
convertToUTC(&f.Cooldowns[i].Sent)
|
||||
}
|
||||
|
||||
convertToUTC(&f.Hour.Start)
|
||||
|
||||
for _, waiting := range f.Waiting {
|
||||
for i := range waiting {
|
||||
convertToUTC(&waiting[i].Time)
|
||||
}
|
||||
}
|
||||
|
||||
for i := range f.AnomalyCounters {
|
||||
counter := &f.AnomalyCounters[i]
|
||||
convertToUTC(&counter.Minute.Start, &counter.Hour.Start,
|
||||
&counter.MinuteBytes.Start, &counter.HourBytes.Start)
|
||||
}
|
||||
}
|
||||
|
||||
// convertToUTC converts each of times that is not nil to UTC.
|
||||
func convertToUTC(times ...*time.Time) {
|
||||
for _, at := range times {
|
||||
if at != nil {
|
||||
*at = at.UTC()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// encodeOnePerLine encodes a state file whose entries, under key, are one
|
||||
// to a line, so that grep shows everything about one client.
|
||||
func encodeOnePerLine[E any](key string, entries []E) ([]byte, error) {
|
||||
@@ -955,7 +1031,8 @@ func checkWritable(dir string) error {
|
||||
}
|
||||
|
||||
// parse reads data, what the state file at path holds, into file, a
|
||||
// pointer to that file's struct, and checks its entries.
|
||||
// pointer to that file's struct, checks its entries, and converts every
|
||||
// time in it to UTC.
|
||||
func parse(path string, data []byte, file stateFile) error {
|
||||
// The version is read first, so that a file of another version is
|
||||
// refused for that, and not for an entry this version cannot read.
|
||||
@@ -985,6 +1062,8 @@ func parse(path string, data []byte, file stateFile) error {
|
||||
return fmt.Errorf("%s%s: %w", path, position(data, err), err)
|
||||
}
|
||||
|
||||
file.toUTC()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user