wfe: remove authz-v3 and chall-v3 paths (#7904)
This removes the `handlerPath` parameter to various calls, which was used solely to distinguish the `-v3`-style paths from the `WithAccount` paths. Also, this removes `WithAccount` from all names that had it. The fact that these URLS include an account ID is now implicit.
This commit is contained in:
parent
d42865c187
commit
e8a49c5a02
116
wfe2/wfe.go
116
wfe2/wfe.go
|
@ -50,31 +50,24 @@ import (
|
|||
// lowercase plus hyphens. If you violate that assumption you should update
|
||||
// measured_http.
|
||||
const (
|
||||
directoryPath = "/directory"
|
||||
newAcctPath = "/acme/new-acct"
|
||||
acctPath = "/acme/acct/"
|
||||
// When we moved to authzv2, we used a "-v3" suffix to avoid confusion
|
||||
// regarding ACMEv2. More recently we moved back to using plain `/acme/authz/`
|
||||
// and `/acme/chall/`, so the `-v3` paths are deprecated.
|
||||
// TODO(#7683): Remove authz-v3 and chall-v3 once the new paths have been
|
||||
// the default in prod for 30 days.
|
||||
deprecatedAuthzPath = "/acme/authz-v3/"
|
||||
authzPathWithAcct = "/acme/authz/"
|
||||
deprecatedChallengePath = "/acme/chall-v3/"
|
||||
challengePathWithAcct = "/acme/chall/"
|
||||
certPath = "/acme/cert/"
|
||||
revokeCertPath = "/acme/revoke-cert"
|
||||
buildIDPath = "/build"
|
||||
rolloverPath = "/acme/key-change"
|
||||
newNoncePath = "/acme/new-nonce"
|
||||
newOrderPath = "/acme/new-order"
|
||||
orderPath = "/acme/order/"
|
||||
finalizeOrderPath = "/acme/finalize/"
|
||||
directoryPath = "/directory"
|
||||
newAcctPath = "/acme/new-acct"
|
||||
acctPath = "/acme/acct/"
|
||||
authzPath = "/acme/authz/"
|
||||
challengePath = "/acme/chall/"
|
||||
certPath = "/acme/cert/"
|
||||
revokeCertPath = "/acme/revoke-cert"
|
||||
buildIDPath = "/build"
|
||||
rolloverPath = "/acme/key-change"
|
||||
newNoncePath = "/acme/new-nonce"
|
||||
newOrderPath = "/acme/new-order"
|
||||
orderPath = "/acme/order/"
|
||||
finalizeOrderPath = "/acme/finalize/"
|
||||
|
||||
getAPIPrefix = "/get/"
|
||||
getOrderPath = getAPIPrefix + "order/"
|
||||
getAuthzPath = getAPIPrefix + "authz-v3/"
|
||||
getChallengePath = getAPIPrefix + "chall-v3/"
|
||||
getAuthzPath = getAPIPrefix + "authz/"
|
||||
getChallengePath = getAPIPrefix + "chall/"
|
||||
getCertPath = getAPIPrefix + "cert/"
|
||||
|
||||
// Draft or likely-to-change paths
|
||||
|
@ -435,15 +428,13 @@ func (wfe *WebFrontEndImpl) Handler(stats prometheus.Registerer, oTelHTTPOptions
|
|||
// TODO(@cpu): After November 1st, 2020 support for "GET" to the following
|
||||
// endpoints will be removed, leaving only POST-as-GET support.
|
||||
wfe.HandleFunc(m, orderPath, wfe.GetOrder, "GET", "POST")
|
||||
wfe.HandleFunc(m, deprecatedAuthzPath, wfe.DeprecatedAuthorizationHandler, "GET", "POST")
|
||||
wfe.HandleFunc(m, authzPathWithAcct, wfe.AuthorizationHandler, "GET", "POST")
|
||||
wfe.HandleFunc(m, deprecatedChallengePath, wfe.DeprecatedChallengeHandler, "GET", "POST")
|
||||
wfe.HandleFunc(m, challengePathWithAcct, wfe.ChallengeHandler, "GET", "POST")
|
||||
wfe.HandleFunc(m, authzPath, wfe.AuthorizationHandler, "GET", "POST")
|
||||
wfe.HandleFunc(m, challengePath, wfe.ChallengeHandler, "GET", "POST")
|
||||
wfe.HandleFunc(m, certPath, wfe.Certificate, "GET", "POST")
|
||||
// Boulder-specific GET-able resource endpoints
|
||||
wfe.HandleFunc(m, getOrderPath, wfe.GetOrder, "GET")
|
||||
wfe.HandleFunc(m, getAuthzPath, wfe.DeprecatedAuthorizationHandler, "GET")
|
||||
wfe.HandleFunc(m, getChallengePath, wfe.DeprecatedChallengeHandler, "GET")
|
||||
wfe.HandleFunc(m, getAuthzPath, wfe.AuthorizationHandler, "GET")
|
||||
wfe.HandleFunc(m, getChallengePath, wfe.ChallengeHandler, "GET")
|
||||
wfe.HandleFunc(m, getCertPath, wfe.Certificate, "GET")
|
||||
|
||||
// Endpoint for draft-ietf-acme-ari
|
||||
|
@ -1089,22 +1080,6 @@ func (wfe *WebFrontEndImpl) RevokeCertificate(
|
|||
response.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
// DeprecatedChallengeHandler handles POST requests to challenge URLs of the form /acme/chall-v3/<authorizationID>/<challengeID>.
|
||||
// Such requests are clients' responses to the server's challenges.
|
||||
func (wfe *WebFrontEndImpl) DeprecatedChallengeHandler(
|
||||
ctx context.Context,
|
||||
logEvent *web.RequestEvent,
|
||||
response http.ResponseWriter,
|
||||
request *http.Request) {
|
||||
slug := strings.Split(request.URL.Path, "/")
|
||||
if len(slug) != 2 {
|
||||
wfe.sendError(response, logEvent, probs.NotFound("No such challenge"), nil)
|
||||
return
|
||||
}
|
||||
|
||||
wfe.Challenge(ctx, logEvent, deprecatedChallengePath, response, request, slug[0], slug[1])
|
||||
}
|
||||
|
||||
// ChallengeHandler handles POST requests to challenge URLs of the form /acme/chall/{regID}/{authzID}/{challID}.
|
||||
func (wfe *WebFrontEndImpl) ChallengeHandler(
|
||||
ctx context.Context,
|
||||
|
@ -1117,14 +1092,13 @@ func (wfe *WebFrontEndImpl) ChallengeHandler(
|
|||
return
|
||||
}
|
||||
// TODO(#7683): the regID is currently ignored.
|
||||
wfe.Challenge(ctx, logEvent, challengePathWithAcct, response, request, slug[1], slug[2])
|
||||
wfe.Challenge(ctx, logEvent, response, request, slug[1], slug[2])
|
||||
}
|
||||
|
||||
// Challenge handles POSTS to both formats of challenge URLs.
|
||||
func (wfe *WebFrontEndImpl) Challenge(
|
||||
ctx context.Context,
|
||||
logEvent *web.RequestEvent,
|
||||
handlerPath string,
|
||||
response http.ResponseWriter,
|
||||
request *http.Request,
|
||||
authorizationIDStr string,
|
||||
|
@ -1182,11 +1156,11 @@ func (wfe *WebFrontEndImpl) Challenge(
|
|||
challenge := authz.Challenges[challengeIndex]
|
||||
switch request.Method {
|
||||
case "GET", "HEAD":
|
||||
wfe.getChallenge(handlerPath, response, request, authz, &challenge, logEvent)
|
||||
wfe.getChallenge(response, request, authz, &challenge, logEvent)
|
||||
|
||||
case "POST":
|
||||
logEvent.ChallengeType = string(challenge.Type)
|
||||
wfe.postChallenge(ctx, handlerPath, response, request, authz, challengeIndex, logEvent)
|
||||
wfe.postChallenge(ctx, response, request, authz, challengeIndex, logEvent)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1212,16 +1186,12 @@ func prepAccountForDisplay(acct *core.Registration) {
|
|||
// the client by filling in its URL field and clearing several unnecessary
|
||||
// fields.
|
||||
func (wfe *WebFrontEndImpl) prepChallengeForDisplay(
|
||||
handlerPath string,
|
||||
request *http.Request,
|
||||
authz core.Authorization,
|
||||
challenge *core.Challenge,
|
||||
) {
|
||||
// Update the challenge URL to be relative to the HTTP request Host
|
||||
challenge.URL = web.RelativeEndpoint(request, fmt.Sprintf("%s%s/%s", deprecatedChallengePath, authz.ID, challenge.StringID()))
|
||||
if handlerPath == challengePathWithAcct || handlerPath == authzPathWithAcct {
|
||||
challenge.URL = web.RelativeEndpoint(request, fmt.Sprintf("%s%d/%s/%s", challengePathWithAcct, authz.RegistrationID, authz.ID, challenge.StringID()))
|
||||
}
|
||||
challenge.URL = web.RelativeEndpoint(request, fmt.Sprintf("%s%d/%s/%s", challengePath, authz.RegistrationID, authz.ID, challenge.StringID()))
|
||||
|
||||
// Internally, we store challenge error problems with just the short form
|
||||
// (e.g. "CAA") of the problem type. But for external display, we need to
|
||||
|
@ -1244,9 +1214,9 @@ func (wfe *WebFrontEndImpl) prepChallengeForDisplay(
|
|||
|
||||
// prepAuthorizationForDisplay takes a core.Authorization and prepares it for
|
||||
// display to the client by preparing all its challenges.
|
||||
func (wfe *WebFrontEndImpl) prepAuthorizationForDisplay(handlerPath string, request *http.Request, authz *core.Authorization) {
|
||||
func (wfe *WebFrontEndImpl) prepAuthorizationForDisplay(request *http.Request, authz *core.Authorization) {
|
||||
for i := range authz.Challenges {
|
||||
wfe.prepChallengeForDisplay(handlerPath, request, *authz, &authz.Challenges[i])
|
||||
wfe.prepChallengeForDisplay(request, *authz, &authz.Challenges[i])
|
||||
}
|
||||
|
||||
// Shuffle the challenges so no one relies on their order.
|
||||
|
@ -1268,15 +1238,14 @@ func (wfe *WebFrontEndImpl) prepAuthorizationForDisplay(handlerPath string, requ
|
|||
}
|
||||
|
||||
func (wfe *WebFrontEndImpl) getChallenge(
|
||||
handlerPath string,
|
||||
response http.ResponseWriter,
|
||||
request *http.Request,
|
||||
authz core.Authorization,
|
||||
challenge *core.Challenge,
|
||||
logEvent *web.RequestEvent) {
|
||||
wfe.prepChallengeForDisplay(handlerPath, request, authz, challenge)
|
||||
wfe.prepChallengeForDisplay(request, authz, challenge)
|
||||
|
||||
authzURL := urlForAuthz(handlerPath, authz, request)
|
||||
authzURL := urlForAuthz(authz, request)
|
||||
response.Header().Add("Location", challenge.URL)
|
||||
response.Header().Add("Link", link(authzURL, "up"))
|
||||
|
||||
|
@ -1291,7 +1260,6 @@ func (wfe *WebFrontEndImpl) getChallenge(
|
|||
|
||||
func (wfe *WebFrontEndImpl) postChallenge(
|
||||
ctx context.Context,
|
||||
handlerPath string,
|
||||
response http.ResponseWriter,
|
||||
request *http.Request,
|
||||
authz core.Authorization,
|
||||
|
@ -1320,7 +1288,7 @@ func (wfe *WebFrontEndImpl) postChallenge(
|
|||
// challenge details, not a POST to initiate a challenge
|
||||
if string(body) == "" {
|
||||
challenge := authz.Challenges[challengeIndex]
|
||||
wfe.getChallenge(handlerPath, response, request, authz, &challenge, logEvent)
|
||||
wfe.getChallenge(response, request, authz, &challenge, logEvent)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -1370,9 +1338,9 @@ func (wfe *WebFrontEndImpl) postChallenge(
|
|||
|
||||
// assumption: PerformValidation does not modify order of challenges
|
||||
challenge := returnAuthz.Challenges[challengeIndex]
|
||||
wfe.prepChallengeForDisplay(handlerPath, request, authz, &challenge)
|
||||
wfe.prepChallengeForDisplay(request, authz, &challenge)
|
||||
|
||||
authzURL := urlForAuthz(handlerPath, authz, request)
|
||||
authzURL := urlForAuthz(authz, request)
|
||||
response.Header().Add("Location", challenge.URL)
|
||||
response.Header().Add("Link", link(authzURL, "up"))
|
||||
|
||||
|
@ -1538,15 +1506,6 @@ func (wfe *WebFrontEndImpl) deactivateAuthorization(
|
|||
return true
|
||||
}
|
||||
|
||||
// DeprecatedAuthorizationHandler handles requests to authorization URLs of the form /acme/authz/{authzID}.
|
||||
func (wfe *WebFrontEndImpl) DeprecatedAuthorizationHandler(
|
||||
ctx context.Context,
|
||||
logEvent *web.RequestEvent,
|
||||
response http.ResponseWriter,
|
||||
request *http.Request) {
|
||||
wfe.Authorization(ctx, deprecatedAuthzPath, logEvent, response, request, request.URL.Path)
|
||||
}
|
||||
|
||||
// AuthorizationHandler handles requests to authorization URLs of the form /acme/authz/{regID}/{authzID}.
|
||||
func (wfe *WebFrontEndImpl) AuthorizationHandler(
|
||||
ctx context.Context,
|
||||
|
@ -1559,14 +1518,13 @@ func (wfe *WebFrontEndImpl) AuthorizationHandler(
|
|||
return
|
||||
}
|
||||
// TODO(#7683): The regID is currently ignored.
|
||||
wfe.Authorization(ctx, authzPathWithAcct, logEvent, response, request, slug[1])
|
||||
wfe.Authorization(ctx, logEvent, response, request, slug[1])
|
||||
}
|
||||
|
||||
// Authorization handles both `/acme/authz/{authzID}` and `/acme/authz/{regID}/{authzID}` requests,
|
||||
// after the calling function has parsed out the authzID.
|
||||
func (wfe *WebFrontEndImpl) Authorization(
|
||||
ctx context.Context,
|
||||
handlerPath string,
|
||||
logEvent *web.RequestEvent,
|
||||
response http.ResponseWriter,
|
||||
request *http.Request,
|
||||
|
@ -1657,7 +1615,7 @@ func (wfe *WebFrontEndImpl) Authorization(
|
|||
return
|
||||
}
|
||||
|
||||
wfe.prepAuthorizationForDisplay(handlerPath, request, &authz)
|
||||
wfe.prepAuthorizationForDisplay(request, &authz)
|
||||
|
||||
err = wfe.writeJsonResponse(response, logEvent, http.StatusOK, authz)
|
||||
if err != nil {
|
||||
|
@ -2050,7 +2008,7 @@ func (wfe *WebFrontEndImpl) orderToOrderJSON(request *http.Request, order *corep
|
|||
respObj.Error.Type = probs.ErrorNS + respObj.Error.Type
|
||||
}
|
||||
for _, v2ID := range order.V2Authorizations {
|
||||
respObj.Authorizations = append(respObj.Authorizations, web.RelativeEndpoint(request, fmt.Sprintf("%s%d/%d", authzPathWithAcct, order.RegistrationID, v2ID)))
|
||||
respObj.Authorizations = append(respObj.Authorizations, web.RelativeEndpoint(request, fmt.Sprintf("%s%d/%d", authzPath, order.RegistrationID, v2ID)))
|
||||
}
|
||||
if respObj.Status == core.StatusValid {
|
||||
certURL := web.RelativeEndpoint(request,
|
||||
|
@ -2766,10 +2724,6 @@ func extractRequesterIP(req *http.Request) (net.IP, error) {
|
|||
return net.ParseIP(host), nil
|
||||
}
|
||||
|
||||
func urlForAuthz(handlerPath string, authz core.Authorization, request *http.Request) string {
|
||||
if handlerPath == challengePathWithAcct || handlerPath == authzPathWithAcct {
|
||||
return web.RelativeEndpoint(request, fmt.Sprintf("%s%d/%s", authzPathWithAcct, authz.RegistrationID, authz.ID))
|
||||
}
|
||||
|
||||
return web.RelativeEndpoint(request, deprecatedAuthzPath+authz.ID)
|
||||
func urlForAuthz(authz core.Authorization, request *http.Request) string {
|
||||
return web.RelativeEndpoint(request, fmt.Sprintf("%s%d/%s", authzPath, authz.RegistrationID, authz.ID))
|
||||
}
|
||||
|
|
406
wfe2/wfe_test.go
406
wfe2/wfe_test.go
|
@ -1041,13 +1041,13 @@ func TestHTTPMethods(t *testing.T) {
|
|||
// TODO(@cpu): Remove GET authz support, support only POST-as-GET
|
||||
{
|
||||
Name: "Authz path should be GET or POST only",
|
||||
Path: deprecatedAuthzPath,
|
||||
Path: authzPath,
|
||||
Allowed: getOrPost,
|
||||
},
|
||||
// TODO(@cpu): Remove GET challenge support, support only POST-as-GET
|
||||
{
|
||||
Name: "Challenge path should be GET or POST only",
|
||||
Path: deprecatedChallengePath,
|
||||
Path: challengePath,
|
||||
Allowed: getOrPost,
|
||||
},
|
||||
// TODO(@cpu): Remove GET certificate support, support only POST-as-GET
|
||||
|
@ -1146,40 +1146,6 @@ func TestGetChallengeHandler(t *testing.T) {
|
|||
// token "token".
|
||||
challSlug := "7TyhFQ"
|
||||
|
||||
for _, method := range []string{"GET", "HEAD"} {
|
||||
resp := httptest.NewRecorder()
|
||||
|
||||
// We set req.URL.Path separately to emulate the path-stripping that
|
||||
// Boulder's request handler does.
|
||||
challengeURL := fmt.Sprintf("http://localhost/acme/chall-v3/1/%s", challSlug)
|
||||
req, err := http.NewRequest(method, challengeURL, nil)
|
||||
test.AssertNotError(t, err, "Could not make NewRequest")
|
||||
req.URL.Path = fmt.Sprintf("1/%s", challSlug)
|
||||
|
||||
wfe.DeprecatedChallengeHandler(ctx, newRequestEvent(), resp, req)
|
||||
test.AssertEquals(t, resp.Code, http.StatusOK)
|
||||
test.AssertEquals(t, resp.Header().Get("Location"), challengeURL)
|
||||
test.AssertEquals(t, resp.Header().Get("Content-Type"), "application/json")
|
||||
test.AssertEquals(t, resp.Header().Get("Link"), `<http://localhost/acme/authz-v3/1>;rel="up"`)
|
||||
|
||||
// Body is only relevant for GET. For HEAD, body will
|
||||
// be discarded by HandleFunc() anyway, so it doesn't
|
||||
// matter what Challenge() writes to it.
|
||||
if method == "GET" {
|
||||
test.AssertUnmarshaledEquals(
|
||||
t, resp.Body.String(),
|
||||
`{"status": "valid", "type":"http-01","token":"token","url":"http://localhost/acme/chall-v3/1/7TyhFQ"}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetChallengeHandlerWithAccount(t *testing.T) {
|
||||
wfe, _, _ := setupWFE(t)
|
||||
|
||||
// The slug "7TyhFQ" is the StringID of a challenge with type "http-01" and
|
||||
// token "token".
|
||||
challSlug := "7TyhFQ"
|
||||
|
||||
for _, method := range []string{"GET", "HEAD"} {
|
||||
resp := httptest.NewRecorder()
|
||||
|
||||
|
@ -1220,85 +1186,6 @@ func TestChallengeHandler(t *testing.T) {
|
|||
return makePostRequestWithPath(path, jwsBody)
|
||||
}
|
||||
|
||||
testCases := []struct {
|
||||
Name string
|
||||
Request *http.Request
|
||||
ExpectedStatus int
|
||||
ExpectedHeaders map[string]string
|
||||
ExpectedBody string
|
||||
}{
|
||||
{
|
||||
Name: "Valid challenge",
|
||||
Request: post("1/7TyhFQ"),
|
||||
ExpectedStatus: http.StatusOK,
|
||||
ExpectedHeaders: map[string]string{
|
||||
"Content-Type": "application/json",
|
||||
"Location": "http://localhost/acme/chall-v3/1/7TyhFQ",
|
||||
"Link": `<http://localhost/acme/authz-v3/1>;rel="up"`,
|
||||
},
|
||||
ExpectedBody: `{"status": "valid", "type":"http-01","token":"token","url":"http://localhost/acme/chall-v3/1/7TyhFQ"}`,
|
||||
},
|
||||
{
|
||||
Name: "Expired challenge",
|
||||
Request: post("3/7TyhFQ"),
|
||||
ExpectedStatus: http.StatusNotFound,
|
||||
ExpectedBody: `{"type":"` + probs.ErrorNS + `malformed","detail":"Expired authorization","status":404}`,
|
||||
},
|
||||
{
|
||||
Name: "Missing challenge",
|
||||
Request: post("1/"),
|
||||
ExpectedStatus: http.StatusNotFound,
|
||||
ExpectedBody: `{"type":"` + probs.ErrorNS + `malformed","detail":"No such challenge","status":404}`,
|
||||
},
|
||||
{
|
||||
Name: "Unspecified database error",
|
||||
Request: post("4/7TyhFQ"),
|
||||
ExpectedStatus: http.StatusInternalServerError,
|
||||
ExpectedBody: `{"type":"` + probs.ErrorNS + `serverInternal","detail":"Problem getting authorization","status":500}`,
|
||||
},
|
||||
{
|
||||
Name: "POST-as-GET, wrong owner",
|
||||
Request: postAsGet(1, "5/7TyhFQ", ""),
|
||||
ExpectedStatus: http.StatusForbidden,
|
||||
ExpectedBody: `{"type":"` + probs.ErrorNS + `unauthorized","detail":"User account ID doesn't match account ID in authorization","status":403}`,
|
||||
},
|
||||
{
|
||||
Name: "Valid POST-as-GET",
|
||||
Request: postAsGet(1, "1/7TyhFQ", ""),
|
||||
ExpectedStatus: http.StatusOK,
|
||||
ExpectedBody: `{"status": "valid", "type":"http-01", "token":"token", "url": "http://localhost/acme/chall-v3/1/7TyhFQ"}`,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.Name, func(t *testing.T) {
|
||||
responseWriter := httptest.NewRecorder()
|
||||
wfe.DeprecatedChallengeHandler(ctx, newRequestEvent(), responseWriter, tc.Request)
|
||||
// Check the response code, headers and body match expected
|
||||
headers := responseWriter.Header()
|
||||
body := responseWriter.Body.String()
|
||||
test.AssertEquals(t, responseWriter.Code, tc.ExpectedStatus)
|
||||
for h, v := range tc.ExpectedHeaders {
|
||||
test.AssertEquals(t, headers.Get(h), v)
|
||||
}
|
||||
test.AssertUnmarshaledEquals(t, body, tc.ExpectedBody)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestChallengeHandlerWithAccount(t *testing.T) {
|
||||
wfe, _, signer := setupWFE(t)
|
||||
|
||||
post := func(path string) *http.Request {
|
||||
signedURL := fmt.Sprintf("http://localhost/%s", path)
|
||||
_, _, jwsBody := signer.byKeyID(1, nil, signedURL, `{}`)
|
||||
return makePostRequestWithPath(path, jwsBody)
|
||||
}
|
||||
postAsGet := func(keyID int64, path, body string) *http.Request {
|
||||
_, _, jwsBody := signer.byKeyID(keyID, nil, fmt.Sprintf("http://localhost/%s", path), body)
|
||||
return makePostRequestWithPath(path, jwsBody)
|
||||
}
|
||||
|
||||
testCases := []struct {
|
||||
Name string
|
||||
Request *http.Request
|
||||
|
@ -1383,28 +1270,6 @@ func TestUpdateChallengeHandlerFinalizedAuthz(t *testing.T) {
|
|||
wfe.ra = &MockRAPerformValidationError{MockRegistrationAuthority{clk: fc}}
|
||||
responseWriter := httptest.NewRecorder()
|
||||
|
||||
signedURL := "http://localhost/1/7TyhFQ"
|
||||
_, _, jwsBody := signer.byKeyID(1, nil, signedURL, `{}`)
|
||||
request := makePostRequestWithPath("1/7TyhFQ", jwsBody)
|
||||
wfe.DeprecatedChallengeHandler(ctx, newRequestEvent(), responseWriter, request)
|
||||
|
||||
body := responseWriter.Body.String()
|
||||
test.AssertUnmarshaledEquals(t, body, `{
|
||||
"status": "valid",
|
||||
"type": "http-01",
|
||||
"token": "token",
|
||||
"url": "http://localhost/acme/chall-v3/1/7TyhFQ"
|
||||
}`)
|
||||
}
|
||||
|
||||
// TestUpdateChallengeHandlerWithAccountFinalizedAuthz tests that POSTing a challenge associated
|
||||
// with an already valid authorization just returns the challenge without calling
|
||||
// the RA.
|
||||
func TestUpdateChallengeHandlerWithAccountFinalizedAuthz(t *testing.T) {
|
||||
wfe, fc, signer := setupWFE(t)
|
||||
wfe.ra = &MockRAPerformValidationError{MockRegistrationAuthority{clk: fc}}
|
||||
responseWriter := httptest.NewRecorder()
|
||||
|
||||
signedURL := "http://localhost/1/1/7TyhFQ"
|
||||
_, _, jwsBody := signer.byKeyID(1, nil, signedURL, `{}`)
|
||||
request := makePostRequestWithPath("1/1/7TyhFQ", jwsBody)
|
||||
|
@ -1427,31 +1292,6 @@ func TestUpdateChallengeHandlerRAError(t *testing.T) {
|
|||
// Mock the RA to always fail PerformValidation
|
||||
wfe.ra = &MockRAPerformValidationError{MockRegistrationAuthority{clk: fc}}
|
||||
|
||||
// Update a pending challenge
|
||||
signedURL := "http://localhost/2/7TyhFQ"
|
||||
_, _, jwsBody := signer.byKeyID(1, nil, signedURL, `{}`)
|
||||
responseWriter := httptest.NewRecorder()
|
||||
request := makePostRequestWithPath("2/7TyhFQ", jwsBody)
|
||||
|
||||
wfe.DeprecatedChallengeHandler(ctx, newRequestEvent(), responseWriter, request)
|
||||
|
||||
// The result should be an internal server error problem.
|
||||
body := responseWriter.Body.String()
|
||||
test.AssertUnmarshaledEquals(t, body, `{
|
||||
"type": "urn:ietf:params:acme:error:serverInternal",
|
||||
"detail": "Unable to update challenge",
|
||||
"status": 500
|
||||
}`)
|
||||
}
|
||||
|
||||
// TestUpdateChallengeHandlerWithAccountRAError tests that when the RA returns an error from
|
||||
// PerformValidation that the WFE returns an internal server error as expected
|
||||
// and does not panic or otherwise bug out.
|
||||
func TestUpdateChallengeHandlerWithAccountRAError(t *testing.T) {
|
||||
wfe, fc, signer := setupWFE(t)
|
||||
// Mock the RA to always fail PerformValidation
|
||||
wfe.ra = &MockRAPerformValidationError{MockRegistrationAuthority{clk: fc}}
|
||||
|
||||
// Update a pending challenge
|
||||
signedURL := "http://localhost/1/2/7TyhFQ"
|
||||
_, _, jwsBody := signer.byKeyID(1, nil, signedURL, `{}`)
|
||||
|
@ -1807,56 +1647,6 @@ func TestNewAccountNoID(t *testing.T) {
|
|||
func TestGetAuthorizationHandler(t *testing.T) {
|
||||
wfe, _, signer := setupWFE(t)
|
||||
|
||||
// Expired authorizations should be inaccessible
|
||||
authzURL := "3"
|
||||
responseWriter := httptest.NewRecorder()
|
||||
wfe.DeprecatedAuthorizationHandler(ctx, newRequestEvent(), responseWriter, &http.Request{
|
||||
Method: "GET",
|
||||
URL: mustParseURL(authzURL),
|
||||
})
|
||||
test.AssertEquals(t, responseWriter.Code, http.StatusNotFound)
|
||||
test.AssertUnmarshaledEquals(t, responseWriter.Body.String(),
|
||||
`{"type":"`+probs.ErrorNS+`malformed","detail":"Expired authorization","status":404}`)
|
||||
responseWriter.Body.Reset()
|
||||
|
||||
// Ensure that a valid authorization can't be reached with an invalid URL
|
||||
wfe.DeprecatedAuthorizationHandler(ctx, newRequestEvent(), responseWriter, &http.Request{
|
||||
URL: mustParseURL("1d"),
|
||||
Method: "GET",
|
||||
})
|
||||
test.AssertUnmarshaledEquals(t, responseWriter.Body.String(),
|
||||
`{"type":"`+probs.ErrorNS+`malformed","detail":"Invalid authorization ID","status":400}`)
|
||||
|
||||
_, _, jwsBody := signer.byKeyID(1, nil, "http://localhost/1", "")
|
||||
postAsGet := makePostRequestWithPath("1", jwsBody)
|
||||
|
||||
responseWriter = httptest.NewRecorder()
|
||||
// Ensure that a POST-as-GET to an authorization works
|
||||
wfe.DeprecatedAuthorizationHandler(ctx, newRequestEvent(), responseWriter, postAsGet)
|
||||
test.AssertEquals(t, responseWriter.Code, http.StatusOK)
|
||||
body := responseWriter.Body.String()
|
||||
test.AssertUnmarshaledEquals(t, body, `
|
||||
{
|
||||
"identifier": {
|
||||
"type": "dns",
|
||||
"value": "not-an-example.com"
|
||||
},
|
||||
"status": "valid",
|
||||
"expires": "2070-01-01T00:00:00Z",
|
||||
"challenges": [
|
||||
{
|
||||
"status": "valid",
|
||||
"type": "http-01",
|
||||
"token":"token",
|
||||
"url": "http://localhost/acme/chall-v3/1/7TyhFQ"
|
||||
}
|
||||
]
|
||||
}`)
|
||||
}
|
||||
|
||||
func TestGetAuthorizationHandlerWithAccount(t *testing.T) {
|
||||
wfe, _, signer := setupWFE(t)
|
||||
|
||||
// Expired authorizations should be inaccessible
|
||||
authzURL := "1/3"
|
||||
responseWriter := httptest.NewRecorder()
|
||||
|
@ -1909,24 +1699,6 @@ func TestGetAuthorizationHandlerWithAccount(t *testing.T) {
|
|||
func TestAuthorizationHandler500(t *testing.T) {
|
||||
wfe, _, _ := setupWFE(t)
|
||||
|
||||
responseWriter := httptest.NewRecorder()
|
||||
wfe.DeprecatedAuthorizationHandler(ctx, newRequestEvent(), responseWriter, &http.Request{
|
||||
Method: "GET",
|
||||
URL: mustParseURL("4"),
|
||||
})
|
||||
expected := `{
|
||||
"type": "urn:ietf:params:acme:error:serverInternal",
|
||||
"detail": "Problem getting authorization",
|
||||
"status": 500
|
||||
}`
|
||||
test.AssertUnmarshaledEquals(t, responseWriter.Body.String(), expected)
|
||||
}
|
||||
|
||||
// TestAuthorizationHandlerWithAccount500 tests that internal errors on GetAuthorization result in
|
||||
// a 500.
|
||||
func TestAuthorizationHandlerWithAccount500(t *testing.T) {
|
||||
wfe, _, _ := setupWFE(t)
|
||||
|
||||
responseWriter := httptest.NewRecorder()
|
||||
wfe.AuthorizationHandler(ctx, newRequestEvent(), responseWriter, &http.Request{
|
||||
Method: "GET",
|
||||
|
@ -1977,30 +1749,9 @@ func TestAuthorizationChallengeHandlerNamespace(t *testing.T) {
|
|||
wfe.ra = &RAWithFailedChallenge{clk: clk}
|
||||
|
||||
responseWriter := httptest.NewRecorder()
|
||||
wfe.DeprecatedAuthorizationHandler(ctx, newRequestEvent(), responseWriter, &http.Request{
|
||||
wfe.AuthorizationHandler(ctx, newRequestEvent(), responseWriter, &http.Request{
|
||||
Method: "GET",
|
||||
URL: mustParseURL("6"),
|
||||
})
|
||||
|
||||
var authz core.Authorization
|
||||
err := json.Unmarshal(responseWriter.Body.Bytes(), &authz)
|
||||
test.AssertNotError(t, err, "Couldn't unmarshal returned authorization object")
|
||||
test.AssertEquals(t, len(authz.Challenges), 1)
|
||||
// The Challenge Error Type should have had the probs.ErrorNS prefix added
|
||||
test.AssertEquals(t, string(authz.Challenges[0].Error.Type), probs.ErrorNS+"things:are:whack")
|
||||
responseWriter.Body.Reset()
|
||||
}
|
||||
|
||||
// TestAuthorizationChallengeHandlerWithAccountNamespace tests that the runtime prefixing of
|
||||
// Challenge Problem Types works as expected
|
||||
func TestAuthorizationChallengeHandlerWithAccountNamespace(t *testing.T) {
|
||||
wfe, clk, _ := setupWFE(t)
|
||||
wfe.ra = &RAWithFailedChallenge{clk: clk}
|
||||
|
||||
responseWriter := httptest.NewRecorder()
|
||||
wfe.DeprecatedAuthorizationHandler(ctx, newRequestEvent(), responseWriter, &http.Request{
|
||||
Method: "GET",
|
||||
URL: mustParseURL("6"),
|
||||
URL: mustParseURL("1/6"),
|
||||
})
|
||||
|
||||
var authz core.Authorization
|
||||
|
@ -2652,20 +2403,20 @@ func TestDeactivateAuthorizationHandler(t *testing.T) {
|
|||
responseWriter.Body.Reset()
|
||||
|
||||
payload := `{"status":""}`
|
||||
_, _, body := signer.byKeyID(1, nil, "http://localhost/1", payload)
|
||||
request := makePostRequestWithPath("1", body)
|
||||
_, _, body := signer.byKeyID(1, nil, "http://localhost/1/1", payload)
|
||||
request := makePostRequestWithPath("1/1", body)
|
||||
|
||||
wfe.DeprecatedAuthorizationHandler(ctx, newRequestEvent(), responseWriter, request)
|
||||
wfe.AuthorizationHandler(ctx, newRequestEvent(), responseWriter, request)
|
||||
test.AssertUnmarshaledEquals(t,
|
||||
responseWriter.Body.String(),
|
||||
`{"type": "`+probs.ErrorNS+`malformed","detail": "Invalid status value","status": 400}`)
|
||||
|
||||
responseWriter.Body.Reset()
|
||||
payload = `{"status":"deactivated"}`
|
||||
_, _, body = signer.byKeyID(1, nil, "http://localhost/1", payload)
|
||||
request = makePostRequestWithPath("1", body)
|
||||
_, _, body = signer.byKeyID(1, nil, "http://localhost/1/1", payload)
|
||||
request = makePostRequestWithPath("1/1", body)
|
||||
|
||||
wfe.DeprecatedAuthorizationHandler(ctx, newRequestEvent(), responseWriter, request)
|
||||
wfe.AuthorizationHandler(ctx, newRequestEvent(), responseWriter, request)
|
||||
test.AssertUnmarshaledEquals(t,
|
||||
responseWriter.Body.String(),
|
||||
`{
|
||||
|
@ -2680,48 +2431,7 @@ func TestDeactivateAuthorizationHandler(t *testing.T) {
|
|||
"status": "valid",
|
||||
"type": "http-01",
|
||||
"token": "token",
|
||||
"url": "http://localhost/acme/chall-v3/1/7TyhFQ"
|
||||
}
|
||||
]
|
||||
}`)
|
||||
}
|
||||
|
||||
func TestDeactivateAuthorizationHandlerWithAccount(t *testing.T) {
|
||||
wfe, _, signer := setupWFE(t)
|
||||
responseWriter := httptest.NewRecorder()
|
||||
|
||||
responseWriter.Body.Reset()
|
||||
|
||||
payload := `{"status":""}`
|
||||
_, _, body := signer.byKeyID(1, nil, "http://localhost/1", payload)
|
||||
request := makePostRequestWithPath("1", body)
|
||||
|
||||
wfe.DeprecatedAuthorizationHandler(ctx, newRequestEvent(), responseWriter, request)
|
||||
test.AssertUnmarshaledEquals(t,
|
||||
responseWriter.Body.String(),
|
||||
`{"type": "`+probs.ErrorNS+`malformed","detail": "Invalid status value","status": 400}`)
|
||||
|
||||
responseWriter.Body.Reset()
|
||||
payload = `{"status":"deactivated"}`
|
||||
_, _, body = signer.byKeyID(1, nil, "http://localhost/1", payload)
|
||||
request = makePostRequestWithPath("1", body)
|
||||
|
||||
wfe.DeprecatedAuthorizationHandler(ctx, newRequestEvent(), responseWriter, request)
|
||||
test.AssertUnmarshaledEquals(t,
|
||||
responseWriter.Body.String(),
|
||||
`{
|
||||
"identifier": {
|
||||
"type": "dns",
|
||||
"value": "not-an-example.com"
|
||||
},
|
||||
"status": "deactivated",
|
||||
"expires": "2070-01-01T00:00:00Z",
|
||||
"challenges": [
|
||||
{
|
||||
"status": "valid",
|
||||
"type": "http-01",
|
||||
"token": "token",
|
||||
"url": "http://localhost/acme/chall-v3/1/7TyhFQ"
|
||||
"url": "http://localhost/acme/chall/1/1/7TyhFQ"
|
||||
}
|
||||
]
|
||||
}`)
|
||||
|
@ -3681,33 +3391,7 @@ func TestPrepAuthzForDisplay(t *testing.T) {
|
|||
}
|
||||
|
||||
// This modifies the authz in-place.
|
||||
wfe.prepAuthorizationForDisplay(deprecatedAuthzPath, &http.Request{Host: "localhost"}, authz)
|
||||
|
||||
// Ensure ID and RegID are omitted.
|
||||
authzJSON, err := json.Marshal(authz)
|
||||
test.AssertNotError(t, err, "Failed to marshal authz")
|
||||
test.AssertNotContains(t, string(authzJSON), "\"id\":\"12345\"")
|
||||
test.AssertNotContains(t, string(authzJSON), "\"registrationID\":\"1\"")
|
||||
}
|
||||
|
||||
func TestPrepAuthzWithAccountForDisplay(t *testing.T) {
|
||||
t.Parallel()
|
||||
wfe, _, _ := setupWFE(t)
|
||||
|
||||
authz := &core.Authorization{
|
||||
ID: "12345",
|
||||
Status: core.StatusPending,
|
||||
RegistrationID: 1,
|
||||
Identifier: identifier.NewDNS("example.com"),
|
||||
Challenges: []core.Challenge{
|
||||
{Type: core.ChallengeTypeDNS01, Status: core.StatusPending, Token: "token"},
|
||||
{Type: core.ChallengeTypeHTTP01, Status: core.StatusPending, Token: "token"},
|
||||
{Type: core.ChallengeTypeTLSALPN01, Status: core.StatusPending, Token: "token"},
|
||||
},
|
||||
}
|
||||
|
||||
// This modifies the authz in-place.
|
||||
wfe.prepAuthorizationForDisplay(authzPathWithAcct, &http.Request{Host: "localhost"}, authz)
|
||||
wfe.prepAuthorizationForDisplay(&http.Request{Host: "localhost"}, authz)
|
||||
|
||||
// Ensure ID and RegID are omitted.
|
||||
authzJSON, err := json.Marshal(authz)
|
||||
|
@ -3733,32 +3417,7 @@ func TestPrepRevokedAuthzForDisplay(t *testing.T) {
|
|||
}
|
||||
|
||||
// This modifies the authz in-place.
|
||||
wfe.prepAuthorizationForDisplay(deprecatedAuthzPath, &http.Request{Host: "localhost"}, authz)
|
||||
|
||||
// All of the challenges should be revoked as well.
|
||||
for _, chall := range authz.Challenges {
|
||||
test.AssertEquals(t, chall.Status, core.StatusInvalid)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPrepRevokedAuthzWithAccountForDisplay(t *testing.T) {
|
||||
t.Parallel()
|
||||
wfe, _, _ := setupWFE(t)
|
||||
|
||||
authz := &core.Authorization{
|
||||
ID: "12345",
|
||||
Status: core.StatusInvalid,
|
||||
RegistrationID: 1,
|
||||
Identifier: identifier.NewDNS("example.com"),
|
||||
Challenges: []core.Challenge{
|
||||
{Type: core.ChallengeTypeDNS01, Status: core.StatusPending, Token: "token"},
|
||||
{Type: core.ChallengeTypeHTTP01, Status: core.StatusPending, Token: "token"},
|
||||
{Type: core.ChallengeTypeTLSALPN01, Status: core.StatusPending, Token: "token"},
|
||||
},
|
||||
}
|
||||
|
||||
// This modifies the authz in-place.
|
||||
wfe.prepAuthorizationForDisplay(authzPathWithAcct, &http.Request{Host: "localhost"}, authz)
|
||||
wfe.prepAuthorizationForDisplay(&http.Request{Host: "localhost"}, authz)
|
||||
|
||||
// All of the challenges should be revoked as well.
|
||||
for _, chall := range authz.Challenges {
|
||||
|
@ -3781,30 +3440,7 @@ func TestPrepWildcardAuthzForDisplay(t *testing.T) {
|
|||
}
|
||||
|
||||
// This modifies the authz in-place.
|
||||
wfe.prepAuthorizationForDisplay(deprecatedAuthzPath, &http.Request{Host: "localhost"}, authz)
|
||||
|
||||
// The identifier should not start with a star, but the authz should be marked
|
||||
// as a wildcard.
|
||||
test.AssertEquals(t, strings.HasPrefix(authz.Identifier.Value, "*."), false)
|
||||
test.AssertEquals(t, authz.Wildcard, true)
|
||||
}
|
||||
|
||||
func TestPrepWildcardAuthzWithAcountForDisplay(t *testing.T) {
|
||||
t.Parallel()
|
||||
wfe, _, _ := setupWFE(t)
|
||||
|
||||
authz := &core.Authorization{
|
||||
ID: "12345",
|
||||
Status: core.StatusPending,
|
||||
RegistrationID: 1,
|
||||
Identifier: identifier.NewDNS("*.example.com"),
|
||||
Challenges: []core.Challenge{
|
||||
{Type: core.ChallengeTypeDNS01, Status: core.StatusPending, Token: "token"},
|
||||
},
|
||||
}
|
||||
|
||||
// This modifies the authz in-place.
|
||||
wfe.prepAuthorizationForDisplay(authzPathWithAcct, &http.Request{Host: "localhost"}, authz)
|
||||
wfe.prepAuthorizationForDisplay(&http.Request{Host: "localhost"}, authz)
|
||||
|
||||
// The identifier should not start with a star, but the authz should be marked
|
||||
// as a wildcard.
|
||||
|
@ -3840,7 +3476,7 @@ func TestPrepAuthzForDisplayShuffle(t *testing.T) {
|
|||
// Prep the authz 100 times, and count where each challenge ended up each time.
|
||||
for range 100 {
|
||||
// This modifies the authz in place
|
||||
wfe.prepAuthorizationForDisplay(deprecatedChallengePath, &http.Request{Host: "localhost"}, authz)
|
||||
wfe.prepAuthorizationForDisplay(&http.Request{Host: "localhost"}, authz)
|
||||
for i, chall := range authz.Challenges {
|
||||
counts[chall.Type][i] += 1
|
||||
}
|
||||
|
@ -3937,12 +3573,12 @@ func TestGETAPIAuthorizationHandler(t *testing.T) {
|
|||
}{
|
||||
{
|
||||
name: "fresh authz",
|
||||
path: "1",
|
||||
path: "1/1",
|
||||
expectTooFreshErr: true,
|
||||
},
|
||||
{
|
||||
name: "old authz",
|
||||
path: "2",
|
||||
path: "1/2",
|
||||
expectTooFreshErr: false,
|
||||
},
|
||||
}
|
||||
|
@ -3951,7 +3587,7 @@ func TestGETAPIAuthorizationHandler(t *testing.T) {
|
|||
for _, tc := range testCases {
|
||||
responseWriter := httptest.NewRecorder()
|
||||
req, logEvent := makeGet(tc.path, getAuthzPath)
|
||||
wfe.DeprecatedAuthorizationHandler(context.Background(), logEvent, responseWriter, req)
|
||||
wfe.AuthorizationHandler(context.Background(), logEvent, responseWriter, req)
|
||||
|
||||
if responseWriter.Code == http.StatusOK && tc.expectTooFreshErr {
|
||||
t.Errorf("expected too fresh error, got http.StatusOK")
|
||||
|
@ -4015,12 +3651,12 @@ func TestGETAPIChallenge(t *testing.T) {
|
|||
}{
|
||||
{
|
||||
name: "fresh authz challenge",
|
||||
path: "1/7TyhFQ",
|
||||
path: "1/1/7TyhFQ",
|
||||
expectTooFreshErr: true,
|
||||
},
|
||||
{
|
||||
name: "old authz challenge",
|
||||
path: "2/7TyhFQ",
|
||||
path: "1/2/7TyhFQ",
|
||||
expectTooFreshErr: false,
|
||||
},
|
||||
}
|
||||
|
@ -4029,7 +3665,7 @@ func TestGETAPIChallenge(t *testing.T) {
|
|||
for _, tc := range testCases {
|
||||
responseWriter := httptest.NewRecorder()
|
||||
req, logEvent := makeGet(tc.path, getAuthzPath)
|
||||
wfe.DeprecatedChallengeHandler(context.Background(), logEvent, responseWriter, req)
|
||||
wfe.ChallengeHandler(context.Background(), logEvent, responseWriter, req)
|
||||
|
||||
if responseWriter.Code == http.StatusOK && tc.expectTooFreshErr {
|
||||
t.Errorf("expected too fresh error, got http.StatusOK")
|
||||
|
|
Loading…
Reference in New Issue