Remove features checks from wfe2 (#2982)

This commit is contained in:
Roland Bracewell Shoemaker 2017-08-16 07:53:47 -07:00 committed by Daniel McCarney
parent e670e6e6b5
commit c560fa4fc5
3 changed files with 77 additions and 230 deletions

View File

@ -95,10 +95,18 @@ func (e BadNonceError) Error() string { return string(e) }
// Random stuff // Random stuff
type randSource interface {
Read(p []byte) (n int, err error)
}
// RandReader is used so that it can be replaced in tests that require
// deterministic output
var RandReader randSource = rand.Reader
// RandomString returns a randomly generated string of the requested length. // RandomString returns a randomly generated string of the requested length.
func RandomString(byteLength int) string { func RandomString(byteLength int) string {
b := make([]byte, byteLength) b := make([]byte, byteLength)
_, err := io.ReadFull(rand.Reader, b) _, err := io.ReadFull(RandReader, b)
if err != nil { if err != nil {
panic(fmt.Sprintf("Error reading random bytes: %s", err)) panic(fmt.Sprintf("Error reading random bytes: %s", err))
} }

View File

@ -19,7 +19,6 @@ import (
"golang.org/x/net/context" "golang.org/x/net/context"
"github.com/letsencrypt/boulder/core" "github.com/letsencrypt/boulder/core"
"github.com/letsencrypt/boulder/features"
"github.com/letsencrypt/boulder/goodkey" "github.com/letsencrypt/boulder/goodkey"
blog "github.com/letsencrypt/boulder/log" blog "github.com/letsencrypt/boulder/log"
"github.com/letsencrypt/boulder/metrics" "github.com/letsencrypt/boulder/metrics"
@ -269,7 +268,7 @@ func (wfe *WebFrontEndImpl) relativeDirectory(request *http.Request, directory m
// the `BaseURL`. Otherwise, prefix each endpoint using the request protocol // the `BaseURL`. Otherwise, prefix each endpoint using the request protocol
// & host. // & host.
for k, v := range directory { for k, v := range directory {
if features.Enabled(features.RandomDirectoryEntry) && v == randomDirKeyExplanationLink { if v == randomDirKeyExplanationLink {
relativeDir[k] = v relativeDir[k] = v
continue continue
} }
@ -308,9 +307,7 @@ func (wfe *WebFrontEndImpl) Handler() http.Handler {
wfe.HandleFunc(m, termsPath, wfe.Terms, "GET") wfe.HandleFunc(m, termsPath, wfe.Terms, "GET")
wfe.HandleFunc(m, issuerPath, wfe.Issuer, "GET") wfe.HandleFunc(m, issuerPath, wfe.Issuer, "GET")
wfe.HandleFunc(m, buildIDPath, wfe.BuildID, "GET") wfe.HandleFunc(m, buildIDPath, wfe.BuildID, "GET")
if features.Enabled(features.AllowKeyRollover) { wfe.HandleFunc(m, rolloverPath, wfe.KeyRollover, "POST")
wfe.HandleFunc(m, rolloverPath, wfe.KeyRollover, "POST")
}
// We don't use our special HandleFunc for "/" because it matches everything, // We don't use our special HandleFunc for "/" because it matches everything,
// meaning we can wind up returning 405 when we mean to return 404. See // meaning we can wind up returning 405 when we mean to return 404. See
// https://github.com/letsencrypt/boulder/issues/717 // https://github.com/letsencrypt/boulder/issues/717
@ -376,26 +373,18 @@ func (wfe *WebFrontEndImpl) Directory(ctx context.Context, logEvent *requestEven
"revoke-cert": revokeCertPath, "revoke-cert": revokeCertPath,
} }
// Versions of Certbot pre-0.6.0 (named LetsEncryptPythonClient at the time) break when they directoryEndpoints["key-change"] = rolloverPath
// encounter a directory containing elements they don't expect so we gate
// adding new directory fields for clients matching this UA. // Add a random key to the directory in order to make sure that clients don't hardcode an
clientDirChangeIntolerant := strings.HasPrefix(request.UserAgent(), "LetsEncryptPythonClient") // expected set of keys. This ensures that we can properly extend the directory when we
if features.Enabled(features.AllowKeyRollover) && !clientDirChangeIntolerant { // need to add a new endpoint or meta element.
directoryEndpoints["key-change"] = rolloverPath directoryEndpoints[core.RandomString(8)] = randomDirKeyExplanationLink
}
if features.Enabled(features.RandomDirectoryEntry) && !clientDirChangeIntolerant { // ACME since draft-02 describes an optional "meta" directory entry. The
// Add a random key to the directory in order to make sure that clients don't hardcode an // meta entry may optionally contain a "terms-of-service" URI for the
// expected set of keys. This ensures that we can properly extend the directory when we // current ToS.
// need to add a new endpoint or meta element. directoryEndpoints["meta"] = map[string]string{
directoryEndpoints[core.RandomString(8)] = randomDirKeyExplanationLink "terms-of-service": wfe.SubscriberAgreementURL,
}
if features.Enabled(features.DirectoryMeta) && !clientDirChangeIntolerant {
// ACME since draft-02 describes an optional "meta" directory entry. The
// meta entry may optionally contain a "terms-of-service" URI for the
// current ToS.
directoryEndpoints["meta"] = map[string]string{
"terms-of-service": wfe.SubscriberAgreementURL,
}
} }
response.Header().Set("Content-Type", "application/json") response.Header().Set("Content-Type", "application/json")
@ -707,15 +696,10 @@ func (wfe *WebFrontEndImpl) NewCertificate(ctx context.Context, logEvent *reques
// TODO Content negotiation // TODO Content negotiation
response.Header().Add("Location", certURL) response.Header().Add("Location", certURL)
if features.Enabled(features.UseAIAIssuerURL) { if err = wfe.addIssuingCertificateURLs(response, parsedCertificate.IssuingCertificateURL); err != nil {
if err = wfe.addIssuingCertificateURLs(response, parsedCertificate.IssuingCertificateURL); err != nil { logEvent.AddError("unable to parse IssuingCertificateURL: %s", err)
logEvent.AddError("unable to parse IssuingCertificateURL: %s", err) wfe.sendError(response, logEvent, probs.ServerInternal("unable to parse IssuingCertificateURL"), err)
wfe.sendError(response, logEvent, probs.ServerInternal("unable to parse IssuingCertificateURL"), err) return
return
}
} else {
relativeIssuerPath := wfe.relativeEndpoint(request, issuerPath)
response.Header().Add("Link", link(relativeIssuerPath, "up"))
} }
response.Header().Set("Content-Type", "application/pkix-cert") response.Header().Set("Content-Type", "application/pkix-cert")
response.WriteHeader(http.StatusCreated) response.WriteHeader(http.StatusCreated)
@ -953,7 +937,7 @@ func (wfe *WebFrontEndImpl) Registration(
// If a user tries to send both a deactivation request and an update to their // If a user tries to send both a deactivation request and an update to their
// contacts or subscriber agreement URL the deactivation will take place and // contacts or subscriber agreement URL the deactivation will take place and
// return before an update would be performed. // return before an update would be performed.
if features.Enabled(features.AllowAccountDeactivation) && (update.Status != "" && update.Status != currReg.Status) { if update.Status != "" && update.Status != currReg.Status {
if update.Status != core.StatusDeactivated { if update.Status != core.StatusDeactivated {
wfe.sendError(response, logEvent, probs.Malformed("Invalid value provided for status field"), nil) wfe.sendError(response, logEvent, probs.Malformed("Invalid value provided for status field"), nil)
return return
@ -1127,22 +1111,18 @@ func (wfe *WebFrontEndImpl) Certificate(ctx context.Context, logEvent *requestEv
// TODO Content negotiation // TODO Content negotiation
response.Header().Set("Content-Type", "application/pkix-cert") response.Header().Set("Content-Type", "application/pkix-cert")
if features.Enabled(features.UseAIAIssuerURL) { parsedCertificate, err := x509.ParseCertificate([]byte(cert.DER))
parsedCertificate, err := x509.ParseCertificate([]byte(cert.DER)) if err != nil {
if err != nil { logEvent.AddError("unable to parse certificate: %s", err)
logEvent.AddError("unable to parse certificate: %s", err) wfe.sendError(response, logEvent, probs.ServerInternal("Unable to parse certificate"), err)
wfe.sendError(response, logEvent, probs.ServerInternal("Unable to parse certificate"), err) return
return
}
if err = wfe.addIssuingCertificateURLs(response, parsedCertificate.IssuingCertificateURL); err != nil {
logEvent.AddError("unable to parse IssuingCertificateURL: %s", err)
wfe.sendError(response, logEvent, probs.ServerInternal("unable to parse IssuingCertificateURL"), err)
return
}
} else {
relativeIssuerPath := wfe.relativeEndpoint(request, issuerPath)
response.Header().Add("Link", link(relativeIssuerPath, "up"))
} }
if err = wfe.addIssuingCertificateURLs(response, parsedCertificate.IssuingCertificateURL); err != nil {
logEvent.AddError("unable to parse IssuingCertificateURL: %s", err)
wfe.sendError(response, logEvent, probs.ServerInternal("unable to parse IssuingCertificateURL"), err)
return
}
response.WriteHeader(http.StatusOK) response.WriteHeader(http.StatusOK)
if _, err = response.Write(cert.DER); err != nil { if _, err = response.Write(cert.DER); err != nil {
logEvent.AddError(err.Error()) logEvent.AddError(err.Error())

View File

@ -4,6 +4,7 @@ import (
"bytes" "bytes"
"crypto" "crypto"
"crypto/ecdsa" "crypto/ecdsa"
"crypto/rand"
"crypto/rsa" "crypto/rsa"
"crypto/x509" "crypto/x509"
"encoding/json" "encoding/json"
@ -26,7 +27,6 @@ import (
"github.com/letsencrypt/boulder/core" "github.com/letsencrypt/boulder/core"
corepb "github.com/letsencrypt/boulder/core/proto" corepb "github.com/letsencrypt/boulder/core/proto"
"github.com/letsencrypt/boulder/features"
"github.com/letsencrypt/boulder/goodkey" "github.com/letsencrypt/boulder/goodkey"
blog "github.com/letsencrypt/boulder/log" blog "github.com/letsencrypt/boulder/log"
"github.com/letsencrypt/boulder/metrics" "github.com/letsencrypt/boulder/metrics"
@ -625,6 +625,12 @@ func randomDirectoryKeyPresent(t *testing.T, buf []byte) bool {
return false return false
} }
type fakeRand struct{}
func (fr fakeRand) Read(p []byte) (int, error) {
return len(p), nil
}
func TestDirectory(t *testing.T) { func TestDirectory(t *testing.T) {
// Note: `TestDirectory` sets the `wfe.BaseURL` specifically to test the // Note: `TestDirectory` sets the `wfe.BaseURL` specifically to test the
// that it overrides the relative /directory behaviour. // that it overrides the relative /directory behaviour.
@ -634,27 +640,8 @@ func TestDirectory(t *testing.T) {
wfe, _ := setupWFE(t) wfe, _ := setupWFE(t)
wfe.BaseURL = "http://localhost:4300" wfe.BaseURL = "http://localhost:4300"
mux := wfe.Handler() mux := wfe.Handler()
core.RandReader = fakeRand{}
const ( defer func() { core.RandReader = rand.Reader }()
oldUA = "LetsEncryptPythonClient"
)
// Directory with a key change endpoint but no meta endpoint or random entry
noMetaJSONWithKeyChange := `{
"key-change": "http://localhost:4300/acme/key-change",
"new-authz": "http://localhost:4300/acme/new-authz",
"new-cert": "http://localhost:4300/acme/new-cert",
"new-reg": "http://localhost:4300/acme/new-reg",
"revoke-cert": "http://localhost:4300/acme/revoke-cert"
}`
// Directory without a key change endpoint or a random entry
noMetaJSONWithoutKeyChange := `{
"new-authz": "http://localhost:4300/acme/new-authz",
"new-cert": "http://localhost:4300/acme/new-cert",
"new-reg": "http://localhost:4300/acme/new-reg",
"revoke-cert": "http://localhost:4300/acme/revoke-cert"
}`
// Directory with a key change endpoint and a meta entry // Directory with a key change endpoint and a meta entry
metaJSON := `{ metaJSON := `{
@ -665,115 +652,37 @@ func TestDirectory(t *testing.T) {
"new-authz": "http://localhost:4300/acme/new-authz", "new-authz": "http://localhost:4300/acme/new-authz",
"new-cert": "http://localhost:4300/acme/new-cert", "new-cert": "http://localhost:4300/acme/new-cert",
"new-reg": "http://localhost:4300/acme/new-reg", "new-reg": "http://localhost:4300/acme/new-reg",
"revoke-cert": "http://localhost:4300/acme/revoke-cert" "revoke-cert": "http://localhost:4300/acme/revoke-cert",
"AAAAAAAAAAA": "https://community.letsencrypt.org/t/adding-random-entries-to-the-directory/33417"
}` }`
// Directory with a meta entry but no key change endpoint // NOTE: the req.URL will be modified and must be constructed per
metaNoKeyChangeJSON := `{ // testcase or things will break and you will be confused and sad.
"meta": { url, _ := url.Parse("/directory")
"terms-of-service": "http://example.invalid/terms" req := &http.Request{
}, Method: "GET",
"new-authz": "http://localhost:4300/acme/new-authz", URL: url,
"new-cert": "http://localhost:4300/acme/new-cert", Host: "127.0.0.1:4300",
"new-reg": "http://localhost:4300/acme/new-reg",
"revoke-cert": "http://localhost:4300/acme/revoke-cert"
}`
testCases := []struct {
Name string
UserAgent string
SetFeatures []string
ExpectedJSON string
RandomEntry bool
}{
{
Name: "No meta feature enabled, no explicit user-agent",
ExpectedJSON: noMetaJSONWithoutKeyChange,
},
{
Name: "Key change feature enabled, no explicit user-agent",
SetFeatures: []string{"AllowKeyRollover"},
ExpectedJSON: noMetaJSONWithKeyChange,
},
{
Name: "DirectoryMeta feature enabled, no explicit user-agent",
SetFeatures: []string{"DirectoryMeta"},
ExpectedJSON: metaNoKeyChangeJSON,
},
{
Name: "DirectoryMeta feature enabled, no key change enabled, explicit old Let's Encrypt user-agent",
SetFeatures: []string{"DirectoryMeta"},
UserAgent: oldUA,
ExpectedJSON: noMetaJSONWithoutKeyChange,
},
{
Name: "DirectoryMeta feature enabled, key change enabled, explicit old Let's Encrypt user-agent",
SetFeatures: []string{"DirectoryMeta", "AllowKeyRollover"},
UserAgent: oldUA,
ExpectedJSON: noMetaJSONWithoutKeyChange,
},
{
Name: "DirectoryMeta feature enabled, key change enabled, no explicit user-agent",
SetFeatures: []string{"DirectoryMeta", "AllowKeyRollover"},
ExpectedJSON: metaJSON,
},
{
Name: "RandomDirectoryEntry feature enabled, no explicit user-agent",
SetFeatures: []string{"RandomDirectoryEntry"},
RandomEntry: true,
},
{
Name: "RandomDirectoryEntry feature enabled, explicit old Let's Encrypt user-agent",
UserAgent: oldUA,
SetFeatures: []string{"RandomDirectoryEntry"},
RandomEntry: false,
},
}
for _, tc := range testCases {
// Each test case will set zero or more feature flags
for _, feature := range tc.SetFeatures {
_ = features.Set(map[string]bool{feature: true})
}
t.Run(tc.Name, func(t *testing.T) {
// NOTE: the req.URL will be modified and must be constructed per
// testcase or things will break and you will be confused and sad.
url, _ := url.Parse("/directory")
req := &http.Request{
Method: "GET",
URL: url,
Host: "127.0.0.1:4300",
}
// Set an explicit User-Agent header as directed by the test case
if tc.UserAgent != "" {
req.Header = map[string][]string{"User-Agent": []string{tc.UserAgent}}
}
// Serve the /directory response for this request into a recorder
responseWriter := httptest.NewRecorder()
mux.ServeHTTP(responseWriter, req)
// We expect all directory requests to return a json object with a good HTTP status
test.AssertEquals(t, responseWriter.Header().Get("Content-Type"), "application/json")
test.AssertEquals(t, responseWriter.Code, http.StatusOK)
// If the test case specifies exact JSON it expects, test that it matches
if tc.ExpectedJSON != "" {
test.AssertUnmarshaledEquals(t, responseWriter.Body.String(), tc.ExpectedJSON)
}
// Check if there is a random directory key present and if so, that it is
// expected to be present
test.AssertEquals(t,
randomDirectoryKeyPresent(t, responseWriter.Body.Bytes()),
tc.RandomEntry)
})
// Reset the feature flags between test cases to get a blank slate
features.Reset()
} }
// Serve the /directory response for this request into a recorder
responseWriter := httptest.NewRecorder()
mux.ServeHTTP(responseWriter, req)
// We expect all directory requests to return a json object with a good HTTP status
test.AssertEquals(t, responseWriter.Header().Get("Content-Type"), "application/json")
test.AssertEquals(t, responseWriter.Code, http.StatusOK)
test.AssertUnmarshaledEquals(t, responseWriter.Body.String(), metaJSON)
// Check if there is a random directory key present and if so, that it is
// expected to be present
test.AssertEquals(t,
randomDirectoryKeyPresent(t, responseWriter.Body.Bytes()),
true)
} }
func TestRelativeDirectory(t *testing.T) { func TestRelativeDirectory(t *testing.T) {
_ = features.Set(map[string]bool{"AllowKeyRollover": true})
defer features.Reset()
wfe, _ := setupWFE(t) wfe, _ := setupWFE(t)
mux := wfe.Handler() mux := wfe.Handler()
core.RandReader = fakeRand{}
defer func() { core.RandReader = rand.Reader }()
dirTests := []struct { dirTests := []struct {
host string host string
@ -781,15 +690,15 @@ func TestRelativeDirectory(t *testing.T) {
result string result string
}{ }{
// Test '' (No host header) with no proto header // Test '' (No host header) with no proto header
{"", "", `{"key-change":"http://localhost/acme/key-change","new-authz":"http://localhost/acme/new-authz","new-cert":"http://localhost/acme/new-cert","new-reg":"http://localhost/acme/new-reg","revoke-cert":"http://localhost/acme/revoke-cert"}`}, {"", "", `{"key-change":"http://localhost/acme/key-change","new-authz":"http://localhost/acme/new-authz","new-cert":"http://localhost/acme/new-cert","new-reg":"http://localhost/acme/new-reg","revoke-cert":"http://localhost/acme/revoke-cert","AAAAAAAAAAA":"https://community.letsencrypt.org/t/adding-random-entries-to-the-directory/33417","meta":{"terms-of-service": "http://example.invalid/terms"}}`},
// Test localhost:4300 with no proto header // Test localhost:4300 with no proto header
{"localhost:4300", "", `{"key-change":"http://localhost:4300/acme/key-change","new-authz":"http://localhost:4300/acme/new-authz","new-cert":"http://localhost:4300/acme/new-cert","new-reg":"http://localhost:4300/acme/new-reg","revoke-cert":"http://localhost:4300/acme/revoke-cert"}`}, {"localhost:4300", "", `{"key-change":"http://localhost:4300/acme/key-change","new-authz":"http://localhost:4300/acme/new-authz","new-cert":"http://localhost:4300/acme/new-cert","new-reg":"http://localhost:4300/acme/new-reg","revoke-cert":"http://localhost:4300/acme/revoke-cert","AAAAAAAAAAA":"https://community.letsencrypt.org/t/adding-random-entries-to-the-directory/33417","meta":{"terms-of-service": "http://example.invalid/terms"}}`},
// Test 127.0.0.1:4300 with no proto header // Test 127.0.0.1:4300 with no proto header
{"127.0.0.1:4300", "", `{"key-change":"http://127.0.0.1:4300/acme/key-change","new-authz":"http://127.0.0.1:4300/acme/new-authz","new-cert":"http://127.0.0.1:4300/acme/new-cert","new-reg":"http://127.0.0.1:4300/acme/new-reg","revoke-cert":"http://127.0.0.1:4300/acme/revoke-cert"}`}, {"127.0.0.1:4300", "", `{"key-change":"http://127.0.0.1:4300/acme/key-change","new-authz":"http://127.0.0.1:4300/acme/new-authz","new-cert":"http://127.0.0.1:4300/acme/new-cert","new-reg":"http://127.0.0.1:4300/acme/new-reg","revoke-cert":"http://127.0.0.1:4300/acme/revoke-cert","AAAAAAAAAAA":"https://community.letsencrypt.org/t/adding-random-entries-to-the-directory/33417","meta":{"terms-of-service": "http://example.invalid/terms"}}`},
// Test localhost:4300 with HTTP proto header // Test localhost:4300 with HTTP proto header
{"localhost:4300", "http", `{"key-change":"http://localhost:4300/acme/key-change","new-authz":"http://localhost:4300/acme/new-authz","new-cert":"http://localhost:4300/acme/new-cert","new-reg":"http://localhost:4300/acme/new-reg","revoke-cert":"http://localhost:4300/acme/revoke-cert"}`}, {"localhost:4300", "http", `{"key-change":"http://localhost:4300/acme/key-change","new-authz":"http://localhost:4300/acme/new-authz","new-cert":"http://localhost:4300/acme/new-cert","new-reg":"http://localhost:4300/acme/new-reg","revoke-cert":"http://localhost:4300/acme/revoke-cert","AAAAAAAAAAA":"https://community.letsencrypt.org/t/adding-random-entries-to-the-directory/33417","meta":{"terms-of-service": "http://example.invalid/terms"}}`},
// Test localhost:4300 with HTTPS proto header // Test localhost:4300 with HTTPS proto header
{"localhost:4300", "https", `{"key-change":"https://localhost:4300/acme/key-change","new-authz":"https://localhost:4300/acme/new-authz","new-cert":"https://localhost:4300/acme/new-cert","new-reg":"https://localhost:4300/acme/new-reg","revoke-cert":"https://localhost:4300/acme/revoke-cert"}`}, {"localhost:4300", "https", `{"key-change":"https://localhost:4300/acme/key-change","new-authz":"https://localhost:4300/acme/new-authz","new-cert":"https://localhost:4300/acme/new-cert","new-reg":"https://localhost:4300/acme/new-reg","revoke-cert":"https://localhost:4300/acme/revoke-cert","AAAAAAAAAAA":"https://community.letsencrypt.org/t/adding-random-entries-to-the-directory/33417","meta":{"terms-of-service": "http://example.invalid/terms"}}`},
} }
for _, tt := range dirTests { for _, tt := range dirTests {
@ -815,10 +724,6 @@ func TestRelativeDirectory(t *testing.T) {
} }
func TestHTTPMethods(t *testing.T) { func TestHTTPMethods(t *testing.T) {
// Always allow key rollover to test the rolloverPath
_ = features.Set(map[string]bool{"AllowKeyRollover": true})
defer features.Reset()
wfe, _ := setupWFE(t) wfe, _ := setupWFE(t)
mux := wfe.Handler() mux := wfe.Handler()
@ -1031,14 +936,6 @@ func TestIssueCertificate(t *testing.T) {
cert, err := core.LoadCert("test/not-an-example.com.crt") cert, err := core.LoadCert("test/not-an-example.com.crt")
test.AssertNotError(t, err, "Could not load cert") test.AssertNotError(t, err, "Could not load cert")
goodCertHeaders := map[string]string{
"Location": "http://localhost/acme/cert/0000ff0000000000000e4b4f67d86e818c46",
"Link": `<http://localhost/acme/issuer-cert>;rel="up"`,
"Content-Type": "application/pkix-cert",
}
// NOTE(@cpu): Unlike the test case above this case expects
// `localhost:4000` in the Link header value since the AIAIssuer flag
// will have been true. The WFE will also promote it from HTTP to HTTPS.
goodCertAIAHeaders := map[string]string{ goodCertAIAHeaders := map[string]string{
"Location": "http://localhost/acme/cert/0000ff0000000000000e4b4f67d86e818c46", "Location": "http://localhost/acme/cert/0000ff0000000000000e4b4f67d86e818c46",
"Link": `<https://localhost:4000/acme/issuer-cert>;rel="up"`, "Link": `<https://localhost:4000/acme/issuer-cert>;rel="up"`,
@ -1058,7 +955,6 @@ func TestIssueCertificate(t *testing.T) {
AssertCSRLogged bool AssertCSRLogged bool
ExpectedHeaders map[string]string ExpectedHeaders map[string]string
ExpectedLogParts []string ExpectedLogParts []string
UseAIAIssuer bool
}{ }{
{ {
Name: "POST, but no body", Name: "POST, but no body",
@ -1101,20 +997,11 @@ func TestIssueCertificate(t *testing.T) {
ExpectedProblem: `{"type":"urn:acme:error:unauthorized","detail":"Error creating new cert :: authorizations for these names not found or expired: meep.com","status":403}`, ExpectedProblem: `{"type":"urn:acme:error:unauthorized","detail":"Error creating new cert :: authorizations for these names not found or expired: meep.com","status":403}`,
AssertCSRLogged: true, AssertCSRLogged: true,
}, },
{
Name: "POST, properly signed JWS, authorizations for all names in CSR",
Request: signAndPost(t, targetPath, signedURL, goodCertCSRPayload, 1, wfe.nonceService),
ExpectedCert: string(cert.Raw),
AssertCSRLogged: true,
ExpectedHeaders: goodCertHeaders,
ExpectedLogParts: goodCertLogParts,
},
{ {
Name: "POST, properly signed JWS, authorizations for all names in CSR, using AIAIssuer", Name: "POST, properly signed JWS, authorizations for all names in CSR, using AIAIssuer",
Request: signAndPost(t, targetPath, signedURL, goodCertCSRPayload, 1, wfe.nonceService), Request: signAndPost(t, targetPath, signedURL, goodCertCSRPayload, 1, wfe.nonceService),
ExpectedCert: string(cert.Raw), ExpectedCert: string(cert.Raw),
AssertCSRLogged: true, AssertCSRLogged: true,
UseAIAIssuer: true,
ExpectedHeaders: goodCertAIAHeaders, ExpectedHeaders: goodCertAIAHeaders,
ExpectedLogParts: goodCertLogParts, ExpectedLogParts: goodCertLogParts,
}, },
@ -1128,10 +1015,6 @@ func TestIssueCertificate(t *testing.T) {
responseWriter.HeaderMap = http.Header{} responseWriter.HeaderMap = http.Header{}
mockLog.Clear() mockLog.Clear()
if tc.UseAIAIssuer {
_ = features.Set(map[string]bool{"UseAIAIssuerURL": true})
}
wfe.NewCertificate(ctx, newRequestEvent(), responseWriter, tc.Request) wfe.NewCertificate(ctx, newRequestEvent(), responseWriter, tc.Request)
if len(tc.ExpectedProblem) > 0 { if len(tc.ExpectedProblem) > 0 {
test.AssertUnmarshaledEquals(t, responseWriter.Body.String(), tc.ExpectedProblem) test.AssertUnmarshaledEquals(t, responseWriter.Body.String(), tc.ExpectedProblem)
@ -1155,7 +1038,6 @@ func TestIssueCertificate(t *testing.T) {
test.AssertContains(t, reqlogs[0], msg) test.AssertContains(t, reqlogs[0], msg)
} }
} }
features.Reset()
}) })
} }
} }
@ -1618,8 +1500,6 @@ func contains(s []string, e string) bool {
} }
func TestRegistration(t *testing.T) { func TestRegistration(t *testing.T) {
_ = features.Set(map[string]bool{"AllowKeyRollover": true})
defer features.Reset()
wfe, _ := setupWFE(t) wfe, _ := setupWFE(t)
mux := wfe.Handler() mux := wfe.Handler()
responseWriter := httptest.NewRecorder() responseWriter := httptest.NewRecorder()
@ -1768,26 +1648,13 @@ func TestGetCertificate(t *testing.T) {
ExpectedBody string ExpectedBody string
ExpectedCert []byte ExpectedCert []byte
}{ }{
{
Name: "Valid serial, cached",
Path: goodSerial,
ExpectedStatus: http.StatusOK,
ExpectedHeaders: map[string]string{
"Content-Type": pkixContent,
"Link": `<http://localhost/acme/issuer-cert>;rel="up"`,
},
ExpectedCert: certBlock.Bytes,
},
{ {
Name: "Valid serial, UseAIAIssuer feature enabled", Name: "Valid serial, UseAIAIssuer feature enabled",
Path: goodSerial, Path: goodSerial,
Features: []string{"UseAIAIssuerURL"},
ExpectedStatus: http.StatusOK, ExpectedStatus: http.StatusOK,
ExpectedHeaders: map[string]string{ ExpectedHeaders: map[string]string{
"Content-Type": pkixContent, "Content-Type": pkixContent,
// NOTE(@cpu): Unlike the test case above we expect the AIA Issuer "Link": `<https://localhost:4000/acme/issuer-cert>;rel="up"`,
// feature to result in a Link header value with the port included.
"Link": `<https://localhost:4000/acme/issuer-cert>;rel="up"`,
}, },
ExpectedCert: certBlock.Bytes, ExpectedCert: certBlock.Bytes,
}, },
@ -1813,9 +1680,6 @@ func TestGetCertificate(t *testing.T) {
for _, tc := range testCases { for _, tc := range testCases {
t.Run(tc.Name, func(t *testing.T) { t.Run(tc.Name, func(t *testing.T) {
for _, feature := range tc.Features {
_ = features.Set(map[string]bool{feature: true})
}
responseWriter := httptest.NewRecorder() responseWriter := httptest.NewRecorder()
mockLog := wfe.log.(*blog.Mock) mockLog := wfe.log.(*blog.Mock)
mockLog.Clear() mockLog.Clear()
@ -1856,9 +1720,6 @@ func TestGetCertificate(t *testing.T) {
test.AssertEquals(t, len(reqlogs), 1) test.AssertEquals(t, len(reqlogs), 1)
test.AssertContains(t, reqlogs[0], `INFO: `) test.AssertContains(t, reqlogs[0], `INFO: `)
} }
/// Reset any features that were set
features.Reset()
}) })
} }
} }
@ -2040,8 +1901,6 @@ func TestDeactivateAuthorization(t *testing.T) {
func TestDeactivateRegistration(t *testing.T) { func TestDeactivateRegistration(t *testing.T) {
responseWriter := httptest.NewRecorder() responseWriter := httptest.NewRecorder()
wfe, _ := setupWFE(t) wfe, _ := setupWFE(t)
_ = features.Set(map[string]bool{"AllowAccountDeactivation": true})
defer features.Reset()
responseWriter.Body.Reset() responseWriter.Body.Reset()
payload := `{"status":"asd"}` payload := `{"status":"asd"}`