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 }