Remove account ID in WFE2 if feature enabled (#4160)
This helps encourage ACME client developers to use the RFC 8555 specified `Location` header instead. Fixes #4136.
This commit is contained in:
		
							parent
							
								
									2e6ed805ed
								
							
						
					
					
						commit
						7ff30cf857
					
				| 
						 | 
					@ -140,7 +140,7 @@ func (cr CertificateRequest) MarshalJSON() ([]byte, error) {
 | 
				
			||||||
// to account keys.
 | 
					// to account keys.
 | 
				
			||||||
type Registration struct {
 | 
					type Registration struct {
 | 
				
			||||||
	// Unique identifier
 | 
						// Unique identifier
 | 
				
			||||||
	ID int64 `json:"id" db:"id"`
 | 
						ID int64 `json:"id,omitempty" db:"id"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Account key to which the details are attached
 | 
						// Account key to which the details are attached
 | 
				
			||||||
	Key *jose.JSONWebKey `json:"key"`
 | 
						Key *jose.JSONWebKey `json:"key"`
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,11 +24,12 @@ func _() {
 | 
				
			||||||
	_ = x[EarlyOrderRateLimit-13]
 | 
						_ = x[EarlyOrderRateLimit-13]
 | 
				
			||||||
	_ = x[EnforceMultiVA-14]
 | 
						_ = x[EnforceMultiVA-14]
 | 
				
			||||||
	_ = x[MultiVAFullResults-15]
 | 
						_ = x[MultiVAFullResults-15]
 | 
				
			||||||
 | 
						_ = x[RemoveWFE2AccountID-16]
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const _FeatureFlag_name = "unusedPerformValidationRPCACME13KeyRolloverSimplifiedVAHTTPTLSSNIRevalidationAllowRenewalFirstRLCAAValidationMethodsCAAAccountURIProbeCTLogsHeadNonceStatusOKNewAuthorizationSchemaRevokeAtRASetIssuedNamesRenewalBitEarlyOrderRateLimitEnforceMultiVAMultiVAFullResults"
 | 
					const _FeatureFlag_name = "unusedPerformValidationRPCACME13KeyRolloverSimplifiedVAHTTPTLSSNIRevalidationAllowRenewalFirstRLCAAValidationMethodsCAAAccountURIProbeCTLogsHeadNonceStatusOKNewAuthorizationSchemaRevokeAtRASetIssuedNamesRenewalBitEarlyOrderRateLimitEnforceMultiVAMultiVAFullResultsRemoveWFE2AccountID"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var _FeatureFlag_index = [...]uint16{0, 6, 26, 43, 59, 77, 96, 116, 129, 140, 157, 179, 189, 213, 232, 246, 264}
 | 
					var _FeatureFlag_index = [...]uint16{0, 6, 26, 43, 59, 77, 96, 116, 129, 140, 157, 179, 189, 213, 232, 246, 264, 283}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (i FeatureFlag) String() string {
 | 
					func (i FeatureFlag) String() string {
 | 
				
			||||||
	if i < 0 || i >= FeatureFlag(len(_FeatureFlag_index)-1) {
 | 
						if i < 0 || i >= FeatureFlag(len(_FeatureFlag_index)-1) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -44,6 +44,9 @@ const (
 | 
				
			||||||
	// MultiVAFullResults will cause the main VA to wait for all of the remote VA
 | 
						// MultiVAFullResults will cause the main VA to wait for all of the remote VA
 | 
				
			||||||
	// results, not just the threshold required to make a decision.
 | 
						// results, not just the threshold required to make a decision.
 | 
				
			||||||
	MultiVAFullResults
 | 
						MultiVAFullResults
 | 
				
			||||||
 | 
						// RemoveWFE2AccountID will remove the account ID from account objects returned
 | 
				
			||||||
 | 
						// from the new-account endpoint if enabled.
 | 
				
			||||||
 | 
						RemoveWFE2AccountID
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// List of features and their default value, protected by fMu
 | 
					// List of features and their default value, protected by fMu
 | 
				
			||||||
| 
						 | 
					@ -64,6 +67,7 @@ var features = map[FeatureFlag]bool{
 | 
				
			||||||
	EarlyOrderRateLimit:      false,
 | 
						EarlyOrderRateLimit:      false,
 | 
				
			||||||
	EnforceMultiVA:           false,
 | 
						EnforceMultiVA:           false,
 | 
				
			||||||
	MultiVAFullResults:       false,
 | 
						MultiVAFullResults:       false,
 | 
				
			||||||
 | 
						RemoveWFE2AccountID:      false,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var fMu = new(sync.RWMutex)
 | 
					var fMu = new(sync.RWMutex)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -37,7 +37,8 @@
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "features": {
 | 
					    "features": {
 | 
				
			||||||
      "HeadNonceStatusOK": true,
 | 
					      "HeadNonceStatusOK": true,
 | 
				
			||||||
      "NewAuthorizationSchema": true
 | 
					      "NewAuthorizationSchema": true,
 | 
				
			||||||
 | 
					      "RemoveWFE2AccountID": true
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										10
									
								
								wfe2/wfe.go
								
								
								
								
							
							
						
						
									
										10
									
								
								wfe2/wfe.go
								
								
								
								
							| 
						 | 
					@ -494,6 +494,11 @@ func (wfe *WebFrontEndImpl) NewAccount(
 | 
				
			||||||
			web.RelativeEndpoint(request, fmt.Sprintf("%s%d", acctPath, existingAcct.ID)))
 | 
								web.RelativeEndpoint(request, fmt.Sprintf("%s%d", acctPath, existingAcct.ID)))
 | 
				
			||||||
		logEvent.Requester = existingAcct.ID
 | 
							logEvent.Requester = existingAcct.ID
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if features.Enabled(features.RemoveWFE2AccountID) {
 | 
				
			||||||
 | 
								// Zero out the account ID so that it isn't marshalled
 | 
				
			||||||
 | 
								existingAcct.ID = 0
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		err = wfe.writeJsonResponse(response, logEvent, http.StatusOK, existingAcct)
 | 
							err = wfe.writeJsonResponse(response, logEvent, http.StatusOK, existingAcct)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			// ServerInternal because we just created this account, and it
 | 
								// ServerInternal because we just created this account, and it
 | 
				
			||||||
| 
						 | 
					@ -569,6 +574,11 @@ func (wfe *WebFrontEndImpl) NewAccount(
 | 
				
			||||||
		response.Header().Add("Link", link(wfe.SubscriberAgreementURL, "terms-of-service"))
 | 
							response.Header().Add("Link", link(wfe.SubscriberAgreementURL, "terms-of-service"))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if features.Enabled(features.RemoveWFE2AccountID) {
 | 
				
			||||||
 | 
							// Zero out the account ID so that it isn't marshalled
 | 
				
			||||||
 | 
							acct.ID = 0
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = wfe.writeJsonResponse(response, logEvent, http.StatusCreated, acct)
 | 
						err = wfe.writeJsonResponse(response, logEvent, http.StatusCreated, acct)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		// ServerInternal because we just created this account, and it
 | 
							// ServerInternal because we just created this account, and it
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -211,6 +211,7 @@ type MockRegistrationAuthority struct {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (ra *MockRegistrationAuthority) NewRegistration(ctx context.Context, acct core.Registration) (core.Registration, error) {
 | 
					func (ra *MockRegistrationAuthority) NewRegistration(ctx context.Context, acct core.Registration) (core.Registration, error) {
 | 
				
			||||||
 | 
						acct.ID = 1
 | 
				
			||||||
	return acct, nil
 | 
						return acct, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1247,7 +1248,7 @@ func TestNewECDSAAccount(t *testing.T) {
 | 
				
			||||||
	test.AssertEquals(t, acct.Agreement, "")
 | 
						test.AssertEquals(t, acct.Agreement, "")
 | 
				
			||||||
	test.AssertEquals(t, acct.InitialIP.String(), "1.1.1.1")
 | 
						test.AssertEquals(t, acct.InitialIP.String(), "1.1.1.1")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	test.AssertEquals(t, responseWriter.Header().Get("Location"), "http://localhost/acme/acct/0")
 | 
						test.AssertEquals(t, responseWriter.Header().Get("Location"), "http://localhost/acme/acct/1")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	key = loadKey(t, []byte(testE1KeyPrivatePEM))
 | 
						key = loadKey(t, []byte(testE1KeyPrivatePEM))
 | 
				
			||||||
	_, ok = key.(*ecdsa.PrivateKey)
 | 
						_, ok = key.(*ecdsa.PrivateKey)
 | 
				
			||||||
| 
						 | 
					@ -1393,7 +1394,7 @@ func TestNewAccount(t *testing.T) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	test.AssertEquals(
 | 
						test.AssertEquals(
 | 
				
			||||||
		t, responseWriter.Header().Get("Location"),
 | 
							t, responseWriter.Header().Get("Location"),
 | 
				
			||||||
		"http://localhost/acme/acct/0")
 | 
							"http://localhost/acme/acct/1")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Load an existing key
 | 
						// Load an existing key
 | 
				
			||||||
	key = loadKey(t, []byte(test1KeyPrivatePEM))
 | 
						key = loadKey(t, []byte(test1KeyPrivatePEM))
 | 
				
			||||||
| 
						 | 
					@ -1415,6 +1416,41 @@ func TestNewAccount(t *testing.T) {
 | 
				
			||||||
	test.AssertEquals(t, responseWriter.Body.String(), "{\n  \"id\": 1,\n  \"key\": {\n    \"kty\": \"RSA\",\n    \"n\": \"yNWVhtYEKJR21y9xsHV-PD_bYwbXSeNuFal46xYxVfRL5mqha7vttvjB_vc7Xg2RvgCxHPCqoxgMPTzHrZT75LjCwIW2K_klBYN8oYvTwwmeSkAz6ut7ZxPv-nZaT5TJhGk0NT2kh_zSpdriEJ_3vW-mqxYbbBmpvHqsa1_zx9fSuHYctAZJWzxzUZXykbWMWQZpEiE0J4ajj51fInEzVn7VxV-mzfMyboQjujPh7aNJxAWSq4oQEJJDgWwSh9leyoJoPpONHxh5nEE5AjE01FkGICSxjpZsF-w8hOTI3XXohUdu29Se26k2B0PolDSuj0GIQU6-W9TdLXSjBb2SpQ\",\n    \"e\": \"AQAB\"\n  },\n  \"contact\": [\n    \"mailto:person@mail.com\"\n  ],\n  \"agreement\": \"http://example.invalid/terms\",\n  \"initialIp\": \"\",\n  \"createdAt\": \"0001-01-01T00:00:00Z\",\n  \"status\": \"valid\"\n}")
 | 
						test.AssertEquals(t, responseWriter.Body.String(), "{\n  \"id\": 1,\n  \"key\": {\n    \"kty\": \"RSA\",\n    \"n\": \"yNWVhtYEKJR21y9xsHV-PD_bYwbXSeNuFal46xYxVfRL5mqha7vttvjB_vc7Xg2RvgCxHPCqoxgMPTzHrZT75LjCwIW2K_klBYN8oYvTwwmeSkAz6ut7ZxPv-nZaT5TJhGk0NT2kh_zSpdriEJ_3vW-mqxYbbBmpvHqsa1_zx9fSuHYctAZJWzxzUZXykbWMWQZpEiE0J4ajj51fInEzVn7VxV-mzfMyboQjujPh7aNJxAWSq4oQEJJDgWwSh9leyoJoPpONHxh5nEE5AjE01FkGICSxjpZsF-w8hOTI3XXohUdu29Se26k2B0PolDSuj0GIQU6-W9TdLXSjBb2SpQ\",\n    \"e\": \"AQAB\"\n  },\n  \"contact\": [\n    \"mailto:person@mail.com\"\n  ],\n  \"agreement\": \"http://example.invalid/terms\",\n  \"initialIp\": \"\",\n  \"createdAt\": \"0001-01-01T00:00:00Z\",\n  \"status\": \"valid\"\n}")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestNewAccountNoID(t *testing.T) {
 | 
				
			||||||
 | 
						wfe, _ := setupWFE(t)
 | 
				
			||||||
 | 
						key := loadKey(t, []byte(test2KeyPrivatePEM))
 | 
				
			||||||
 | 
						_, ok := key.(*rsa.PrivateKey)
 | 
				
			||||||
 | 
						test.Assert(t, ok, "Couldn't load test2 key")
 | 
				
			||||||
 | 
						path := newAcctPath
 | 
				
			||||||
 | 
						signedURL := fmt.Sprintf("http://localhost%s", path)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_ = features.Set(map[string]bool{
 | 
				
			||||||
 | 
							"RemoveWFE2AccountID": true,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						payload := `{"contact":["mailto:person@mail.com"],"termsOfServiceAgreed":true}`
 | 
				
			||||||
 | 
						_, _, body := signRequestEmbed(t, key, signedURL, payload, wfe.nonceService)
 | 
				
			||||||
 | 
						request := makePostRequestWithPath(path, body)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						responseWriter := httptest.NewRecorder()
 | 
				
			||||||
 | 
						wfe.NewAccount(ctx, newRequestEvent(), responseWriter, request)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						responseBody := responseWriter.Body.String()
 | 
				
			||||||
 | 
						test.AssertUnmarshaledEquals(t, responseBody, `{
 | 
				
			||||||
 | 
							"key": {
 | 
				
			||||||
 | 
								"kty": "RSA",
 | 
				
			||||||
 | 
								"n": "qnARLrT7Xz4gRcKyLdydmCr-ey9OuPImX4X40thk3on26FkMznR3fRjs66eLK7mmPcBZ6uOJseURU6wAaZNmemoYx1dMvqvWWIyiQleHSD7Q8vBrhR6uIoO4jAzJZR-ChzZuSDt7iHN-3xUVspu5XGwXU_MVJZshTwp4TaFx5elHIT_ObnTvTOU3Xhish07AbgZKmWsVbXh5s-CrIicU4OexJPgunWZ_YJJueOKmTvnLlTV4MzKR2oZlBKZ27S0-SfdV_QDx_ydle5oMAyKVtlAV35cyPMIsYNwgUGBCdY_2Uzi5eX0lTc7MPRwz6qR1kip-i59VcGcUQgqHV6Fyqw",
 | 
				
			||||||
 | 
								"e": "AQAB"
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"contact": [
 | 
				
			||||||
 | 
								"mailto:person@mail.com"
 | 
				
			||||||
 | 
							],
 | 
				
			||||||
 | 
							"initialIp": "1.1.1.1",
 | 
				
			||||||
 | 
							"createdAt": "0001-01-01T00:00:00Z",
 | 
				
			||||||
 | 
							"status": ""
 | 
				
			||||||
 | 
						}`)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestGetAuthorization(t *testing.T) {
 | 
					func TestGetAuthorization(t *testing.T) {
 | 
				
			||||||
	wfe, _ := setupWFE(t)
 | 
						wfe, _ := setupWFE(t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue