From ac2d11fb1eb94febdbd6cdfa9d895e4b4977ef91 Mon Sep 17 00:00:00 2001 From: Andrew Ayer Date: Wed, 7 Jan 2026 21:23:04 +0000 Subject: [PATCH] Save certs to temporary files when -no_save is used Closes: #115 --- man/certspotter-script.md | 14 +++++++------- monitor/fsstate.go | 15 ++++++++++++++- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/man/certspotter-script.md b/man/certspotter-script.md index ec55a0e..3764bd0 100644 --- a/man/certspotter-script.md +++ b/man/certspotter-script.md @@ -74,18 +74,18 @@ The following environment variables are set for `discovered_cert` events: `CERT_FILENAME` -: Path to a file containing the PEM-encoded certificate chain. Not set if `-no_save` was used. +: Path to a file containing the PEM-encoded certificate chain. When `-no_save` is used, this points to a temporary file that is automatically deleted after your script completes. `JSON_FILENAME` : Path to a JSON file containing additional information about the certificate. See below for the format of the JSON file. - Not set if `-no_save` was used. + When `-no_save` is used, this points to a temporary file that is automatically deleted after your script completes. `TEXT_FILENAME` : Path to a text file containing information about the certificate. This file contains the same text that certspotter uses in emails. You should not attempt to parse this file because its format may change in the future. - Not set if `-no_save` was used. + When `-no_save` is used, this points to a temporary file that is automatically deleted after your script completes. `NOT_BEFORE`, `NOT_BEFORE_UNIXTIME`, `NOT_BEFORE_RFC3339` @@ -165,10 +165,10 @@ The following environment variables are set for `error` events: # JSON FILE FORMAT -Unless `-no_save` is used, certspotter saves a JSON file for every discovered certificate -in its state directory, and puts the path to the file in `$JSON_FILENAME`. Your -script can read the JSON file, such as with the jq(1) command, to get additional information -about the certificate which isn't appropriate for environment variables. +certspotter saves a JSON file for every discovered certificate and puts the path to the file in `$JSON_FILENAME`. +When `-no_save` is used, the JSON file is created in a temporary location and automatically deleted after your script completes. +Otherwise, it is saved in the state directory for permanent storage. Your script can read the JSON file, such as with the jq(1) command, +to get additional information about the certificate which isn't appropriate for environment variables. The JSON file contains an object with the following fields: diff --git a/monitor/fsstate.go b/monitor/fsstate.go index f89ec0d..c1231da 100644 --- a/monitor/fsstate.go +++ b/monitor/fsstate.go @@ -11,6 +11,7 @@ package monitor import ( "context" + "crypto/rand" "encoding/hex" "encoding/json" "errors" @@ -169,7 +170,19 @@ func (s *FilesystemState) NotifyCert(ctx context.Context, cert *DiscoveredCert) return fmt.Errorf("error saving certificate %x: %w", cert.SHA256, err) } } else { - // TODO-4: save cert to temporary files, and defer their unlinking + paths = &certPaths{ + certPath: filepath.Join(os.TempDir(), "certspotter-"+rand.Text()+".pem"), + jsonPath: filepath.Join(os.TempDir(), "certspotter-"+rand.Text()+".v1.json"), + textPath: filepath.Join(os.TempDir(), "certspotter-"+rand.Text()+".txt"), + } + defer func() { + os.Remove(paths.certPath) + os.Remove(paths.jsonPath) + os.Remove(paths.textPath) + }() + if err := writeCertFiles(cert, paths); err != nil { + return fmt.Errorf("error saving certificate %x to temporary files: %w", cert.SHA256, err) + } } if err := s.notify(ctx, ¬ification{