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
This commit is contained in:
Aaron Gable 2022-10-21 14:58:34 -07:00 committed by GitHub
parent 410732e8a7
commit 30d8f19895
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 107 additions and 475 deletions

View File

@ -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 {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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": {

View File

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

View File

@ -56,6 +56,7 @@
"admin-revoker.boulder",
"bad-key-revoker.boulder",
"health-checker.boulder",
"ocsp-responder.boulder",
"wfe.boulder"
]
},

View File

@ -24,6 +24,7 @@
"crl-updater.boulder",
"expiration-mailer.boulder",
"health-checker.boulder",
"ocsp-responder.boulder",
"orphan-finder.boulder",
"ra.boulder",
"sa.boulder",