github.com/letsencrypt/boulder@v0.20251208.0/features/features.go (about)

     1  // features provides the Config struct, which is used to define feature flags
     2  // that can affect behavior across Boulder components. It also maintains a
     3  // global singleton Config which can be referenced by arbitrary Boulder code
     4  // without having to pass a collection of feature flags through the function
     5  // call graph.
     6  package features
     7  
     8  import (
     9  	"sync"
    10  )
    11  
    12  // Config contains one boolean field for every Boulder feature flag. It can be
    13  // included directly in an executable's Config struct to have feature flags be
    14  // automatically parsed by the json config loader; executables that do so must
    15  // then call features.Set(parsedConfig) to load the parsed struct into this
    16  // package's global Config.
    17  type Config struct {
    18  	// Deprecated flags.
    19  	IncrementRateLimits         bool
    20  	UseKvLimitsForNewOrder      bool
    21  	DisableLegacyLimitWrites    bool
    22  	MultipleCertificateProfiles bool
    23  	InsertAuthzsIndividually    bool
    24  	EnforceMultiCAA             bool
    25  	EnforceMPIC                 bool
    26  	MPICFullResults             bool
    27  	UnsplitIssuance             bool
    28  	ExpirationMailerUsesJoin    bool
    29  	DOH                         bool
    30  	IgnoreAccountContacts       bool
    31  	NoPendingAuthzReuse         bool
    32  
    33  	// ServeRenewalInfo exposes the renewalInfo endpoint in the directory and for
    34  	// GET requests. WARNING: This feature is a draft and highly unstable.
    35  	ServeRenewalInfo bool
    36  
    37  	// CertCheckerChecksValidations enables an extra query for each certificate
    38  	// checked, to find the relevant authzs. Since this query might be
    39  	// expensive, we gate it behind a feature flag.
    40  	CertCheckerChecksValidations bool
    41  
    42  	// CertCheckerRequiresValidations causes cert-checker to fail if the
    43  	// query enabled by CertCheckerChecksValidations didn't find corresponding
    44  	// authorizations.
    45  	CertCheckerRequiresValidations bool
    46  
    47  	// AsyncFinalize enables the RA to return approximately immediately from
    48  	// requests to finalize orders. This allows us to take longer getting SCTs,
    49  	// issuing certs, and updating the database; it indirectly reduces the number
    50  	// of issuances that fail due to timeouts during storage. However, it also
    51  	// requires clients to properly implement polling the Order object to wait
    52  	// for the cert URL to appear.
    53  	AsyncFinalize bool
    54  
    55  	// CheckIdentifiersPaused checks if any of the identifiers in the order are
    56  	// currently paused at NewOrder time. If any are paused, an error is
    57  	// returned to the Subscriber indicating that the order cannot be processed
    58  	// until the paused identifiers are unpaused and the order is resubmitted.
    59  	CheckIdentifiersPaused bool
    60  
    61  	// PropagateCancels controls whether the WFE allows
    62  	// cancellation of an inbound request to cancel downstream gRPC and other
    63  	// queries. In practice, cancellation of an inbound request is achieved by
    64  	// Nginx closing the connection on which the request was happening. This may
    65  	// help shed load in overcapacity situations. However, note that in-progress
    66  	// database queries (for instance, in the SA) are not cancelled. Database
    67  	// queries waiting for an available connection may be cancelled.
    68  	PropagateCancels bool
    69  
    70  	// AutomaticallyPauseZombieClients configures the RA to automatically track
    71  	// and pause issuance for each (account, hostname) pair that repeatedly
    72  	// fails validation.
    73  	AutomaticallyPauseZombieClients bool
    74  
    75  	// StoreARIReplacesInOrders causes the SA to store and retrieve the optional
    76  	// ARI replaces field in the orders table.
    77  	StoreARIReplacesInOrders bool
    78  
    79  	// DNSAccount01Enabled controls support for the dns-account-01 challenge
    80  	// type. When enabled, the server can offer and validate this challenge
    81  	// during certificate issuance. This flag must be set to true in the
    82  	// RA, VA, and WFE2 services for full functionality.
    83  	DNSAccount01Enabled bool
    84  
    85  	// StoreAuthzsInOrders causes the SA to write to the `authzs`
    86  	// column in NewOrder and read from it in GetOrder. It should be enabled
    87  	// after the migration to add that column has been run.
    88  	StoreAuthzsInOrders bool
    89  }
    90  
    91  var fMu = new(sync.RWMutex)
    92  var global = Config{}
    93  
    94  // Set changes the global FeatureSet to match the input FeatureSet. This
    95  // overrides any previous changes made to the global FeatureSet.
    96  //
    97  // When used in tests, the caller must defer features.Reset() to avoid leaving
    98  // dirty global state.
    99  func Set(fs Config) {
   100  	fMu.Lock()
   101  	defer fMu.Unlock()
   102  	// If the FeatureSet type ever changes, this must be updated to still copy
   103  	// the input argument, never hold a reference to it.
   104  	global = fs
   105  }
   106  
   107  // Reset resets all features to their initial state (false).
   108  func Reset() {
   109  	fMu.Lock()
   110  	defer fMu.Unlock()
   111  	global = Config{}
   112  }
   113  
   114  // Get returns a copy of the current global FeatureSet, indicating which
   115  // features are currently enabled (set to true). Expected caller behavior looks
   116  // like:
   117  //
   118  //	if features.Get().FeatureName { ...
   119  func Get() Config {
   120  	fMu.RLock()
   121  	defer fMu.RUnlock()
   122  	// If the FeatureSet type ever changes, this must be updated to still return
   123  	// only a copy of the current state, never a reference directly to it.
   124  	return global
   125  }