mirror of
https://github.com/fleetdm/fleet
synced 2026-04-21 13:37:30 +00:00
Resolves #37192 Separating generic endpoint_utils middleware logic from domain-specific business logic. New bounded contexts would share the generic logic and implement their own domain-specific logic. The two approaches used in this PR are: - Use common `platform` types - Use interfaces In the next PR we will move `endpointer_utils`, `authzcheck` and `ratelimit` into `platform` directory. # Checklist for submitter - [x] Added changes file ## Testing - [x] Added/updated tests - [x] QA'd all new/changed functionality manually <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Restructured internal error handling and context management to support bounded context architecture. * Improved error context collection and telemetry observability through a provider-based mechanism. * Decoupled licensing and authentication concerns into interfaces for better modularity. * **Chores** * Updated internal package dependencies to align with new architectural boundaries. <sub>✏️ Tip: You can customize this high-level summary in your review settings.</sub> <!-- end of auto-generated comment: release notes by coderabbit.ai -->
110 lines
3.2 KiB
Go
110 lines
3.2 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
|
|
platform_http "github.com/fleetdm/fleet/v4/server/platform/http"
|
|
"github.com/fleetdm/fleet/v4/server/service/middleware/endpoint_utils"
|
|
)
|
|
|
|
// FleetErrorEncoder handles fleet-specific error encoding for MailError
|
|
// and OsqueryError.
|
|
func FleetErrorEncoder(ctx context.Context, err error, w http.ResponseWriter, enc *json.Encoder, jsonErr *endpoint_utils.JsonError) bool {
|
|
switch e := err.(type) {
|
|
case MailError:
|
|
jsonErr.Message = "Mail Error"
|
|
jsonErr.Errors = []map[string]string{
|
|
{
|
|
"name": "base",
|
|
"reason": e.Message,
|
|
},
|
|
}
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
enc.Encode(jsonErr) //nolint:errcheck
|
|
return true
|
|
|
|
case *OsqueryError:
|
|
// osquery expects to receive the node_invalid key when a TLS
|
|
// request provides an invalid node_key for authentication. It
|
|
// doesn't use the error message provided, but we provide this
|
|
// for debugging purposes (and perhaps osquery will use this
|
|
// error message in the future).
|
|
|
|
errMap := map[string]any{
|
|
"error": e.Error(),
|
|
"uuid": jsonErr.UUID,
|
|
}
|
|
if e.NodeInvalid() { //nolint:gocritic // ignore ifElseChain
|
|
w.WriteHeader(http.StatusUnauthorized)
|
|
errMap["node_invalid"] = true
|
|
} else if e.Status() != 0 {
|
|
w.WriteHeader(e.Status())
|
|
} else {
|
|
// TODO: osqueryError is not always the result of an internal error on
|
|
// our side, it is also used to represent a client error (invalid data,
|
|
// e.g. malformed json, carve too large, etc., so 4xx), are we returning
|
|
// a 500 because of some osquery-specific requirement?
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
}
|
|
enc.Encode(errMap) //nolint:errcheck
|
|
return true
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
// MailError is set when an error performing mail operations
|
|
type MailError struct {
|
|
Message string
|
|
}
|
|
|
|
func (e MailError) Error() string {
|
|
return fmt.Sprintf("a mail error occurred: %s", e.Message)
|
|
}
|
|
|
|
// OsqueryError is the error returned to osquery agents.
|
|
type OsqueryError struct {
|
|
message string
|
|
nodeInvalid bool
|
|
StatusCode int
|
|
platform_http.ErrorWithUUID
|
|
}
|
|
|
|
var _ platform_http.ErrorUUIDer = (*OsqueryError)(nil)
|
|
|
|
// Error implements the error interface.
|
|
func (e *OsqueryError) Error() string {
|
|
return e.message
|
|
}
|
|
|
|
// NodeInvalid returns whether the error returned to osquery
|
|
// should contain the node_invalid property.
|
|
func (e *OsqueryError) NodeInvalid() bool {
|
|
return e.nodeInvalid
|
|
}
|
|
|
|
func (e *OsqueryError) Status() int {
|
|
return e.StatusCode
|
|
}
|
|
|
|
func NewOsqueryError(message string, nodeInvalid bool) *OsqueryError {
|
|
return &OsqueryError{
|
|
message: message,
|
|
nodeInvalid: nodeInvalid,
|
|
}
|
|
}
|
|
|
|
// encodeError is a convenience function that calls endpoint_utils.EncodeError
|
|
// with the FleetErrorEncoder. Use this for direct error encoding in handlers.
|
|
func encodeError(ctx context.Context, err error, w http.ResponseWriter) {
|
|
endpoint_utils.EncodeError(ctx, err, w, FleetErrorEncoder)
|
|
}
|
|
|
|
// fleetErrorEncoder is an adapter that wraps endpoint_utils.EncodeError with
|
|
// FleetErrorEncoder for use as a kithttp.ErrorEncoder.
|
|
func fleetErrorEncoder(ctx context.Context, err error, w http.ResponseWriter) {
|
|
endpoint_utils.EncodeError(ctx, err, w, FleetErrorEncoder)
|
|
}
|