Cache issuer certificates retrieved from static-ct-api logs
This commit is contained in:
parent
958e7a9efb
commit
6151cb26da
|
@ -93,6 +93,23 @@ func (s *FilesystemState) RemoveSTH(ctx context.Context, logID LogID, sth *cttyp
|
|||
return removeSTHFromDir(sthsDirPath, sth)
|
||||
}
|
||||
|
||||
func (s *FilesystemState) StoreIssuer(ctx context.Context, fingerprint *[32]byte, issuer []byte) error {
|
||||
filePath := filepath.Join(s.StateDir, "issuers", hex.EncodeToString(fingerprint[:]))
|
||||
return writeFile(filePath, issuer, 0666)
|
||||
}
|
||||
|
||||
func (s *FilesystemState) LoadIssuer(ctx context.Context, fingerprint *[32]byte) ([]byte, error) {
|
||||
filePath := filepath.Join(s.StateDir, "issuers", hex.EncodeToString(fingerprint[:]))
|
||||
issuer, err := os.ReadFile(filePath)
|
||||
if errors.Is(err, fs.ErrNotExist) {
|
||||
return nil, nil
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return issuer, err
|
||||
}
|
||||
}
|
||||
|
||||
func (s *FilesystemState) NotifyCert(ctx context.Context, cert *DiscoveredCert) error {
|
||||
var notifiedPath string
|
||||
var paths *certPaths
|
||||
|
|
|
@ -142,22 +142,34 @@ func (client *logClient) ReconstructTree(ctx context.Context, sth *cttypes.Signe
|
|||
}
|
||||
|
||||
type issuerGetter struct {
|
||||
state StateProvider
|
||||
logGetter ctclient.IssuerGetter
|
||||
}
|
||||
|
||||
func (ig *issuerGetter) GetIssuer(ctx context.Context, fingerprint *[32]byte) (issuer []byte, err error) {
|
||||
// TODO-2 check cache
|
||||
err = withRetry(ctx, 7, func() error {
|
||||
func (ig *issuerGetter) GetIssuer(ctx context.Context, fingerprint *[32]byte) ([]byte, error) {
|
||||
if issuer, err := ig.state.LoadIssuer(ctx, fingerprint); err != nil {
|
||||
log.Printf("error loading cached issuer %x (issuer will be retrieved from log instead): %s", *fingerprint, err)
|
||||
} else if issuer != nil {
|
||||
return issuer, nil
|
||||
}
|
||||
|
||||
var issuer []byte
|
||||
if err := withRetry(ctx, 7, func() error {
|
||||
var err error
|
||||
issuer, err = ig.logGetter.GetIssuer(ctx, fingerprint)
|
||||
return err
|
||||
})
|
||||
if err == nil {
|
||||
// TODO-2 insert into cache
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return
|
||||
|
||||
if err := ig.state.StoreIssuer(ctx, fingerprint, issuer); err != nil {
|
||||
log.Printf("error caching issuer %x (issuer will be re-retrieved from log in the future): %s", *fingerprint, err)
|
||||
}
|
||||
|
||||
return issuer, nil
|
||||
}
|
||||
|
||||
func newLogClient(ctlog *loglist.Log) (ctclient.Log, ctclient.IssuerGetter, error) {
|
||||
func newLogClient(config *Config, ctlog *loglist.Log) (ctclient.Log, ctclient.IssuerGetter, error) {
|
||||
switch {
|
||||
case ctlog.IsRFC6962():
|
||||
logURL, err := url.Parse(ctlog.URL)
|
||||
|
@ -186,6 +198,7 @@ func newLogClient(ctlog *loglist.Log) (ctclient.Log, ctclient.IssuerGetter, erro
|
|||
log: ctlog,
|
||||
client: client,
|
||||
}, &issuerGetter{
|
||||
state: config.State,
|
||||
logGetter: client,
|
||||
}, nil
|
||||
default:
|
||||
|
@ -194,7 +207,7 @@ func newLogClient(ctlog *loglist.Log) (ctclient.Log, ctclient.IssuerGetter, erro
|
|||
}
|
||||
|
||||
func monitorLogContinously(ctx context.Context, config *Config, ctlog *loglist.Log) (returnedErr error) {
|
||||
client, issuerGetter, err := newLogClient(ctlog)
|
||||
client, issuerGetter, err := newLogClient(config, ctlog)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -63,6 +63,14 @@ type StateProvider interface {
|
|||
// Remove an STH so it is no longer returned by LoadSTHs.
|
||||
RemoveSTH(context.Context, LogID, *cttypes.SignedTreeHead) error
|
||||
|
||||
// Store a DER-encoded issuer certificate with the given fingerprint for
|
||||
// retrieval by LoadIssuer. Returns nil if the issuer has already been stored.
|
||||
StoreIssuer(context.Context, *[32]byte, []byte) error
|
||||
|
||||
// Retrieve a DER-encoded issuer certificate previously stored with StoreIssuer.
|
||||
// Returns nil, nil if this issuer certificate has not been stored.
|
||||
LoadIssuer(context.Context, *[32]byte) ([]byte, error)
|
||||
|
||||
// Called when a certificate matching the watch list is discovered.
|
||||
NotifyCert(context.Context, *DiscoveredCert) error
|
||||
|
||||
|
|
|
@ -145,7 +145,7 @@ func prepareStateDir(stateDir string) error {
|
|||
return fmt.Errorf("%s was created by a newer version of certspotter; upgrade to the latest version of certspotter or remove this directory to start from scratch", stateDir)
|
||||
}
|
||||
|
||||
for _, subdir := range []string{"certs", "logs", "healthchecks"} {
|
||||
for _, subdir := range []string{"certs", "logs", "healthchecks", "issuers"} {
|
||||
if err := os.Mkdir(filepath.Join(stateDir, subdir), 0777); err != nil && !errors.Is(err, fs.ErrExist) {
|
||||
return err
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue