cert-checker: use config log level and handle nil mariadb response (#6066)

- Fix cert-checker to use the syslog and stdout logging facilities it
reads from the config file instead of having them hard-coded to zero.
- Fix cert-checker to handle a nil response from mariadb if no records
are found.
- Fix comment in log.go to correctly describe when the initialize function
and therefore default values would be used.

Fixes #6067
This commit is contained in:
Daniel Jeffery 2022-05-02 14:29:53 -06:00 committed by GitHub
parent 8ec10c4848
commit a2ff222fda
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 52 additions and 9 deletions

View File

@ -4,7 +4,9 @@ import (
"bytes"
"context"
"crypto/x509"
"database/sql"
"encoding/json"
"errors"
"flag"
"fmt"
"log/syslog"
@ -80,7 +82,7 @@ type reportEntry struct {
// out the saDbMap implementation.
type certDB interface {
Select(i interface{}, query string, args ...interface{}) ([]interface{}, error)
SelectInt(query string, args ...interface{}) (int64, error)
SelectNullInt(query string, args ...interface{}) (sql.NullInt64, error)
}
type certChecker struct {
@ -118,13 +120,19 @@ func (c *certChecker) getCerts(unexpiredOnly bool) error {
args["now"] = c.clock.Now()
}
initialID, err := c.dbMap.SelectInt(
sni, err := c.dbMap.SelectNullInt(
"SELECT MIN(id) FROM certificates WHERE issued >= :issued AND expires >= :now",
args,
)
if err != nil {
return err
}
if !sni.Valid {
// a nil response was returned by the DB, so return error and fail
return errors.New("the SELECT query resulted in a NULL response from the DB")
}
initialID := sni.Int64
if initialID > 0 {
// decrement the initial ID so that we select below as we aren't using >=
initialID -= 1
@ -368,8 +376,12 @@ func main() {
syslogger, err := syslog.Dial("", "", syslog.LOG_INFO|syslog.LOG_LOCAL0, "")
cmd.FailOnError(err, "Failed to dial syslog")
logger, err := blog.New(syslogger, 0, 0)
cmd.FailOnError(err, "Failed to construct logger")
syslogLevel := int(syslog.LOG_INFO)
if config.Syslog.SyslogLevel != 0 {
syslogLevel = config.Syslog.SyslogLevel
}
logger, err := blog.New(syslogger, config.Syslog.StdoutLevel, syslogLevel)
cmd.FailOnError(err, "Could not connect to Syslog")
err = blog.Set(logger)
cmd.FailOnError(err, "Failed to set audit logger")

View File

@ -9,6 +9,7 @@ import (
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"database/sql"
"encoding/asn1"
"encoding/pem"
"io/ioutil"
@ -380,8 +381,12 @@ type mismatchedCountDB struct{}
// `getCerts` calls `SelectInt` first to determine how many rows there are
// matching the `getCertsCountQuery` criteria. For this mock we return
// a non-zero number
func (db mismatchedCountDB) SelectInt(_ string, _ ...interface{}) (int64, error) {
return 99999, nil
func (db mismatchedCountDB) SelectNullInt(_ string, _ ...interface{}) (sql.NullInt64, error) {
return sql.NullInt64{
Int64: 99999,
Valid: true,
},
nil
}
// `getCerts` then calls `Select` to retrieve the Certificate rows. We pull
@ -422,6 +427,33 @@ func TestGetCertsEmptyResults(t *testing.T) {
test.AssertNotError(t, err, "Failed to retrieve certificates")
}
// emptyDB is a certDB object with methods used for testing that 'null'
// responses received from the database are handled properly.
type emptyDB struct {
certDB
}
// SelectNullInt is a method that returns a false sql.NullInt64 struct to
// mock a null DB response
func (db emptyDB) SelectNullInt(_ string, _ ...interface{}) (sql.NullInt64, error) {
return sql.NullInt64{Valid: false},
nil
}
// TestGetCertsNullResults tests that a null response from the database will
// be handled properly. It uses the emptyDB above to mock the response
// expected if the DB finds no certificates to match the SELECT query and
// should return an error.
func TestGetCertsNullResults(t *testing.T) {
saDbMap, err := sa.NewDbMap(vars.DBConnSA, sa.DbSettings{})
test.AssertNotError(t, err, "Couldn't connect to database")
checker := newChecker(saDbMap, clock.NewFake(), pa, kp, time.Hour, testValidityDurations)
checker.dbMap = emptyDB{}
err = checker.getCerts(false)
test.AssertError(t, err, "Should have gotten error from empty DB")
}
func TestSaveReport(t *testing.T) {
r := report{
begin: time.Time{},

View File

@ -65,10 +65,9 @@ func New(log *syslog.Writer, stdoutLogLevel int, syslogLogLevel int) (Logger, er
}, nil
}
// initialize should only be used in unit tests.
// initialize is used in unit tests and called by `Get` before the logger
// is fully set up.
func initialize() {
// defaultPriority is never used because we always use specific priority-based
// logging methods.
const defaultPriority = syslog.LOG_INFO | syslog.LOG_LOCAL0
syslogger, err := syslog.Dial("", "", defaultPriority, "test")
if err != nil {