Save malformed entries, and put paths in environment variables

To allow scripts to access them.
This commit is contained in:
Andrew Ayer 2023-02-18 21:09:04 -05:00
parent ee8ae0c1f3
commit bd2bab5fcb
4 changed files with 49 additions and 10 deletions

View File

@ -138,6 +138,14 @@ The following environment variables are set for `malformed_cert` events:
: A human-readable string describing why the certificate is malformed.
`ENTRY_FILENAME`
: Path to a file containing the JSON log entry. The file contains a JSON object with two fields, `leaf_input` and `extra_data`, as described in RFC 6962 Section 4.6.
`TEXT_FILENAME`
: Path to a file containing a text message describing the malformed certificate. This file contains the same text that certspotter uses in emails.
# JSON FILE FORMAT
Unless `-no_save` is used, certspotter saves a JSON file for every discovered certificate

View File

@ -15,8 +15,30 @@ import (
)
type malformedLogEntry struct {
Entry *logEntry
Error string
Entry *logEntry
Error string
EntryPath string
TextPath string
}
func (malformed *malformedLogEntry) entryJSON() any {
return struct {
LeafInput []byte `json:"leaf_input"`
ExtraData []byte `json:"extra_data"`
}{
LeafInput: malformed.Entry.LeafInput,
ExtraData: malformed.Entry.ExtraData,
}
}
func (malformed *malformedLogEntry) save() error {
if err := writeJSONFile(malformed.EntryPath, malformed.entryJSON(), 0666); err != nil {
return err
}
if err := writeTextFile(malformed.TextPath, malformed.Text(), 0666); err != nil {
return err
}
return nil
}
func (malformed *malformedLogEntry) Environ() []string {
@ -27,6 +49,8 @@ func (malformed *malformedLogEntry) Environ() []string {
"ENTRY_INDEX=" + fmt.Sprint(malformed.Entry.Index),
"LEAF_HASH=" + malformed.Entry.LeafHash.Base64String(),
"PARSE_ERROR=" + malformed.Error,
"ENTRY_FILENAME=" + malformed.EntryPath,
"TEXT_FILENAME=" + malformed.TextPath,
"CERT_PARSEABLE=no", // backwards compat with pre-0.15.0; not documented
}
}

View File

@ -74,11 +74,12 @@ func monitorLog(ctx context.Context, config *Config, ctlog *loglist.Log, logClie
defer cancel()
var (
stateDirPath = filepath.Join(config.StateDir, "logs", ctlog.LogID.Base64URLString())
stateFilePath = filepath.Join(stateDirPath, "state.json")
sthsDirPath = filepath.Join(stateDirPath, "unverified_sths")
stateDirPath = filepath.Join(config.StateDir, "logs", ctlog.LogID.Base64URLString())
stateFilePath = filepath.Join(stateDirPath, "state.json")
sthsDirPath = filepath.Join(stateDirPath, "unverified_sths")
malformedDirPath = filepath.Join(stateDirPath, "malformed_entries")
)
for _, dirPath := range []string{stateDirPath, sthsDirPath} {
for _, dirPath := range []string{stateDirPath, sthsDirPath, malformedDirPath} {
if err := os.Mkdir(dirPath, 0777); err != nil && !errors.Is(err, fs.ErrExist) {
return fmt.Errorf("error creating state directory: %w", err)
}

View File

@ -157,12 +157,18 @@ func processCertificate(ctx context.Context, config *Config, entry *logEntry, ce
}
func processMalformedLogEntry(ctx context.Context, config *Config, entry *logEntry, parseError error) error {
// TODO-4: save the malformed entry (in get-entries format) in the state directory so user can inspect it
dirPath := filepath.Join(config.StateDir, "logs", entry.Log.LogID.Base64URLString(), "malformed_entries")
malformed := &malformedLogEntry{
Entry: entry,
Error: parseError.Error(),
Entry: entry,
Error: parseError.Error(),
EntryPath: filepath.Join(dirPath, fmt.Sprintf("%d.json", entry.Index)),
TextPath: filepath.Join(dirPath, fmt.Sprintf("%d.txt", entry.Index)),
}
if err := malformed.save(); err != nil {
return fmt.Errorf("error saving malformed log entry %d in %s (%q): %w", entry.Index, entry.Log.URL, parseError, err)
}
if err := notify(ctx, config, malformed); err != nil {
return fmt.Errorf("error notifying about malformed log entry %d in %s (%q): %w", entry.Index, entry.Log.URL, parseError, err)
}