Skip to content

Commit ac17b9d

Browse files
authored
Start accepting a new log checksum format (#8413)
This is change 1 of 3 described in #8414. It adds a new checksum format accepted by the log validator, but not using it.
1 parent a5cf372 commit ac17b9d

File tree

4 files changed

+63
-5
lines changed

4 files changed

+63
-5
lines changed

log/log.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,19 @@ type stdoutWriter struct {
160160
isatty bool
161161
}
162162

163+
// NewLineChecksum computes a CRC32 over the log line, which can be checked by
164+
// log-validator to ensure no unexpected log corruption has occurred.
165+
// It is currently only accepted for Validation, and will be switched in for
166+
// LogLineChecksum in an upcoming release.
167+
func NewLineChecksum(line string) string {
168+
crc := crc32.ChecksumIEEE([]byte(line))
169+
buf := make([]byte, crc32.Size)
170+
// Error is unreachable because we provide a supported type and buffer size
171+
_, _ = binary.Encode(buf, binary.LittleEndian, crc)
172+
return base64.RawURLEncoding.EncodeToString(buf)
173+
}
174+
175+
// LogLineChecksum is the current checksum algorithm, emitted in every log line.
163176
func LogLineChecksum(line string) string {
164177
crc := crc32.ChecksumIEEE([]byte(line))
165178
// Using the hash.Hash32 doesn't make this any easier

log/log_test.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"time"
1313

1414
"github.com/jmhodges/clock"
15+
1516
"github.com/letsencrypt/boulder/test"
1617
)
1718

@@ -342,3 +343,34 @@ func TestLogAtLevelEscapesNewlines(t *testing.T) {
342343

343344
test.Assert(t, strings.Contains(buf.String(), "foo\\nbar"), "failed to escape newline")
344345
}
346+
347+
func TestLogLineChecksum(t *testing.T) {
348+
testCases := []struct {
349+
name string
350+
function func(string) string
351+
input string
352+
expected string
353+
}{
354+
{
355+
name: "NewLineChecksum with Hello, World!",
356+
function: NewLineChecksum,
357+
input: "Hello, World!",
358+
expected: "0MNK7A",
359+
},
360+
{
361+
name: "LogLineChecksum with Info log",
362+
function: LogLineChecksum,
363+
input: "Info log",
364+
expected: "pcbo7wk",
365+
},
366+
}
367+
368+
for _, tc := range testCases {
369+
t.Run(tc.name, func(t *testing.T) {
370+
checksum := tc.function(tc.input)
371+
if checksum != tc.expected {
372+
t.Fatalf("got %q, want %q", checksum, tc.expected)
373+
}
374+
})
375+
}
376+
}

log/validator/validator.go

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -186,9 +186,10 @@ func lineValid(text string) error {
186186
}
187187
checksum := fields[5]
188188
_, err := base64.RawURLEncoding.DecodeString(checksum)
189-
if err != nil || len(checksum) != 7 {
189+
// TODO(#8414): Temporarily accept length 6 or 7 checksums
190+
if err != nil || (len(checksum) != 6 && len(checksum) != 7) {
190191
return fmt.Errorf(
191-
"%s expected a 7 character base64 raw URL decodable string, got %q: %w",
192+
"%s expected a 6 or 7 character base64 raw URL decodable string, got %q: %w",
192193
errorPrefix,
193194
checksum,
194195
errInvalidChecksum,
@@ -204,7 +205,14 @@ func lineValid(text string) error {
204205
return nil
205206
}
206207
// Check the extracted checksum against the computed checksum
207-
if computedChecksum := log.LogLineChecksum(line); checksum != computedChecksum {
208+
// TODO(#8414): Accept both the old and new checksum format, distinguished by length
209+
var computedChecksum string
210+
if len(checksum) == 6 {
211+
computedChecksum = log.NewLineChecksum(line)
212+
} else {
213+
computedChecksum = log.LogLineChecksum(line)
214+
}
215+
if checksum != computedChecksum {
208216
return fmt.Errorf("%s invalid checksum (expected %q, got %q)", errorPrefix, computedChecksum, checksum)
209217
}
210218
return nil

log/validator/validator_test.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,16 @@ import (
66
"github.com/letsencrypt/boulder/test"
77
)
88

9-
func TestLineValidAccepts(t *testing.T) {
10-
err := lineValid("2020-07-06T18:07:43.109389+00:00 70877f679c72 datacenter 6 boulder-wfe[1595]: kKG6cwA Caught SIGTERM")
9+
func TestLineValidAcceptsNew(t *testing.T) {
10+
err := lineValid("2020-07-06T18:07:43.109389+00:00 70877f679c72 datacenter 6 boulder-wfe[1595]: kJBuDg Caught SIGTERM")
1111
test.AssertNotError(t, err, "errored on valid checksum")
1212
}
1313

14+
func TestLineValidAcceptsOld(t *testing.T) {
15+
err := lineValid("2020-07-06T18:07:43.109389+00:00 70877f679c72 datacenter 6 boulder-wfe[1595]: kKG6cwA Caught SIGTERM")
16+
test.AssertNotError(t, err, "errored on valid old checksum")
17+
}
18+
1419
func TestLineValidRejects(t *testing.T) {
1520
err := lineValid("2020-07-06T18:07:43.109389+00:00 70877f679c72 datacenter 6 boulder-wfe[1595]: xxxxxxx Caught SIGTERM")
1621
test.AssertError(t, err, "didn't error on invalid checksum")

0 commit comments

Comments
 (0)