summaryrefslogtreecommitdiff
path: root/vendor/github.com/letsencrypt/boulder/features/features.go
blob: 4608d1d63ff1f9bf0b64673096c9735144fee38a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
//go:generate stringer -type=FeatureFlag

package features

import (
	"fmt"
	"sync"
)

type FeatureFlag int

const (
	unused FeatureFlag = iota // unused is used for testing
	//   Deprecated features, these can be removed once stripped from production configs
	PrecertificateRevocation
	StripDefaultSchemePort
	NonCFSSLSigner
	StoreIssuerInfo
	StreamlineOrderAndAuthzs
	V1DisableNewValidations

	//   Currently in-use features
	// Check CAA and respect validationmethods parameter.
	CAAValidationMethods
	// Check CAA and respect accounturi parameter.
	CAAAccountURI
	// EnforceMultiVA causes the VA to block on remote VA PerformValidation
	// requests in order to make a valid/invalid decision with the results.
	EnforceMultiVA
	// MultiVAFullResults will cause the main VA to wait for all of the remote VA
	// results, not just the threshold required to make a decision.
	MultiVAFullResults
	// MandatoryPOSTAsGET forbids legacy unauthenticated GET requests for ACME
	// resources.
	MandatoryPOSTAsGET
	// Allow creation of new registrations in ACMEv1.
	AllowV1Registration
	// StoreRevokerInfo enables storage of the revoker and a bool indicating if the row
	// was checked for extant unrevoked certificates in the blockedKeys table.
	StoreRevokerInfo
	// RestrictRSAKeySizes enables restriction of acceptable RSA public key moduli to
	// the common sizes (2048, 3072, and 4096 bits).
	RestrictRSAKeySizes
	// FasterNewOrdersRateLimit enables use of a separate table for counting the
	// new orders rate limit.
	FasterNewOrdersRateLimit
	// ECDSAForAll enables all accounts, regardless of their presence in the CA's
	// ecdsaAllowedAccounts config value, to get issuance from ECDSA issuers.
	ECDSAForAll
	// ServeRenewalInfo exposes the renewalInfo endpoint in the directory and for
	// GET requests. WARNING: This feature is a draft and highly unstable.
	ServeRenewalInfo
	// GetAuthzReadOnly causes the SA to use its read-only database connection
	// (which is generally pointed at a replica rather than the primary db) when
	// querying the authz2 table.
	GetAuthzReadOnly
	// GetAuthzUseIndex causes the SA to use to add a USE INDEX hint when it
	// queries the authz2 table.
	GetAuthzUseIndex
	// Check the failed authorization limit before doing authz reuse.
	CheckFailedAuthorizationsFirst
	// AllowReRevocation causes the RA to allow the revocation reason of an
	// already-revoked certificate to be updated to `keyCompromise` from any
	// other reason if that compromise is demonstrated by making the second
	// revocation request signed by the certificate keypair.
	AllowReRevocation
	// MozRevocationReasons causes the RA to enforce the following upcoming
	// Mozilla policies regarding revocation:
	// - A subscriber can request that their certificate be revoked with reason
	//   keyCompromise, even without demonstrating that compromise at the time.
	//   However, the cert's pubkey will not be added to the blocked keys list.
	// - When an applicant other than the original subscriber requests that a
	//   certificate be revoked (by demonstrating control over all names in it),
	//   the cert will be revoked with reason cessationOfOperation, regardless of
	//   what revocation reason they request.
	// - When anyone requests that a certificate be revoked by signing the request
	//   with the certificate's keypair, the cert will be revoked with reason
	//   keyCompromise, regardless of what revocation reason they request.
	MozRevocationReasons
)

// List of features and their default value, protected by fMu
var features = map[FeatureFlag]bool{
	unused:                         false,
	CAAValidationMethods:           false,
	CAAAccountURI:                  false,
	EnforceMultiVA:                 false,
	MultiVAFullResults:             false,
	MandatoryPOSTAsGET:             false,
	AllowV1Registration:            true,
	V1DisableNewValidations:        false,
	PrecertificateRevocation:       false,
	StripDefaultSchemePort:         false,
	StoreIssuerInfo:                false,
	StoreRevokerInfo:               false,
	RestrictRSAKeySizes:            false,
	FasterNewOrdersRateLimit:       false,
	NonCFSSLSigner:                 false,
	ECDSAForAll:                    false,
	StreamlineOrderAndAuthzs:       false,
	ServeRenewalInfo:               false,
	GetAuthzReadOnly:               false,
	GetAuthzUseIndex:               false,
	CheckFailedAuthorizationsFirst: false,
	AllowReRevocation:              false,
	MozRevocationReasons:           false,
}

var fMu = new(sync.RWMutex)

var initial = map[FeatureFlag]bool{}

var nameToFeature = make(map[string]FeatureFlag, len(features))

func init() {
	for f, v := range features {
		nameToFeature[f.String()] = f
		initial[f] = v
	}
}

// Set accepts a list of features and whether they should
// be enabled or disabled, it will return a error if passed
// a feature name that it doesn't know
func Set(featureSet map[string]bool) error {
	fMu.Lock()
	defer fMu.Unlock()
	for n, v := range featureSet {
		f, present := nameToFeature[n]
		if !present {
			return fmt.Errorf("feature '%s' doesn't exist", n)
		}
		features[f] = v
	}
	return nil
}

// Enabled returns true if the feature is enabled or false
// if it isn't, it will panic if passed a feature that it
// doesn't know.
func Enabled(n FeatureFlag) bool {
	fMu.RLock()
	defer fMu.RUnlock()
	v, present := features[n]
	if !present {
		panic(fmt.Sprintf("feature '%s' doesn't exist", n.String()))
	}
	return v
}

// Reset resets the features to their initial state
func Reset() {
	fMu.Lock()
	defer fMu.Unlock()
	for k, v := range initial {
		features[k] = v
	}
}