crl-checker: a simple tool to validate public CRLs (#6381)
Add crl-checker, a simple tool which downloads, parses, lints, and validates signatures on a list of CRLs. It takes its input in the form of a JSON Array of Sharded CRL URLs, the exact same format as we will be disclosing in CCADB. We can add additional checks -- such as ensuring that a set of known-revoked serials are present, or checking that all of the downloaded CRLs are "recent enough" -- over time.
This commit is contained in:
parent
d53c90a3bc
commit
aed604294e
|
@ -19,6 +19,7 @@ import (
|
|||
_ "github.com/letsencrypt/boulder/cmd/ceremony"
|
||||
_ "github.com/letsencrypt/boulder/cmd/cert-checker"
|
||||
_ "github.com/letsencrypt/boulder/cmd/contact-auditor"
|
||||
_ "github.com/letsencrypt/boulder/cmd/crl-checker"
|
||||
_ "github.com/letsencrypt/boulder/cmd/crl-storer"
|
||||
_ "github.com/letsencrypt/boulder/cmd/crl-updater"
|
||||
_ "github.com/letsencrypt/boulder/cmd/expiration-mailer"
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
package notmain
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"github.com/letsencrypt/boulder/cmd"
|
||||
"github.com/letsencrypt/boulder/crl/crl_x509"
|
||||
"github.com/letsencrypt/boulder/issuance"
|
||||
"github.com/letsencrypt/boulder/linter"
|
||||
crlint "github.com/letsencrypt/boulder/linter/lints/crl"
|
||||
)
|
||||
|
||||
func validateShard(url string, issuer *issuance.Certificate) error {
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
return fmt.Errorf("downloading crl: %w", err)
|
||||
}
|
||||
|
||||
crlBytes, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("reading CRL bytes: %w", err)
|
||||
}
|
||||
|
||||
crl, err := crl_x509.ParseRevocationList(crlBytes)
|
||||
if err != nil {
|
||||
return fmt.Errorf("parsing CRL: %w", err)
|
||||
}
|
||||
|
||||
err = linter.ProcessResultSet(crlint.LintCRL(crl))
|
||||
if err != nil {
|
||||
return fmt.Errorf("linting CRL: %w", err)
|
||||
}
|
||||
|
||||
err = crl.CheckSignatureFrom(issuer.Certificate)
|
||||
if err != nil {
|
||||
return fmt.Errorf("checking CRL signature: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
urlFile := flag.String("crls", "", "path to a file containing a JSON Array of CRL URLs")
|
||||
issuerFile := flag.String("issuer", "", "path to an issuer certificate on disk")
|
||||
flag.Parse()
|
||||
|
||||
logger := cmd.NewLogger(cmd.SyslogConfig{StdoutLevel: 6, SyslogLevel: -1})
|
||||
|
||||
urlFileContents, err := os.ReadFile(*urlFile)
|
||||
cmd.FailOnError(err, "Reading CRL URLs file")
|
||||
|
||||
var urls []string
|
||||
err = json.Unmarshal(urlFileContents, &urls)
|
||||
cmd.FailOnError(err, "Parsing JSON Array of CRL URLs")
|
||||
|
||||
issuer, err := issuance.LoadCertificate(*issuerFile)
|
||||
cmd.FailOnError(err, "Loading issuer certificate")
|
||||
|
||||
errCount := 0
|
||||
for _, url := range urls {
|
||||
err = validateShard(url, issuer)
|
||||
if err != nil {
|
||||
errCount += 1
|
||||
logger.Errf("CRL %q failed: %s\n", url, err)
|
||||
}
|
||||
}
|
||||
|
||||
if errCount != 0 {
|
||||
cmd.Fail(fmt.Sprintf("Encountered %d errors", errCount))
|
||||
}
|
||||
logger.AuditInfo("All CRLs validated")
|
||||
}
|
||||
|
||||
func init() {
|
||||
cmd.RegisterCommand("crl-checker", main)
|
||||
}
|
|
@ -76,7 +76,7 @@ func (l Linter) Check(tbs *x509.Certificate, subjectPubKey crypto.PublicKey) err
|
|||
return err
|
||||
}
|
||||
lintRes := zlint.LintCertificateEx(cert, l.registry)
|
||||
return processResultSet(lintRes)
|
||||
return ProcessResultSet(lintRes)
|
||||
}
|
||||
|
||||
// CheckCRL signs the given RevocationList template using the Linter's fake
|
||||
|
@ -88,7 +88,7 @@ func (l Linter) CheckCRL(tbs *crl_x509.RevocationList) error {
|
|||
return err
|
||||
}
|
||||
lintRes := crllints.LintCRL(crl)
|
||||
return processResultSet(lintRes)
|
||||
return ProcessResultSet(lintRes)
|
||||
}
|
||||
|
||||
func makeSigner(realSigner crypto.Signer) (crypto.Signer, error) {
|
||||
|
@ -190,7 +190,7 @@ func makeLintCert(tbs *x509.Certificate, subjectPubKey crypto.PublicKey, issuer
|
|||
return lintCert, nil
|
||||
}
|
||||
|
||||
func processResultSet(lintRes *zlint.ResultSet) error {
|
||||
func ProcessResultSet(lintRes *zlint.ResultSet) error {
|
||||
if lintRes.NoticesPresent || lintRes.WarningsPresent || lintRes.ErrorsPresent || lintRes.FatalsPresent {
|
||||
var failedLints []string
|
||||
for lintName, result := range lintRes.Results {
|
||||
|
|
Loading…
Reference in New Issue