boulder/features/features.go

129 lines
5.0 KiB
Go

// features provides the Config struct, which is used to define feature flags
// that can affect behavior across Boulder components. It also maintains a
// global singleton Config which can be referenced by arbitrary Boulder code
// without having to pass a collection of feature flags through the function
// call graph.
package features
import (
"sync"
)
// Config contains one boolean field for every Boulder feature flag. It can be
// included directly in an executable's Config struct to have feature flags be
// automatically parsed by the json config loader; executables that do so must
// then call features.Set(parsedConfig) to load the parsed struct into this
// package's global Config.
type Config struct {
// Deprecated flags.
IncrementRateLimits bool
UseKvLimitsForNewOrder bool
DisableLegacyLimitWrites bool
MultipleCertificateProfiles bool
InsertAuthzsIndividually bool
EnforceMultiCAA bool
EnforceMPIC bool
MPICFullResults bool
UnsplitIssuance bool
// ServeRenewalInfo exposes the renewalInfo endpoint in the directory and for
// GET requests. WARNING: This feature is a draft and highly unstable.
ServeRenewalInfo bool
// ExpirationMailerUsesJoin enables using a JOIN query in expiration-mailer
// rather than a SELECT from certificateStatus followed by thousands of
// one-row SELECTs from certificates.
ExpirationMailerUsesJoin bool
// CertCheckerChecksValidations enables an extra query for each certificate
// checked, to find the relevant authzs. Since this query might be
// expensive, we gate it behind a feature flag.
CertCheckerChecksValidations bool
// CertCheckerRequiresValidations causes cert-checker to fail if the
// query enabled by CertCheckerChecksValidations didn't find corresponding
// authorizations.
CertCheckerRequiresValidations bool
// AsyncFinalize enables the RA to return approximately immediately from
// requests to finalize orders. This allows us to take longer getting SCTs,
// issuing certs, and updating the database; it indirectly reduces the number
// of issuances that fail due to timeouts during storage. However, it also
// requires clients to properly implement polling the Order object to wait
// for the cert URL to appear.
AsyncFinalize bool
// DOH enables DNS-over-HTTPS queries for validation
DOH bool
// CheckIdentifiersPaused checks if any of the identifiers in the order are
// currently paused at NewOrder time. If any are paused, an error is
// returned to the Subscriber indicating that the order cannot be processed
// until the paused identifiers are unpaused and the order is resubmitted.
CheckIdentifiersPaused bool
// PropagateCancels controls whether the WFE and ocsp-responder allows
// cancellation of an inbound request to cancel downstream gRPC and other
// queries. In practice, cancellation of an inbound request is achieved by
// Nginx closing the connection on which the request was happening. This may
// help shed load in overcapacity situations. However, note that in-progress
// database queries (for instance, in the SA) are not cancelled. Database
// queries waiting for an available connection may be cancelled.
PropagateCancels bool
// AutomaticallyPauseZombieClients configures the RA to automatically track
// and pause issuance for each (account, hostname) pair that repeatedly
// fails validation.
AutomaticallyPauseZombieClients bool
// NoPendingAuthzReuse causes the RA to only select already-validated authzs
// to attach to a newly created order. This preserves important client-facing
// functionality (valid authz reuse) while letting us simplify our code by
// removing pending authz reuse.
NoPendingAuthzReuse bool
// StoreARIReplacesInOrders causes the SA to store and retrieve the optional
// ARI replaces field in the orders table.
StoreARIReplacesInOrders bool
// IgnoreAccountContacts causes the SA to omit the contacts column when
// creating new account rows, and when retrieving existing account rows.
IgnoreAccountContacts bool
}
var fMu = new(sync.RWMutex)
var global = Config{}
// Set changes the global FeatureSet to match the input FeatureSet. This
// overrides any previous changes made to the global FeatureSet.
//
// When used in tests, the caller must defer features.Reset() to avoid leaving
// dirty global state.
func Set(fs Config) {
fMu.Lock()
defer fMu.Unlock()
// If the FeatureSet type ever changes, this must be updated to still copy
// the input argument, never hold a reference to it.
global = fs
}
// Reset resets all features to their initial state (false).
func Reset() {
fMu.Lock()
defer fMu.Unlock()
global = Config{}
}
// Get returns a copy of the current global FeatureSet, indicating which
// features are currently enabled (set to true). Expected caller behavior looks
// like:
//
// if features.Get().FeatureName { ...
func Get() Config {
fMu.RLock()
defer fMu.RUnlock()
// If the FeatureSet type ever changes, this must be updated to still return
// only a copy of the current state, never a reference directly to it.
return global
}