OCSP Updater "stale max age" parameter. (#2419)
This PR adds a new `OCSPStaleMaxAge` configuration parameter to the `ocsp-updater`. The default value when not provided is 30 days, and this is explicitly added to both `config/ocsp-updater.json` and `config-next/ocsp-updater.json`. The OCSP updater uses this new parameter in `findStaleOCSPResponses` as a lower bound on the `ocspLastUpdated` field of the certificateStatus table. This is intended to speed up the processing of this query until we can land the proper fixes that require more intensive migrations & backfilling. The `TestGenerateOCSPResponses` and `TestFindStaleOCSPResponses` unit tests had to be updated to explicitly set the `ocspLastUpdated` field of the certificate status rows that the tests add, because otherwise they are left at a default value of `0` and are excluded by the new `OCSPStaleMaxAge` functionality.
This commit is contained in:
parent
0f2af77660
commit
11100f5873
|
|
@ -225,6 +225,7 @@ type OCSPUpdaterConfig struct {
|
|||
RevokedCertificateBatchSize int
|
||||
|
||||
OCSPMinTimeToExpiry ConfigDuration
|
||||
OCSPStaleMaxAge ConfigDuration
|
||||
OldestIssuedSCT ConfigDuration
|
||||
|
||||
AkamaiBaseURL string
|
||||
|
|
|
|||
|
|
@ -52,8 +52,10 @@ type OCSPUpdater struct {
|
|||
pubc core.Publisher
|
||||
sac core.StorageAuthority
|
||||
|
||||
// Used to calculate how far back stale OCSP responses should be looked for
|
||||
// Used to calculate how far back stale OCSP responses should be looked for
|
||||
ocspMinTimeToExpiry time.Duration
|
||||
// Used to caculate how far back in time the findStaleOCSPResponse will look
|
||||
ocspStaleMaxAge time.Duration
|
||||
// Used to calculate how far back missing SCT receipts should be looked for
|
||||
oldestIssuedSCT time.Duration
|
||||
// Number of CT logs we expect to have receipts from
|
||||
|
|
@ -89,6 +91,10 @@ func newUpdater(
|
|||
config.MissingSCTWindow.Duration == 0 {
|
||||
return nil, fmt.Errorf("Loop window sizes must be non-zero")
|
||||
}
|
||||
if config.OCSPStaleMaxAge.Duration == 0 {
|
||||
// Default to 30 days
|
||||
config.OCSPStaleMaxAge = cmd.ConfigDuration{Duration: time.Hour * 24 * 30}
|
||||
}
|
||||
|
||||
updater := OCSPUpdater{
|
||||
stats: stats,
|
||||
|
|
@ -100,6 +106,7 @@ func newUpdater(
|
|||
pubc: pub,
|
||||
numLogs: numLogs,
|
||||
ocspMinTimeToExpiry: config.OCSPMinTimeToExpiry.Duration,
|
||||
ocspStaleMaxAge: config.OCSPStaleMaxAge.Duration,
|
||||
oldestIssuedSCT: config.OldestIssuedSCT.Duration,
|
||||
}
|
||||
|
||||
|
|
@ -209,6 +216,8 @@ func (updater *OCSPUpdater) findStaleOCSPResponses(oldestLastUpdatedTime time.Ti
|
|||
var statuses []core.CertificateStatus
|
||||
// TODO(@cpu): Once the notafter-backfill cmd has been run & completed then
|
||||
// the query below can be rewritten to use `AND NOT cs.isExpired`.
|
||||
now := updater.clk.Now()
|
||||
maxAgeCutoff := now.Add(-updater.ocspStaleMaxAge)
|
||||
_, err := updater.dbMap.Select(
|
||||
&statuses,
|
||||
`SELECT
|
||||
|
|
@ -218,12 +227,14 @@ func (updater *OCSPUpdater) findStaleOCSPResponses(oldestLastUpdatedTime time.Ti
|
|||
FROM certificateStatus AS cs
|
||||
JOIN certificates AS cert
|
||||
ON cs.serial = cert.serial
|
||||
WHERE cs.ocspLastUpdated < :lastUpdate
|
||||
WHERE cs.ocspLastUpdated > :maxAge
|
||||
AND cs.ocspLastUpdated < :lastUpdate
|
||||
AND cert.expires > now()
|
||||
ORDER BY cs.ocspLastUpdated ASC
|
||||
LIMIT :limit`,
|
||||
map[string]interface{}{
|
||||
"lastUpdate": oldestLastUpdatedTime,
|
||||
"maxAge": maxAgeCutoff,
|
||||
"limit": batchSize,
|
||||
},
|
||||
)
|
||||
|
|
|
|||
|
|
@ -125,19 +125,29 @@ func TestGenerateAndStoreOCSPResponse(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestGenerateOCSPResponses(t *testing.T) {
|
||||
updater, sa, _, fc, cleanUp := setup(t)
|
||||
updater, sa, dbMap, fc, cleanUp := setup(t)
|
||||
defer cleanUp()
|
||||
|
||||
reg := satest.CreateWorkingRegistration(t, sa)
|
||||
parsedCert, err := core.LoadCert("test-cert.pem")
|
||||
parsedCertA, err := core.LoadCert("test-cert.pem")
|
||||
test.AssertNotError(t, err, "Couldn't read test certificate")
|
||||
_, err = sa.AddCertificate(ctx, parsedCert.Raw, reg.ID)
|
||||
_, err = sa.AddCertificate(ctx, parsedCertA.Raw, reg.ID)
|
||||
test.AssertNotError(t, err, "Couldn't add test-cert.pem")
|
||||
parsedCert, err = core.LoadCert("test-cert-b.pem")
|
||||
parsedCertB, err := core.LoadCert("test-cert-b.pem")
|
||||
test.AssertNotError(t, err, "Couldn't read test certificate")
|
||||
_, err = sa.AddCertificate(ctx, parsedCert.Raw, reg.ID)
|
||||
_, err = sa.AddCertificate(ctx, parsedCertB.Raw, reg.ID)
|
||||
test.AssertNotError(t, err, "Couldn't add test-cert-b.pem")
|
||||
|
||||
// We need to set a fake "ocspLastUpdated" value for the two certs we created
|
||||
// in order to satisfy the "ocspStaleMaxAge" constraint.
|
||||
fakeLastUpdate := fc.Now().Add(-time.Hour * 24 * 3)
|
||||
_, err = dbMap.Exec(
|
||||
"UPDATE certificateStatus SET ocspLastUpdated = ? WHERE serial IN (?, ?)",
|
||||
fakeLastUpdate,
|
||||
core.SerialToString(parsedCertA.SerialNumber),
|
||||
core.SerialToString(parsedCertB.SerialNumber))
|
||||
test.AssertNotError(t, err, "Couldn't update ocspLastUpdated")
|
||||
|
||||
earliest := fc.Now().Add(-time.Hour)
|
||||
certs, err := updater.findStaleOCSPResponses(earliest, 10)
|
||||
test.AssertNotError(t, err, "Couldn't find stale responses")
|
||||
|
|
@ -152,7 +162,7 @@ func TestGenerateOCSPResponses(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestFindStaleOCSPResponses(t *testing.T) {
|
||||
updater, sa, _, fc, cleanUp := setup(t)
|
||||
updater, sa, dbMap, fc, cleanUp := setup(t)
|
||||
defer cleanUp()
|
||||
|
||||
reg := satest.CreateWorkingRegistration(t, sa)
|
||||
|
|
@ -161,6 +171,15 @@ func TestFindStaleOCSPResponses(t *testing.T) {
|
|||
_, err = sa.AddCertificate(ctx, parsedCert.Raw, reg.ID)
|
||||
test.AssertNotError(t, err, "Couldn't add test-cert.pem")
|
||||
|
||||
// We need to set a fake "ocspLastUpdated" value for the cert we created
|
||||
// in order to satisfy the "ocspStaleMaxAge" constraint.
|
||||
fakeLastUpdate := fc.Now().Add(-time.Hour * 24 * 3)
|
||||
_, err = dbMap.Exec(
|
||||
"UPDATE certificateStatus SET ocspLastUpdated = ? WHERE serial = ?",
|
||||
fakeLastUpdate,
|
||||
core.SerialToString(parsedCert.SerialNumber))
|
||||
test.AssertNotError(t, err, "Couldn't update ocspLastUpdated")
|
||||
|
||||
earliest := fc.Now().Add(-time.Hour)
|
||||
certs, err := updater.findStaleOCSPResponses(earliest, 10)
|
||||
test.AssertNotError(t, err, "Couldn't find certificate")
|
||||
|
|
@ -179,6 +198,46 @@ func TestFindStaleOCSPResponses(t *testing.T) {
|
|||
test.AssertEquals(t, len(certs), 0)
|
||||
}
|
||||
|
||||
func TestFindStaleOCSPResponsesStaleMaxAge(t *testing.T) {
|
||||
updater, sa, dbMap, fc, cleanUp := setup(t)
|
||||
defer cleanUp()
|
||||
|
||||
reg := satest.CreateWorkingRegistration(t, sa)
|
||||
parsedCertA, err := core.LoadCert("test-cert.pem")
|
||||
test.AssertNotError(t, err, "Couldn't read test certificate")
|
||||
_, err = sa.AddCertificate(ctx, parsedCertA.Raw, reg.ID)
|
||||
test.AssertNotError(t, err, "Couldn't add test-cert.pem")
|
||||
parsedCertB, err := core.LoadCert("test-cert-b.pem")
|
||||
test.AssertNotError(t, err, "Couldn't read test certificate")
|
||||
_, err = sa.AddCertificate(ctx, parsedCertB.Raw, reg.ID)
|
||||
test.AssertNotError(t, err, "Couldn't add test-cert-b.pem")
|
||||
|
||||
// Set a "ocspLastUpdated" value of 3 days ago for parsedCertA
|
||||
okLastUpdated := fc.Now().Add(-time.Hour * 24 * 3)
|
||||
_, err = dbMap.Exec(
|
||||
"UPDATE certificateStatus SET ocspLastUpdated = ? WHERE serial = ?",
|
||||
okLastUpdated,
|
||||
core.SerialToString(parsedCertA.SerialNumber))
|
||||
test.AssertNotError(t, err, "Couldn't update ocspLastUpdated for parsedCertA")
|
||||
|
||||
// Set a "ocspLastUpdated" value of 35 days ago for parsedCertB
|
||||
excludedLastUpdated := fc.Now().Add(-time.Hour * 24 * 35)
|
||||
_, err = dbMap.Exec(
|
||||
"UPDATE certificateStatus SET ocspLastUpdated = ? WHERE serial = ?",
|
||||
excludedLastUpdated,
|
||||
core.SerialToString(parsedCertB.SerialNumber))
|
||||
test.AssertNotError(t, err, "Couldn't update ocspLastUpdated for parsedCertB")
|
||||
|
||||
// Running `findStaleOCSPResponses should only find *ONE* of the above
|
||||
// certificates, parsedCertA. The second should be excluded by the
|
||||
// `ocspStaleMaxAge` cutoff.
|
||||
earliest := fc.Now().Add(-time.Hour)
|
||||
certs, err := updater.findStaleOCSPResponses(earliest, 10)
|
||||
test.AssertNotError(t, err, "Couldn't find stale responses")
|
||||
test.AssertEquals(t, len(certs), 1)
|
||||
test.AssertEquals(t, certs[0].Serial, core.SerialToString(parsedCertA.SerialNumber))
|
||||
}
|
||||
|
||||
func TestGetCertificatesWithMissingResponses(t *testing.T) {
|
||||
updater, sa, _, _, cleanUp := setup(t)
|
||||
defer cleanUp()
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
"missingSCTBatchSize": 5000,
|
||||
"revokedCertificateBatchSize": 1000,
|
||||
"ocspMinTimeToExpiry": "72h",
|
||||
"ocspStaleMaxAge": "720h",
|
||||
"oldestIssuedSCT": "72h",
|
||||
"signFailureBackoffFactor": 1.2,
|
||||
"signFailureBackoffMax": "30m",
|
||||
|
|
|
|||
Loading…
Reference in New Issue