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)
 | |
| }
 |