X Tutup
Skip to content

Commit 9464d02

Browse files
authored
Fix OCSP log queue blocking when maxLogLen = 0. (letsencrypt#5230)
Move responsibility for handling the default path (maxLogLen = 0) from the ocspLogQueue component to CertificateAuthorityImpl. Now the ocspLogQueue isn't constructed at all unless we configure it to be used. Also, remove buffer from OCSP audit log chan. The bug this fixes was hidden by the large buffer, and on reconsideration the large buffer was unnecessary. Verified that with the buffer removed, the integration test fails. Then adding the fixes to the maxLogLen = 0 case fixes the integration test. Fixes letsencrypt#5228
1 parent 8b91458 commit 9464d02

File tree

3 files changed

+24
-17
lines changed

3 files changed

+24
-17
lines changed

ca/ca.go

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,10 @@ func NewCertificateAuthorityImpl(
360360
}, []string{"type"})
361361
stats.MustRegister(signErrorCounter)
362362

363-
ocspLogQueue := newOCSPLogQueue(ocspLogMaxLength, ocspLogPeriod, stats, logger)
363+
var ocspLogQueue *ocspLogQueue
364+
if ocspLogMaxLength > 0 {
365+
ocspLogQueue = newOCSPLogQueue(ocspLogMaxLength, ocspLogPeriod, stats, logger)
366+
}
364367

365368
ca = &CertificateAuthorityImpl{
366369
sa: sa,
@@ -533,7 +536,9 @@ func (ca *CertificateAuthorityImpl) GenerateOCSP(ctx context.Context, req *capb.
533536
tbsResponse.RevocationReason = int(req.Reason)
534537
}
535538

536-
ca.ocspLogQueue.enqueue(serial.Bytes(), now, ocsp.ResponseStatus(tbsResponse.Status))
539+
if ca.ocspLogQueue != nil {
540+
ca.ocspLogQueue.enqueue(serial.Bytes(), now, ocsp.ResponseStatus(tbsResponse.Status))
541+
}
537542

538543
ocspResponse, err := ocsp.CreateResponse(issuer.cert.Certificate, issuer.cert.Certificate, tbsResponse, issuer.ocspSigner)
539544
ca.noteSignError(err)
@@ -943,15 +948,19 @@ func (ca *CertificateAuthorityImpl) OrphanIntegrationLoop() {
943948
// LogOCSPLoop collects OCSP generation log events into bundles, and logs
944949
// them periodically.
945950
func (ca *CertificateAuthorityImpl) LogOCSPLoop() {
946-
ca.ocspLogQueue.loop()
951+
if ca.ocspLogQueue != nil {
952+
ca.ocspLogQueue.loop()
953+
}
947954
}
948955

949956
// Stop asks this CertificateAuthorityImpl to shut down. It must be called
950957
// after the corresponding RPC service is shut down and there are no longer
951958
// any inflight RPCs. It will attempt to drain any logging queues (which may
952959
// block), and will return only when done.
953960
func (ca *CertificateAuthorityImpl) Stop() {
954-
ca.ocspLogQueue.stop()
961+
if ca.ocspLogQueue != nil {
962+
ca.ocspLogQueue.stop()
963+
}
955964
}
956965

957966
// integrateOrpan removes an orphan from the queue and adds it to the database. The

ca/ocsp.go

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ import (
2323
// 3900 bytes per log line.
2424
// Summary of log line usage:
2525
// serial in hex: 36 bytes, separator characters: 2 bytes, status: 1 byte
26-
// If maxLogLen is 0, do not perform any accumulation or logging.
26+
// If maxLogLen is less than the length of a single log item, generate
27+
// one log line for every item.
2728
type ocspLogQueue struct {
2829
// Maximum length, in bytes, of a single log line.
2930
maxLogLen int
@@ -58,7 +59,7 @@ func newOCSPLogQueue(
5859
olq := ocspLogQueue{
5960
maxLogLen: maxLogLen,
6061
period: period,
61-
queue: make(chan ocspLog, 1000),
62+
queue: make(chan ocspLog),
6263
wg: sync.WaitGroup{},
6364
depth: depth,
6465
logger: logger,
@@ -85,9 +86,6 @@ const ocspSingleLogEntryLen = 39
8586
// whichever comes first.
8687
func (olq *ocspLogQueue) loop() {
8788
defer olq.wg.Done()
88-
if olq.maxLogLen == 0 {
89-
return
90-
}
9189
done := false
9290
for !done {
9391
var builder strings.Builder
@@ -106,7 +104,7 @@ func (olq *ocspLogQueue) loop() {
106104
case <-deadline:
107105
break inner
108106
}
109-
if builder.Len()+ocspSingleLogEntryLen > olq.maxLogLen {
107+
if builder.Len()+ocspSingleLogEntryLen >= olq.maxLogLen {
110108
break
111109
}
112110
}
@@ -123,9 +121,6 @@ func (olq *ocspLogQueue) loop() {
123121
// If this is called without previously starting a goroutine running `.loop()`,
124122
// it will block forever.
125123
func (olq *ocspLogQueue) stop() {
126-
if olq.maxLogLen == 0 {
127-
return
128-
}
129124
close(olq.queue)
130125
olq.wg.Wait()
131126
}

ca/ocsp_test.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,17 +97,20 @@ func TestOcspNoEmptyLines(t *testing.T) {
9797
test.AssertDeepEquals(t, log.GetAll(), []string{})
9898
}
9999

100-
// If the maxLogLen is 0, don't log anything.
101-
func TestOcspLogMaxLenZeroMeansNoLog(t *testing.T) {
100+
// If the maxLogLen is shorter than one entry, log everything immediately.
101+
func TestOcspLogWhenMaxLogLenIsShort(t *testing.T) {
102102
t.Parallel()
103103
log := blog.NewMock()
104104
stats := metrics.NoopRegisterer
105-
queue := newOCSPLogQueue(0, 10000*time.Millisecond, stats, log)
105+
queue := newOCSPLogQueue(3, 10000*time.Millisecond, stats, log)
106106
go queue.loop()
107107
queue.enqueue(serial(t), time.Now(), ocsp.ResponseStatus(ocsp.Good))
108108
queue.stop()
109109

110-
test.AssertDeepEquals(t, log.GetAll(), []string{})
110+
expected := []string{
111+
"INFO: [AUDIT] OCSP signed: aabbccddeeffaabbccddeeff000102030405:0,",
112+
}
113+
test.AssertDeepEquals(t, log.GetAll(), expected)
111114
}
112115

113116
// Enqueueing entries after stop causes panic.

0 commit comments

Comments
 (0)
X Tutup