Merge pull request #354 from letsencrypt/344-internal_server_errors
Resolves Issue #344: Only send InternalServerError when needed
This commit is contained in:
commit
01c41c1bd0
|
@ -42,6 +42,12 @@ var BuildTime string
|
||||||
|
|
||||||
// Errors
|
// Errors
|
||||||
|
|
||||||
|
// InternalServerError indicates that something has gone wrong unrelated to the
|
||||||
|
// user's input, and will be considered by the Load Balancer as an indication
|
||||||
|
// that this Boulder instance may be malfunctioning. Minimally, returning this
|
||||||
|
// will cause an error page to be generated at the CDN/LB for the client.
|
||||||
|
// Consequently, you should only use this error when Boulder's internal
|
||||||
|
// constraints have been violated.
|
||||||
type InternalServerError string
|
type InternalServerError string
|
||||||
type NotSupportedError string
|
type NotSupportedError string
|
||||||
type MalformedRequestError string
|
type MalformedRequestError string
|
||||||
|
|
|
@ -61,17 +61,32 @@ func validateEmail(address string) (err error) {
|
||||||
domain := strings.ToLower(splitEmail[len(splitEmail)-1])
|
domain := strings.ToLower(splitEmail[len(splitEmail)-1])
|
||||||
var mx []*net.MX
|
var mx []*net.MX
|
||||||
mx, err = net.LookupMX(domain)
|
mx, err = net.LookupMX(domain)
|
||||||
if err != nil {
|
if err != nil || len(mx) == 0 {
|
||||||
err = core.InternalServerError(err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if len(mx) == 0 {
|
|
||||||
err = core.MalformedRequestError(fmt.Sprintf("No MX record for domain %s", domain))
|
err = core.MalformedRequestError(fmt.Sprintf("No MX record for domain %s", domain))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func validateContacts(contacts []core.AcmeURL) (err error) {
|
||||||
|
for _, contact := range contacts {
|
||||||
|
switch contact.Scheme {
|
||||||
|
case "tel":
|
||||||
|
continue
|
||||||
|
case "mailto":
|
||||||
|
err = validateEmail(contact.Opaque)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
err = core.MalformedRequestError(fmt.Sprintf("Contact method %s is not supported", contact.Scheme))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
type certificateRequestEvent struct {
|
type certificateRequestEvent struct {
|
||||||
ID string `json:",omitempty"`
|
ID string `json:",omitempty"`
|
||||||
Requester int64 `json:",omitempty"`
|
Requester int64 `json:",omitempty"`
|
||||||
|
@ -98,24 +113,16 @@ func (ra *RegistrationAuthorityImpl) NewRegistration(init core.Registration) (re
|
||||||
}
|
}
|
||||||
reg.MergeUpdate(init)
|
reg.MergeUpdate(init)
|
||||||
|
|
||||||
for _, contact := range reg.Contact {
|
err = validateContacts(reg.Contact)
|
||||||
switch contact.Scheme {
|
|
||||||
case "tel":
|
|
||||||
continue
|
|
||||||
case "mailto":
|
|
||||||
err = validateEmail(contact.Opaque)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
default:
|
|
||||||
err = core.MalformedRequestError(fmt.Sprintf("Contact method %s is not supported", contact.Scheme))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Store the authorization object, then return it
|
// Store the authorization object, then return it
|
||||||
reg, err = ra.SA.NewRegistration(reg)
|
reg, err = ra.SA.NewRegistration(reg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// InternalServerError since the user-data was validated before being
|
||||||
|
// passed to the SA.
|
||||||
err = core.InternalServerError(err.Error())
|
err = core.InternalServerError(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,7 +131,7 @@ func (ra *RegistrationAuthorityImpl) NewRegistration(init core.Registration) (re
|
||||||
|
|
||||||
func (ra *RegistrationAuthorityImpl) NewAuthorization(request core.Authorization, regID int64) (authz core.Authorization, err error) {
|
func (ra *RegistrationAuthorityImpl) NewAuthorization(request core.Authorization, regID int64) (authz core.Authorization, err error) {
|
||||||
if regID <= 0 {
|
if regID <= 0 {
|
||||||
err = core.InternalServerError("Invalid registration ID")
|
err = core.MalformedRequestError(fmt.Sprintf("Invalid registration ID: %d", regID))
|
||||||
return authz, err
|
return authz, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,7 +169,9 @@ func (ra *RegistrationAuthorityImpl) NewAuthorization(request core.Authorization
|
||||||
// Get a pending Auth first so we can get our ID back, then update with challenges
|
// Get a pending Auth first so we can get our ID back, then update with challenges
|
||||||
authz, err = ra.SA.NewPendingAuthorization(authz)
|
authz, err = ra.SA.NewPendingAuthorization(authz)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = core.InternalServerError(err.Error())
|
// InternalServerError since the user-data was validated before being
|
||||||
|
// passed to the SA.
|
||||||
|
err = core.InternalServerError(fmt.Sprintf("Invalid authorization request: %s", err))
|
||||||
return authz, err
|
return authz, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,6 +182,8 @@ func (ra *RegistrationAuthorityImpl) NewAuthorization(request core.Authorization
|
||||||
challenges[i].URI = core.AcmeURL(*challengeURI)
|
challenges[i].URI = core.AcmeURL(*challengeURI)
|
||||||
|
|
||||||
if !challenges[i].IsSane(false) {
|
if !challenges[i].IsSane(false) {
|
||||||
|
// InternalServerError because we generated these challenges, they should
|
||||||
|
// be OK.
|
||||||
err = core.InternalServerError(fmt.Sprintf("Challenge didn't pass sanity check: %+v", challenges[i]))
|
err = core.InternalServerError(fmt.Sprintf("Challenge didn't pass sanity check: %+v", challenges[i]))
|
||||||
return authz, err
|
return authz, err
|
||||||
}
|
}
|
||||||
|
@ -184,6 +195,8 @@ func (ra *RegistrationAuthorityImpl) NewAuthorization(request core.Authorization
|
||||||
// Store the authorization object, then return it
|
// Store the authorization object, then return it
|
||||||
err = ra.SA.UpdatePendingAuthorization(authz)
|
err = ra.SA.UpdatePendingAuthorization(authz)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// InternalServerError because we created the authorization just above,
|
||||||
|
// and adding Sane challenges should not break it.
|
||||||
err = core.InternalServerError(err.Error())
|
err = core.InternalServerError(err.Error())
|
||||||
}
|
}
|
||||||
return authz, err
|
return authz, err
|
||||||
|
@ -211,7 +224,7 @@ func (ra *RegistrationAuthorityImpl) NewCertificate(req core.CertificateRequest,
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if regID <= 0 {
|
if regID <= 0 {
|
||||||
err = core.InternalServerError("Invalid registration ID")
|
err = core.MalformedRequestError(fmt.Sprintf("Invalid registration ID: %d", regID))
|
||||||
return emptyCert, err
|
return emptyCert, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,7 +325,10 @@ func (ra *RegistrationAuthorityImpl) NewCertificate(req core.CertificateRequest,
|
||||||
|
|
||||||
// Create the certificate and log the result
|
// Create the certificate and log the result
|
||||||
if cert, err = ra.CA.IssueCertificate(*csr, regID, earliestExpiry); err != nil {
|
if cert, err = ra.CA.IssueCertificate(*csr, regID, earliestExpiry); err != nil {
|
||||||
err = core.InternalServerError(err.Error())
|
// While this could be InternalServerError for certain conditions, most
|
||||||
|
// of the failure reasons (such as GoodKey failing) are caused by malformed
|
||||||
|
// requests.
|
||||||
|
err = core.MalformedRequestError(err.Error())
|
||||||
logEvent.Error = err.Error()
|
logEvent.Error = err.Error()
|
||||||
return emptyCert, err
|
return emptyCert, err
|
||||||
}
|
}
|
||||||
|
@ -325,6 +341,8 @@ func (ra *RegistrationAuthorityImpl) NewCertificate(req core.CertificateRequest,
|
||||||
|
|
||||||
parsedCertificate, err := x509.ParseCertificate([]byte(cert.DER))
|
parsedCertificate, err := x509.ParseCertificate([]byte(cert.DER))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// InternalServerError because the certificate from the CA should be
|
||||||
|
// parseable.
|
||||||
err = core.InternalServerError(err.Error())
|
err = core.InternalServerError(err.Error())
|
||||||
logEvent.Error = err.Error()
|
logEvent.Error = err.Error()
|
||||||
return emptyCert, err
|
return emptyCert, err
|
||||||
|
@ -342,10 +360,18 @@ func (ra *RegistrationAuthorityImpl) NewCertificate(req core.CertificateRequest,
|
||||||
|
|
||||||
func (ra *RegistrationAuthorityImpl) UpdateRegistration(base core.Registration, update core.Registration) (reg core.Registration, err error) {
|
func (ra *RegistrationAuthorityImpl) UpdateRegistration(base core.Registration, update core.Registration) (reg core.Registration, err error) {
|
||||||
base.MergeUpdate(update)
|
base.MergeUpdate(update)
|
||||||
|
|
||||||
|
err = validateContacts(base.Contact)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
reg = base
|
reg = base
|
||||||
err = ra.SA.UpdateRegistration(base)
|
err = ra.SA.UpdateRegistration(base)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = core.InternalServerError(err.Error())
|
// InternalServerError since the user-data was validated before being
|
||||||
|
// passed to the SA.
|
||||||
|
err = core.InternalServerError(fmt.Sprintf("Could not update registration: %s", err))
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -354,14 +380,16 @@ func (ra *RegistrationAuthorityImpl) UpdateAuthorization(base core.Authorization
|
||||||
// Copy information over that the client is allowed to supply
|
// Copy information over that the client is allowed to supply
|
||||||
authz = base
|
authz = base
|
||||||
if challengeIndex >= len(authz.Challenges) {
|
if challengeIndex >= len(authz.Challenges) {
|
||||||
err = core.MalformedRequestError("Invalid challenge index")
|
err = core.MalformedRequestError(fmt.Sprintf("Invalid challenge index: %d", challengeIndex))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
authz.Challenges[challengeIndex] = authz.Challenges[challengeIndex].MergeResponse(response)
|
authz.Challenges[challengeIndex] = authz.Challenges[challengeIndex].MergeResponse(response)
|
||||||
|
|
||||||
// Store the updated version
|
// Store the updated version
|
||||||
if err = ra.SA.UpdatePendingAuthorization(authz); err != nil {
|
if err = ra.SA.UpdatePendingAuthorization(authz); err != nil {
|
||||||
err = core.InternalServerError(err.Error())
|
// This can pretty much only happen when the client corrupts the Challenge
|
||||||
|
// data.
|
||||||
|
err = core.MalformedRequestError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -219,6 +219,48 @@ func assertAuthzEqual(t *testing.T, a1, a2 core.Authorization) {
|
||||||
// Not testing: Challenges
|
// Not testing: Challenges
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestValidateContacts(t *testing.T) {
|
||||||
|
tel, _ := url.Parse("tel:")
|
||||||
|
ansible, _ := url.Parse("ansible:earth.sol.milkyway.laniakea/letsencrypt")
|
||||||
|
validEmail, _ := url.Parse("mailto:admin@email.com")
|
||||||
|
invalidEmail, _ := url.Parse("mailto:admin@example.com")
|
||||||
|
malformedEmail, _ := url.Parse("mailto:admin.com")
|
||||||
|
|
||||||
|
err := validateContacts([]core.AcmeURL{})
|
||||||
|
test.AssertNotError(t, err, "No Contacts")
|
||||||
|
|
||||||
|
err = validateContacts([]core.AcmeURL{core.AcmeURL(*tel)})
|
||||||
|
test.AssertNotError(t, err, "Simple Telephone")
|
||||||
|
|
||||||
|
err = validateContacts([]core.AcmeURL{core.AcmeURL(*validEmail)})
|
||||||
|
test.AssertNotError(t, err, "Valid Email")
|
||||||
|
|
||||||
|
err = validateContacts([]core.AcmeURL{core.AcmeURL(*invalidEmail)})
|
||||||
|
test.AssertError(t, err, "Invalid Email")
|
||||||
|
|
||||||
|
err = validateContacts([]core.AcmeURL{core.AcmeURL(*malformedEmail)})
|
||||||
|
test.AssertError(t, err, "Malformed Email")
|
||||||
|
|
||||||
|
err = validateContacts([]core.AcmeURL{core.AcmeURL(*ansible)})
|
||||||
|
test.AssertError(t, err, "Unknown scehme")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestValidateEmail(t *testing.T) {
|
||||||
|
err := validateEmail("an email`")
|
||||||
|
test.AssertError(t, err, "Malformed")
|
||||||
|
|
||||||
|
err = validateEmail("a@not.a.domain")
|
||||||
|
test.AssertError(t, err, "Cannot resolve")
|
||||||
|
t.Logf("No Resolve: %s", err)
|
||||||
|
|
||||||
|
err = validateEmail("a@example.com")
|
||||||
|
test.AssertError(t, err, "No MX Record")
|
||||||
|
t.Logf("No MX: %s", err)
|
||||||
|
|
||||||
|
err = validateEmail("a@email.com")
|
||||||
|
test.AssertNotError(t, err, "Valid")
|
||||||
|
}
|
||||||
|
|
||||||
func TestNewRegistration(t *testing.T) {
|
func TestNewRegistration(t *testing.T) {
|
||||||
_, _, sa, ra := initAuthorities(t)
|
_, _, sa, ra := initAuthorities(t)
|
||||||
mailto, _ := url.Parse("mailto:foo@letsencrypt.org")
|
mailto, _ := url.Parse("mailto:foo@letsencrypt.org")
|
||||||
|
|
|
@ -71,8 +71,18 @@ func statusCodeFromError(err interface{}) int {
|
||||||
switch err.(type) {
|
switch err.(type) {
|
||||||
case core.MalformedRequestError:
|
case core.MalformedRequestError:
|
||||||
return http.StatusBadRequest
|
return http.StatusBadRequest
|
||||||
|
case core.NotSupportedError:
|
||||||
|
return http.StatusNotImplemented
|
||||||
|
case core.SyntaxError:
|
||||||
|
return http.StatusBadRequest
|
||||||
case core.UnauthorizedError:
|
case core.UnauthorizedError:
|
||||||
return http.StatusForbidden
|
return http.StatusForbidden
|
||||||
|
case core.NotFoundError:
|
||||||
|
return http.StatusNotFound
|
||||||
|
case core.SignatureValidationError:
|
||||||
|
return http.StatusPreconditionFailed
|
||||||
|
case core.InternalServerError:
|
||||||
|
return http.StatusInternalServerError
|
||||||
default:
|
default:
|
||||||
return http.StatusInternalServerError
|
return http.StatusInternalServerError
|
||||||
}
|
}
|
||||||
|
@ -327,6 +337,7 @@ func (wfe *WebFrontEndImpl) NewRegistration(response http.ResponseWriter, reques
|
||||||
regURL := fmt.Sprintf("%s%d", wfe.RegBase, id)
|
regURL := fmt.Sprintf("%s%d", wfe.RegBase, id)
|
||||||
responseBody, err := json.Marshal(reg)
|
responseBody, err := json.Marshal(reg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// StatusInternalServerError because we just created this registration, it should be OK.
|
||||||
wfe.sendError(response, "Error marshaling registration", err, http.StatusInternalServerError)
|
wfe.sendError(response, "Error marshaling registration", err, http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -390,6 +401,7 @@ func (wfe *WebFrontEndImpl) NewAuthorization(response http.ResponseWriter, reque
|
||||||
authz.RegistrationID = 0
|
authz.RegistrationID = 0
|
||||||
responseBody, err := json.Marshal(authz)
|
responseBody, err := json.Marshal(authz)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// StatusInternalServerError because we generated the authz, it should be OK
|
||||||
wfe.sendError(response, "Error marshaling authz", err, http.StatusInternalServerError)
|
wfe.sendError(response, "Error marshaling authz", err, http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -446,6 +458,7 @@ func (wfe *WebFrontEndImpl) RevokeCertificate(response http.ResponseWriter, requ
|
||||||
}
|
}
|
||||||
parsedCertificate, err := x509.ParseCertificate(cert.DER)
|
parsedCertificate, err := x509.ParseCertificate(cert.DER)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// InternalServerError because this is a failure to decode from our DB.
|
||||||
wfe.sendError(response, "Invalid certificate", err, http.StatusInternalServerError)
|
wfe.sendError(response, "Invalid certificate", err, http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -557,7 +570,7 @@ func (wfe *WebFrontEndImpl) NewCertificate(response http.ResponseWriter, request
|
||||||
wfe.Stats.Inc("Certificates", 1, 1.0)
|
wfe.Stats.Inc("Certificates", 1, 1.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (wfe *WebFrontEndImpl) Challenge(authz core.Authorization, response http.ResponseWriter, request *http.Request) {
|
func (wfe *WebFrontEndImpl) challenge(authz core.Authorization, response http.ResponseWriter, request *http.Request) {
|
||||||
wfe.sendStandardHeaders(response)
|
wfe.sendStandardHeaders(response)
|
||||||
|
|
||||||
if request.Method != "GET" && request.Method != "POST" {
|
if request.Method != "GET" && request.Method != "POST" {
|
||||||
|
@ -593,6 +606,8 @@ func (wfe *WebFrontEndImpl) Challenge(authz core.Authorization, response http.Re
|
||||||
challenge := authz.Challenges[challengeIndex]
|
challenge := authz.Challenges[challengeIndex]
|
||||||
jsonReply, err := json.Marshal(challenge)
|
jsonReply, err := json.Marshal(challenge)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// InternalServerError because this is a failure to decode data passed in
|
||||||
|
// by the caller, which got it from the DB.
|
||||||
wfe.sendError(response, "Failed to marshal challenge", err, http.StatusInternalServerError)
|
wfe.sendError(response, "Failed to marshal challenge", err, http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -651,6 +666,7 @@ func (wfe *WebFrontEndImpl) Challenge(authz core.Authorization, response http.Re
|
||||||
// assumption: UpdateAuthorization does not modify order of challenges
|
// assumption: UpdateAuthorization does not modify order of challenges
|
||||||
jsonReply, err := json.Marshal(challenge)
|
jsonReply, err := json.Marshal(challenge)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// StatusInternalServerError because we made the challenges, they should be OK
|
||||||
wfe.sendError(response, "Failed to marshal challenge", err, http.StatusInternalServerError)
|
wfe.sendError(response, "Failed to marshal challenge", err, http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -734,6 +750,7 @@ func (wfe *WebFrontEndImpl) Registration(response http.ResponseWriter, request *
|
||||||
|
|
||||||
jsonReply, err := json.Marshal(updatedReg)
|
jsonReply, err := json.Marshal(updatedReg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// StatusInternalServerError because we just generated the reg, it should be OK
|
||||||
wfe.sendError(response, "Failed to marshal registration", err, http.StatusInternalServerError)
|
wfe.sendError(response, "Failed to marshal registration", err, http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -763,7 +780,7 @@ func (wfe *WebFrontEndImpl) Authorization(response http.ResponseWriter, request
|
||||||
|
|
||||||
// If there is a fragment, then this is actually a request to a challenge URI
|
// If there is a fragment, then this is actually a request to a challenge URI
|
||||||
if len(request.URL.RawQuery) != 0 {
|
if len(request.URL.RawQuery) != 0 {
|
||||||
wfe.Challenge(authz, response, request)
|
wfe.challenge(authz, response, request)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -780,6 +797,7 @@ func (wfe *WebFrontEndImpl) Authorization(response http.ResponseWriter, request
|
||||||
|
|
||||||
jsonReply, err := json.Marshal(authz)
|
jsonReply, err := json.Marshal(authz)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// InternalServerError because this is a failure to decode from our DB.
|
||||||
wfe.sendError(response, "Failed to marshal authz", err, http.StatusInternalServerError)
|
wfe.sendError(response, "Failed to marshal authz", err, http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -827,7 +845,7 @@ func (wfe *WebFrontEndImpl) Certificate(response http.ResponseWriter, request *h
|
||||||
cert, err := wfe.SA.GetCertificateByShortSerial(serial)
|
cert, err := wfe.SA.GetCertificateByShortSerial(serial)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if strings.HasPrefix(err.Error(), "gorp: multiple rows returned") {
|
if strings.HasPrefix(err.Error(), "gorp: multiple rows returned") {
|
||||||
wfe.sendError(response, "Multiple certificates with same short serial", err, http.StatusInternalServerError)
|
wfe.sendError(response, "Multiple certificates with same short serial", err, http.StatusConflict)
|
||||||
} else {
|
} else {
|
||||||
wfe.sendError(response, "Not found", err, http.StatusNotFound)
|
wfe.sendError(response, "Not found", err, http.StatusNotFound)
|
||||||
}
|
}
|
||||||
|
|
|
@ -550,7 +550,7 @@ func TestChallenge(t *testing.T) {
|
||||||
RegistrationID: 1,
|
RegistrationID: 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
wfe.Challenge(authz, responseWriter, &http.Request{
|
wfe.challenge(authz, responseWriter, &http.Request{
|
||||||
Method: "POST",
|
Method: "POST",
|
||||||
URL: challengeURL,
|
URL: challengeURL,
|
||||||
Body: makeBody(signRequest(t, "{}", &wfe.nonceService)),
|
Body: makeBody(signRequest(t, "{}", &wfe.nonceService)),
|
||||||
|
|
Loading…
Reference in New Issue