Merge pull request #2420 from letsencrypt/cpu-staging-hotfix

OCSP Updater "stale max age" parameter
This commit is contained in:
Daniel McCarney 2016-12-12 16:20:15 -05:00 committed by GitHub
commit 276530f68d
4 changed files with 80 additions and 8 deletions

View File

@ -225,6 +225,7 @@ type OCSPUpdaterConfig struct {
RevokedCertificateBatchSize int
OCSPMinTimeToExpiry ConfigDuration
OCSPStaleMaxAge ConfigDuration
OldestIssuedSCT ConfigDuration
AkamaiBaseURL string

View File

@ -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,
},
)

View File

@ -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()

View File

@ -11,6 +11,7 @@
"missingSCTBatchSize": 5000,
"revokedCertificateBatchSize": 1000,
"ocspMinTimeToExpiry": "72h",
"ocspStaleMaxAge": "720h",
"oldestIssuedSCT": "72h",
"signFailureBackoffFactor": 1.2,
"signFailureBackoffMax": "30m",