From 30d8f19895342507c10624221694f7a56a828435 Mon Sep 17 00:00:00 2001 From: Aaron Gable Date: Fri, 21 Oct 2022 14:58:34 -0700 Subject: [PATCH] Deprecate ROCSP Stage 1, 2, and 3 flags (#6460) These flags are set in both staging and prod. Deprecate them, make all code gated behind them the only path, and delete code (multi_source) which was only accessible when these flags were not set. Part of #6285 --- cmd/ocsp-responder/main.go | 83 +++++------ features/featureflag_string.go | 52 +++---- features/features.go | 17 +-- ocsp/responder/multi_source.go | 204 --------------------------- ocsp/responder/multi_source_test.go | 172 ---------------------- sa/sa_test.go | 2 +- test/config-next/ocsp-responder.json | 7 +- test/config/ocsp-responder.json | 43 +++++- test/config/ra.json | 1 + test/config/sa.json | 1 + 10 files changed, 107 insertions(+), 475 deletions(-) delete mode 100644 ocsp/responder/multi_source.go delete mode 100644 ocsp/responder/multi_source_test.go diff --git a/cmd/ocsp-responder/main.go b/cmd/ocsp-responder/main.go index f41ba5905..f23cf2ade 100644 --- a/cmd/ocsp-responder/main.go +++ b/cmd/ocsp-responder/main.go @@ -166,60 +166,43 @@ as generated by Boulder's ceremony command. dbMap, err := sa.InitWrappedDb(config.DB, stats, logger) cmd.FailOnError(err, "While initializing dbMap") - source, err = responder.NewDbSource(dbMap, stats, logger) - cmd.FailOnError(err, "Could not create database source") + // Set up the redis source and the combined multiplex source. + rocspReader, err := rocsp_config.MakeClient(&c.OCSPResponder.Redis, clk, stats) + cmd.FailOnError(err, "Could not make redis client") - // Set up the redis source and the combined multiplex source if there - // is a config for it and the feature flag is enabled. Otherwise - // just pass through the existing mysql source. - if c.OCSPResponder.Redis.Addrs != nil && features.Enabled(features.ROCSPStage1) { - rocspReader, err := rocsp_config.MakeClient(&c.OCSPResponder.Redis, clk, stats) - cmd.FailOnError(err, "Could not make redis client") + err = rocspReader.Ping(context.Background()) + cmd.FailOnError(err, "pinging Redis") - err = rocspReader.Ping(context.Background()) - cmd.FailOnError(err, "pinging Redis") - - expectedFreshness := c.OCSPResponder.ExpectedFreshness.Duration - if expectedFreshness == 0 { - expectedFreshness = 61 * time.Hour - } - - liveSigningPeriod := c.OCSPResponder.LiveSigningPeriod.Duration - if liveSigningPeriod == 0 { - liveSigningPeriod = 60 * time.Hour - } - - tlsConfig, err := c.OCSPResponder.TLS.Load() - cmd.FailOnError(err, "TLS config") - clientMetrics := bgrpc.NewClientMetrics(stats) - raConn, err := bgrpc.ClientSetup(c.OCSPResponder.RAService, tlsConfig, clientMetrics, clk) - cmd.FailOnError(err, "Failed to load credentials and create gRPC connection to RA") - rac := rapb.NewRegistrationAuthorityClient(raConn) - - maxInflight := c.OCSPResponder.MaxInflightSignings - if maxInflight == 0 { - maxInflight = 1000 - } - liveSource := live.New(rac, int64(maxInflight)) - - rocspSource, err := redis_responder.NewRedisSource(rocspReader, liveSource, liveSigningPeriod, clk, stats, logger) - cmd.FailOnError(err, "Could not create redis source") - - if features.Enabled(features.ROCSPStage3) { - var sac sapb.StorageAuthorityClient - if c.OCSPResponder.SAService != nil { - saConn, err := bgrpc.ClientSetup(c.OCSPResponder.SAService, tlsConfig, clientMetrics, clk) - cmd.FailOnError(err, "Failed to load credentials and create gRPC connection to SA") - sac = sapb.NewStorageAuthorityClient(saConn) - } - source, err = redis_responder.NewCheckedRedisSource(rocspSource, dbMap, sac, stats, logger) - cmd.FailOnError(err, "Could not create checkedRedis source") - } else { - source, err = responder.NewMultiSource(source, rocspSource, expectedFreshness, stats, logger) - cmd.FailOnError(err, "Could not create multiplex source") - } + liveSigningPeriod := c.OCSPResponder.LiveSigningPeriod.Duration + if liveSigningPeriod == 0 { + liveSigningPeriod = 60 * time.Hour } + tlsConfig, err := c.OCSPResponder.TLS.Load() + cmd.FailOnError(err, "TLS config") + clientMetrics := bgrpc.NewClientMetrics(stats) + raConn, err := bgrpc.ClientSetup(c.OCSPResponder.RAService, tlsConfig, clientMetrics, clk) + cmd.FailOnError(err, "Failed to load credentials and create gRPC connection to RA") + rac := rapb.NewRegistrationAuthorityClient(raConn) + + maxInflight := c.OCSPResponder.MaxInflightSignings + if maxInflight == 0 { + maxInflight = 1000 + } + liveSource := live.New(rac, int64(maxInflight)) + + rocspSource, err := redis_responder.NewRedisSource(rocspReader, liveSource, liveSigningPeriod, clk, stats, logger) + cmd.FailOnError(err, "Could not create redis source") + + var sac sapb.StorageAuthorityClient + if c.OCSPResponder.SAService != nil { + saConn, err := bgrpc.ClientSetup(c.OCSPResponder.SAService, tlsConfig, clientMetrics, clk) + cmd.FailOnError(err, "Failed to load credentials and create gRPC connection to SA") + sac = sapb.NewStorageAuthorityClient(saConn) + } + source, err = redis_responder.NewCheckedRedisSource(rocspSource, dbMap, sac, stats, logger) + cmd.FailOnError(err, "Could not create checkedRedis source") + // Load the certificate from the file path. issuerCerts := make([]*issuance.Certificate, len(c.OCSPResponder.IssuerCerts)) for i, issuerFile := range c.OCSPResponder.IssuerCerts { diff --git a/features/featureflag_string.go b/features/featureflag_string.go index d94c8427f..7ba1e5217 100644 --- a/features/featureflag_string.go +++ b/features/featureflag_string.go @@ -16,36 +16,36 @@ func _() { _ = x[StreamlineOrderAndAuthzs-5] _ = x[V1DisableNewValidations-6] _ = x[ExpirationMailerDontLookTwice-7] - _ = x[CAAValidationMethods-8] - _ = x[CAAAccountURI-9] - _ = x[EnforceMultiVA-10] - _ = x[MultiVAFullResults-11] - _ = x[MandatoryPOSTAsGET-12] - _ = x[AllowV1Registration-13] - _ = x[StoreRevokerInfo-14] - _ = x[RestrictRSAKeySizes-15] - _ = x[FasterNewOrdersRateLimit-16] - _ = x[ECDSAForAll-17] - _ = x[ServeRenewalInfo-18] - _ = x[GetAuthzReadOnly-19] - _ = x[GetAuthzUseIndex-20] - _ = x[CheckFailedAuthorizationsFirst-21] - _ = x[AllowReRevocation-22] - _ = x[MozRevocationReasons-23] - _ = x[OldTLSOutbound-24] - _ = x[OldTLSInbound-25] - _ = x[SHA1CSRs-26] - _ = x[AllowUnrecognizedFeatures-27] - _ = x[RejectDuplicateCSRExtensions-28] - _ = x[ROCSPStage1-29] - _ = x[ROCSPStage2-30] - _ = x[ROCSPStage3-31] + _ = x[ROCSPStage1-8] + _ = x[ROCSPStage2-9] + _ = x[ROCSPStage3-10] + _ = x[CAAValidationMethods-11] + _ = x[CAAAccountURI-12] + _ = x[EnforceMultiVA-13] + _ = x[MultiVAFullResults-14] + _ = x[MandatoryPOSTAsGET-15] + _ = x[AllowV1Registration-16] + _ = x[StoreRevokerInfo-17] + _ = x[RestrictRSAKeySizes-18] + _ = x[FasterNewOrdersRateLimit-19] + _ = x[ECDSAForAll-20] + _ = x[ServeRenewalInfo-21] + _ = x[GetAuthzReadOnly-22] + _ = x[GetAuthzUseIndex-23] + _ = x[CheckFailedAuthorizationsFirst-24] + _ = x[AllowReRevocation-25] + _ = x[MozRevocationReasons-26] + _ = x[OldTLSOutbound-27] + _ = x[OldTLSInbound-28] + _ = x[SHA1CSRs-29] + _ = x[AllowUnrecognizedFeatures-30] + _ = x[RejectDuplicateCSRExtensions-31] _ = x[ROCSPStage6-32] } -const _FeatureFlag_name = "unusedPrecertificateRevocationStripDefaultSchemePortNonCFSSLSignerStoreIssuerInfoStreamlineOrderAndAuthzsV1DisableNewValidationsExpirationMailerDontLookTwiceCAAValidationMethodsCAAAccountURIEnforceMultiVAMultiVAFullResultsMandatoryPOSTAsGETAllowV1RegistrationStoreRevokerInfoRestrictRSAKeySizesFasterNewOrdersRateLimitECDSAForAllServeRenewalInfoGetAuthzReadOnlyGetAuthzUseIndexCheckFailedAuthorizationsFirstAllowReRevocationMozRevocationReasonsOldTLSOutboundOldTLSInboundSHA1CSRsAllowUnrecognizedFeaturesRejectDuplicateCSRExtensionsROCSPStage1ROCSPStage2ROCSPStage3ROCSPStage6" +const _FeatureFlag_name = "unusedPrecertificateRevocationStripDefaultSchemePortNonCFSSLSignerStoreIssuerInfoStreamlineOrderAndAuthzsV1DisableNewValidationsExpirationMailerDontLookTwiceROCSPStage1ROCSPStage2ROCSPStage3CAAValidationMethodsCAAAccountURIEnforceMultiVAMultiVAFullResultsMandatoryPOSTAsGETAllowV1RegistrationStoreRevokerInfoRestrictRSAKeySizesFasterNewOrdersRateLimitECDSAForAllServeRenewalInfoGetAuthzReadOnlyGetAuthzUseIndexCheckFailedAuthorizationsFirstAllowReRevocationMozRevocationReasonsOldTLSOutboundOldTLSInboundSHA1CSRsAllowUnrecognizedFeaturesRejectDuplicateCSRExtensionsROCSPStage6" -var _FeatureFlag_index = [...]uint16{0, 6, 30, 52, 66, 81, 105, 128, 157, 177, 190, 204, 222, 240, 259, 275, 294, 318, 329, 345, 361, 377, 407, 424, 444, 458, 471, 479, 504, 532, 543, 554, 565, 576} +var _FeatureFlag_index = [...]uint16{0, 6, 30, 52, 66, 81, 105, 128, 157, 168, 179, 190, 210, 223, 237, 255, 273, 292, 308, 327, 351, 362, 378, 394, 410, 440, 457, 477, 491, 504, 512, 537, 565, 576} func (i FeatureFlag) String() string { if i < 0 || i >= FeatureFlag(len(_FeatureFlag_index)-1) { diff --git a/features/features.go b/features/features.go index cee792835..8a97ae469 100644 --- a/features/features.go +++ b/features/features.go @@ -20,6 +20,9 @@ const ( StreamlineOrderAndAuthzs V1DisableNewValidations ExpirationMailerDontLookTwice + ROCSPStage1 + ROCSPStage2 + ROCSPStage3 // Currently in-use features // Check CAA and respect validationmethods parameter. @@ -98,20 +101,6 @@ const ( // go1.19. RejectDuplicateCSRExtensions - // ROCSPStage1 enables querying Redis, live-signing response, and storing - // to Redis, but doesn't serve responses from Redis. - ROCSPStage1 - // ROCSPStage2 enables querying Redis, live-signing a response, and storing - // to Redis, and does serve responses from Redis when appropriate (when - // they are fresh, and agree with MariaDB's status for the certificate). - ROCSPStage2 - // ROCSPStage3 enables querying Redis, live-signing a response, and serving - // from Redis, without any fallback to serving bytes from MariaDB. In this - // mode we still make a parallel request to MariaDB to cross-check the - // _status_ of the response. If that request indicates a different status - // than what's stored in Redis, we'll trigger a fresh signing and serve and - // store the result. - ROCSPStage3 // ROCSPStage6 disables writing full OCSP Responses to MariaDB during // (pre)certificate issuance and during revocation. Because Stage 4 involved // disabling ocsp-updater, this means that no ocsp response bytes will be diff --git a/ocsp/responder/multi_source.go b/ocsp/responder/multi_source.go deleted file mode 100644 index cdbf17860..000000000 --- a/ocsp/responder/multi_source.go +++ /dev/null @@ -1,204 +0,0 @@ -package responder - -import ( - "context" - "errors" - "time" - - "github.com/letsencrypt/boulder/features" - blog "github.com/letsencrypt/boulder/log" - "github.com/letsencrypt/boulder/rocsp" - "github.com/prometheus/client_golang/prometheus" - "golang.org/x/crypto/ocsp" -) - -type multiSource struct { - primary Source - secondary Source - expectedFreshness time.Duration - counter *prometheus.CounterVec - checkSecondaryCounter *prometheus.CounterVec - log blog.Logger -} - -// NewMultiSource creates a source that combines a primary and a secondary source. -// -// It performs lookups using both the primary and secondary Sources. -// It always waits for a response from the primary. If the primary response is -// stale (older than expectedFreshness), it will wait for a "better" response -// from the secondary. -// -// The secondary response will be served only if (a) it has the same status as -// the primary response (good or revoked), and (b) it is fresher than the -// primary response. -// -// A stale response from the primary will still be served if there is no -// better response available from the secondary (due to error, timeout, etc). -func NewMultiSource(primary, secondary Source, expectedFreshness time.Duration, stats prometheus.Registerer, log blog.Logger) (*multiSource, error) { - if primary == nil || secondary == nil { - return nil, errors.New("must provide both primary and secondary sources") - } - - counter := prometheus.NewCounterVec(prometheus.CounterOpts{ - Name: "ocsp_multiplex_responses", - Help: "Count of OCSP requests/responses by action taken by the multiSource", - }, []string{"result"}) - stats.MustRegister(counter) - - checkSecondaryCounter := prometheus.NewCounterVec(prometheus.CounterOpts{ - Name: "ocsp_multiplex_check_secondary", - Help: "Count of OCSP requests/responses by action taken by the multiSource", - }, []string{"result"}) - stats.MustRegister(checkSecondaryCounter) - - return &multiSource{ - primary: primary, - secondary: secondary, - expectedFreshness: expectedFreshness, - counter: counter, - checkSecondaryCounter: checkSecondaryCounter, - log: log, - }, nil -} - -// Response implements the Source interface. -func (src *multiSource) Response(ctx context.Context, req *ocsp.Request) (*Response, error) { - primaryChan := getResponse(ctx, src.primary, req) - - // Use a separate context for the secondary source. This prevents cancellations - // from reaching the backend layer (Redis) and causing connections to be closed - // unnecessarily. - // https://blog.uptrace.dev/posts/go-context-timeout.html - redisCtx := context.Background() - deadline, ok := ctx.Deadline() - if ok { - // We don't call the CancelFunc returned by WithDeadline because it - // would defeat the purpose. That leaks the context, but only until - // the deadline is reached. - ////nolint:govet - redisCtx, _ = context.WithDeadline(redisCtx, deadline) - } - - secondaryChan := getResponse(redisCtx, src.secondary, req) - - var primaryResponse *Response - - // If the primary source returns first, check the output and return - // it. If the secondary source wins, then wait for the primary so the - // results from the secondary can be verified. It is important that we - // never return a response from the secondary source that is good if the - // primary has a revoked status. If the secondary source wins the race and - // passes these checks, return its response instead. - select { - case <-ctx.Done(): - src.counter.WithLabelValues("primary_timed_out").Inc() - return nil, ctx.Err() - - case r := <-primaryChan: - // If there was an error requesting from the primary, don't bother - // waiting for the secondary, because we wouldn't be able to - // check the secondary's status against the (more reliable) primary's - // status. - if r.err != nil { - if errors.Is(r.err, ErrNotFound) { - src.counter.WithLabelValues("primary_not_found").Inc() - } else { - src.counter.WithLabelValues("primary_error").Inc() - } - return nil, r.err - } - primaryResponse = r.resp - } - - // The primary response was fresh enough to serve, go ahead and serve it. - if time.Since(primaryResponse.ThisUpdate) < src.expectedFreshness { - src.checkSecondary(secondaryChan) - src.counter.WithLabelValues("primary_result").Inc() - return primaryResponse, nil - } - - // The primary response was too stale to (ideally) serve. This will be - // a common path once we stop ocsp-updater from writing updated blobs - // to MariaDB. Try to serve from the secondary. - var secondaryResponse *Response - select { - case <-ctx.Done(): - src.counter.WithLabelValues("timed_out_awaiting_secondary").Inc() - // Best-effort: return the primary response even though it's stale. - return primaryResponse, nil - - case secondaryResult := <-secondaryChan: - if secondaryResult.err != nil { - if errors.Is(secondaryResult.err, rocsp.ErrRedisNotFound) { - // This case will happen for several hours after first issuance. - src.counter.WithLabelValues("primary_stale_secondary_not_found").Inc() - } else { - src.counter.WithLabelValues("primary_stale_secondary_error").Inc() - } - - // Best-effort: return the primary response even though it's stale. - return primaryResponse, nil - } - secondaryResponse = secondaryResult.resp - } - - // If the secondary response status doesn't match primary, return - // primary response. For instance this will happen for several hours - // after any revocation. - if secondaryResponse.Status != primaryResponse.Status { - src.counter.WithLabelValues("primary_stale_status_wins").Inc() - return primaryResponse, nil - } - - // ROCSP Stage 2 enables serving responses from Redis - if features.Enabled(features.ROCSPStage2) { - src.counter.WithLabelValues("secondary").Inc() - return secondaryResponse, nil - } - - src.counter.WithLabelValues("primary").Inc() - return primaryResponse, nil -} - -// checkSecondary updates the src.counter metrics when we're planning to return -// a primary response. It checks if the secondary result has already arrived -// (without blocking on it) and updates the metrics accordingly. -func (src *multiSource) checkSecondary(secondaryChan <-chan responseResult) { - select { - case secondaryResult := <-secondaryChan: - if secondaryResult.err != nil { - if errors.Is(secondaryResult.err, rocsp.ErrRedisNotFound) { - // This case will happen for several hours after first issuance. - src.checkSecondaryCounter.WithLabelValues("not_found").Inc() - } else { - src.checkSecondaryCounter.WithLabelValues("error").Inc() - } - } - src.checkSecondaryCounter.WithLabelValues("good").Inc() - default: - src.checkSecondaryCounter.WithLabelValues("slow").Inc() - } -} - -type responseResult struct { - resp *Response - err error -} - -// getResponse provides a thin wrapper around an underlying Source's Response -// method, calling it in a goroutine and passing the result back on a channel. -func getResponse(ctx context.Context, src Source, req *ocsp.Request) chan responseResult { - // Use a buffer so the following goroutine can exit as soon as it's done, - // rather than blocking on a reader (which would introduce a risk that the - // other never reads, leaking the goroutine). - responseChan := make(chan responseResult, 1) - - go func() { - defer close(responseChan) - - resp, err := src.Response(ctx, req) - responseChan <- responseResult{resp, err} - }() - - return responseChan -} diff --git a/ocsp/responder/multi_source_test.go b/ocsp/responder/multi_source_test.go deleted file mode 100644 index e7b8c6640..000000000 --- a/ocsp/responder/multi_source_test.go +++ /dev/null @@ -1,172 +0,0 @@ -package responder - -import ( - "context" - "errors" - "runtime" - "testing" - "time" - - "github.com/letsencrypt/boulder/features" - blog "github.com/letsencrypt/boulder/log" - "github.com/letsencrypt/boulder/metrics" - "github.com/letsencrypt/boulder/test" - "golang.org/x/crypto/ocsp" -) - -const expectedFreshness = 61 * time.Hour - -type ok struct{} - -func (src ok) Response(context.Context, *ocsp.Request) (*Response, error) { - return &Response{ - Response: &ocsp.Response{ - Status: ocsp.Good, - ThisUpdate: time.Now().Add(-10 * time.Hour), - }, - Raw: nil, - }, nil -} - -type revoked struct{} - -func (src revoked) Response(context.Context, *ocsp.Request) (*Response, error) { - return &Response{ - Response: &ocsp.Response{ - Status: ocsp.Revoked, - ThisUpdate: time.Now().Add(-10 * time.Hour), - }, - Raw: nil, - }, nil -} - -type stale struct{} - -func (src stale) Response(context.Context, *ocsp.Request) (*Response, error) { - return &Response{ - Response: &ocsp.Response{ - Status: ocsp.Good, - ThisUpdate: time.Now().Add(-70 * time.Hour), - }, - Raw: nil, - }, nil -} - -type fail struct{} - -func (src fail) Response(context.Context, *ocsp.Request) (*Response, error) { - return nil, errors.New("failure") -} - -// timeout is a Source that will not return until its chan is closed. -type timeout struct { - ch <-chan struct{} -} - -func (src timeout) Response(context.Context, *ocsp.Request) (*Response, error) { - <-src.ch - return nil, errors.New("failure") -} - -func TestMultiSource(t *testing.T) { - type testCase struct { - primary Source - secondary Source - expectedError bool - expectedStatus int // only checked if expectedError is false - } - ignored := 99 - cases := map[string]testCase{ - "ok-ok": {ok{}, ok{}, false, ocsp.Good}, - "ok-fail": {ok{}, fail{}, false, ocsp.Good}, - "ok-revoked": {ok{}, revoked{}, false, ocsp.Good}, - "ok-stale": {ok{}, stale{}, false, ocsp.Good}, - "ok-timeout": {ok{}, timeout{}, false, ocsp.Good}, - "fail-ok": {fail{}, ok{}, true, ignored}, - "fail-fail": {fail{}, fail{}, true, ignored}, - "fail-revoked": {fail{}, revoked{}, true, ignored}, - "fail-stale": {fail{}, stale{}, true, ignored}, - "fail-timeout": {fail{}, timeout{}, true, ignored}, - "revoked-ok": {revoked{}, ok{}, false, ocsp.Revoked}, - "revoked-fail": {revoked{}, fail{}, false, ocsp.Revoked}, - "revoked-revoked": {revoked{}, revoked{}, false, ocsp.Revoked}, - "revoked-stale": {revoked{}, stale{}, false, ocsp.Revoked}, - "revoked-timeout": {revoked{}, timeout{}, false, ocsp.Revoked}, - "stale-ok": {stale{}, ok{}, false, ocsp.Good}, - "stale-fail": {stale{}, fail{}, false, ocsp.Good}, - "stale-revoked": {stale{}, revoked{}, false, ocsp.Good}, - "stale-stale": {stale{}, stale{}, false, ocsp.Good}, - "stale-timeout": {stale{}, timeout{}, false, ocsp.Good}, - "timeout-ok": {timeout{}, ok{}, true, ignored}, - "timeout-fail": {timeout{}, fail{}, true, ignored}, - "timeout-revoked": {timeout{}, revoked{}, true, ignored}, - "timeout-stale": {timeout{}, stale{}, true, ignored}, - "timeout-timeout": {timeout{}, timeout{}, true, ignored}, - } - for name, tc := range cases { - t.Run(name, func(t *testing.T) { - src, err := NewMultiSource(tc.primary, tc.secondary, expectedFreshness, metrics.NoopRegisterer, blog.NewMock()) - test.AssertNotError(t, err, "failed to create multiSource") - - ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond) - defer cancel() - resp, err := src.Response(ctx, &ocsp.Request{}) - if err != nil { - if !tc.expectedError { - t.Fatalf("unexpected error: %s", err) - } - return - } - if tc.expectedError { - t.Errorf("expected error, got none") - } - if resp.Status != tc.expectedStatus { - t.Errorf("expected response status %d, got %d", tc.expectedStatus, resp.Status) - } - }) - } -} - -func TestSecondaryTimeout(t *testing.T) { - ch := make(chan struct{}) - src, err := NewMultiSource(&ok{}, &timeout{ch: ch}, expectedFreshness, metrics.NoopRegisterer, blog.NewMock()) - test.AssertNotError(t, err, "failed to create multiSource") - - ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second) - defer cancel() - - starting_goroutines := runtime.NumGoroutine() - - for i := 0; i < 1000; i++ { - _, err = src.Response(ctx, &ocsp.Request{}) - test.AssertNotError(t, err, "unexpected error") - } - - close(ch) - // Wait for the goroutines to exit - time.Sleep(40 * time.Millisecond) - goroutine_diff := runtime.NumGoroutine() - starting_goroutines - if goroutine_diff > 0 { - t.Fatalf("expected no lingering goroutines. found %d", goroutine_diff) - } -} - -func TestPrimaryStale(t *testing.T) { - err := features.Set(map[string]bool{ - "ROCSPStage2": true, - }) - test.AssertNotError(t, err, "setting features") - - src, err := NewMultiSource(stale{}, ok{}, expectedFreshness, metrics.NoopRegisterer, blog.NewMock()) - test.AssertNotError(t, err, "failed to create multiSource") - - ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond) - defer cancel() - resp, err := src.Response(ctx, &ocsp.Request{}) - test.AssertNotError(t, err, "getting response") - - age := time.Since(resp.ThisUpdate) - if age > expectedFreshness { - t.Errorf("expected response to be fresh, but it was %s old", age) - } -} diff --git a/sa/sa_test.go b/sa/sa_test.go index bb618cd3a..53cf4de00 100644 --- a/sa/sa_test.go +++ b/sa/sa_test.go @@ -1769,7 +1769,7 @@ func TestRevokeCertificateNoResponse(t *testing.T) { Date: now.UnixNano(), Reason: reason, }) - test.AssertNotError(t, err, "RevokeCertificate should succeed with no response when ROCSPStage3 is enabled") + test.AssertNotError(t, err, "RevokeCertificate should succeed with no response when ROCSPStage6 is enabled") } func TestUpdateRevokedCertificate(t *testing.T) { diff --git a/test/config-next/ocsp-responder.json b/test/config-next/ocsp-responder.json index 9c64fb6e1..58f6bacf0 100644 --- a/test/config-next/ocsp-responder.json +++ b/test/config-next/ocsp-responder.json @@ -48,17 +48,12 @@ "/hierarchy/intermediate-cert-rsa-b.pem", "/hierarchy/intermediate-cert-ecdsa-a.pem" ], - "expectedFreshness": "61h", "liveSigningPeriod": "60h", "timeout": "4.9s", "shutdownStopTimeout": "10s", "debugAddr": ":8005", "requiredSerialPrefixes": ["ff"], - "features": { - "ROCSPStage1": true, - "ROCSPStage2": true, - "ROCSPStage3": true - } + "features": {} }, "syslog": { diff --git a/test/config/ocsp-responder.json b/test/config/ocsp-responder.json index 4a918aa4b..4d28a28ca 100644 --- a/test/config/ocsp-responder.json +++ b/test/config/ocsp-responder.json @@ -4,6 +4,43 @@ "dbConnectFile": "test/secrets/ocsp_responder_dburl", "maxOpenConns": 10 }, + "redis": { + "username": "ocsp-responder", + "passwordFile": "test/secrets/ocsp_responder_redis_password", + "addrs": [ + "10.33.33.7:4218" + ], + "timeout": "5s", + "poolSize": 100, + "routeRandomly": true, + "tls": { + "caCertFile": "test/redis-tls/minica.pem", + "certFile": "test/redis-tls/boulder/cert.pem", + "keyFile": "test/redis-tls/boulder/key.pem" + } + }, + "tls": { + "caCertFile": "test/grpc-creds/minica.pem", + "certFile": "test/grpc-creds/ocsp-responder.boulder/cert.pem", + "keyFile": "test/grpc-creds/ocsp-responder.boulder/key.pem" + }, + "raService": { + "srvLookup": { + "service": "ra", + "domain": "service.consul" + }, + "hostOverride": "ra.boulder", + "timeout": "15s" + }, + "saService": { + "srvLookup": { + "service": "sa", + "domain": "service.consul" + }, + "timeout": "15s", + "hostOverride": "sa.boulder" + }, + "logSampleRate": 1, "path": "/", "listenAddress": "0.0.0.0:4002", "issuerCerts": [ @@ -11,15 +48,17 @@ "/hierarchy/intermediate-cert-rsa-b.pem", "/hierarchy/intermediate-cert-ecdsa-a.pem" ], + "liveSigningPeriod": "60h", "timeout": "4.9s", "shutdownStopTimeout": "10s", "debugAddr": ":8005", - "requiredSerialPrefixes": ["ff"] + "requiredSerialPrefixes": ["ff"], + "features": {} }, "syslog": { "stdoutlevel": 6, - "sysloglevel": 6 + "sysloglevel": -1 }, "beeline": { "mute": true, diff --git a/test/config/ra.json b/test/config/ra.json index 63ccb4787..a8f19fa4d 100644 --- a/test/config/ra.json +++ b/test/config/ra.json @@ -56,6 +56,7 @@ "admin-revoker.boulder", "bad-key-revoker.boulder", "health-checker.boulder", + "ocsp-responder.boulder", "wfe.boulder" ] }, diff --git a/test/config/sa.json b/test/config/sa.json index 34fd53a93..70ae4115f 100644 --- a/test/config/sa.json +++ b/test/config/sa.json @@ -24,6 +24,7 @@ "crl-updater.boulder", "expiration-mailer.boulder", "health-checker.boulder", + "ocsp-responder.boulder", "orphan-finder.boulder", "ra.boulder", "sa.boulder",