fleet/server/service/middleware/log/log.go
Victor Lyuboslavsky 7f67ac940f
Okta IdP Apple profile endpoint + fixes (#35526)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #34539

Added endpoint to get a sample Apple config profile that IT admin can
use for Okta conditional access configuration.
`/api/_version_/fleet/conditional_access/idp/apple/profile`

And additional cleanup/improvements:
- logging
- error handling (sending errors to Sentry/OTEL)
- redirect end user to error page if IT admin hasn't set up conditional
access in Fleet

Contributor API changes at:
https://github.com/fleetdm/fleet/pull/35632/files

# Checklist for submitter

- [ ] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
  - Will be added to related PR: #35204

## Testing

- [x] Added/updated automated tests
- [x] QA'd all new/changed functionality manually

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Added Apple profile generation for Okta conditional access IdP
integration.
* New endpoint for retrieving conditional access Apple configuration
profiles.

* **Bug Fixes**
* Improved error handling and logging for conditional access operations.
  * Enhanced error responses for missing server URL configuration.

* **Refactoring**
* Centralized error handling for internal server errors with improved
context logging.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-11-14 13:49:08 -06:00

79 lines
2.4 KiB
Go

package log
import (
"context"
"net/http"
"github.com/fleetdm/fleet/v4/server/contexts/logging"
"github.com/go-kit/kit/endpoint"
kithttp "github.com/go-kit/kit/transport/http"
kitlog "github.com/go-kit/log"
)
// Logged wraps an endpoint and adds the error if the context supports it
func Logged(next endpoint.Endpoint) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
res, err := next(ctx, request)
if err != nil {
logging.WithErr(ctx, err)
return nil, err
}
if errResp, ok := res.(interface{ Error() error }); ok {
err = errResp.Error()
if err != nil {
logging.WithErr(ctx, err)
}
}
return res, nil
}
}
func LogRequestEnd(logger kitlog.Logger) func(context.Context, http.ResponseWriter) context.Context {
return func(ctx context.Context, w http.ResponseWriter) context.Context {
logCtx, ok := logging.FromContext(ctx)
if !ok {
return ctx
}
logCtx.Log(ctx, logger)
return ctx
}
}
func LogResponseEndMiddleware(logger kitlog.Logger, next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
next.ServeHTTP(w, r)
LogRequestEnd(logger)(r.Context(), w)
})
}
// NewLoggingMiddleware creates middleware that initializes logging context and logs requests.
// This middleware should be used for raw http.Handler endpoints (not go-kit endpoints).
// It initializes the logging context with request metadata and logs the request after completion.
func NewLoggingMiddleware(logger kitlog.Logger) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Create logging context
lc := &logging.LoggingContext{}
// Populate request context with kithttp fields (method, URI, etc.)
ctx := logging.NewContext(kithttp.PopulateRequestContext(r.Context(), r), lc)
// Set start time
ctx = logging.WithStartTime(ctx)
// Add IP address information to logging context
remoteAddr, _ := ctx.Value(kithttp.ContextKeyRequestRemoteAddr).(string)
xForwardedFor, _ := ctx.Value(kithttp.ContextKeyRequestXForwardedFor).(string)
lc.SetExtras("ip_addr", remoteAddr, "x_for_ip_addr", xForwardedFor)
// Create new request with updated context
r = r.WithContext(ctx)
// Call next handler
next.ServeHTTP(w, r)
// Log the request
LogRequestEnd(logger)(ctx, w)
})
}
}