Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wfe: remove authz-v3 and chall-v3 paths #7904

Merged
merged 1 commit into from
Dec 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 35 additions & 81 deletions wfe2/wfe.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -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)
}
}

Expand All @@ -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
Expand All @@ -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.
Expand All @@ -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"))

Expand All @@ -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,
Expand Down Expand Up @@ -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
}

Expand Down Expand Up @@ -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"))

Expand Down Expand 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,
Expand All @@ -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,
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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))
}
Loading
Loading