123 lines
3.7 KiB
Go
123 lines
3.7 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"net/http"
|
|
|
|
"github.com/letsencrypt/challtestsrv"
|
|
)
|
|
|
|
// clearHistory handles an HTTP POST request to clear the challenge server
|
|
// request history for a specific hostname and type of event.
|
|
//
|
|
// The POST body is expected to have two parameters:
|
|
// "host" - the hostname to clear history for.
|
|
// "type" - the type of event to clear. May be "http", "dns", or "tlsalpn".
|
|
//
|
|
// A successful POST will write http.StatusOK to the client.
|
|
func (srv *managementServer) clearHistory(w http.ResponseWriter, r *http.Request) {
|
|
var request struct {
|
|
Host string
|
|
Type string `json:"type"`
|
|
}
|
|
if err := mustParsePOST(&request, r); err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
typeMap := map[string]challtestsrv.RequestEventType{
|
|
"http": challtestsrv.HTTPRequestEventType,
|
|
"dns": challtestsrv.DNSRequestEventType,
|
|
"tlsalpn": challtestsrv.TLSALPNRequestEventType,
|
|
}
|
|
if request.Host == "" {
|
|
http.Error(w, "host parameter must not be empty", http.StatusBadRequest)
|
|
return
|
|
}
|
|
if code, ok := typeMap[request.Type]; ok {
|
|
srv.challSrv.ClearRequestHistory(request.Host, code)
|
|
srv.log.Printf("Cleared challenge server request history for %q %q events\n",
|
|
request.Host, request.Type)
|
|
w.WriteHeader(http.StatusOK)
|
|
return
|
|
}
|
|
|
|
http.Error(w, fmt.Sprintf("%q event type unknown", request.Type), http.StatusBadRequest)
|
|
}
|
|
|
|
// getHTTPHistory returns only the HTTPRequestEvents for the given hostname
|
|
// from the challenge server's request history in JSON form.
|
|
func (srv *managementServer) getHTTPHistory(w http.ResponseWriter, r *http.Request) {
|
|
host, err := requestHost(r)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
srv.writeHistory(
|
|
srv.challSrv.RequestHistory(host, challtestsrv.HTTPRequestEventType),
|
|
w)
|
|
}
|
|
|
|
// getDNSHistory returns only the DNSRequestEvents from the challenge
|
|
// server's request history in JSON form.
|
|
func (srv *managementServer) getDNSHistory(w http.ResponseWriter, r *http.Request) {
|
|
host, err := requestHost(r)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
srv.writeHistory(
|
|
srv.challSrv.RequestHistory(host, challtestsrv.DNSRequestEventType),
|
|
w)
|
|
}
|
|
|
|
// getTLSALPNHistory returns only the TLSALPNRequestEvents from the challenge
|
|
// server's request history in JSON form.
|
|
func (srv *managementServer) getTLSALPNHistory(w http.ResponseWriter, r *http.Request) {
|
|
host, err := requestHost(r)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
srv.writeHistory(
|
|
srv.challSrv.RequestHistory(host, challtestsrv.TLSALPNRequestEventType),
|
|
w)
|
|
}
|
|
|
|
// requestHost extracts the Host parameter of a JSON POST body in the provided
|
|
// request, or returns an error.
|
|
func requestHost(r *http.Request) (string, error) {
|
|
var request struct {
|
|
Host string
|
|
}
|
|
if err := mustParsePOST(&request, r); err != nil {
|
|
return "", err
|
|
}
|
|
if request.Host == "" {
|
|
return "", errors.New("host parameter of POST body must not be empty")
|
|
}
|
|
return request.Host, nil
|
|
}
|
|
|
|
// writeHistory writes the provided list of challtestsrv.RequestEvents to the
|
|
// provided http.ResponseWriter in JSON form.
|
|
func (srv *managementServer) writeHistory(
|
|
history []challtestsrv.RequestEvent, w http.ResponseWriter,
|
|
) {
|
|
// Always write an empty JSON list instead of `null`
|
|
if history == nil {
|
|
history = []challtestsrv.RequestEvent{}
|
|
}
|
|
jsonHistory, err := json.MarshalIndent(history, "", " ")
|
|
if err != nil {
|
|
srv.log.Printf("Error marshaling history: %v\n", err)
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
|
w.WriteHeader(http.StatusOK)
|
|
_, _ = w.Write(jsonHistory)
|
|
}
|