Skip to content

Commit

Permalink
clean up handler methods, common logging
Browse files Browse the repository at this point in the history
Signed-off-by: Kristoffer Dalby <[email protected]>
  • Loading branch information
kradalby committed Jan 27, 2025
1 parent 4c8e847 commit a7cb02f
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 93 deletions.
73 changes: 17 additions & 56 deletions hscontrol/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ const (
reservedResponseHeaderSize = 4
)

// httpError logs an error and sends an HTTP error response with the given
func httpError(w http.ResponseWriter, err error, userError string, code int) {
log.Error().Err(err).Msg(userError)
http.Error(w, userError, code)
}

var ErrRegisterMethodCLIDoesNotSupportExpire = errors.New(
"machines registered with CLI does not support expire",
)
Expand All @@ -52,7 +58,7 @@ func parseCabailityVersion(req *http.Request) (tailcfg.CapabilityVersion, error)
return tailcfg.CapabilityVersion(clientCapabilityVersion), nil
}

func (h *Headscale) handleVerifyRequest(
func (h *Headscale) derpRequestIsAllowed(
req *http.Request,
) (bool, error) {
body, err := io.ReadAll(req.Body)
Expand All @@ -79,36 +85,22 @@ func (h *Headscale) VerifyHandler(
req *http.Request,
) {
if req.Method != http.MethodPost {
http.Error(writer, "Wrong method", http.StatusMethodNotAllowed)

httpError(writer, nil, "Wrong method", http.StatusMethodNotAllowed)
return
}
log.Debug().
Str("handler", "/verify").
Msg("verify client")

allow, err := h.handleVerifyRequest(req)
allow, err := h.derpRequestIsAllowed(req)
if err != nil {
log.Error().
Caller().
Err(err).
Msg("Failed to verify client")
http.Error(writer, "Internal error", http.StatusInternalServerError)
httpError(writer, err, "Internal error", http.StatusInternalServerError)
return
}

resp := tailcfg.DERPAdmitClientResponse{
Allow: allow,
}

writer.Header().Set("Content-Type", "application/json")
writer.WriteHeader(http.StatusOK)
err = json.NewEncoder(writer).Encode(resp)
if err != nil {
log.Error().
Caller().
Err(err).
Msg("Failed to write response")
}
json.NewEncoder(writer).Encode(resp)
}

// KeyHandler provides the Headscale pub key
Expand All @@ -120,35 +112,17 @@ func (h *Headscale) KeyHandler(
// New Tailscale clients send a 'v' parameter to indicate the CurrentCapabilityVersion
capVer, err := parseCabailityVersion(req)
if err != nil {
log.Error().
Caller().
Err(err).
Msg("could not get capability version")
writer.Header().Set("Content-Type", "text/plain; charset=utf-8")
writer.WriteHeader(http.StatusInternalServerError)

httpError(writer, err, "Internal error", http.StatusInternalServerError)
return
}

log.Debug().
Str("handler", "/key").
Int("cap_ver", int(capVer)).
Msg("New noise client")

// TS2021 (Tailscale v2 protocol) requires to have a different key
if capVer >= NoiseCapabilityVersion {
resp := tailcfg.OverTLSPublicKeyResponse{
PublicKey: h.noisePrivateKey.Public(),
}
writer.Header().Set("Content-Type", "application/json")
writer.WriteHeader(http.StatusOK)
err = json.NewEncoder(writer).Encode(resp)
if err != nil {
log.Error().
Caller().
Err(err).
Msg("Failed to write response")
}
json.NewEncoder(writer).Encode(resp)

return
}
Expand All @@ -169,18 +143,10 @@ func (h *Headscale) HealthHandler(

if err != nil {
writer.WriteHeader(http.StatusInternalServerError)
log.Error().Caller().Err(err).Msg("health check failed")
res.Status = "fail"
}

buf, err := json.Marshal(res)
if err != nil {
log.Error().Caller().Err(err).Msg("marshal failed")
}
_, err = writer.Write(buf)
if err != nil {
log.Error().Caller().Err(err).Msg("write failed")
}
json.NewEncoder(writer).Encode(res)
}

if err := h.db.PingDB(req.Context()); err != nil {
Expand Down Expand Up @@ -233,16 +199,11 @@ func (a *AuthProviderWeb) RegisterHandler(
// the template and log an error.
registrationId, err := types.RegistrationIDFromString(registrationIdStr)
if err != nil {
http.Error(writer, "invalid registration ID", http.StatusBadRequest)
httpError(writer, err, "invalid registration ID", http.StatusBadRequest)
return
}

writer.Header().Set("Content-Type", "text/html; charset=utf-8")
writer.WriteHeader(http.StatusOK)
if _, err := writer.Write([]byte(templates.RegisterWeb(registrationId).Render())); err != nil {
log.Error().
Caller().
Err(err).
Msg("Failed to write response")
}
writer.Write([]byte(templates.RegisterWeb(registrationId).Render()))
}
42 changes: 5 additions & 37 deletions hscontrol/noise.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,12 +160,7 @@ func isSupportedVersion(version tailcfg.CapabilityVersion) bool {
func rejectUnsupported(writer http.ResponseWriter, version tailcfg.CapabilityVersion) bool {
// Reject unsupported versions
if !isSupportedVersion(version) {
log.Info().
Caller().
Int("min_version", int(MinimumCapVersion)).
Int("client_version", int(version)).
Msg("unsupported client connected")
http.Error(writer, "unsupported client version", http.StatusBadRequest)
httpError(writer, nil, "unsupported client version", http.StatusBadRequest)

return true
}
Expand All @@ -190,23 +185,10 @@ func (ns *noiseServer) NoisePollNetMapHandler(

var mapRequest tailcfg.MapRequest
if err := json.Unmarshal(body, &mapRequest); err != nil {
log.Error().
Caller().
Err(err).
Msg("Cannot parse MapRequest")
http.Error(writer, "Internal error", http.StatusInternalServerError)

httpError(writer, err, "Internal error", http.StatusInternalServerError)
return
}

log.Trace().
Caller().
Str("handler", "NoisePollNetMap").
Any("headers", req.Header).
Str("node", mapRequest.Hostinfo.Hostname).
Int("capver", int(mapRequest.Version)).
Msg("PollNetMapHandler called")

// Reject unsupported versions
if rejectUnsupported(writer, mapRequest.Version) {
return
Expand All @@ -220,11 +202,7 @@ func (ns *noiseServer) NoisePollNetMapHandler(
key.NodePublic{},
)
if err != nil {
log.Error().
Str("handler", "NoisePollNetMap").
Msgf("Failed to fetch node from the database with node key: %s", mapRequest.NodeKey.String())
http.Error(writer, "Internal error", http.StatusInternalServerError)

httpError(writer, err, "Internal error", http.StatusInternalServerError)
return
}

Expand All @@ -242,26 +220,16 @@ func (ns *noiseServer) NoiseRegistrationHandler(
writer http.ResponseWriter,
req *http.Request,
) {
log.Trace().Caller().Msgf("Noise registration handler for client %s", req.RemoteAddr)
if req.Method != http.MethodPost {
http.Error(writer, "Wrong method", http.StatusMethodNotAllowed)
httpError(writer, nil, "Wrong method", http.StatusMethodNotAllowed)

return
}

log.Trace().
Any("headers", req.Header).
Caller().
Msg("Headers")

body, _ := io.ReadAll(req.Body)
var registerRequest tailcfg.RegisterRequest
if err := json.Unmarshal(body, &registerRequest); err != nil {
log.Error().
Caller().
Err(err).
Msg("Cannot parse RegisterRequest")
http.Error(writer, "Internal error", http.StatusInternalServerError)
httpError(writer, err, "Internal error", http.StatusInternalServerError)

return
}
Expand Down

0 comments on commit a7cb02f

Please sign in to comment.