Enable integration tests for authz2 and fix a few bugs (#4221)
Enables integration tests for authz2 and fixes a few bugs that were flagged up during the process. Disables expired-authorization-purger integration tests if config-next is being used as expired-authz-purger expects to purge some stuff but doesn't know about authz2 authorizations, a new test will be added with #4188. Fixes #4079.
This commit is contained in:
parent
1014a81606
commit
4d40cf58e4
|
|
@ -421,7 +421,7 @@ func orderValid(order *corepb.Order) bool {
|
||||||
// `order.CertificateSerial` to be nil such that it can be used in places where
|
// `order.CertificateSerial` to be nil such that it can be used in places where
|
||||||
// the order has not been finalized yet.
|
// the order has not been finalized yet.
|
||||||
func newOrderValid(order *corepb.Order) bool {
|
func newOrderValid(order *corepb.Order) bool {
|
||||||
return !(order.RegistrationID == nil || order.Expires == nil || order.Authorizations == nil || order.Names == nil)
|
return !(order.RegistrationID == nil || order.Expires == nil || (order.Authorizations == nil && order.V2Authorizations == nil) || order.Names == nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func authorizationValid(authz *corepb.Authorization) bool {
|
func authorizationValid(authz *corepb.Authorization) bool {
|
||||||
|
|
|
||||||
|
|
@ -1213,7 +1213,7 @@ func (sas StorageAuthorityServerWrapper) FinalizeAuthorization2(ctx context.Cont
|
||||||
return nil, errIncompleteRequest
|
return nil, errIncompleteRequest
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, sas.inner.FinalizeAuthorization2(ctx, req)
|
return &corepb.Empty{}, sas.inner.FinalizeAuthorization2(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sas StorageAuthorityServerWrapper) GetPendingAuthorization2(ctx context.Context, req *sapb.GetPendingAuthorizationRequest) (*corepb.Authorization, error) {
|
func (sas StorageAuthorityServerWrapper) GetPendingAuthorization2(ctx context.Context, req *sapb.GetPendingAuthorizationRequest) (*corepb.Authorization, error) {
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,8 @@
|
||||||
},
|
},
|
||||||
"features": {
|
"features": {
|
||||||
"RevokeAtRA": true,
|
"RevokeAtRA": true,
|
||||||
"EarlyOrderRateLimit": true
|
"EarlyOrderRateLimit": true,
|
||||||
|
"NewAuthorizationSchema": true
|
||||||
},
|
},
|
||||||
"CTLogGroups2": [
|
"CTLogGroups2": [
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@
|
||||||
"timeout": "15s"
|
"timeout": "15s"
|
||||||
},
|
},
|
||||||
"features": {
|
"features": {
|
||||||
|
"NewAuthorizationSchema": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -239,7 +239,8 @@ def main():
|
||||||
# traffic.
|
# traffic.
|
||||||
if not args.test_case_filter:
|
if not args.test_case_filter:
|
||||||
check_balance()
|
check_balance()
|
||||||
run_expired_authz_purger()
|
if not CONFIG_NEXT:
|
||||||
|
run_expired_authz_purger()
|
||||||
|
|
||||||
# Run the load-generator last. run_loadtest will stop the
|
# Run the load-generator last. run_loadtest will stop the
|
||||||
# pebble-challtestsrv before running the load-generator and will not restart
|
# pebble-challtestsrv before running the load-generator and will not restart
|
||||||
|
|
|
||||||
45
wfe/wfe.go
45
wfe/wfe.go
|
|
@ -58,6 +58,8 @@ const (
|
||||||
rolloverPath = "/acme/key-change"
|
rolloverPath = "/acme/key-change"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const authz2Prefix = "v2"
|
||||||
|
|
||||||
// WebFrontEndImpl provides all the logic for Boulder's web-facing interface,
|
// WebFrontEndImpl provides all the logic for Boulder's web-facing interface,
|
||||||
// i.e., ACME. Its members configure the paths for various ACME functions,
|
// i.e., ACME. Its members configure the paths for various ACME functions,
|
||||||
// plus a few other data items used in ACME. Its methods are primarily handlers
|
// plus a few other data items used in ACME. Its methods are primarily handlers
|
||||||
|
|
@ -688,7 +690,12 @@ func (wfe *WebFrontEndImpl) NewAuthorization(ctx context.Context, logEvent *web.
|
||||||
logEvent.Created = authz.ID
|
logEvent.Created = authz.ID
|
||||||
|
|
||||||
// Make a URL for this authz, then blow away the ID and RegID before serializing
|
// Make a URL for this authz, then blow away the ID and RegID before serializing
|
||||||
authzURL := web.RelativeEndpoint(request, authzPath+string(authz.ID))
|
var authzURL string
|
||||||
|
if authz.V2 {
|
||||||
|
authzURL = web.RelativeEndpoint(request, fmt.Sprintf("%s%s/%s", authzPath, authz2Prefix, authz.ID))
|
||||||
|
} else {
|
||||||
|
authzURL = web.RelativeEndpoint(request, authzPath+string(authz.ID))
|
||||||
|
}
|
||||||
wfe.prepAuthorizationForDisplay(request, &authz)
|
wfe.prepAuthorizationForDisplay(request, &authz)
|
||||||
|
|
||||||
response.Header().Add("Location", authzURL)
|
response.Header().Add("Location", authzURL)
|
||||||
|
|
@ -703,16 +710,34 @@ func (wfe *WebFrontEndImpl) NewAuthorization(ctx context.Context, logEvent *web.
|
||||||
}
|
}
|
||||||
|
|
||||||
func (wfe *WebFrontEndImpl) regHoldsAuthorizations(ctx context.Context, regID int64, names []string) (bool, error) {
|
func (wfe *WebFrontEndImpl) regHoldsAuthorizations(ctx context.Context, regID int64, names []string) (bool, error) {
|
||||||
authz, err := wfe.SA.GetValidAuthorizations(ctx, regID, names, wfe.clk.Now())
|
var authzMap map[string]*core.Authorization
|
||||||
if err != nil {
|
if features.Enabled(features.NewAuthorizationSchema) {
|
||||||
return false, err
|
now := wfe.clk.Now().UnixNano()
|
||||||
|
authzMapPB, err := wfe.SA.GetValidAuthorizations2(ctx, &sapb.GetValidAuthorizationsRequest{
|
||||||
|
RegistrationID: ®ID,
|
||||||
|
Domains: names,
|
||||||
|
Now: &now,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
authzMap, err = bgrpc.PBToAuthzMap(authzMapPB)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var err error
|
||||||
|
authzMap, err = wfe.SA.GetValidAuthorizations(ctx, regID, names, wfe.clk.Now())
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if len(names) != len(authz) {
|
if len(names) != len(authzMap) {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
missingNames := false
|
missingNames := false
|
||||||
for _, name := range names {
|
for _, name := range names {
|
||||||
if _, present := authz[name]; !present {
|
if _, present := authzMap[name]; !present {
|
||||||
missingNames = true
|
missingNames = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -955,7 +980,7 @@ func (wfe *WebFrontEndImpl) Challenge(
|
||||||
var err error
|
var err error
|
||||||
var v2 bool
|
var v2 bool
|
||||||
if len(slug) == 3 {
|
if len(slug) == 3 {
|
||||||
if !features.Enabled(features.NewAuthorizationSchema) || slug[0] != "v2" {
|
if !features.Enabled(features.NewAuthorizationSchema) || slug[0] != authz2Prefix {
|
||||||
notFound()
|
notFound()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -1042,7 +1067,7 @@ func (wfe *WebFrontEndImpl) Challenge(
|
||||||
func (wfe *WebFrontEndImpl) prepChallengeForDisplay(request *http.Request, authz core.Authorization, challenge *core.Challenge) {
|
func (wfe *WebFrontEndImpl) prepChallengeForDisplay(request *http.Request, authz core.Authorization, challenge *core.Challenge) {
|
||||||
// Update the challenge URI to be relative to the HTTP request Host
|
// Update the challenge URI to be relative to the HTTP request Host
|
||||||
if authz.V2 {
|
if authz.V2 {
|
||||||
challenge.URI = web.RelativeEndpoint(request, fmt.Sprintf("%sv2/%s/%s", challengePath, authz.ID, challenge.StringID()))
|
challenge.URI = web.RelativeEndpoint(request, fmt.Sprintf("%s%s/%s/%s", challengePath, authz2Prefix, authz.ID, challenge.StringID()))
|
||||||
} else {
|
} else {
|
||||||
challenge.URI = web.RelativeEndpoint(request, fmt.Sprintf("%s%s/%d", challengePath, authz.ID, challenge.ID))
|
challenge.URI = web.RelativeEndpoint(request, fmt.Sprintf("%s%s/%d", challengePath, authz.ID, challenge.ID))
|
||||||
}
|
}
|
||||||
|
|
@ -1324,8 +1349,8 @@ func (wfe *WebFrontEndImpl) Authorization(ctx context.Context, logEvent *web.Req
|
||||||
id := request.URL.Path
|
id := request.URL.Path
|
||||||
var authz core.Authorization
|
var authz core.Authorization
|
||||||
var err error
|
var err error
|
||||||
if features.Enabled(features.NewAuthorizationSchema) && strings.HasPrefix(id, "/v2/") {
|
if features.Enabled(features.NewAuthorizationSchema) && strings.HasPrefix(id, authz2Prefix) {
|
||||||
authzID, err := strconv.ParseInt(id[4:], 10, 64)
|
authzID, err := strconv.ParseInt(strings.TrimPrefix(id, authz2Prefix+"/"), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
wfe.sendError(response, logEvent, probs.NotFound("No such authorization"), nil)
|
wfe.sendError(response, logEvent, probs.NotFound("No such authorization"), nil)
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -1845,7 +1845,7 @@ func TestAuthorization(t *testing.T) {
|
||||||
// Test retrieving a v2 style authorization
|
// Test retrieving a v2 style authorization
|
||||||
responseWriter = httptest.NewRecorder()
|
responseWriter = httptest.NewRecorder()
|
||||||
wfe.Authorization(ctx, newRequestEvent(), responseWriter, &http.Request{
|
wfe.Authorization(ctx, newRequestEvent(), responseWriter, &http.Request{
|
||||||
URL: mustParseURL("/v2/1"),
|
URL: mustParseURL("v2/1"),
|
||||||
Method: "GET",
|
Method: "GET",
|
||||||
})
|
})
|
||||||
test.AssertEquals(t, responseWriter.Code, http.StatusOK)
|
test.AssertEquals(t, responseWriter.Code, http.StatusOK)
|
||||||
|
|
|
||||||
40
wfe2/wfe.go
40
wfe2/wfe.go
|
|
@ -58,6 +58,8 @@ const (
|
||||||
finalizeOrderPath = "/acme/finalize/"
|
finalizeOrderPath = "/acme/finalize/"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const authz2Prefix = "v2"
|
||||||
|
|
||||||
// WebFrontEndImpl provides all the logic for Boulder's web-facing interface,
|
// WebFrontEndImpl provides all the logic for Boulder's web-facing interface,
|
||||||
// i.e., ACME. Its members configure the paths for various ACME functions,
|
// i.e., ACME. Its members configure the paths for various ACME functions,
|
||||||
// plus a few other data items used in ACME. Its methods are primarily handlers
|
// plus a few other data items used in ACME. Its methods are primarily handlers
|
||||||
|
|
@ -593,16 +595,34 @@ func (wfe *WebFrontEndImpl) NewAccount(
|
||||||
}
|
}
|
||||||
|
|
||||||
func (wfe *WebFrontEndImpl) acctHoldsAuthorizations(ctx context.Context, acctID int64, names []string) (bool, error) {
|
func (wfe *WebFrontEndImpl) acctHoldsAuthorizations(ctx context.Context, acctID int64, names []string) (bool, error) {
|
||||||
authz, err := wfe.SA.GetValidAuthorizations(ctx, acctID, names, wfe.clk.Now())
|
var authzMap map[string]*core.Authorization
|
||||||
if err != nil {
|
if features.Enabled(features.NewAuthorizationSchema) {
|
||||||
return false, err
|
now := wfe.clk.Now().UnixNano()
|
||||||
|
authzMapPB, err := wfe.SA.GetValidAuthorizations2(ctx, &sapb.GetValidAuthorizationsRequest{
|
||||||
|
RegistrationID: &acctID,
|
||||||
|
Domains: names,
|
||||||
|
Now: &now,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
authzMap, err = bgrpc.PBToAuthzMap(authzMapPB)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var err error
|
||||||
|
authzMap, err = wfe.SA.GetValidAuthorizations(ctx, acctID, names, wfe.clk.Now())
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if len(names) != len(authz) {
|
if len(names) != len(authzMap) {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
missingNames := false
|
missingNames := false
|
||||||
for _, name := range names {
|
for _, name := range names {
|
||||||
if _, present := authz[name]; !present {
|
if _, present := authzMap[name]; !present {
|
||||||
missingNames = true
|
missingNames = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -865,7 +885,7 @@ func (wfe *WebFrontEndImpl) Challenge(
|
||||||
var err error
|
var err error
|
||||||
var v2 bool
|
var v2 bool
|
||||||
if len(slug) == 3 {
|
if len(slug) == 3 {
|
||||||
if !features.Enabled(features.NewAuthorizationSchema) || slug[0] != "v2" {
|
if !features.Enabled(features.NewAuthorizationSchema) || slug[0] != authz2Prefix {
|
||||||
notFound()
|
notFound()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -952,7 +972,7 @@ func (wfe *WebFrontEndImpl) Challenge(
|
||||||
func (wfe *WebFrontEndImpl) prepChallengeForDisplay(request *http.Request, authz core.Authorization, challenge *core.Challenge) {
|
func (wfe *WebFrontEndImpl) prepChallengeForDisplay(request *http.Request, authz core.Authorization, challenge *core.Challenge) {
|
||||||
// Update the challenge URL to be relative to the HTTP request Host
|
// Update the challenge URL to be relative to the HTTP request Host
|
||||||
if authz.V2 {
|
if authz.V2 {
|
||||||
challenge.URL = web.RelativeEndpoint(request, fmt.Sprintf("%sv2/%s/%s", challengePath, authz.ID, challenge.StringID()))
|
challenge.URL = web.RelativeEndpoint(request, fmt.Sprintf("%s%s/%s/%s", challengePath, authz2Prefix, authz.ID, challenge.StringID()))
|
||||||
} else {
|
} else {
|
||||||
challenge.URL = web.RelativeEndpoint(request, fmt.Sprintf("%s%s/%d", challengePath, authz.ID, challenge.ID))
|
challenge.URL = web.RelativeEndpoint(request, fmt.Sprintf("%s%s/%d", challengePath, authz.ID, challenge.ID))
|
||||||
}
|
}
|
||||||
|
|
@ -1305,8 +1325,8 @@ func (wfe *WebFrontEndImpl) Authorization(ctx context.Context, logEvent *web.Req
|
||||||
id := request.URL.Path
|
id := request.URL.Path
|
||||||
var authz core.Authorization
|
var authz core.Authorization
|
||||||
var err error
|
var err error
|
||||||
if features.Enabled(features.NewAuthorizationSchema) && strings.HasPrefix(id, "/v2/") {
|
if features.Enabled(features.NewAuthorizationSchema) && strings.HasPrefix(id, authz2Prefix) {
|
||||||
authzID, err := strconv.ParseInt(id[4:], 10, 64)
|
authzID, err := strconv.ParseInt(strings.TrimPrefix(id, authz2Prefix+"/"), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
wfe.sendError(response, logEvent, probs.NotFound("No such authorization"), nil)
|
wfe.sendError(response, logEvent, probs.NotFound("No such authorization"), nil)
|
||||||
return
|
return
|
||||||
|
|
@ -1700,7 +1720,7 @@ func (wfe *WebFrontEndImpl) orderToOrderJSON(request *http.Request, order *corep
|
||||||
respObj.Authorizations = append(respObj.Authorizations, web.RelativeEndpoint(request, fmt.Sprintf("%s%s", authzPath, authzID)))
|
respObj.Authorizations = append(respObj.Authorizations, web.RelativeEndpoint(request, fmt.Sprintf("%s%s", authzPath, authzID)))
|
||||||
}
|
}
|
||||||
for _, v2ID := range order.V2Authorizations {
|
for _, v2ID := range order.V2Authorizations {
|
||||||
respObj.Authorizations = append(respObj.Authorizations, web.RelativeEndpoint(request, fmt.Sprintf("%sv2/%d", authzPath, v2ID)))
|
respObj.Authorizations = append(respObj.Authorizations, web.RelativeEndpoint(request, fmt.Sprintf("%s%s/%d", authzPath, authz2Prefix, v2ID)))
|
||||||
}
|
}
|
||||||
if respObj.Status == core.StatusValid {
|
if respObj.Status == core.StatusValid {
|
||||||
certURL := web.RelativeEndpoint(request,
|
certURL := web.RelativeEndpoint(request,
|
||||||
|
|
|
||||||
|
|
@ -1539,7 +1539,7 @@ func TestGetAuthorization(t *testing.T) {
|
||||||
|
|
||||||
responseWriter = httptest.NewRecorder()
|
responseWriter = httptest.NewRecorder()
|
||||||
wfe.Authorization(ctx, newRequestEvent(), responseWriter, &http.Request{
|
wfe.Authorization(ctx, newRequestEvent(), responseWriter, &http.Request{
|
||||||
URL: mustParseURL("/v2/1"),
|
URL: mustParseURL("v2/1"),
|
||||||
Method: "GET",
|
Method: "GET",
|
||||||
})
|
})
|
||||||
test.AssertEquals(t, responseWriter.Code, http.StatusOK)
|
test.AssertEquals(t, responseWriter.Code, http.StatusOK)
|
||||||
|
|
@ -1563,7 +1563,7 @@ func TestGetAuthorization(t *testing.T) {
|
||||||
|
|
||||||
responseWriter = httptest.NewRecorder()
|
responseWriter = httptest.NewRecorder()
|
||||||
_, _, jwsBody = signRequestKeyID(t, 1, nil, "http://localhost/v2/1", "", wfe.nonceService)
|
_, _, jwsBody = signRequestKeyID(t, 1, nil, "http://localhost/v2/1", "", wfe.nonceService)
|
||||||
postAsGet = makePostRequestWithPath("http://localhost/v2/1", jwsBody)
|
postAsGet = makePostRequestWithPath("v2/1", jwsBody)
|
||||||
wfe.Authorization(ctx, newRequestEvent(), responseWriter, postAsGet)
|
wfe.Authorization(ctx, newRequestEvent(), responseWriter, postAsGet)
|
||||||
test.AssertEquals(t, responseWriter.Code, http.StatusOK)
|
test.AssertEquals(t, responseWriter.Code, http.StatusOK)
|
||||||
body = responseWriter.Body.String()
|
body = responseWriter.Body.String()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue