2016-09-26 18:48:55 +00:00
package service
2016-08-28 03:59:17 +00:00
import (
2017-03-15 15:55:30 +00:00
"context"
2024-11-22 15:56:36 +00:00
"encoding/json"
Added missing OpenTelemetry instrumentation to several API endpoints. (#32960)
Fixes #32331
Manually tested all paths. `/test` path removed in
https://github.com/fleetdm/fleet/pull/32962
Also added support for sending errors to OpenTelemetry, like we do for
APM/Sentry.
# Checklist for submitter
- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files)
for more information.
## Testing
- [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 OpenTelemetry tracing across core HTTP endpoints (health,
version, assets, metrics, enroll/root, debug, Apple MDM, SCEP, SCIM)
with dynamic per-request route instrumentation.
* Enhanced error reporting to include OpenTelemetry spans/events with
contextual user/host attributes.
* **Tests**
* Added unit tests validating SCIM and error-handling telemetry, span
naming, and sensitive-data redaction.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-09-16 16:10:33 +00:00
"errors"
2023-01-16 20:06:30 +00:00
"fmt"
2016-08-28 03:59:17 +00:00
"net/http"
2024-11-11 19:25:21 +00:00
"os"
2022-03-08 16:27:38 +00:00
"regexp"
2024-11-11 19:25:21 +00:00
"strings"
2025-03-14 17:16:51 +00:00
"time"
2016-08-28 03:59:17 +00:00
2024-10-09 18:47:27 +00:00
eeservice "github.com/fleetdm/fleet/v4/ee/server/service"
2021-06-26 04:46:51 +00:00
"github.com/fleetdm/fleet/v4/server/config"
2022-03-21 16:29:52 +00:00
"github.com/fleetdm/fleet/v4/server/contexts/publicip"
2025-09-26 18:03:50 +00:00
"github.com/fleetdm/fleet/v4/server/datastore/redis"
2021-06-26 04:46:51 +00:00
"github.com/fleetdm/fleet/v4/server/fleet"
2022-10-05 22:53:54 +00:00
apple_mdm "github.com/fleetdm/fleet/v4/server/mdm/apple"
2024-05-30 21:18:42 +00:00
mdmcrypto "github.com/fleetdm/fleet/v4/server/mdm/crypto"
2024-11-20 17:47:11 +00:00
"github.com/fleetdm/fleet/v4/server/mdm/nanomdm/cryptoutil"
2024-01-12 02:28:48 +00:00
httpmdm "github.com/fleetdm/fleet/v4/server/mdm/nanomdm/http/mdm"
nanomdm_service "github.com/fleetdm/fleet/v4/server/mdm/nanomdm/service"
"github.com/fleetdm/fleet/v4/server/mdm/nanomdm/service/certauth"
"github.com/fleetdm/fleet/v4/server/mdm/nanomdm/service/multi"
"github.com/fleetdm/fleet/v4/server/mdm/nanomdm/service/nanomdm"
2024-02-22 22:24:11 +00:00
scep_depot "github.com/fleetdm/fleet/v4/server/mdm/scep/depot"
scepserver "github.com/fleetdm/fleet/v4/server/mdm/scep/server"
2025-04-10 19:08:45 +00:00
"github.com/fleetdm/fleet/v4/server/service/contract"
2025-02-03 17:23:26 +00:00
"github.com/fleetdm/fleet/v4/server/service/middleware/auth"
2025-02-13 20:32:19 +00:00
"github.com/fleetdm/fleet/v4/server/service/middleware/endpoint_utils"
2025-02-26 16:47:05 +00:00
"github.com/fleetdm/fleet/v4/server/service/middleware/log"
2023-03-27 19:30:29 +00:00
"github.com/fleetdm/fleet/v4/server/service/middleware/mdmconfigured"
Added missing OpenTelemetry instrumentation to several API endpoints. (#32960)
Fixes #32331
Manually tested all paths. `/test` path removed in
https://github.com/fleetdm/fleet/pull/32962
Also added support for sending errors to OpenTelemetry, like we do for
APM/Sentry.
# Checklist for submitter
- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files)
for more information.
## Testing
- [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 OpenTelemetry tracing across core HTTP endpoints (health,
version, assets, metrics, enroll/root, debug, Apple MDM, SCEP, SCIM)
with dynamic per-request route instrumentation.
* Enhanced error reporting to include OpenTelemetry spans/events with
contextual user/host attributes.
* **Tests**
* Added unit tests validating SCIM and error-handling telemetry, span
naming, and sensitive-data redaction.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-09-16 16:10:33 +00:00
"github.com/fleetdm/fleet/v4/server/service/middleware/otel"
2021-06-26 04:46:51 +00:00
"github.com/fleetdm/fleet/v4/server/service/middleware/ratelimit"
2016-08-28 03:59:17 +00:00
kithttp "github.com/go-kit/kit/transport/http"
2024-04-29 19:43:15 +00:00
kitlog "github.com/go-kit/log"
"github.com/go-kit/log/level"
2016-08-28 03:59:17 +00:00
"github.com/gorilla/mux"
2024-11-20 17:47:11 +00:00
nanomdm_log "github.com/micromdm/nanolib/log"
2016-12-22 17:39:44 +00:00
"github.com/prometheus/client_golang/prometheus"
2021-12-20 14:20:58 +00:00
"github.com/prometheus/client_golang/prometheus/promhttp"
2021-03-26 18:23:29 +00:00
"github.com/throttled/throttled/v2"
2023-04-24 05:13:15 +00:00
"go.elastic.co/apm/module/apmgorilla/v2"
2022-02-15 17:42:22 +00:00
otmiddleware "go.opentelemetry.io/contrib/instrumentation/github.com/gorilla/mux/otelmux"
2023-06-22 20:31:17 +00:00
microsoft_mdm "github.com/fleetdm/fleet/v4/server/mdm/microsoft"
2016-08-28 03:59:17 +00:00
)
2021-08-26 13:28:53 +00:00
func checkLicenseExpiration ( svc fleet . Service ) func ( context . Context , http . ResponseWriter ) context . Context {
return func ( ctx context . Context , w http . ResponseWriter ) context . Context {
license , err := svc . License ( ctx )
if err != nil || license == nil {
return ctx
}
2021-09-03 16:05:23 +00:00
if license . IsPremium ( ) && license . IsExpired ( ) {
2021-08-26 13:28:53 +00:00
w . Header ( ) . Set ( fleet . HeaderLicenseKey , fleet . HeaderLicenseValueExpired )
}
return ctx
}
}
2022-04-19 13:35:53 +00:00
type extraHandlerOpts struct {
2025-05-30 22:34:47 +00:00
loginRateLimit * throttled . Rate
mdmSsoRateLimit * throttled . Rate
2025-07-16 18:08:27 +00:00
httpSigVerifier mux . MiddlewareFunc
2022-04-19 13:35:53 +00:00
}
// ExtraHandlerOption allows adding extra configuration to the HTTP handler.
type ExtraHandlerOption func ( * extraHandlerOpts )
2025-05-30 22:34:47 +00:00
// WithLoginRateLimit configures the rate limit for the login endpoints.
2022-04-19 13:35:53 +00:00
func WithLoginRateLimit ( r throttled . Rate ) ExtraHandlerOption {
return func ( o * extraHandlerOpts ) {
o . loginRateLimit = & r
}
}
2025-05-30 22:34:47 +00:00
// WithMdmSsoRateLimit configures the rate limit for the MDM SSO endpoints (falls back to login rate limit otherwise).
func WithMdmSsoRateLimit ( r throttled . Rate ) ExtraHandlerOption {
return func ( o * extraHandlerOpts ) {
o . mdmSsoRateLimit = & r
}
}
2025-07-16 18:08:27 +00:00
func WithHTTPSigVerifier ( m mux . MiddlewareFunc ) ExtraHandlerOption {
return func ( o * extraHandlerOpts ) {
o . httpSigVerifier = m
}
}
2019-01-24 17:39:32 +00:00
// MakeHandler creates an HTTP handler for the Fleet server endpoints.
2022-04-19 13:35:53 +00:00
func MakeHandler (
svc fleet . Service ,
config config . FleetConfig ,
logger kitlog . Logger ,
limitStore throttled . GCRAStore ,
2025-09-26 18:03:50 +00:00
redisPool fleet . RedisPool ,
2025-02-13 20:32:19 +00:00
featureRoutes [ ] endpoint_utils . HandlerRoutesFunc ,
2022-04-19 13:35:53 +00:00
extra ... ExtraHandlerOption ,
) http . Handler {
var eopts extraHandlerOpts
for _ , fn := range extra {
fn ( & eopts )
}
2021-06-04 23:51:18 +00:00
fleetAPIOptions := [ ] kithttp . ServerOption {
2016-09-04 19:43:12 +00:00
kithttp . ServerBefore (
2017-12-01 00:52:23 +00:00
kithttp . PopulateRequestContext , // populate the request context with common fields
2025-02-03 17:23:26 +00:00
auth . SetRequestsContexts ( svc ) ,
2016-09-04 19:43:12 +00:00
) ,
2025-02-13 20:32:19 +00:00
kithttp . ServerErrorHandler ( & endpoint_utils . ErrorHandler { Logger : logger } ) ,
kithttp . ServerErrorEncoder ( endpoint_utils . EncodeError ) ,
2016-09-04 19:43:12 +00:00
kithttp . ServerAfter (
kithttp . SetContentType ( "application/json; charset=utf-8" ) ,
2025-02-26 16:47:05 +00:00
log . LogRequestEnd ( logger ) ,
2021-08-26 13:28:53 +00:00
checkLicenseExpiration ( svc ) ,
2016-09-04 19:43:12 +00:00
) ,
}
2016-08-28 03:59:17 +00:00
2016-09-04 19:43:12 +00:00
r := mux . NewRouter ( )
2023-04-24 05:13:15 +00:00
if config . Logging . TracingEnabled {
if config . Logging . TracingType == "opentelemetry" {
OpenTelemetry minor improvements (#32324)
Fixes #32313
OpenTelemetry Tracing
- Added tracing to async task collectors: FlushHostsLastSeen,
collectHostsLastSeen, collectLabelQueryExecutions,
collectPolicyQueryExecutions, collectScheduledQueryStats
- Updated HTTP middleware to use OTEL semantic convention for span names
({method} {route})
- Added OTELEnabled() helper to FleetConfig
Optimizations
- Reduced OTEL batch size from 512 to 256 spans to prevent gRPC message
size errors
- Enabled gzip compression for trace exports
NOTE: I tried to improve OTEL instrumentation for cron jobs, but it got
too complicated due to goroutines in `schedule.go` so that effort should
be separate. We do have SQL instrumentation for cron jobs, but we are
missing root spans for cron jobs as a whole.
# Checklist for submitter
If some of the following don't apply, delete the relevant line.
- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
## Testing
- [x] QA'd all new/changed functionality manually
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Expanded OpenTelemetry tracing for async tasks (host last seen, label
membership, policy membership, scheduled query stats) to provide richer
observability.
* More descriptive HTTP span names using “METHOD /route” for clearer
trace analysis.
* **Bug Fixes**
* Improved OTLP gRPC exporter reliability by enabling gzip compression
and reducing export batch size, mitigating intermittent gRPC errors.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-08-29 00:32:46 +00:00
r . Use ( otmiddleware . Middleware (
"service" ,
otmiddleware . WithSpanNameFormatter ( func ( route string , r * http . Request ) string {
// Use the guideline for span names: {method} {target}
// See https://opentelemetry.io/docs/specs/semconv/http/http-spans/
return r . Method + " " + route
} ) ) )
2023-04-24 05:13:15 +00:00
} else {
apmgorilla . Instrument ( r )
}
2022-02-15 17:42:22 +00:00
}
2021-02-10 20:13:11 +00:00
2022-03-21 16:29:52 +00:00
r . Use ( publicIP )
2025-07-16 18:08:27 +00:00
if eopts . httpSigVerifier != nil {
r . Use ( eopts . httpSigVerifier )
}
2022-03-21 16:29:52 +00:00
2025-09-26 18:03:50 +00:00
attachFleetAPIRoutes ( r , svc , config , logger , limitStore , redisPool , fleetAPIOptions , eopts )
2025-02-13 20:32:19 +00:00
for _ , featureRoute := range featureRoutes {
featureRoute ( r , fleetAPIOptions )
}
2020-11-13 03:06:56 +00:00
addMetrics ( r )
2016-08-28 03:59:17 +00:00
return r
}
2016-09-26 17:14:39 +00:00
2022-03-21 16:29:52 +00:00
func publicIP ( handler http . Handler ) http . Handler {
return http . HandlerFunc ( func ( w http . ResponseWriter , r * http . Request ) {
2025-02-13 20:32:19 +00:00
ip := endpoint_utils . ExtractIP ( r )
2022-03-21 16:29:52 +00:00
if ip != "" {
r . RemoteAddr = ip
}
handler . ServeHTTP ( w , r . WithContext ( publicip . NewContext ( r . Context ( ) , ip ) ) )
} )
}
2022-04-07 12:40:53 +00:00
// PrometheusMetricsHandler wraps the provided handler with prometheus metrics
2021-12-20 14:20:58 +00:00
// middleware and returns the resulting handler that should be mounted for that
// route.
2022-04-07 12:40:53 +00:00
func PrometheusMetricsHandler ( name string , handler http . Handler ) http . Handler {
2021-12-20 14:20:58 +00:00
reg := prometheus . DefaultRegisterer
registerOrExisting := func ( coll prometheus . Collector ) prometheus . Collector {
if err := reg . Register ( coll ) ; err != nil {
if are , ok := err . ( prometheus . AlreadyRegisteredError ) ; ok {
return are . ExistingCollector
}
panic ( err )
}
return coll
}
// this configuration is to keep prometheus metrics as close as possible to
// what the v0.9.3 (that we used to use) provided via the now-deprecated
// prometheus.InstrumentHandler.
reqCnt := registerOrExisting ( prometheus . NewCounterVec (
prometheus . CounterOpts {
Subsystem : "http" ,
Name : "requests_total" ,
Help : "Total number of HTTP requests made." ,
ConstLabels : prometheus . Labels { "handler" : name } ,
} ,
[ ] string { "method" , "code" } ,
) ) . ( * prometheus . CounterVec )
reqDur := registerOrExisting ( prometheus . NewHistogramVec (
prometheus . HistogramOpts {
Subsystem : "http" ,
Name : "request_duration_seconds" ,
Help : "The HTTP request latencies in seconds." ,
ConstLabels : prometheus . Labels { "handler" : name } ,
// Use default buckets, as they are suited for durations.
} ,
nil ,
) ) . ( * prometheus . HistogramVec )
// 1KB, 100KB, 1MB, 100MB, 1GB
sizeBuckets := [ ] float64 { 1024 , 100 * 1024 , 1024 * 1024 , 100 * 1024 * 1024 , 1024 * 1024 * 1024 }
resSz := registerOrExisting ( prometheus . NewHistogramVec (
prometheus . HistogramOpts {
Subsystem : "http" ,
Name : "response_size_bytes" ,
Help : "The HTTP response sizes in bytes." ,
ConstLabels : prometheus . Labels { "handler" : name } ,
Buckets : sizeBuckets ,
} ,
nil ,
) ) . ( * prometheus . HistogramVec )
reqSz := registerOrExisting ( prometheus . NewHistogramVec (
prometheus . HistogramOpts {
Subsystem : "http" ,
Name : "request_size_bytes" ,
Help : "The HTTP request sizes in bytes." ,
ConstLabels : prometheus . Labels { "handler" : name } ,
Buckets : sizeBuckets ,
} ,
nil ,
) ) . ( * prometheus . HistogramVec )
return promhttp . InstrumentHandlerDuration ( reqDur ,
promhttp . InstrumentHandlerCounter ( reqCnt ,
promhttp . InstrumentHandlerResponseSize ( resSz ,
promhttp . InstrumentHandlerRequestSize ( reqSz , handler ) ) ) )
}
// addMetrics decorates each handler with prometheus instrumentation
2016-12-22 17:39:44 +00:00
func addMetrics ( r * mux . Router ) {
walkFn := func ( route * mux . Route , router * mux . Router , ancestors [ ] * mux . Route ) error {
2022-04-07 12:40:53 +00:00
route . Handler ( PrometheusMetricsHandler ( route . GetName ( ) , route . GetHandler ( ) ) )
2016-12-22 17:39:44 +00:00
return nil
}
2022-12-05 22:50:49 +00:00
r . Walk ( walkFn ) //nolint:errcheck
2016-12-22 17:39:44 +00:00
}
2023-06-15 19:41:04 +00:00
// These are defined as const so that they can be used in tests.
const (
2025-09-26 18:03:50 +00:00
forgotPasswordRateLimitMaxBurst = 9 // Max burst used for rate limiting on the the forgot_password endpoint.
// Fleet Desktop API endpoints rate limiting:
//
// Allow up to 1_000 consecutive failing requests per minute.
// If the threshold of 1_000 consecutive failures is reached for an IP,
// ban requests from such IP for a duration of 1 minute.
//
deviceIPAllowedConsecutiveFailingRequestsCount = 1_000
deviceIPAllowedConsecutiveFailingRequestsTimeWindow = 1 * time . Minute
deviceIPBanTime = 1 * time . Minute
2023-06-15 19:41:04 +00:00
)
2022-07-18 17:22:49 +00:00
2022-03-08 16:27:38 +00:00
func attachFleetAPIRoutes ( r * mux . Router , svc fleet . Service , config config . FleetConfig ,
2025-09-26 18:03:50 +00:00
logger kitlog . Logger , limitStore throttled . GCRAStore , redisPool fleet . RedisPool , opts [ ] kithttp . ServerOption ,
2022-04-19 13:35:53 +00:00
extra extraHandlerOpts ,
Add read replica testing helpers and fix non-sso login bug (#4908)
not set on the INSERT.
- OUT: Only sets the ID on the passed session and returns it. (`CreatedAt`, `AccessedAt`, are not set.)
New version:
```go
func (ds *Datastore) NewSession(ctx context.Context, userID uint, sessionKey string) (*fleet.Session, error) {
sqlStatement := `
INSERT INTO sessions (
user_id,
` + "`key`" + `
)
VALUES(?,?)
`
result, err := ds.writer.ExecContext(ctx, sqlStatement, userID, sessionKey)
if err != nil {
return nil, ctxerr.Wrap(ctx, err, "inserting session")
}
id, _ := result.LastInsertId() // cannot fail with the mysql driver
return ds.sessionByID(ctx, ds.writer, uint(id))
}
```
- IN: Define arguments that are truly used when creating a session.
- OUT: Load and return the fleet.Session struct with all values set (using the `ds.writer` to support read replicas correctly).
PS: The new `NewSession` version mimics what we already do with other entities, like policies (`Datastore.NewGlobalPolicy`).
2022-04-04 23:52:05 +00:00
) {
2022-04-05 15:35:53 +00:00
apiVersions := [ ] string { "v1" , "2022-04" }
2022-03-07 18:10:55 +00:00
// user-authenticated endpoints
2022-04-05 15:35:53 +00:00
ue := newUserAuthenticatedEndpointer ( svc , opts , r , apiVersions ... )
2022-03-07 18:10:55 +00:00
2022-11-30 17:57:42 +00:00
ue . POST ( "/api/_version_/fleet/trigger" , triggerEndpoint , triggerRequest { } )
2022-11-28 19:28:06 +00:00
2025-01-09 18:04:47 +00:00
ue . GET ( "/api/_version_/fleet/me" , meEndpoint , getMeRequest { } )
2022-03-07 18:10:55 +00:00
ue . GET ( "/api/_version_/fleet/sessions/{id:[0-9]+}" , getInfoAboutSessionEndpoint , getInfoAboutSessionRequest { } )
ue . DELETE ( "/api/_version_/fleet/sessions/{id:[0-9]+}" , deleteSessionEndpoint , deleteSessionRequest { } )
ue . GET ( "/api/_version_/fleet/config/certificate" , getCertificateEndpoint , nil )
ue . GET ( "/api/_version_/fleet/config" , getAppConfigEndpoint , nil )
ue . PATCH ( "/api/_version_/fleet/config" , modifyAppConfigEndpoint , modifyAppConfigRequest { } )
ue . POST ( "/api/_version_/fleet/spec/enroll_secret" , applyEnrollSecretSpecEndpoint , applyEnrollSecretSpecRequest { } )
ue . GET ( "/api/_version_/fleet/spec/enroll_secret" , getEnrollSecretSpecEndpoint , nil )
ue . GET ( "/api/_version_/fleet/version" , versionEndpoint , nil )
ue . POST ( "/api/_version_/fleet/users/roles/spec" , applyUserRoleSpecsEndpoint , applyUserRoleSpecsRequest { } )
ue . POST ( "/api/_version_/fleet/translate" , translatorEndpoint , translatorRequest { } )
ue . POST ( "/api/_version_/fleet/spec/teams" , applyTeamSpecsEndpoint , applyTeamSpecsRequest { } )
ue . PATCH ( "/api/_version_/fleet/teams/{team_id:[0-9]+}/secrets" , modifyTeamEnrollSecretsEndpoint , modifyTeamEnrollSecretsRequest { } )
ue . POST ( "/api/_version_/fleet/teams" , createTeamEndpoint , createTeamRequest { } )
ue . GET ( "/api/_version_/fleet/teams" , listTeamsEndpoint , listTeamsRequest { } )
ue . GET ( "/api/_version_/fleet/teams/{id:[0-9]+}" , getTeamEndpoint , getTeamRequest { } )
ue . PATCH ( "/api/_version_/fleet/teams/{id:[0-9]+}" , modifyTeamEndpoint , modifyTeamRequest { } )
ue . DELETE ( "/api/_version_/fleet/teams/{id:[0-9]+}" , deleteTeamEndpoint , deleteTeamRequest { } )
ue . POST ( "/api/_version_/fleet/teams/{id:[0-9]+}/agent_options" , modifyTeamAgentOptionsEndpoint , modifyTeamAgentOptionsRequest { } )
ue . GET ( "/api/_version_/fleet/teams/{id:[0-9]+}/users" , listTeamUsersEndpoint , listTeamUsersRequest { } )
ue . PATCH ( "/api/_version_/fleet/teams/{id:[0-9]+}/users" , addTeamUsersEndpoint , modifyTeamUsersRequest { } )
ue . DELETE ( "/api/_version_/fleet/teams/{id:[0-9]+}/users" , deleteTeamUsersEndpoint , modifyTeamUsersRequest { } )
ue . GET ( "/api/_version_/fleet/teams/{id:[0-9]+}/secrets" , teamEnrollSecretsEndpoint , teamEnrollSecretsRequest { } )
2021-12-21 15:23:12 +00:00
2022-03-07 18:10:55 +00:00
ue . GET ( "/api/_version_/fleet/users" , listUsersEndpoint , listUsersRequest { } )
ue . POST ( "/api/_version_/fleet/users/admin" , createUserEndpoint , createUserRequest { } )
ue . GET ( "/api/_version_/fleet/users/{id:[0-9]+}" , getUserEndpoint , getUserRequest { } )
ue . PATCH ( "/api/_version_/fleet/users/{id:[0-9]+}" , modifyUserEndpoint , modifyUserRequest { } )
ue . DELETE ( "/api/_version_/fleet/users/{id:[0-9]+}" , deleteUserEndpoint , deleteUserRequest { } )
ue . POST ( "/api/_version_/fleet/users/{id:[0-9]+}/require_password_reset" , requirePasswordResetEndpoint , requirePasswordResetRequest { } )
ue . GET ( "/api/_version_/fleet/users/{id:[0-9]+}/sessions" , getInfoAboutSessionsForUserEndpoint , getInfoAboutSessionsForUserRequest { } )
ue . DELETE ( "/api/_version_/fleet/users/{id:[0-9]+}/sessions" , deleteSessionsForUserEndpoint , deleteSessionsForUserRequest { } )
ue . POST ( "/api/_version_/fleet/change_password" , changePasswordEndpoint , changePasswordRequest { } )
ue . GET ( "/api/_version_/fleet/email/change/{token}" , changeEmailEndpoint , changeEmailRequest { } )
2022-06-10 18:29:45 +00:00
// TODO: searchTargetsEndpoint will be removed in Fleet 5.0
2022-03-07 18:10:55 +00:00
ue . POST ( "/api/_version_/fleet/targets" , searchTargetsEndpoint , searchTargetsRequest { } )
2022-06-10 18:29:45 +00:00
ue . POST ( "/api/_version_/fleet/targets/count" , countTargetsEndpoint , countTargetsRequest { } )
2022-03-07 18:10:55 +00:00
ue . POST ( "/api/_version_/fleet/invites" , createInviteEndpoint , createInviteRequest { } )
ue . GET ( "/api/_version_/fleet/invites" , listInvitesEndpoint , listInvitesRequest { } )
ue . DELETE ( "/api/_version_/fleet/invites/{id:[0-9]+}" , deleteInviteEndpoint , deleteInviteRequest { } )
ue . PATCH ( "/api/_version_/fleet/invites/{id:[0-9]+}" , updateInviteEndpoint , updateInviteRequest { } )
2022-04-05 15:35:53 +00:00
ue . EndingAtVersion ( "v1" ) . POST ( "/api/_version_/fleet/global/policies" , globalPolicyEndpoint , globalPolicyRequest { } )
ue . StartingAtVersion ( "2022-04" ) . POST ( "/api/_version_/fleet/policies" , globalPolicyEndpoint , globalPolicyRequest { } )
2023-08-30 22:30:17 +00:00
ue . EndingAtVersion ( "v1" ) . GET ( "/api/_version_/fleet/global/policies" , listGlobalPoliciesEndpoint , listGlobalPoliciesRequest { } )
ue . StartingAtVersion ( "2022-04" ) . GET ( "/api/_version_/fleet/policies" , listGlobalPoliciesEndpoint , listGlobalPoliciesRequest { } )
ue . GET ( "/api/_version_/fleet/policies/count" , countGlobalPoliciesEndpoint , countGlobalPoliciesRequest { } )
2022-04-05 15:35:53 +00:00
ue . EndingAtVersion ( "v1" ) . GET ( "/api/_version_/fleet/global/policies/{policy_id}" , getPolicyByIDEndpoint , getPolicyByIDRequest { } )
ue . StartingAtVersion ( "2022-04" ) . GET ( "/api/_version_/fleet/policies/{policy_id}" , getPolicyByIDEndpoint , getPolicyByIDRequest { } )
ue . EndingAtVersion ( "v1" ) . POST ( "/api/_version_/fleet/global/policies/delete" , deleteGlobalPoliciesEndpoint , deleteGlobalPoliciesRequest { } )
ue . StartingAtVersion ( "2022-04" ) . POST ( "/api/_version_/fleet/policies/delete" , deleteGlobalPoliciesEndpoint , deleteGlobalPoliciesRequest { } )
ue . EndingAtVersion ( "v1" ) . PATCH ( "/api/_version_/fleet/global/policies/{policy_id}" , modifyGlobalPolicyEndpoint , modifyGlobalPolicyRequest { } )
ue . StartingAtVersion ( "2022-04" ) . PATCH ( "/api/_version_/fleet/policies/{policy_id}" , modifyGlobalPolicyEndpoint , modifyGlobalPolicyRequest { } )
2022-12-16 21:00:54 +00:00
ue . POST ( "/api/_version_/fleet/automations/reset" , resetAutomationEndpoint , resetAutomationRequest { } )
2021-12-21 15:23:12 +00:00
// Alias /api/_version_/fleet/team/ -> /api/_version_/fleet/teams/
2022-04-05 15:35:53 +00:00
ue . WithAltPaths ( "/api/_version_/fleet/team/{team_id}/policies" ) .
POST ( "/api/_version_/fleet/teams/{team_id}/policies" , teamPolicyEndpoint , teamPolicyRequest { } )
ue . WithAltPaths ( "/api/_version_/fleet/team/{team_id}/policies" ) .
GET ( "/api/_version_/fleet/teams/{team_id}/policies" , listTeamPoliciesEndpoint , listTeamPoliciesRequest { } )
2023-08-30 22:30:17 +00:00
ue . WithAltPaths ( "/api/_version_/fleet/team/{team_id}/policies/count" ) .
GET ( "/api/_version_/fleet/teams/{team_id}/policies/count" , countTeamPoliciesEndpoint , countTeamPoliciesRequest { } )
2022-04-05 15:35:53 +00:00
ue . WithAltPaths ( "/api/_version_/fleet/team/{team_id}/policies/{policy_id}" ) .
GET ( "/api/_version_/fleet/teams/{team_id}/policies/{policy_id}" , getTeamPolicyByIDEndpoint , getTeamPolicyByIDRequest { } )
ue . WithAltPaths ( "/api/_version_/fleet/team/{team_id}/policies/delete" ) .
POST ( "/api/_version_/fleet/teams/{team_id}/policies/delete" , deleteTeamPoliciesEndpoint , deleteTeamPoliciesRequest { } )
2022-03-07 18:10:55 +00:00
ue . PATCH ( "/api/_version_/fleet/teams/{team_id}/policies/{policy_id}" , modifyTeamPolicyEndpoint , modifyTeamPolicyRequest { } )
ue . POST ( "/api/_version_/fleet/spec/policies" , applyPolicySpecsEndpoint , applyPolicySpecsRequest { } )
ue . GET ( "/api/_version_/fleet/queries/{id:[0-9]+}" , getQueryEndpoint , getQueryRequest { } )
ue . GET ( "/api/_version_/fleet/queries" , listQueriesEndpoint , listQueriesRequest { } )
2023-10-10 12:44:03 +00:00
ue . GET ( "/api/_version_/fleet/queries/{id:[0-9]+}/report" , getQueryReportEndpoint , getQueryReportRequest { } )
2022-03-07 18:10:55 +00:00
ue . POST ( "/api/_version_/fleet/queries" , createQueryEndpoint , createQueryRequest { } )
ue . PATCH ( "/api/_version_/fleet/queries/{id:[0-9]+}" , modifyQueryEndpoint , modifyQueryRequest { } )
ue . DELETE ( "/api/_version_/fleet/queries/{name}" , deleteQueryEndpoint , deleteQueryRequest { } )
ue . DELETE ( "/api/_version_/fleet/queries/id/{id:[0-9]+}" , deleteQueryByIDEndpoint , deleteQueryByIDRequest { } )
ue . POST ( "/api/_version_/fleet/queries/delete" , deleteQueriesEndpoint , deleteQueriesRequest { } )
ue . POST ( "/api/_version_/fleet/spec/queries" , applyQuerySpecsEndpoint , applyQuerySpecsRequest { } )
2023-07-25 00:17:20 +00:00
ue . GET ( "/api/_version_/fleet/spec/queries" , getQuerySpecsEndpoint , getQuerySpecsRequest { } )
ue . GET ( "/api/_version_/fleet/spec/queries/{name}" , getQuerySpecEndpoint , getQuerySpecRequest { } )
2022-03-07 18:10:55 +00:00
ue . GET ( "/api/_version_/fleet/packs/{id:[0-9]+}" , getPackEndpoint , getPackRequest { } )
ue . POST ( "/api/_version_/fleet/packs" , createPackEndpoint , createPackRequest { } )
ue . PATCH ( "/api/_version_/fleet/packs/{id:[0-9]+}" , modifyPackEndpoint , modifyPackRequest { } )
ue . GET ( "/api/_version_/fleet/packs" , listPacksEndpoint , listPacksRequest { } )
ue . DELETE ( "/api/_version_/fleet/packs/{name}" , deletePackEndpoint , deletePackRequest { } )
ue . DELETE ( "/api/_version_/fleet/packs/id/{id:[0-9]+}" , deletePackByIDEndpoint , deletePackByIDRequest { } )
ue . POST ( "/api/_version_/fleet/spec/packs" , applyPackSpecsEndpoint , applyPackSpecsRequest { } )
ue . GET ( "/api/_version_/fleet/spec/packs" , getPackSpecsEndpoint , nil )
ue . GET ( "/api/_version_/fleet/spec/packs/{name}" , getPackSpecEndpoint , getGenericSpecRequest { } )
2023-12-06 14:30:49 +00:00
ue . GET ( "/api/_version_/fleet/software/versions" , listSoftwareVersionsEndpoint , listSoftwareRequest { } )
ue . GET ( "/api/_version_/fleet/software/versions/{id:[0-9]+}" , getSoftwareEndpoint , getSoftwareRequest { } )
// DEPRECATED: use /api/_version_/fleet/software/versions instead
2022-03-07 18:10:55 +00:00
ue . GET ( "/api/_version_/fleet/software" , listSoftwareEndpoint , listSoftwareRequest { } )
2023-12-06 14:30:49 +00:00
// DEPRECATED: use /api/_version_/fleet/software/versions{id:[0-9]+} instead
2022-05-20 16:58:40 +00:00
ue . GET ( "/api/_version_/fleet/software/{id:[0-9]+}" , getSoftwareEndpoint , getSoftwareRequest { } )
2023-12-06 14:30:49 +00:00
// DEPRECATED: software version counts are now included directly in the software version list
2022-03-07 18:10:55 +00:00
ue . GET ( "/api/_version_/fleet/software/count" , countSoftwareEndpoint , countSoftwareRequest { } )
2023-12-06 18:28:31 +00:00
ue . GET ( "/api/_version_/fleet/software/titles" , listSoftwareTitlesEndpoint , listSoftwareTitlesRequest { } )
ue . GET ( "/api/_version_/fleet/software/titles/{id:[0-9]+}" , getSoftwareTitleEndpoint , getSoftwareTitleRequest { } )
2024-09-09 16:13:20 +00:00
ue . POST ( "/api/_version_/fleet/hosts/{host_id:[0-9]+}/software/{software_title_id:[0-9]+}/install" , installSoftwareTitleEndpoint ,
installSoftwareRequest { } )
2024-09-05 19:20:36 +00:00
ue . POST ( "/api/_version_/fleet/hosts/{host_id:[0-9]+}/software/{software_title_id:[0-9]+}/uninstall" , uninstallSoftwareTitleEndpoint ,
uninstallSoftwareRequest { } )
2023-12-06 18:28:31 +00:00
2024-09-17 13:40:47 +00:00
// Software installers
2024-07-17 18:19:13 +00:00
ue . GET ( "/api/_version_/fleet/software/titles/{title_id:[0-9]+}/package" , getSoftwareInstallerEndpoint , getSoftwareInstallerRequest { } )
2024-08-20 17:37:29 +00:00
ue . POST ( "/api/_version_/fleet/software/titles/{title_id:[0-9]+}/package/token" , getSoftwareInstallerTokenEndpoint ,
getSoftwareInstallerRequest { } )
2024-05-02 13:20:54 +00:00
ue . POST ( "/api/_version_/fleet/software/package" , uploadSoftwareInstallerEndpoint , uploadSoftwareInstallerRequest { } )
2025-03-07 17:36:17 +00:00
ue . PATCH ( "/api/_version_/fleet/software/titles/{id:[0-9]+}/name" , updateSoftwareNameEndpoint , updateSoftwareNameRequest { } )
2024-09-17 13:40:47 +00:00
ue . PATCH ( "/api/_version_/fleet/software/titles/{id:[0-9]+}/package" , updateSoftwareInstallerEndpoint , updateSoftwareInstallerRequest { } )
2024-07-17 18:19:13 +00:00
ue . DELETE ( "/api/_version_/fleet/software/titles/{title_id:[0-9]+}/available_for_install" , deleteSoftwareInstallerEndpoint , deleteSoftwareInstallerRequest { } )
2024-09-09 19:43:52 +00:00
ue . GET ( "/api/_version_/fleet/software/install/{install_uuid}/results" , getSoftwareInstallResultsEndpoint ,
getSoftwareInstallResultsRequest { } )
2024-09-20 14:55:47 +00:00
// POST /api/_version_/fleet/software/batch is asynchronous, meaning it will start the process of software download+upload in the background
// and will return a request UUID to be used in GET /api/_version_/fleet/software/batch/{request_uuid} to query for the status of the operation.
2024-05-14 18:06:33 +00:00
ue . POST ( "/api/_version_/fleet/software/batch" , batchSetSoftwareInstallersEndpoint , batchSetSoftwareInstallersRequest { } )
2024-09-20 14:55:47 +00:00
ue . GET ( "/api/_version_/fleet/software/batch/{request_uuid}" , batchSetSoftwareInstallersResultEndpoint , batchSetSoftwareInstallersResultRequest { } )
2024-05-02 13:20:54 +00:00
2025-09-05 22:31:03 +00:00
// software title custom icons
ue . GET ( "/api/_version_/fleet/software/titles/{title_id:[0-9]+}/icon" , getSoftwareTitleIconsEndpoint , getSoftwareTitleIconsRequest { } )
ue . PUT ( "/api/_version_/fleet/software/titles/{title_id:[0-9]+}/icon" , putSoftwareTitleIconEndpoint , putSoftwareTitleIconRequest { } )
ue . DELETE ( "/api/_version_/fleet/software/titles/{title_id:[0-9]+}/icon" , deleteSoftwareTitleIconEndpoint , deleteSoftwareTitleIconRequest { } )
2024-07-11 20:09:30 +00:00
// App store software
ue . GET ( "/api/_version_/fleet/software/app_store_apps" , getAppStoreAppsEndpoint , getAppStoreAppsRequest { } )
ue . POST ( "/api/_version_/fleet/software/app_store_apps" , addAppStoreAppEndpoint , addAppStoreAppRequest { } )
2025-02-03 17:16:21 +00:00
ue . PATCH ( "/api/_version_/fleet/software/titles/{title_id:[0-9]+}/app_store_app" , updateAppStoreAppEndpoint , updateAppStoreAppRequest { } )
2024-07-11 20:09:30 +00:00
2024-10-08 20:41:57 +00:00
// Setup Experience
2025-09-04 15:58:47 +00:00
//
// Setup experience software endpoints:
2024-10-08 20:41:57 +00:00
ue . PUT ( "/api/_version_/fleet/setup_experience/software" , putSetupExperienceSoftware , putSetupExperienceSoftwareRequest { } )
ue . GET ( "/api/_version_/fleet/setup_experience/software" , getSetupExperienceSoftware , getSetupExperienceSoftwareRequest { } )
2025-09-04 15:58:47 +00:00
// Setup experience script endpoints:
2024-10-09 16:43:12 +00:00
ue . GET ( "/api/_version_/fleet/setup_experience/script" , getSetupExperienceScriptEndpoint , getSetupExperienceScriptRequest { } )
ue . POST ( "/api/_version_/fleet/setup_experience/script" , setSetupExperienceScriptEndpoint , setSetupExperienceScriptRequest { } )
ue . DELETE ( "/api/_version_/fleet/setup_experience/script" , deleteSetupExperienceScriptEndpoint , deleteSetupExperienceScriptRequest { } )
2024-10-08 20:41:57 +00:00
2024-09-18 16:21:53 +00:00
// Fleet-maintained apps
ue . POST ( "/api/_version_/fleet/software/fleet_maintained_apps" , addFleetMaintainedAppEndpoint , addFleetMaintainedAppRequest { } )
2024-10-09 14:49:06 +00:00
ue . GET ( "/api/_version_/fleet/software/fleet_maintained_apps" , listFleetMaintainedAppsEndpoint , listFleetMaintainedAppsRequest { } )
2024-09-20 14:42:43 +00:00
ue . GET ( "/api/_version_/fleet/software/fleet_maintained_apps/{app_id}" , getFleetMaintainedApp , getFleetMaintainedAppRequest { } )
2024-09-18 16:21:53 +00:00
2024-02-10 03:54:44 +00:00
// Vulnerabilities
ue . GET ( "/api/_version_/fleet/vulnerabilities" , listVulnerabilitiesEndpoint , listVulnerabilitiesRequest { } )
2024-02-14 21:42:16 +00:00
ue . GET ( "/api/_version_/fleet/vulnerabilities/{cve}" , getVulnerabilityEndpoint , getVulnerabilityRequest { } )
2024-02-10 03:54:44 +00:00
// Hosts
2022-03-07 18:10:55 +00:00
ue . GET ( "/api/_version_/fleet/host_summary" , getHostSummaryEndpoint , getHostSummaryRequest { } )
ue . GET ( "/api/_version_/fleet/hosts" , listHostsEndpoint , listHostsRequest { } )
ue . POST ( "/api/_version_/fleet/hosts/delete" , deleteHostsEndpoint , deleteHostsRequest { } )
ue . GET ( "/api/_version_/fleet/hosts/{id:[0-9]+}" , getHostEndpoint , getHostRequest { } )
ue . GET ( "/api/_version_/fleet/hosts/count" , countHostsEndpoint , countHostsRequest { } )
2022-06-10 18:29:45 +00:00
ue . POST ( "/api/_version_/fleet/hosts/search" , searchHostsEndpoint , searchHostsRequest { } )
2022-03-07 18:10:55 +00:00
ue . GET ( "/api/_version_/fleet/hosts/identifier/{identifier}" , hostByIdentifierEndpoint , hostByIdentifierRequest { } )
2024-02-14 04:45:07 +00:00
ue . POST ( "/api/_version_/fleet/hosts/identifier/{identifier}/query" , runLiveQueryOnHostEndpoint , runLiveQueryOnHostRequest { } )
ue . POST ( "/api/_version_/fleet/hosts/{id:[0-9]+}/query" , runLiveQueryOnHostByIDEndpoint , runLiveQueryOnHostByIDRequest { } )
2022-03-07 18:10:55 +00:00
ue . DELETE ( "/api/_version_/fleet/hosts/{id:[0-9]+}" , deleteHostEndpoint , deleteHostRequest { } )
ue . POST ( "/api/_version_/fleet/hosts/transfer" , addHostsToTeamEndpoint , addHostsToTeamRequest { } )
ue . POST ( "/api/_version_/fleet/hosts/transfer/filter" , addHostsToTeamByFilterEndpoint , addHostsToTeamByFilterRequest { } )
ue . POST ( "/api/_version_/fleet/hosts/{id:[0-9]+}/refetch" , refetchHostEndpoint , refetchHostRequest { } )
2025-04-08 14:35:06 +00:00
// Deprecated: Emails are now included in host details endpoint: /api/_version_/fleet/hosts/{id}
2022-03-07 18:10:55 +00:00
ue . GET ( "/api/_version_/fleet/hosts/{id:[0-9]+}/device_mapping" , listHostDeviceMappingEndpoint , listHostDeviceMappingRequest { } )
2025-05-19 18:29:46 +00:00
// Deprecated: Because the corresponding GET endpoint is deprecated.
// /api/fleet/orbit/device_mapping can be used instead.
// FIXME(sarah): Is this really deprecated? The orbit-authenticated endpoint is not a substitute
// for the user-authenticated endpoint?
2023-12-21 17:21:39 +00:00
ue . PUT ( "/api/_version_/fleet/hosts/{id:[0-9]+}/device_mapping" , putHostDeviceMappingEndpoint , putHostDeviceMappingRequest { } )
2022-03-15 19:14:42 +00:00
ue . GET ( "/api/_version_/fleet/hosts/report" , hostsReportEndpoint , hostsReportRequest { } )
2022-03-28 15:15:45 +00:00
ue . GET ( "/api/_version_/fleet/os_versions" , osVersionsEndpoint , osVersionsRequest { } )
2024-01-31 17:14:24 +00:00
ue . GET ( "/api/_version_/fleet/os_versions/{id:[0-9]+}" , getOSVersionEndpoint , getOSVersionRequest { } )
2023-12-11 22:33:31 +00:00
ue . GET ( "/api/_version_/fleet/hosts/{id:[0-9]+}/queries/{query_id:[0-9]+}" , getHostQueryReportEndpoint , getHostQueryReportRequest { } )
2023-12-06 19:42:29 +00:00
ue . GET ( "/api/_version_/fleet/hosts/{id:[0-9]+}/health" , getHostHealthEndpoint , getHostHealthRequest { } )
2024-04-16 09:37:58 +00:00
ue . POST ( "/api/_version_/fleet/hosts/{id:[0-9]+}/labels" , addLabelsToHostEndpoint , addLabelsToHostRequest { } )
ue . DELETE ( "/api/_version_/fleet/hosts/{id:[0-9]+}/labels" , removeLabelsFromHostEndpoint , removeLabelsFromHostRequest { } )
2024-05-01 18:37:52 +00:00
ue . GET ( "/api/_version_/fleet/hosts/{id:[0-9]+}/software" , getHostSoftwareEndpoint , getHostSoftwareRequest { } )
2025-02-24 17:52:39 +00:00
ue . GET ( "/api/_version_/fleet/hosts/{id:[0-9]+}/certificates" , listHostCertificatesEndpoint , listHostCertificatesRequest { } )
2022-03-07 18:10:55 +00:00
2022-11-01 17:22:07 +00:00
ue . GET ( "/api/_version_/fleet/hosts/summary/mdm" , getHostMDMSummary , getHostMDMSummaryRequest { } )
ue . GET ( "/api/_version_/fleet/hosts/{id:[0-9]+}/mdm" , getHostMDM , getHostMDMRequest { } )
2022-03-07 18:10:55 +00:00
ue . POST ( "/api/_version_/fleet/labels" , createLabelEndpoint , createLabelRequest { } )
ue . PATCH ( "/api/_version_/fleet/labels/{id:[0-9]+}" , modifyLabelEndpoint , modifyLabelRequest { } )
ue . GET ( "/api/_version_/fleet/labels/{id:[0-9]+}" , getLabelEndpoint , getLabelRequest { } )
ue . GET ( "/api/_version_/fleet/labels" , listLabelsEndpoint , listLabelsRequest { } )
2022-06-10 18:29:45 +00:00
ue . GET ( "/api/_version_/fleet/labels/summary" , getLabelsSummaryEndpoint , nil )
2022-03-07 18:10:55 +00:00
ue . GET ( "/api/_version_/fleet/labels/{id:[0-9]+}/hosts" , listHostsInLabelEndpoint , listHostsInLabelRequest { } )
ue . DELETE ( "/api/_version_/fleet/labels/{name}" , deleteLabelEndpoint , deleteLabelRequest { } )
ue . DELETE ( "/api/_version_/fleet/labels/id/{id:[0-9]+}" , deleteLabelByIDEndpoint , deleteLabelByIDRequest { } )
ue . POST ( "/api/_version_/fleet/spec/labels" , applyLabelSpecsEndpoint , applyLabelSpecsRequest { } )
ue . GET ( "/api/_version_/fleet/spec/labels" , getLabelSpecsEndpoint , nil )
ue . GET ( "/api/_version_/fleet/spec/labels/{name}" , getLabelSpecEndpoint , getGenericSpecRequest { } )
2024-01-03 15:39:16 +00:00
// This endpoint runs live queries synchronously (with a configured timeout).
ue . POST ( "/api/_version_/fleet/queries/{id:[0-9]+}/run" , runOneLiveQueryEndpoint , runOneLiveQueryRequest { } )
// Old endpoint, removed from docs. This GET endpoint runs live queries synchronously (with a configured timeout).
2022-03-07 18:10:55 +00:00
ue . GET ( "/api/_version_/fleet/queries/run" , runLiveQueryEndpoint , runLiveQueryRequest { } )
2023-01-30 21:35:56 +00:00
// The following two POST APIs are the asynchronous way to run live queries.
// The live queries are created with these two endpoints and their results can be queried via
// websockets via the `GET /api/_version_/fleet/results/` endpoint.
2022-03-07 18:10:55 +00:00
ue . POST ( "/api/_version_/fleet/queries/run" , createDistributedQueryCampaignEndpoint , createDistributedQueryCampaignRequest { } )
2024-07-09 17:25:01 +00:00
ue . POST ( "/api/_version_/fleet/queries/run_by_identifiers" , createDistributedQueryCampaignByIdentifierEndpoint , createDistributedQueryCampaignByIdentifierRequest { } )
// This endpoint is deprecated and maintained for backwards compatibility. This and above endpoint are functionally equivalent
ue . POST ( "/api/_version_/fleet/queries/run_by_names" , createDistributedQueryCampaignByIdentifierEndpoint , createDistributedQueryCampaignByIdentifierRequest { } )
2022-03-07 18:10:55 +00:00
ue . GET ( "/api/_version_/fleet/activities" , listActivitiesEndpoint , listActivitiesRequest { } )
2022-04-05 15:35:53 +00:00
ue . GET ( "/api/_version_/fleet/packs/{id:[0-9]+}/scheduled" , getScheduledQueriesInPackEndpoint , getScheduledQueriesInPackRequest { } )
ue . EndingAtVersion ( "v1" ) . POST ( "/api/_version_/fleet/schedule" , scheduleQueryEndpoint , scheduleQueryRequest { } )
ue . StartingAtVersion ( "2022-04" ) . POST ( "/api/_version_/fleet/packs/schedule" , scheduleQueryEndpoint , scheduleQueryRequest { } )
ue . GET ( "/api/_version_/fleet/schedule/{id:[0-9]+}" , getScheduledQueryEndpoint , getScheduledQueryRequest { } )
ue . EndingAtVersion ( "v1" ) . PATCH ( "/api/_version_/fleet/schedule/{id:[0-9]+}" , modifyScheduledQueryEndpoint , modifyScheduledQueryRequest { } )
ue . StartingAtVersion ( "2022-04" ) . PATCH ( "/api/_version_/fleet/packs/schedule/{id:[0-9]+}" , modifyScheduledQueryEndpoint , modifyScheduledQueryRequest { } )
ue . EndingAtVersion ( "v1" ) . DELETE ( "/api/_version_/fleet/schedule/{id:[0-9]+}" , deleteScheduledQueryEndpoint , deleteScheduledQueryRequest { } )
ue . StartingAtVersion ( "2022-04" ) . DELETE ( "/api/_version_/fleet/packs/schedule/{id:[0-9]+}" , deleteScheduledQueryEndpoint , deleteScheduledQueryRequest { } )
ue . EndingAtVersion ( "v1" ) . GET ( "/api/_version_/fleet/global/schedule" , getGlobalScheduleEndpoint , getGlobalScheduleRequest { } )
ue . StartingAtVersion ( "2022-04" ) . GET ( "/api/_version_/fleet/schedule" , getGlobalScheduleEndpoint , getGlobalScheduleRequest { } )
ue . EndingAtVersion ( "v1" ) . POST ( "/api/_version_/fleet/global/schedule" , globalScheduleQueryEndpoint , globalScheduleQueryRequest { } )
ue . StartingAtVersion ( "2022-04" ) . POST ( "/api/_version_/fleet/schedule" , globalScheduleQueryEndpoint , globalScheduleQueryRequest { } )
ue . EndingAtVersion ( "v1" ) . PATCH ( "/api/_version_/fleet/global/schedule/{id:[0-9]+}" , modifyGlobalScheduleEndpoint , modifyGlobalScheduleRequest { } )
ue . StartingAtVersion ( "2022-04" ) . PATCH ( "/api/_version_/fleet/schedule/{id:[0-9]+}" , modifyGlobalScheduleEndpoint , modifyGlobalScheduleRequest { } )
ue . EndingAtVersion ( "v1" ) . DELETE ( "/api/_version_/fleet/global/schedule/{id:[0-9]+}" , deleteGlobalScheduleEndpoint , deleteGlobalScheduleRequest { } )
ue . StartingAtVersion ( "2022-04" ) . DELETE ( "/api/_version_/fleet/schedule/{id:[0-9]+}" , deleteGlobalScheduleEndpoint , deleteGlobalScheduleRequest { } )
// Alias /api/_version_/fleet/team/ -> /api/_version_/fleet/teams/
ue . WithAltPaths ( "/api/_version_/fleet/team/{team_id}/schedule" ) .
GET ( "/api/_version_/fleet/teams/{team_id}/schedule" , getTeamScheduleEndpoint , getTeamScheduleRequest { } )
ue . WithAltPaths ( "/api/_version_/fleet/team/{team_id}/schedule" ) .
POST ( "/api/_version_/fleet/teams/{team_id}/schedule" , teamScheduleQueryEndpoint , teamScheduleQueryRequest { } )
ue . WithAltPaths ( "/api/_version_/fleet/team/{team_id}/schedule/{scheduled_query_id}" ) .
PATCH ( "/api/_version_/fleet/teams/{team_id}/schedule/{scheduled_query_id}" , modifyTeamScheduleEndpoint , modifyTeamScheduleRequest { } )
ue . WithAltPaths ( "/api/_version_/fleet/team/{team_id}/schedule/{scheduled_query_id}" ) .
DELETE ( "/api/_version_/fleet/teams/{team_id}/schedule/{scheduled_query_id}" , deleteTeamScheduleEndpoint , deleteTeamScheduleRequest { } )
2022-03-07 18:10:55 +00:00
ue . GET ( "/api/_version_/fleet/carves" , listCarvesEndpoint , listCarvesRequest { } )
ue . GET ( "/api/_version_/fleet/carves/{id:[0-9]+}" , getCarveEndpoint , getCarveRequest { } )
ue . GET ( "/api/_version_/fleet/carves/{id:[0-9]+}/block/{block_id}" , getCarveBlockEndpoint , getCarveBlockRequest { } )
ue . GET ( "/api/_version_/fleet/hosts/{id:[0-9]+}/macadmins" , getMacadminsDataEndpoint , getMacadminsDataRequest { } )
ue . GET ( "/api/_version_/fleet/macadmins" , getAggregatedMacadminsDataEndpoint , getAggregatedMacadminsDataRequest { } )
ue . GET ( "/api/_version_/fleet/status/result_store" , statusResultStoreEndpoint , nil )
ue . GET ( "/api/_version_/fleet/status/live_query" , statusLiveQueryEndpoint , nil )
2023-08-21 18:47:19 +00:00
ue . POST ( "/api/_version_/fleet/scripts/run" , runScriptEndpoint , runScriptRequest { } )
2024-03-05 14:53:17 +00:00
ue . POST ( "/api/_version_/fleet/scripts/run/sync" , runScriptSyncEndpoint , runScriptSyncRequest { } )
2025-04-30 16:54:46 +00:00
ue . POST ( "/api/_version_/fleet/scripts/run/batch" , batchScriptRunEndpoint , batchScriptRunRequest { } )
2023-09-05 20:38:53 +00:00
ue . GET ( "/api/_version_/fleet/scripts/results/{execution_id}" , getScriptResultEndpoint , getScriptResultRequest { } )
2023-10-10 22:00:45 +00:00
ue . POST ( "/api/_version_/fleet/scripts" , createScriptEndpoint , createScriptRequest { } )
ue . GET ( "/api/_version_/fleet/scripts" , listScriptsEndpoint , listScriptsRequest { } )
ue . GET ( "/api/_version_/fleet/scripts/{script_id:[0-9]+}" , getScriptEndpoint , getScriptRequest { } )
2025-01-30 18:01:51 +00:00
ue . PATCH ( "/api/_version_/fleet/scripts/{script_id:[0-9]+}" , updateScriptEndpoint , updateScriptRequest { } )
2023-10-10 22:00:45 +00:00
ue . DELETE ( "/api/_version_/fleet/scripts/{script_id:[0-9]+}" , deleteScriptEndpoint , deleteScriptRequest { } )
ue . POST ( "/api/_version_/fleet/scripts/batch" , batchSetScriptsEndpoint , batchSetScriptsRequest { } )
2025-08-11 19:17:57 +00:00
ue . POST ( "/api/_version_/fleet/scripts/batch/{batch_execution_id:[a-zA-Z0-9-]+}/cancel" , batchScriptCancelEndpoint , batchScriptCancelRequest { } )
2025-08-08 18:24:48 +00:00
// Deprecated, will remove in favor of batchScriptExecutionStatusEndpoint when batch script details page is ready.
2025-05-22 20:07:35 +00:00
ue . GET ( "/api/_version_/fleet/scripts/batch/summary/{batch_execution_id:[a-zA-Z0-9-]+}" , batchScriptExecutionSummaryEndpoint , batchScriptExecutionSummaryRequest { } )
2025-08-27 21:39:43 +00:00
ue . GET ( "/api/_version_/fleet/scripts/batch/{batch_execution_id:[a-zA-Z0-9-]+}/host-results" , batchScriptExecutionHostResultsEndpoint , batchScriptExecutionHostResultsRequest { } )
2025-08-08 18:24:48 +00:00
ue . GET ( "/api/_version_/fleet/scripts/batch/{batch_execution_id:[a-zA-Z0-9-]+}" , batchScriptExecutionStatusEndpoint , batchScriptExecutionStatusRequest { } )
ue . GET ( "/api/_version_/fleet/scripts/batch" , batchScriptExecutionListEndpoint , batchScriptExecutionListRequest { } )
2023-10-10 22:00:45 +00:00
ue . GET ( "/api/_version_/fleet/hosts/{id:[0-9]+}/scripts" , getHostScriptDetailsEndpoint , getHostScriptDetailsRequest { } )
2024-01-29 14:37:54 +00:00
ue . GET ( "/api/_version_/fleet/hosts/{id:[0-9]+}/activities/upcoming" , listHostUpcomingActivitiesEndpoint , listHostUpcomingActivitiesRequest { } )
ue . GET ( "/api/_version_/fleet/hosts/{id:[0-9]+}/activities" , listHostPastActivitiesEndpoint , listHostPastActivitiesRequest { } )
2025-04-01 18:08:56 +00:00
ue . DELETE ( "/api/_version_/fleet/hosts/{id:[0-9]+}/activities/upcoming/{activity_id}" , cancelHostUpcomingActivityEndpoint , cancelHostUpcomingActivityRequest { } )
2024-02-13 18:03:53 +00:00
ue . POST ( "/api/_version_/fleet/hosts/{id:[0-9]+}/lock" , lockHostEndpoint , lockHostRequest { } )
ue . POST ( "/api/_version_/fleet/hosts/{id:[0-9]+}/unlock" , unlockHostEndpoint , unlockHostRequest { } )
2024-02-26 16:31:00 +00:00
ue . POST ( "/api/_version_/fleet/hosts/{id:[0-9]+}/wipe" , wipeHostEndpoint , wipeHostRequest { } )
2023-08-21 18:47:19 +00:00
2024-05-01 22:07:36 +00:00
// Generative AI
ue . POST ( "/api/_version_/fleet/autofill/policy" , autofillPoliciesEndpoint , autofillPoliciesRequest { } )
2024-12-10 21:32:51 +00:00
// Secret variables
2025-08-14 22:33:47 +00:00
ue . PUT ( "/api/_version_/fleet/spec/secret_variables" , createSecretVariablesEndpoint , createSecretVariablesRequest { } )
ue . POST ( "/api/_version_/fleet/custom_variables" , createSecretVariableEndpoint , createSecretVariableRequest { } )
ue . GET ( "/api/_version_/fleet/custom_variables" , listSecretVariablesEndpoint , listSecretVariablesRequest { } )
ue . DELETE ( "/api/_version_/fleet/custom_variables/{id:[0-9]+}" , deleteSecretVariableEndpoint , deleteSecretVariableRequest { } )
2024-12-10 21:32:51 +00:00
2025-04-10 19:08:45 +00:00
// Scim details
ue . GET ( "/api/_version_/fleet/scim/details" , getScimDetailsEndpoint , nil )
2025-06-11 17:22:46 +00:00
// Microsoft Compliance Partner
ue . POST ( "/api/_version_/fleet/conditional-access/microsoft" , conditionalAccessMicrosoftCreateEndpoint , conditionalAccessMicrosoftCreateRequest { } )
ue . POST ( "/api/_version_/fleet/conditional-access/microsoft/confirm" , conditionalAccessMicrosoftConfirmEndpoint , conditionalAccessMicrosoftConfirmRequest { } )
ue . DELETE ( "/api/_version_/fleet/conditional-access/microsoft" , conditionalAccessMicrosoftDeleteEndpoint , conditionalAccessMicrosoftDeleteRequest { } )
2023-01-24 16:57:22 +00:00
// Only Fleet MDM specific endpoints should be within the root /mdm/ path.
2023-05-02 13:09:33 +00:00
// NOTE: remember to update
2023-10-09 21:28:35 +00:00
// `service.mdmConfigurationRequiredEndpoints` when you add an
2023-05-02 13:09:33 +00:00
// endpoint that's behind the mdmConfiguredMiddleware, this applies
// both to this set of endpoints and to any public/token-authenticated
// endpoints using `neMDM` below in this file.
2023-06-22 20:31:17 +00:00
mdmConfiguredMiddleware := mdmconfigured . NewMDMConfigMiddleware ( svc )
mdmAppleMW := ue . WithCustomMiddleware ( mdmConfiguredMiddleware . VerifyAppleMDM ( ) )
2023-11-01 14:13:12 +00:00
// Deprecated: POST /mdm/apple/enqueue is now deprecated, replaced by the
// platform-agnostic POST /mdm/commands/run. It is still supported
// indefinitely for backwards compatibility.
2023-06-22 20:31:17 +00:00
mdmAppleMW . POST ( "/api/_version_/fleet/mdm/apple/enqueue" , enqueueMDMAppleCommandEndpoint , enqueueMDMAppleCommandRequest { } )
2023-11-01 14:13:12 +00:00
// Deprecated: POST /mdm/apple/commandresults is now deprecated, replaced by the
// platform-agnostic POST /mdm/commands/commandresults. It is still supported
// indefinitely for backwards compatibility.
2023-06-22 20:31:17 +00:00
mdmAppleMW . GET ( "/api/_version_/fleet/mdm/apple/commandresults" , getMDMAppleCommandResultsEndpoint , getMDMAppleCommandResultsRequest { } )
2023-11-01 14:13:12 +00:00
// Deprecated: POST /mdm/apple/commands is now deprecated, replaced by the
// platform-agnostic POST /mdm/commands/commands. It is still supported
// indefinitely for backwards compatibility.
2023-06-22 20:31:17 +00:00
mdmAppleMW . GET ( "/api/_version_/fleet/mdm/apple/commands" , listMDMAppleCommandsEndpoint , listMDMAppleCommandsRequest { } )
2023-11-15 15:58:59 +00:00
// Deprecated: those /mdm/apple/profiles/... endpoints are now deprecated,
// replaced by the platform-agnostic /mdm/profiles/... It is still supported
// indefinitely for backwards compatibility.
2023-11-08 16:36:57 +00:00
mdmAppleMW . GET ( "/api/_version_/fleet/mdm/apple/profiles/{profile_id:[0-9]+}" , getMDMAppleConfigProfileEndpoint , getMDMAppleConfigProfileRequest { } )
mdmAppleMW . DELETE ( "/api/_version_/fleet/mdm/apple/profiles/{profile_id:[0-9]+}" , deleteMDMAppleConfigProfileEndpoint , deleteMDMAppleConfigProfileRequest { } )
2023-11-15 15:58:59 +00:00
mdmAppleMW . POST ( "/api/_version_/fleet/mdm/apple/profiles" , newMDMAppleConfigProfileEndpoint , newMDMAppleConfigProfileRequest { } )
2023-11-15 20:36:20 +00:00
mdmAppleMW . GET ( "/api/_version_/fleet/mdm/apple/profiles" , listMDMAppleConfigProfilesEndpoint , listMDMAppleConfigProfilesRequest { } )
2023-11-01 14:13:12 +00:00
2023-11-17 16:49:30 +00:00
// Deprecated: GET /mdm/apple/filevault/summary is now deprecated, replaced by the
// platform-agnostic GET /mdm/disk_encryption/summary. It is still supported indefinitely
// for backwards compatibility.
2023-06-22 20:31:17 +00:00
mdmAppleMW . GET ( "/api/_version_/fleet/mdm/apple/filevault/summary" , getMdmAppleFileVaultSummaryEndpoint , getMDMAppleFileVaultSummaryRequest { } )
2023-11-17 16:49:30 +00:00
// Deprecated: GET /mdm/apple/profiles/summary is now deprecated, replaced by the
// platform-agnostic GET /mdm/profiles/summary. It is still supported indefinitely
// for backwards compatibility.
2023-06-22 20:31:17 +00:00
mdmAppleMW . GET ( "/api/_version_/fleet/mdm/apple/profiles/summary" , getMDMAppleProfilesSummaryEndpoint , getMDMAppleProfilesSummaryRequest { } )
2023-11-17 16:49:30 +00:00
2024-03-13 14:27:29 +00:00
// Deprecated: POST /mdm/apple/enrollment_profile is now deprecated, replaced by the
// POST /enrollment_profiles/automatic endpoint.
2023-06-22 20:31:17 +00:00
mdmAppleMW . POST ( "/api/_version_/fleet/mdm/apple/enrollment_profile" , createMDMAppleSetupAssistantEndpoint , createMDMAppleSetupAssistantRequest { } )
2024-03-13 14:27:29 +00:00
mdmAppleMW . POST ( "/api/_version_/fleet/enrollment_profiles/automatic" , createMDMAppleSetupAssistantEndpoint , createMDMAppleSetupAssistantRequest { } )
// Deprecated: GET /mdm/apple/enrollment_profile is now deprecated, replaced by the
// GET /enrollment_profiles/automatic endpoint.
2023-06-22 20:31:17 +00:00
mdmAppleMW . GET ( "/api/_version_/fleet/mdm/apple/enrollment_profile" , getMDMAppleSetupAssistantEndpoint , getMDMAppleSetupAssistantRequest { } )
2024-03-13 14:27:29 +00:00
mdmAppleMW . GET ( "/api/_version_/fleet/enrollment_profiles/automatic" , getMDMAppleSetupAssistantEndpoint , getMDMAppleSetupAssistantRequest { } )
// Deprecated: DELETE /mdm/apple/enrollment_profile is now deprecated, replaced by the
// DELETE /enrollment_profiles/automatic endpoint.
2023-06-22 20:31:17 +00:00
mdmAppleMW . DELETE ( "/api/_version_/fleet/mdm/apple/enrollment_profile" , deleteMDMAppleSetupAssistantEndpoint , deleteMDMAppleSetupAssistantRequest { } )
2024-03-13 14:27:29 +00:00
mdmAppleMW . DELETE ( "/api/_version_/fleet/enrollment_profiles/automatic" , deleteMDMAppleSetupAssistantEndpoint , deleteMDMAppleSetupAssistantRequest { } )
2023-03-27 19:30:29 +00:00
2023-04-17 15:45:16 +00:00
// TODO: are those undocumented endpoints still needed? I think they were only used
// by 'fleetctl apple-mdm' sub-commands.
2023-06-22 20:31:17 +00:00
mdmAppleMW . POST ( "/api/_version_/fleet/mdm/apple/installers" , uploadAppleInstallerEndpoint , uploadAppleInstallerRequest { } )
mdmAppleMW . GET ( "/api/_version_/fleet/mdm/apple/installers/{installer_id:[0-9]+}" , getAppleInstallerEndpoint , getAppleInstallerDetailsRequest { } )
mdmAppleMW . DELETE ( "/api/_version_/fleet/mdm/apple/installers/{installer_id:[0-9]+}" , deleteAppleInstallerEndpoint , deleteAppleInstallerDetailsRequest { } )
mdmAppleMW . GET ( "/api/_version_/fleet/mdm/apple/installers" , listMDMAppleInstallersEndpoint , listMDMAppleInstallersRequest { } )
mdmAppleMW . GET ( "/api/_version_/fleet/mdm/apple/devices" , listMDMAppleDevicesEndpoint , listMDMAppleDevicesRequest { } )
2024-03-13 14:27:29 +00:00
// Deprecated: GET /mdm/manual_enrollment_profile is now deprecated, replaced by the
// GET /enrollment_profiles/manual endpoint.
2024-10-22 17:05:35 +00:00
// Ref: https://github.com/fleetdm/fleet/issues/16252
2024-01-27 00:57:19 +00:00
mdmAppleMW . GET ( "/api/_version_/fleet/mdm/manual_enrollment_profile" , getManualEnrollmentProfileEndpoint , getManualEnrollmentProfileRequest { } )
2024-03-13 14:27:29 +00:00
mdmAppleMW . GET ( "/api/_version_/fleet/enrollment_profiles/manual" , getManualEnrollmentProfileEndpoint , getManualEnrollmentProfileRequest { } )
2023-04-17 15:45:16 +00:00
2023-04-07 20:31:02 +00:00
// bootstrap-package routes
2024-03-13 14:27:29 +00:00
// Deprecated: POST /mdm/bootstrap is now deprecated, replaced by the
// POST /bootstrap endpoint.
2024-02-07 12:24:24 +00:00
mdmAppleMW . POST ( "/api/_version_/fleet/mdm/bootstrap" , uploadBootstrapPackageEndpoint , uploadBootstrapPackageRequest { } )
2024-03-13 14:27:29 +00:00
mdmAppleMW . POST ( "/api/_version_/fleet/bootstrap" , uploadBootstrapPackageEndpoint , uploadBootstrapPackageRequest { } )
// Deprecated: GET /mdm/bootstrap/:team_id/metadata is now deprecated, replaced by the
// GET /bootstrap/:team_id/metadata endpoint.
2024-02-07 12:24:24 +00:00
mdmAppleMW . GET ( "/api/_version_/fleet/mdm/bootstrap/{team_id:[0-9]+}/metadata" , bootstrapPackageMetadataEndpoint , bootstrapPackageMetadataRequest { } )
2024-03-13 14:27:29 +00:00
mdmAppleMW . GET ( "/api/_version_/fleet/bootstrap/{team_id:[0-9]+}/metadata" , bootstrapPackageMetadataEndpoint , bootstrapPackageMetadataRequest { } )
// Deprecated: DELETE /mdm/bootstrap/:team_id is now deprecated, replaced by the
// DELETE /bootstrap/:team_id endpoint.
2024-02-07 12:24:24 +00:00
mdmAppleMW . DELETE ( "/api/_version_/fleet/mdm/bootstrap/{team_id:[0-9]+}" , deleteBootstrapPackageEndpoint , deleteBootstrapPackageRequest { } )
2024-03-13 14:27:29 +00:00
mdmAppleMW . DELETE ( "/api/_version_/fleet/bootstrap/{team_id:[0-9]+}" , deleteBootstrapPackageEndpoint , deleteBootstrapPackageRequest { } )
// Deprecated: GET /mdm/bootstrap/summary is now deprecated, replaced by the
// GET /bootstrap/summary endpoint.
2024-02-07 12:24:24 +00:00
mdmAppleMW . GET ( "/api/_version_/fleet/mdm/bootstrap/summary" , getMDMAppleBootstrapPackageSummaryEndpoint , getMDMAppleBootstrapPackageSummaryRequest { } )
2024-03-13 14:27:29 +00:00
mdmAppleMW . GET ( "/api/_version_/fleet/bootstrap/summary" , getMDMAppleBootstrapPackageSummaryEndpoint , getMDMAppleBootstrapPackageSummaryRequest { } )
2024-02-07 12:24:24 +00:00
// Deprecated: POST /mdm/apple/bootstrap is now deprecated, replaced by the platform agnostic /mdm/bootstrap
2023-06-22 20:31:17 +00:00
mdmAppleMW . POST ( "/api/_version_/fleet/mdm/apple/bootstrap" , uploadBootstrapPackageEndpoint , uploadBootstrapPackageRequest { } )
2024-02-07 12:24:24 +00:00
// Deprecated: GET /mdm/apple/bootstrap/:team_id/metadata is now deprecated, replaced by the platform agnostic /mdm/bootstrap/:team_id/metadata
2023-06-22 20:31:17 +00:00
mdmAppleMW . GET ( "/api/_version_/fleet/mdm/apple/bootstrap/{team_id:[0-9]+}/metadata" , bootstrapPackageMetadataEndpoint , bootstrapPackageMetadataRequest { } )
2024-02-07 12:24:24 +00:00
// Deprecated: DELETE /mdm/apple/bootstrap/:team_id is now deprecated, replaced by the platform agnostic /mdm/bootstrap/:team_id
2023-06-22 20:31:17 +00:00
mdmAppleMW . DELETE ( "/api/_version_/fleet/mdm/apple/bootstrap/{team_id:[0-9]+}" , deleteBootstrapPackageEndpoint , deleteBootstrapPackageRequest { } )
2024-02-07 12:24:24 +00:00
// Deprecated: GET /mdm/apple/bootstrap/summary is now deprecated, replaced by the platform agnostic /mdm/bootstrap/summary
2023-06-22 20:31:17 +00:00
mdmAppleMW . GET ( "/api/_version_/fleet/mdm/apple/bootstrap/summary" , getMDMAppleBootstrapPackageSummaryEndpoint , getMDMAppleBootstrapPackageSummaryRequest { } )
2023-04-07 20:31:02 +00:00
2023-03-27 19:30:29 +00:00
// host-specific mdm routes
2024-03-13 14:27:29 +00:00
// Deprecated: PATCH /mdm/hosts/:id/unenroll is now deprecated, replaced by
// DELETE /hosts/:id/mdm.
2023-06-22 20:31:17 +00:00
mdmAppleMW . PATCH ( "/api/_version_/fleet/mdm/hosts/{id:[0-9]+}/unenroll" , mdmAppleCommandRemoveEnrollmentProfileEndpoint , mdmAppleCommandRemoveEnrollmentProfileRequest { } )
2024-03-13 14:27:29 +00:00
mdmAppleMW . DELETE ( "/api/_version_/fleet/hosts/{id:[0-9]+}/mdm" , mdmAppleCommandRemoveEnrollmentProfileEndpoint , mdmAppleCommandRemoveEnrollmentProfileRequest { } )
2023-10-09 21:28:35 +00:00
2024-06-17 16:30:53 +00:00
// Deprecated: POST /mdm/hosts/:id/lock is now deprecated, replaced by
// POST /hosts/:id/lock.
2023-06-22 20:31:17 +00:00
mdmAppleMW . POST ( "/api/_version_/fleet/mdm/hosts/{id:[0-9]+}/lock" , deviceLockEndpoint , deviceLockRequest { } )
mdmAppleMW . POST ( "/api/_version_/fleet/mdm/hosts/{id:[0-9]+}/wipe" , deviceWipeEndpoint , deviceWipeRequest { } )
2024-03-13 14:27:29 +00:00
// Deprecated: GET /mdm/hosts/:id/profiles is now deprecated, replaced by
// GET /hosts/:id/configuration_profiles.
2023-07-14 15:53:03 +00:00
mdmAppleMW . GET ( "/api/_version_/fleet/mdm/hosts/{id:[0-9]+}/profiles" , getHostProfilesEndpoint , getHostProfilesRequest { } )
2024-04-12 19:34:54 +00:00
// TODO: Confirm if response should be updated to include Windows profiles and use mdmAnyMW
2024-03-13 14:27:29 +00:00
mdmAppleMW . GET ( "/api/_version_/fleet/hosts/{id:[0-9]+}/configuration_profiles" , getHostProfilesEndpoint , getHostProfilesRequest { } )
2023-03-27 19:30:29 +00:00
2024-03-13 14:27:29 +00:00
// Deprecated: PATCH /mdm/apple/setup is now deprecated, replaced by the
// PATCH /setup_experience endpoint.
2023-06-22 20:31:17 +00:00
mdmAppleMW . PATCH ( "/api/_version_/fleet/mdm/apple/setup" , updateMDMAppleSetupEndpoint , updateMDMAppleSetupRequest { } )
2024-03-13 14:27:29 +00:00
mdmAppleMW . PATCH ( "/api/_version_/fleet/setup_experience" , updateMDMAppleSetupEndpoint , updateMDMAppleSetupRequest { } )
// Deprecated: GET /mdm/apple is now deprecated, replaced by the
// GET /apns endpoint.
2023-06-22 20:31:17 +00:00
mdmAppleMW . GET ( "/api/_version_/fleet/mdm/apple" , getAppleMDMEndpoint , nil )
2024-03-13 14:27:29 +00:00
mdmAppleMW . GET ( "/api/_version_/fleet/apns" , getAppleMDMEndpoint , nil )
2023-03-27 19:30:29 +00:00
2024-02-07 12:24:24 +00:00
// EULA routes
2024-03-13 14:27:29 +00:00
// Deprecated: POST /mdm/setup/eula is now deprecated, replaced by the
// POST /setup_experience/eula endpoint.
2024-02-07 12:24:24 +00:00
mdmAppleMW . POST ( "/api/_version_/fleet/mdm/setup/eula" , createMDMEULAEndpoint , createMDMEULARequest { } )
2024-03-13 14:27:29 +00:00
mdmAppleMW . POST ( "/api/_version_/fleet/setup_experience/eula" , createMDMEULAEndpoint , createMDMEULARequest { } )
// Deprecated: GET /mdm/setup/eula/metadata is now deprecated, replaced by the
// GET /setup_experience/eula/metadata endpoint.
2024-02-07 12:24:24 +00:00
mdmAppleMW . GET ( "/api/_version_/fleet/mdm/setup/eula/metadata" , getMDMEULAMetadataEndpoint , getMDMEULAMetadataRequest { } )
2024-03-13 14:27:29 +00:00
mdmAppleMW . GET ( "/api/_version_/fleet/setup_experience/eula/metadata" , getMDMEULAMetadataEndpoint , getMDMEULAMetadataRequest { } )
// Deprecated: DELETE /mdm/setup/eula/:token is now deprecated, replaced by the
// DELETE /setup_experience/eula/:token endpoint.
2024-02-07 12:24:24 +00:00
mdmAppleMW . DELETE ( "/api/_version_/fleet/mdm/setup/eula/{token}" , deleteMDMEULAEndpoint , deleteMDMEULARequest { } )
2024-03-13 14:27:29 +00:00
mdmAppleMW . DELETE ( "/api/_version_/fleet/setup_experience/eula/{token}" , deleteMDMEULAEndpoint , deleteMDMEULARequest { } )
2024-02-07 12:24:24 +00:00
// Deprecated: POST /mdm/apple/setup/eula is now deprecated, replaced by the platform agnostic /mdm/setup/eula
mdmAppleMW . POST ( "/api/_version_/fleet/mdm/apple/setup/eula" , createMDMEULAEndpoint , createMDMEULARequest { } )
// Deprecated: GET /mdm/apple/setup/eula/metadata is now deprecated, replaced by the platform agnostic /mdm/setup/eula/metadata
mdmAppleMW . GET ( "/api/_version_/fleet/mdm/apple/setup/eula/metadata" , getMDMEULAMetadataEndpoint , getMDMEULAMetadataRequest { } )
// Deprecated: DELETE /mdm/apple/setup/eula/:token is now deprecated, replaced by the platform agnostic /mdm/setup/eula/:token
mdmAppleMW . DELETE ( "/api/_version_/fleet/mdm/apple/setup/eula/{token}" , deleteMDMEULAEndpoint , deleteMDMEULARequest { } )
2023-05-02 13:09:33 +00:00
2023-06-22 20:31:17 +00:00
mdmAppleMW . POST ( "/api/_version_/fleet/mdm/apple/profiles/preassign" , preassignMDMAppleProfileEndpoint , preassignMDMAppleProfileRequest { } )
mdmAppleMW . POST ( "/api/_version_/fleet/mdm/apple/profiles/match" , matchMDMApplePreassignmentEndpoint , matchMDMApplePreassignmentRequest { } )
2023-05-31 13:24:22 +00:00
2023-11-01 14:13:12 +00:00
mdmAnyMW := ue . WithCustomMiddleware ( mdmConfiguredMiddleware . VerifyAppleOrWindowsMDM ( ) )
2024-03-13 14:27:29 +00:00
// Deprecated: POST /mdm/commands/run is now deprecated, replaced by the
// POST /commands/run endpoint.
2023-11-01 14:13:12 +00:00
mdmAnyMW . POST ( "/api/_version_/fleet/mdm/commands/run" , runMDMCommandEndpoint , runMDMCommandRequest { } )
2024-03-13 14:27:29 +00:00
mdmAnyMW . POST ( "/api/_version_/fleet/commands/run" , runMDMCommandEndpoint , runMDMCommandRequest { } )
// Deprecated: GET /mdm/commandresults is now deprecated, replaced by the
// GET /commands/results endpoint.
2023-11-01 14:13:12 +00:00
mdmAnyMW . GET ( "/api/_version_/fleet/mdm/commandresults" , getMDMCommandResultsEndpoint , getMDMCommandResultsRequest { } )
2024-03-13 14:27:29 +00:00
mdmAnyMW . GET ( "/api/_version_/fleet/commands/results" , getMDMCommandResultsEndpoint , getMDMCommandResultsRequest { } )
// Deprecated: GET /mdm/commands is now deprecated, replaced by the
// GET /commands endpoint.
2023-11-01 14:13:12 +00:00
mdmAnyMW . GET ( "/api/_version_/fleet/mdm/commands" , listMDMCommandsEndpoint , listMDMCommandsRequest { } )
2024-03-13 14:27:29 +00:00
mdmAnyMW . GET ( "/api/_version_/fleet/commands" , listMDMCommandsEndpoint , listMDMCommandsRequest { } )
// Deprecated: GET /mdm/disk_encryption/summary is now deprecated, replaced by the
// GET /disk_encryption endpoint.
Linux disk encryption: frontend changes, backend missing private key errors, remove disk encryption endpoints dependence on MDM being enabled (#23714)
## Addresses #22702, #23713, #23756, #23746, #23747, and #23876
_-Note that much of this code as is will render as expected only once
integrated with the backend or if manipulated manually for testing
purposes_
**Frontend**:
- Update banners on my device page, tests
- Build new logic for calling endpoint to trigger linux key escrow on
clicking `Create key`
- Add `CreateLinuxKeyModal` to inform user of next steps after clicking
`Create key`
- Update banners on host details page, tests
- Update the Controls > OS settings section with new logic related to
linux disk encryption
- Expect and include counts of Linux hosts in aggregate disk encryption
stats UI
- Add "Linux" column to the disk encryption table
- Show disk encryption related UI for supported Linux platforms
- TODO: confirm platform string matching functionality in manual e2e
testing
- Expand capabilities of `SectionHeader` component, apply to new UI
- Flash "missing private key" error, with clickable link, when trying to
update disk encryption enabled while no server private key is present.
- TODO: QA this once other endpoints on Controls > Disk encryption are
enabled even when MDM not turned on
- Update Disk encryption key modal copy
-Other TODO:
- Confirm when integrated with API:
- Aggregate disk encryption counts
- Disk encryption table Linux column
- Show disk encryption key action on host details page when expected
- Opens Disk encryption key modal, displays key as expected
**Backend**:
- For "No team" and teams, error when trying to update disk encryption
enabled while no server private key is present.
- Remove requirement of mdm being enabled for use of various endpoints
related to Linux disk encryption
- Update tests
_________
**Host details and my device page banners**

**Create key modal**
<img width="1799" alt="create-key-modal"
src="https://github.com/user-attachments/assets/81a55ccb-b6b9-4eb6-b2ff-a463c60724c0">
**Enabling disk encryption**

**Disk encryption: Fleet free**
<img width="1912" alt="free"
src="https://github.com/user-attachments/assets/9f9cace3-8955-47c2-87d9-24ff9387ac1a">
**Custom settings: turn on MDM**
<img width="1912" alt="turn on mdm"
src="https://github.com/user-attachments/assets/4d3ad47b-4035-4d93-86f0-dc2691b38bb4">
**Device status indicators**

**Encryption key action and modal**

- [x] Changes file added for user-visible changes in `changes/`
- [x] Added/updated tests
- [x] Manual QA for all new/changed functionality
- [ ] Full e2e testing to do when integrated with backend
---------
Co-authored-by: Jacob Shandling <jacob@fleetdm.com>
Co-authored-by: Ian Littman <iansltx@gmail.com>
2024-11-20 19:58:47 +00:00
ue . GET ( "/api/_version_/fleet/mdm/disk_encryption/summary" , getMDMDiskEncryptionSummaryEndpoint , getMDMDiskEncryptionSummaryRequest { } )
ue . GET ( "/api/_version_/fleet/disk_encryption" , getMDMDiskEncryptionSummaryEndpoint , getMDMDiskEncryptionSummaryRequest { } )
2024-03-13 14:27:29 +00:00
// Deprecated: GET /mdm/hosts/:id/encryption_key is now deprecated, replaced by
// GET /hosts/:id/encryption_key.
2024-11-21 00:51:00 +00:00
ue . GET ( "/api/_version_/fleet/mdm/hosts/{id:[0-9]+}/encryption_key" , getHostEncryptionKey , getHostEncryptionKeyRequest { } )
ue . GET ( "/api/_version_/fleet/hosts/{id:[0-9]+}/encryption_key" , getHostEncryptionKey , getHostEncryptionKeyRequest { } )
2023-11-14 13:19:29 +00:00
2024-03-13 14:27:29 +00:00
// Deprecated: GET /mdm/profiles/summary is now deprecated, replaced by the
// GET /configuration_profiles/summary endpoint.
Linux disk encryption: frontend changes, backend missing private key errors, remove disk encryption endpoints dependence on MDM being enabled (#23714)
## Addresses #22702, #23713, #23756, #23746, #23747, and #23876
_-Note that much of this code as is will render as expected only once
integrated with the backend or if manipulated manually for testing
purposes_
**Frontend**:
- Update banners on my device page, tests
- Build new logic for calling endpoint to trigger linux key escrow on
clicking `Create key`
- Add `CreateLinuxKeyModal` to inform user of next steps after clicking
`Create key`
- Update banners on host details page, tests
- Update the Controls > OS settings section with new logic related to
linux disk encryption
- Expect and include counts of Linux hosts in aggregate disk encryption
stats UI
- Add "Linux" column to the disk encryption table
- Show disk encryption related UI for supported Linux platforms
- TODO: confirm platform string matching functionality in manual e2e
testing
- Expand capabilities of `SectionHeader` component, apply to new UI
- Flash "missing private key" error, with clickable link, when trying to
update disk encryption enabled while no server private key is present.
- TODO: QA this once other endpoints on Controls > Disk encryption are
enabled even when MDM not turned on
- Update Disk encryption key modal copy
-Other TODO:
- Confirm when integrated with API:
- Aggregate disk encryption counts
- Disk encryption table Linux column
- Show disk encryption key action on host details page when expected
- Opens Disk encryption key modal, displays key as expected
**Backend**:
- For "No team" and teams, error when trying to update disk encryption
enabled while no server private key is present.
- Remove requirement of mdm being enabled for use of various endpoints
related to Linux disk encryption
- Update tests
_________
**Host details and my device page banners**

**Create key modal**
<img width="1799" alt="create-key-modal"
src="https://github.com/user-attachments/assets/81a55ccb-b6b9-4eb6-b2ff-a463c60724c0">
**Enabling disk encryption**

**Disk encryption: Fleet free**
<img width="1912" alt="free"
src="https://github.com/user-attachments/assets/9f9cace3-8955-47c2-87d9-24ff9387ac1a">
**Custom settings: turn on MDM**
<img width="1912" alt="turn on mdm"
src="https://github.com/user-attachments/assets/4d3ad47b-4035-4d93-86f0-dc2691b38bb4">
**Device status indicators**

**Encryption key action and modal**

- [x] Changes file added for user-visible changes in `changes/`
- [x] Added/updated tests
- [x] Manual QA for all new/changed functionality
- [ ] Full e2e testing to do when integrated with backend
---------
Co-authored-by: Jacob Shandling <jacob@fleetdm.com>
Co-authored-by: Ian Littman <iansltx@gmail.com>
2024-11-20 19:58:47 +00:00
ue . GET ( "/api/_version_/fleet/mdm/profiles/summary" , getMDMProfilesSummaryEndpoint , getMDMProfilesSummaryRequest { } )
ue . GET ( "/api/_version_/fleet/configuration_profiles/summary" , getMDMProfilesSummaryEndpoint , getMDMProfilesSummaryRequest { } )
2024-03-13 14:27:29 +00:00
// Deprecated: GET /mdm/profiles/:profile_uuid is now deprecated, replaced by
// GET /configuration_profiles/:profile_uuid.
2023-12-04 15:04:06 +00:00
mdmAnyMW . GET ( "/api/_version_/fleet/mdm/profiles/{profile_uuid}" , getMDMConfigProfileEndpoint , getMDMConfigProfileRequest { } )
2024-03-13 14:27:29 +00:00
mdmAnyMW . GET ( "/api/_version_/fleet/configuration_profiles/{profile_uuid}" , getMDMConfigProfileEndpoint , getMDMConfigProfileRequest { } )
// Deprecated: DELETE /mdm/profiles/:profile_uuid is now deprecated, replaced by
// DELETE /configuration_profiles/:profile_uuid.
2023-12-04 15:04:06 +00:00
mdmAnyMW . DELETE ( "/api/_version_/fleet/mdm/profiles/{profile_uuid}" , deleteMDMConfigProfileEndpoint , deleteMDMConfigProfileRequest { } )
2024-03-13 14:27:29 +00:00
mdmAnyMW . DELETE ( "/api/_version_/fleet/configuration_profiles/{profile_uuid}" , deleteMDMConfigProfileEndpoint , deleteMDMConfigProfileRequest { } )
// Deprecated: GET /mdm/profiles is now deprecated, replaced by the
// GET /configuration_profiles endpoint.
2023-11-29 14:32:42 +00:00
mdmAnyMW . GET ( "/api/_version_/fleet/mdm/profiles" , listMDMConfigProfilesEndpoint , listMDMConfigProfilesRequest { } )
2024-03-13 14:27:29 +00:00
mdmAnyMW . GET ( "/api/_version_/fleet/configuration_profiles" , listMDMConfigProfilesEndpoint , listMDMConfigProfilesRequest { } )
// Deprecated: POST /mdm/profiles is now deprecated, replaced by the
// POST /configuration_profiles endpoint.
mdmAnyMW . POST ( "/api/_version_/fleet/mdm/profiles" , newMDMConfigProfileEndpoint , newMDMConfigProfileRequest { } )
mdmAnyMW . POST ( "/api/_version_/fleet/configuration_profiles" , newMDMConfigProfileEndpoint , newMDMConfigProfileRequest { } )
2025-09-08 13:52:30 +00:00
mdmAnyMW . POST ( "/api/_version_/fleet/configuration_profiles/batch" , batchModifyMDMConfigProfilesEndpoint , batchModifyMDMConfigProfilesRequest { } )
2024-03-13 14:27:29 +00:00
2024-11-27 20:39:55 +00:00
// Deprecated: POST /hosts/{host_id:[0-9]+}/configuration_profiles/resend/{profile_uuid} is now deprecated, replaced by the
// POST /hosts/{host_id:[0-9]+}/configuration_profiles/{profile_uuid}/resend endpoint.
2024-04-12 19:34:54 +00:00
mdmAnyMW . POST ( "/api/_version_/fleet/hosts/{host_id:[0-9]+}/configuration_profiles/resend/{profile_uuid}" , resendHostMDMProfileEndpoint , resendHostMDMProfileRequest { } )
2024-11-27 20:39:55 +00:00
mdmAnyMW . POST ( "/api/_version_/fleet/hosts/{host_id:[0-9]+}/configuration_profiles/{profile_uuid}/resend" , resendHostMDMProfileEndpoint , resendHostMDMProfileRequest { } )
2025-05-07 20:48:18 +00:00
mdmAnyMW . POST ( "/api/_version_/fleet/configuration_profiles/resend/batch" , batchResendMDMProfileToHostsEndpoint , batchResendMDMProfileToHostsRequest { } )
2025-05-13 12:49:08 +00:00
mdmAnyMW . GET ( "/api/_version_/fleet/configuration_profiles/{profile_uuid}/status" , getMDMConfigProfileStatusEndpoint , getMDMConfigProfileStatusRequest { } )
2024-04-12 19:34:54 +00:00
2024-03-13 14:27:29 +00:00
// Deprecated: PATCH /mdm/apple/settings is deprecated, replaced by POST /disk_encryption.
// It was only used to set disk encryption.
2024-01-03 19:15:09 +00:00
mdmAnyMW . PATCH ( "/api/_version_/fleet/mdm/apple/settings" , updateMDMAppleSettingsEndpoint , updateMDMAppleSettingsRequest { } )
Linux disk encryption: frontend changes, backend missing private key errors, remove disk encryption endpoints dependence on MDM being enabled (#23714)
## Addresses #22702, #23713, #23756, #23746, #23747, and #23876
_-Note that much of this code as is will render as expected only once
integrated with the backend or if manipulated manually for testing
purposes_
**Frontend**:
- Update banners on my device page, tests
- Build new logic for calling endpoint to trigger linux key escrow on
clicking `Create key`
- Add `CreateLinuxKeyModal` to inform user of next steps after clicking
`Create key`
- Update banners on host details page, tests
- Update the Controls > OS settings section with new logic related to
linux disk encryption
- Expect and include counts of Linux hosts in aggregate disk encryption
stats UI
- Add "Linux" column to the disk encryption table
- Show disk encryption related UI for supported Linux platforms
- TODO: confirm platform string matching functionality in manual e2e
testing
- Expand capabilities of `SectionHeader` component, apply to new UI
- Flash "missing private key" error, with clickable link, when trying to
update disk encryption enabled while no server private key is present.
- TODO: QA this once other endpoints on Controls > Disk encryption are
enabled even when MDM not turned on
- Update Disk encryption key modal copy
-Other TODO:
- Confirm when integrated with API:
- Aggregate disk encryption counts
- Disk encryption table Linux column
- Show disk encryption key action on host details page when expected
- Opens Disk encryption key modal, displays key as expected
**Backend**:
- For "No team" and teams, error when trying to update disk encryption
enabled while no server private key is present.
- Remove requirement of mdm being enabled for use of various endpoints
related to Linux disk encryption
- Update tests
_________
**Host details and my device page banners**

**Create key modal**
<img width="1799" alt="create-key-modal"
src="https://github.com/user-attachments/assets/81a55ccb-b6b9-4eb6-b2ff-a463c60724c0">
**Enabling disk encryption**

**Disk encryption: Fleet free**
<img width="1912" alt="free"
src="https://github.com/user-attachments/assets/9f9cace3-8955-47c2-87d9-24ff9387ac1a">
**Custom settings: turn on MDM**
<img width="1912" alt="turn on mdm"
src="https://github.com/user-attachments/assets/4d3ad47b-4035-4d93-86f0-dc2691b38bb4">
**Device status indicators**

**Encryption key action and modal**

- [x] Changes file added for user-visible changes in `changes/`
- [x] Added/updated tests
- [x] Manual QA for all new/changed functionality
- [ ] Full e2e testing to do when integrated with backend
---------
Co-authored-by: Jacob Shandling <jacob@fleetdm.com>
Co-authored-by: Ian Littman <iansltx@gmail.com>
2024-11-20 19:58:47 +00:00
ue . POST ( "/api/_version_/fleet/disk_encryption" , updateDiskEncryptionEndpoint , updateDiskEncryptionRequest { } )
2023-10-09 21:28:35 +00:00
2023-03-27 19:30:29 +00:00
// the following set of mdm endpoints must always be accessible (even
// if MDM is not configured) as it bootstraps the setup of MDM
// (generates CSR request for APNs, plus the SCEP and ABM keypairs).
2024-05-28 15:10:32 +00:00
// Deprecated: this endpoint shouldn't be used anymore in favor of the
// new flow described in https://github.com/fleetdm/fleet/issues/10383
2023-03-27 19:30:29 +00:00
ue . POST ( "/api/_version_/fleet/mdm/apple/request_csr" , requestMDMAppleCSREndpoint , requestMDMAppleCSRRequest { } )
2024-05-28 15:10:32 +00:00
// Deprecated: this endpoint shouldn't be used anymore in favor of the
// new flow described in https://github.com/fleetdm/fleet/issues/10383
2023-02-03 19:02:50 +00:00
ue . POST ( "/api/_version_/fleet/mdm/apple/dep/key_pair" , newMDMAppleDEPKeyPairEndpoint , nil )
2024-05-28 15:10:32 +00:00
ue . GET ( "/api/_version_/fleet/mdm/apple/abm_public_key" , generateABMKeyPairEndpoint , nil )
2024-08-29 22:51:46 +00:00
ue . POST ( "/api/_version_/fleet/abm_tokens" , uploadABMTokenEndpoint , uploadABMTokenRequest { } )
ue . DELETE ( "/api/_version_/fleet/abm_tokens/{id:[0-9]+}" , deleteABMTokenEndpoint , deleteABMTokenRequest { } )
ue . GET ( "/api/_version_/fleet/abm_tokens" , listABMTokensEndpoint , nil )
2024-12-03 16:12:07 +00:00
ue . GET ( "/api/_version_/fleet/abm_tokens/count" , countABMTokensEndpoint , nil )
2024-08-29 22:51:46 +00:00
ue . PATCH ( "/api/_version_/fleet/abm_tokens/{id:[0-9]+}/teams" , updateABMTokenTeamsEndpoint , updateABMTokenTeamsRequest { } )
ue . PATCH ( "/api/_version_/fleet/abm_tokens/{id:[0-9]+}/renew" , renewABMTokenEndpoint , renewABMTokenRequest { } )
2024-03-13 14:27:29 +00:00
2024-05-27 14:13:08 +00:00
ue . GET ( "/api/_version_/fleet/mdm/apple/request_csr" , getMDMAppleCSREndpoint , getMDMAppleCSRRequest { } )
ue . POST ( "/api/_version_/fleet/mdm/apple/apns_certificate" , uploadMDMAppleAPNSCertEndpoint , uploadMDMAppleAPNSCertRequest { } )
ue . DELETE ( "/api/_version_/fleet/mdm/apple/apns_certificate" , deleteMDMAppleAPNSCertEndpoint , deleteMDMAppleAPNSCertRequest { } )
2024-03-13 14:27:29 +00:00
2024-08-29 22:51:46 +00:00
// VPP Tokens
ue . GET ( "/api/_version_/fleet/vpp_tokens" , getVPPTokens , getVPPTokensRequest { } )
ue . POST ( "/api/_version_/fleet/vpp_tokens" , uploadVPPTokenEndpoint , uploadVPPTokenRequest { } )
ue . PATCH ( "/api/_version_/fleet/vpp_tokens/{id}/teams" , patchVPPTokensTeams , patchVPPTokensTeamsRequest { } )
ue . PATCH ( "/api/_version_/fleet/vpp_tokens/{id}/renew" , patchVPPTokenRenewEndpoint , patchVPPTokenRenewRequest { } )
ue . DELETE ( "/api/_version_/fleet/vpp_tokens/{id}" , deleteVPPToken , deleteVPPTokenRequest { } )
// Batch VPP Associations
2024-07-22 17:19:19 +00:00
ue . POST ( "/api/_version_/fleet/software/app_store_apps/batch" , batchAssociateAppStoreAppsEndpoint , batchAssociateAppStoreAppsRequest { } )
2024-07-02 15:46:59 +00:00
2024-03-13 14:27:29 +00:00
// Deprecated: GET /mdm/apple_bm is now deprecated, replaced by the
// GET /abm endpoint.
2022-12-12 20:45:53 +00:00
ue . GET ( "/api/_version_/fleet/mdm/apple_bm" , getAppleBMEndpoint , nil )
2024-08-29 22:51:46 +00:00
// Deprecated: GET /abm is now deprecated, replaced by the GET /abm_tokens endpoint.
2024-03-13 14:27:29 +00:00
ue . GET ( "/api/_version_/fleet/abm" , getAppleBMEndpoint , nil )
2023-11-15 12:37:19 +00:00
// Deprecated: POST /mdm/apple/profiles/batch is now deprecated, replaced by the
2024-03-13 14:27:29 +00:00
// platform-agnostic POST /mdm/profiles/batch. It is still supported
2023-11-15 12:37:19 +00:00
// indefinitely for backwards compatibility.
//
2023-03-27 19:30:29 +00:00
// batch-apply is accessible even though MDM is not enabled, it needs
// to support the case where `fleetctl get config`'s output is used as
// input to `fleetctl apply`
2023-02-15 18:01:44 +00:00
ue . POST ( "/api/_version_/fleet/mdm/apple/profiles/batch" , batchSetMDMAppleProfilesEndpoint , batchSetMDMAppleProfilesRequest { } )
2022-10-05 22:53:54 +00:00
2023-11-29 14:32:42 +00:00
// batch-apply is accessible even though MDM is not enabled, it needs
// to support the case where `fleetctl get config`'s output is used as
// input to `fleetctl apply`
ue . POST ( "/api/_version_/fleet/mdm/profiles/batch" , batchSetMDMProfilesEndpoint , batchSetMDMProfilesRequest { } )
2025-09-04 16:39:41 +00:00
// Certificate Authority endpoints
ue . POST ( "/api/_version_/fleet/certificate_authorities" , createCertificateAuthorityEndpoint , createCertificateAuthorityRequest { } )
ue . GET ( "/api/_version_/fleet/certificate_authorities" , listCertificateAuthoritiesEndpoint , listCertificateAuthoritiesRequest { } )
ue . GET ( "/api/_version_/fleet/certificate_authorities/{id:[0-9]+}" , getCertificateAuthorityEndpoint , getCertificateAuthorityRequest { } )
ue . DELETE ( "/api/_version_/fleet/certificate_authorities/{id:[0-9]+}" , deleteCertificateAuthorityEndpoint , deleteCertificateAuthorityRequest { } )
ue . PATCH ( "/api/_version_/fleet/certificate_authorities/{id:[0-9]+}" , updateCertificateAuthorityEndpoint , updateCertificateAuthorityRequest { } )
ue . POST ( "/api/_version_/fleet/certificate_authorities/{id:[0-9]+}/request_certificate" , requestCertificateEndpoint , requestCertificateRequest { } )
ue . POST ( "/api/_version_/fleet/spec/certificate_authorities" , batchApplyCertificateAuthoritiesEndpoint , batchApplyCertificateAuthoritiesRequest { } )
ue . GET ( "/api/_version_/fleet/spec/certificate_authorities" , getCertificateAuthoritiesSpecEndpoint , getCertificateAuthoritiesSpecRequest { } )
2025-09-26 18:03:50 +00:00
ipBanner := redis . NewIPBanner ( redisPool , "ipbanner::" ,
deviceIPAllowedConsecutiveFailingRequestsCount ,
deviceIPAllowedConsecutiveFailingRequestsTimeWindow ,
deviceIPBanTime ,
)
errorLimiter := ratelimit . NewErrorMiddleware ( ipBanner ) . Limit ( logger )
2022-07-11 13:49:05 +00:00
2025-09-26 18:03:50 +00:00
// Device-authenticated endpoints.
2022-04-05 15:35:53 +00:00
de := newDeviceAuthenticatedEndpointer ( svc , logger , opts , r , apiVersions ... )
2025-09-26 18:03:50 +00:00
de . WithCustomMiddleware ( errorLimiter ) . GET ( "/api/_version_/fleet/device/{token}" , getDeviceHostEndpoint , getDeviceHostRequest { } )
de . WithCustomMiddleware ( errorLimiter ) . GET ( "/api/_version_/fleet/device/{token}/desktop" , getFleetDesktopEndpoint , getFleetDesktopRequest { } )
de . WithCustomMiddleware ( errorLimiter ) . HEAD ( "/api/_version_/fleet/device/{token}/ping" , devicePingEndpoint , deviceAuthPingRequest { } )
de . WithCustomMiddleware ( errorLimiter ) . POST ( "/api/_version_/fleet/device/{token}/refetch" , refetchDeviceHostEndpoint , refetchDeviceHostRequest { } )
de . WithCustomMiddleware ( errorLimiter ) . GET ( "/api/_version_/fleet/device/{token}/device_mapping" , listDeviceHostDeviceMappingEndpoint , listDeviceHostDeviceMappingRequest { } )
de . WithCustomMiddleware ( errorLimiter ) . GET ( "/api/_version_/fleet/device/{token}/macadmins" , getDeviceMacadminsDataEndpoint , getDeviceMacadminsDataRequest { } )
de . WithCustomMiddleware ( errorLimiter ) . GET ( "/api/_version_/fleet/device/{token}/policies" , listDevicePoliciesEndpoint , listDevicePoliciesRequest { } )
de . WithCustomMiddleware ( errorLimiter ) . GET ( "/api/_version_/fleet/device/{token}/transparency" , transparencyURL , transparencyURLRequest { } )
de . WithCustomMiddleware ( errorLimiter ) . POST ( "/api/_version_/fleet/device/{token}/debug/errors" , fleetdError , fleetdErrorRequest { } )
de . WithCustomMiddleware ( errorLimiter ) . GET ( "/api/_version_/fleet/device/{token}/software" , getDeviceSoftwareEndpoint , getDeviceSoftwareRequest { } )
de . WithCustomMiddleware ( errorLimiter ) . POST ( "/api/_version_/fleet/device/{token}/software/install/{software_title_id}" , submitSelfServiceSoftwareInstall , fleetSelfServiceSoftwareInstallRequest { } )
de . WithCustomMiddleware ( errorLimiter ) . POST ( "/api/_version_/fleet/device/{token}/software/uninstall/{software_title_id}" , submitDeviceSoftwareUninstall , fleetDeviceSoftwareUninstallRequest { } )
de . WithCustomMiddleware ( errorLimiter ) . GET ( "/api/_version_/fleet/device/{token}/software/install/{install_uuid}/results" , getDeviceSoftwareInstallResultsEndpoint , getDeviceSoftwareInstallResultsRequest { } )
de . WithCustomMiddleware ( errorLimiter ) . GET ( "/api/_version_/fleet/device/{token}/software/uninstall/{execution_id}/results" , getDeviceSoftwareUninstallResultsEndpoint , getDeviceSoftwareUninstallResultsRequest { } )
de . WithCustomMiddleware ( errorLimiter ) . GET ( "/api/_version_/fleet/device/{token}/certificates" , listDeviceCertificatesEndpoint , listDeviceCertificatesRequest { } )
de . WithCustomMiddleware ( errorLimiter ) . POST ( "/api/_version_/fleet/device/{token}/setup_experience/status" , getDeviceSetupExperienceStatusEndpoint , getDeviceSetupExperienceStatusRequest { } )
de . WithCustomMiddleware ( errorLimiter ) . GET ( "/api/_version_/fleet/device/{token}/software/titles/{software_title_id}/icon" , getDeviceSoftwareIconEndpoint , getDeviceSoftwareIconRequest { } )
de . WithCustomMiddleware ( errorLimiter ) . POST ( "/api/_version_/fleet/device/{token}/mdm/linux/trigger_escrow" , triggerLinuxDiskEncryptionEscrowEndpoint , triggerLinuxDiskEncryptionEscrowRequest { } )
// Device authenticated, Apple MDM endpoints.
2023-06-22 20:31:17 +00:00
demdm := de . WithCustomMiddleware ( mdmConfiguredMiddleware . VerifyAppleMDM ( ) )
2025-09-26 18:03:50 +00:00
demdm . AppendCustomMiddleware ( errorLimiter ) . GET ( "/api/_version_/fleet/device/{token}/mdm/apple/manual_enrollment_profile" , getDeviceMDMManualEnrollProfileEndpoint , getDeviceMDMManualEnrollProfileRequest { } )
demdm . AppendCustomMiddleware ( errorLimiter ) . GET ( "/api/_version_/fleet/device/{token}/software/commands/{command_uuid}/results" , getDeviceMDMCommandResultsEndpoint , getDeviceMDMCommandResultsRequest { } )
demdm . AppendCustomMiddleware ( errorLimiter ) . POST ( "/api/_version_/fleet/device/{token}/configuration_profiles/{profile_uuid}/resend" , resendDeviceConfigurationProfileEndpoint , resendDeviceConfigurationProfileRequest { } )
demdm . AppendCustomMiddleware ( errorLimiter ) . POST ( "/api/_version_/fleet/device/{token}/migrate_mdm" , migrateMDMDeviceEndpoint , deviceMigrateMDMRequest { } )
2024-11-18 22:44:25 +00:00
2022-03-07 18:10:55 +00:00
// host-authenticated endpoints
2022-04-05 15:35:53 +00:00
he := newHostAuthenticatedEndpointer ( svc , logger , opts , r , apiVersions ... )
// Note that the /osquery/ endpoints are *not* versioned, i.e. there is no
// `_version_` placeholder in the path. This is deliberate, see
// https://github.com/fleetdm/fleet/pull/4731#discussion_r838931732 For now
// we add an alias to `/api/v1/osquery` so that it is backwards compatible,
// but even that `v1` is *not* part of the standard versioning, it will still
// work even after we remove support for the `v1` version for the rest of the
// API. This allows us to deprecate osquery endpoints separately.
he . WithAltPaths ( "/api/v1/osquery/config" ) .
POST ( "/api/osquery/config" , getClientConfigEndpoint , getClientConfigRequest { } )
he . WithAltPaths ( "/api/v1/osquery/distributed/read" ) .
POST ( "/api/osquery/distributed/read" , getDistributedQueriesEndpoint , getDistributedQueriesRequest { } )
he . WithAltPaths ( "/api/v1/osquery/distributed/write" ) .
POST ( "/api/osquery/distributed/write" , submitDistributedQueryResultsEndpoint , submitDistributedQueryResultsRequestShim { } )
he . WithAltPaths ( "/api/v1/osquery/carve/begin" ) .
POST ( "/api/osquery/carve/begin" , carveBeginEndpoint , carveBeginRequest { } )
he . WithAltPaths ( "/api/v1/osquery/log" ) .
POST ( "/api/osquery/log" , submitLogsEndpoint , submitLogsRequest { } )
2024-11-13 17:01:08 +00:00
he . WithAltPaths ( "/api/v1/osquery/yara/{name}" ) .
POST ( "/api/osquery/yara/{name}" , getYaraEndpoint , getYaraRequest { } )
2022-03-08 16:27:38 +00:00
2022-09-23 19:00:23 +00:00
// orbit authenticated endpoints
oe := newOrbitAuthenticatedEndpointer ( svc , logger , opts , r , apiVersions ... )
2022-10-10 20:15:35 +00:00
oe . POST ( "/api/fleet/orbit/device_token" , setOrUpdateDeviceTokenEndpoint , setOrUpdateDeviceTokenRequest { } )
2022-09-23 19:00:23 +00:00
oe . POST ( "/api/fleet/orbit/config" , getOrbitConfigEndpoint , orbitGetConfigRequest { } )
2023-08-23 20:47:47 +00:00
// using POST to get a script execution request since all authenticated orbit
// endpoints are POST due to passing the device token in the JSON body.
oe . POST ( "/api/fleet/orbit/scripts/request" , getOrbitScriptEndpoint , orbitGetScriptRequest { } )
oe . POST ( "/api/fleet/orbit/scripts/result" , postOrbitScriptResultEndpoint , orbitPostScriptResultRequest { } )
2023-12-21 17:21:39 +00:00
oe . PUT ( "/api/fleet/orbit/device_mapping" , putOrbitDeviceMappingEndpoint , orbitPutDeviceMappingRequest { } )
2024-05-03 16:03:59 +00:00
oe . POST ( "/api/fleet/orbit/software_install/result" , postOrbitSoftwareInstallResultEndpoint , orbitPostSoftwareInstallResultRequest { } )
2024-05-03 00:08:20 +00:00
oe . POST ( "/api/fleet/orbit/software_install/package" , orbitDownloadSoftwareInstallerEndpoint , orbitDownloadSoftwareInstallerRequest { } )
2024-05-06 19:19:45 +00:00
oe . POST ( "/api/fleet/orbit/software_install/details" , getOrbitSoftwareInstallDetails , orbitGetSoftwareInstallRequest { } )
2025-09-04 15:58:47 +00:00
oe . POST ( "/api/fleet/orbit/setup_experience/init" , orbitSetupExperienceInitEndpoint , orbitSetupExperienceInitRequest { } )
2024-05-06 19:19:45 +00:00
2025-09-16 16:26:00 +00:00
// POST /api/fleet/orbit/setup_experience/status is used by macOS and Linux hosts.
// For macOS hosts we verify Apple MDM is enabled and configured.
oeAppleMDM := oe . WithCustomMiddlewareAfterAuth ( mdmConfiguredMiddleware . VerifyAppleMDMOnMacOSHosts ( ) )
2024-10-09 19:38:13 +00:00
oeAppleMDM . POST ( "/api/fleet/orbit/setup_experience/status" , getOrbitSetupExperienceStatusEndpoint , getOrbitSetupExperienceStatusRequest { } )
2024-10-07 21:16:32 +00:00
2023-10-09 21:28:35 +00:00
oeWindowsMDM := oe . WithCustomMiddleware ( mdmConfiguredMiddleware . VerifyWindowsMDM ( ) )
oeWindowsMDM . POST ( "/api/fleet/orbit/disk_encryption_key" , postOrbitDiskEncryptionKeyEndpoint , orbitPostDiskEncryptionKeyRequest { } )
2024-11-18 22:44:25 +00:00
oe . POST ( "/api/fleet/orbit/luks_data" , postOrbitLUKSEndpoint , orbitPostLUKSRequest { } )
2022-03-08 16:27:38 +00:00
// unauthenticated endpoints - most of those are either login-related,
// invite-related or host-enrolling. So they typically do some kind of
// one-time authentication by verifying that a valid secret token is provided
// with the request.
2022-04-05 15:35:53 +00:00
ne := newNoAuthEndpointer ( svc , opts , r , apiVersions ... )
ne . WithAltPaths ( "/api/v1/osquery/enroll" ) .
2025-07-16 18:08:27 +00:00
POST ( "/api/osquery/enroll" , enrollAgentEndpoint , contract . EnrollOsqueryAgentRequest { } )
2022-04-05 15:35:53 +00:00
2023-03-27 19:30:29 +00:00
// These endpoint are token authenticated.
2023-05-02 13:09:33 +00:00
// NOTE: remember to update
2023-10-09 21:28:35 +00:00
// `service.mdmConfigurationRequiredEndpoints` when you add an
2023-05-02 13:09:33 +00:00
// endpoint that's behind the mdmConfiguredMiddleware, this applies
// both to this set of endpoints and to any user authenticated
2023-06-22 20:31:17 +00:00
// endpoints using `mdmAppleMW.*` above in this file.
neAppleMDM := ne . WithCustomMiddleware ( mdmConfiguredMiddleware . VerifyAppleMDM ( ) )
neAppleMDM . GET ( apple_mdm . EnrollPath , mdmAppleEnrollEndpoint , mdmAppleEnrollRequest { } )
2025-05-20 19:50:48 +00:00
neAppleMDM . POST ( apple_mdm . EnrollPath , mdmAppleEnrollEndpoint , mdmAppleEnrollRequest { } )
2025-07-15 19:02:11 +00:00
2023-06-22 20:31:17 +00:00
neAppleMDM . GET ( apple_mdm . InstallerPath , mdmAppleGetInstallerEndpoint , mdmAppleGetInstallerRequest { } )
neAppleMDM . HEAD ( apple_mdm . InstallerPath , mdmAppleHeadInstallerEndpoint , mdmAppleHeadInstallerRequest { } )
2024-09-10 19:52:17 +00:00
neAppleMDM . POST ( "/api/_version_/fleet/ota_enrollment" , mdmAppleOTAEndpoint , mdmAppleOTARequest { } )
2024-03-13 14:27:29 +00:00
// Deprecated: GET /mdm/bootstrap is now deprecated, replaced by the
// GET /bootstrap endpoint.
2024-02-07 12:24:24 +00:00
neAppleMDM . GET ( "/api/_version_/fleet/mdm/bootstrap" , downloadBootstrapPackageEndpoint , downloadBootstrapPackageRequest { } )
2024-03-13 14:27:29 +00:00
neAppleMDM . GET ( "/api/_version_/fleet/bootstrap" , downloadBootstrapPackageEndpoint , downloadBootstrapPackageRequest { } )
2024-02-07 12:24:24 +00:00
// Deprecated: GET /mdm/apple/bootstrap is now deprecated, replaced by the platform agnostic /mdm/bootstrap
2023-06-22 20:31:17 +00:00
neAppleMDM . GET ( "/api/_version_/fleet/mdm/apple/bootstrap" , downloadBootstrapPackageEndpoint , downloadBootstrapPackageRequest { } )
2024-03-13 14:27:29 +00:00
// Deprecated: GET /mdm/setup/eula/:token is now deprecated, replaced by the
// GET /setup_experience/eula/:token endpoint.
2024-02-07 12:24:24 +00:00
neAppleMDM . GET ( "/api/_version_/fleet/mdm/setup/eula/{token}" , getMDMEULAEndpoint , getMDMEULARequest { } )
2024-03-13 14:27:29 +00:00
neAppleMDM . GET ( "/api/_version_/fleet/setup_experience/eula/{token}" , getMDMEULAEndpoint , getMDMEULARequest { } )
2024-02-07 12:24:24 +00:00
// Deprecated: GET /mdm/apple/setup/eula/:token is now deprecated, replaced by the platform agnostic /mdm/setup/eula/:token
neAppleMDM . GET ( "/api/_version_/fleet/mdm/apple/setup/eula/{token}" , getMDMEULAEndpoint , getMDMEULARequest { } )
2023-06-22 20:31:17 +00:00
2024-09-05 11:47:34 +00:00
// Get OTA profile
neAppleMDM . GET ( "/api/_version_/fleet/enrollment_profiles/ota" , getOTAProfileEndpoint , getOTAProfileRequest { } )
2025-07-15 19:02:11 +00:00
// This is the account-driven enrollment endpoint for BYoD Apple devices, also known as User Enrollment.
neAppleMDM . POST ( apple_mdm . AccountDrivenEnrollPath , mdmAppleAccountEnrollEndpoint , mdmAppleAccountEnrollRequest { } )
// This is for OAUTH2 token based auth
// ne.POST(apple_mdm.EnrollPath+"/token", mdmAppleAccountEnrollTokenEndpoint, mdmAppleAccountEnrollTokenRequest{})
2023-06-22 20:31:17 +00:00
// These endpoint are used by Microsoft devices during MDM device enrollment phase
2023-06-27 15:59:33 +00:00
neWindowsMDM := ne . WithCustomMiddleware ( mdmConfiguredMiddleware . VerifyWindowsMDM ( ) )
2023-06-22 20:31:17 +00:00
2023-07-19 16:30:24 +00:00
// Microsoft MS-MDE2 Endpoints
// This endpoint is unauthenticated and is used by Microsoft devices to discover the MDM server endpoints
2023-06-27 15:59:33 +00:00
neWindowsMDM . POST ( microsoft_mdm . MDE2DiscoveryPath , mdmMicrosoftDiscoveryEndpoint , SoapRequestContainer { } )
2023-07-19 16:30:24 +00:00
// This endpoint is unauthenticated and is used by Microsoft devices to retrieve the opaque STS auth token
neWindowsMDM . GET ( microsoft_mdm . MDE2AuthPath , mdmMicrosoftAuthEndpoint , SoapRequestContainer { } )
2023-06-27 15:59:33 +00:00
// This endpoint is authenticated using the BinarySecurityToken header field
neWindowsMDM . POST ( microsoft_mdm . MDE2PolicyPath , mdmMicrosoftPolicyEndpoint , SoapRequestContainer { } )
2022-10-05 22:53:54 +00:00
2023-07-05 13:06:37 +00:00
// This endpoint is authenticated using the BinarySecurityToken header field
neWindowsMDM . POST ( microsoft_mdm . MDE2EnrollPath , mdmMicrosoftEnrollEndpoint , SoapRequestContainer { } )
2023-07-20 14:54:04 +00:00
// This endpoint is unauthenticated for now
// It should be authenticated through TLS headers once proper implementation is in place
neWindowsMDM . POST ( microsoft_mdm . MDE2ManagementPath , mdmMicrosoftManagementEndpoint , SyncMLReqMsgContainer { } )
2023-07-21 17:36:26 +00:00
// This endpoint is unauthenticated and is used by to retrieve the MDM enrollment Terms of Use
neWindowsMDM . GET ( microsoft_mdm . MDE2TOSPath , mdmMicrosoftTOSEndpoint , MDMWebContainer { } )
2025-07-16 18:08:27 +00:00
ne . POST ( "/api/fleet/orbit/enroll" , enrollOrbitEndpoint , contract . EnrollOrbitRequest { } )
2022-09-23 19:00:23 +00:00
2022-04-19 13:35:53 +00:00
// For some reason osquery does not provide a node key with the block data.
// Instead the carve session ID should be verified in the service method.
2022-04-05 15:35:53 +00:00
ne . WithAltPaths ( "/api/v1/osquery/carve/block" ) .
POST ( "/api/osquery/carve/block" , carveBlockEndpoint , carveBlockRequest { } )
2022-03-08 16:27:38 +00:00
2024-08-20 17:37:29 +00:00
ne . GET ( "/api/_version_/fleet/software/titles/{title_id:[0-9]+}/package/token/{token}" , downloadSoftwareInstallerEndpoint ,
downloadSoftwareInstallerRequest { } )
2022-03-08 16:27:38 +00:00
ne . POST ( "/api/_version_/fleet/perform_required_password_reset" , performRequiredPasswordResetEndpoint , performRequiredPasswordResetRequest { } )
ne . POST ( "/api/_version_/fleet/users" , createUserFromInviteEndpoint , createUserRequest { } )
ne . GET ( "/api/_version_/fleet/invites/{token}" , verifyInviteEndpoint , verifyInviteRequest { } )
ne . POST ( "/api/_version_/fleet/reset_password" , resetPasswordEndpoint , resetPasswordRequest { } )
ne . POST ( "/api/_version_/fleet/logout" , logoutEndpoint , nil )
2022-04-20 16:46:45 +00:00
ne . POST ( "/api/v1/fleet/sso" , initiateSSOEndpoint , initiateSSORequest { } )
ne . POST ( "/api/v1/fleet/sso/callback" , makeCallbackSSOEndpoint ( config . Server . URLPrefix ) , callbackSSORequest { } )
ne . GET ( "/api/v1/fleet/sso" , settingsSSOEndpoint , nil )
2022-07-01 19:52:55 +00:00
2022-04-20 19:57:26 +00:00
// the websocket distributed query results endpoint is a bit different - the
// provided path is a prefix, not an exact match, and it is not a go-kit
// endpoint but a raw http.Handler. It uses the NoAuthEndpointer because
// authentication is done when the websocket session is established, inside
// the handler.
2025-02-18 17:09:43 +00:00
ne . UsePathPrefix ( ) . PathHandler ( "GET" , "/api/_version_/fleet/results/" ,
makeStreamDistributedQueryCampaignResultsHandler ( config . Server , svc , logger ) )
2022-03-08 16:27:38 +00:00
2023-06-15 19:41:04 +00:00
quota := throttled . RateQuota { MaxRate : throttled . PerHour ( 10 ) , MaxBurst : forgotPasswordRateLimitMaxBurst }
2022-03-08 16:27:38 +00:00
limiter := ratelimit . NewMiddleware ( limitStore )
ne .
2022-07-11 13:49:05 +00:00
WithCustomMiddleware ( limiter . Limit ( "forgot_password" , quota ) ) .
2022-03-08 16:27:38 +00:00
POST ( "/api/_version_/fleet/forgot_password" , forgotPasswordEndpoint , forgotPasswordRequest { } )
2025-06-02 22:18:58 +00:00
// By default, MDM SSO shares the login rate limit bucket; if MDM SSO limit is overridden, MDM SSO gets its
// own rate limit bucket.
loginRateLimit := throttled . PerMin ( 10 )
2022-04-19 13:35:53 +00:00
if extra . loginRateLimit != nil {
loginRateLimit = * extra . loginRateLimit
}
2025-06-02 22:18:58 +00:00
loginLimiter := limiter . Limit ( "login" , throttled . RateQuota { MaxRate : loginRateLimit , MaxBurst : 9 } )
mdmSsoLimiter := loginLimiter
2025-05-30 22:34:47 +00:00
if extra . mdmSsoRateLimit != nil {
2025-06-02 22:18:58 +00:00
mdmSsoLimiter = limiter . Limit ( "mdm_sso" , throttled . RateQuota { MaxRate : * extra . mdmSsoRateLimit , MaxBurst : 9 } )
2025-05-30 22:34:47 +00:00
}
2022-04-19 13:35:53 +00:00
2025-06-02 22:18:58 +00:00
ne . WithCustomMiddleware ( loginLimiter ) .
2025-04-10 19:08:45 +00:00
POST ( "/api/_version_/fleet/login" , loginEndpoint , contract . LoginRequest { } )
2024-12-05 14:37:10 +00:00
ne . WithCustomMiddleware ( limiter . Limit ( "mfa" , throttled . RateQuota { MaxRate : loginRateLimit , MaxBurst : 9 } ) ) .
POST ( "/api/_version_/fleet/sessions" , sessionCreateEndpoint , sessionCreateRequest { } )
add headers denoting capabilities between fleet server / desktop / orbit (#7833)
This adds a new mechanism to allow us to handle compatibility issues between Orbit, Fleet Server and Fleet Desktop.
The general idea is to _always_ send a custom header of the form:
```
fleet-capabilities-header = "X-Fleet-Capabilities:" capabilities
capabilities = capability * (,)
capability = string
```
Both from the server to the clients (Orbit, Fleet Desktop) and vice-versa. For an example, see: https://github.com/fleetdm/fleet/commit/8c0bbdd291f54e03e19766bcdfead0fb8067f60c
Also, the following applies:
- Backwards compat: if the header is not present, assume that orbit/fleet doesn't have the capability
- The current capabilities endpoint will be removed
### Motivation
This solution is trying to solve the following problems:
- We have three independent processes communicating with each other (Fleet Desktop, Orbit and Fleet Server). Each process can be updated independently, and therefore we need a way for each process to know what features are supported by its peers.
- We originally implemented a dedicated API endpoint in the server that returned a list of the capabilities (or "features") enabled, we found this, and any other server-only solution (like API versioning) to be insufficient because:
- There are cases in which the server also needs to know which features are supported by its clients
- Clients needed to poll for changes to detect if the capabilities supported by the server change, by sending the capabilities on each request we have a much cleaner way to handling different responses.
- We are also introducing an unauthenticated endpoint to get the server features, this gives us flexibility if we need to implement different authentication mechanisms, and was one of the pitfalls of the first implementation.
Related to https://github.com/fleetdm/fleet/issues/7929
2022-09-26 10:53:53 +00:00
2024-01-25 18:05:52 +00:00
ne . HEAD ( "/api/fleet/device/ping" , devicePingEndpoint , devicePingRequest { } )
add headers denoting capabilities between fleet server / desktop / orbit (#7833)
This adds a new mechanism to allow us to handle compatibility issues between Orbit, Fleet Server and Fleet Desktop.
The general idea is to _always_ send a custom header of the form:
```
fleet-capabilities-header = "X-Fleet-Capabilities:" capabilities
capabilities = capability * (,)
capability = string
```
Both from the server to the clients (Orbit, Fleet Desktop) and vice-versa. For an example, see: https://github.com/fleetdm/fleet/commit/8c0bbdd291f54e03e19766bcdfead0fb8067f60c
Also, the following applies:
- Backwards compat: if the header is not present, assume that orbit/fleet doesn't have the capability
- The current capabilities endpoint will be removed
### Motivation
This solution is trying to solve the following problems:
- We have three independent processes communicating with each other (Fleet Desktop, Orbit and Fleet Server). Each process can be updated independently, and therefore we need a way for each process to know what features are supported by its peers.
- We originally implemented a dedicated API endpoint in the server that returned a list of the capabilities (or "features") enabled, we found this, and any other server-only solution (like API versioning) to be insufficient because:
- There are cases in which the server also needs to know which features are supported by its clients
- Clients needed to poll for changes to detect if the capabilities supported by the server change, by sending the capabilities on each request we have a much cleaner way to handling different responses.
- We are also introducing an unauthenticated endpoint to get the server features, this gives us flexibility if we need to implement different authentication mechanisms, and was one of the pitfalls of the first implementation.
Related to https://github.com/fleetdm/fleet/issues/7929
2022-09-26 10:53:53 +00:00
2024-01-25 18:05:52 +00:00
ne . HEAD ( "/api/fleet/orbit/ping" , orbitPingEndpoint , orbitPingRequest { } )
2023-04-27 12:43:20 +00:00
2024-07-08 15:20:03 +00:00
// This is a callback endpoint for calendar integration -- it is called to notify an event change in a user calendar
2024-07-24 11:40:33 +00:00
ne . POST ( "/api/_version_/fleet/calendar/webhook/{event_uuid}" , calendarWebhookEndpoint , calendarWebhookRequest { } )
2024-07-08 15:20:03 +00:00
2025-06-02 22:18:58 +00:00
neAppleMDM . WithCustomMiddleware ( mdmSsoLimiter ) .
2025-08-18 16:31:53 +00:00
POST ( "/api/_version_/fleet/mdm/sso" , initiateMDMSSOEndpoint , initiateMDMSSORequest { } )
ne . WithCustomMiddleware ( mdmSsoLimiter ) .
POST ( "/api/_version_/fleet/mdm/sso/callback" , callbackMDMSSOEndpoint , callbackMDMSSORequest { } )
2021-07-16 18:28:13 +00:00
}
2020-11-18 19:10:55 +00:00
// WithSetup is an http middleware that checks if setup procedures have been completed.
2017-02-09 18:43:45 +00:00
// If setup hasn't been completed it serves the API with a setup middleware.
2016-11-09 17:19:07 +00:00
// If the server is already configured, the default API handler is exposed.
2021-06-06 22:07:29 +00:00
func WithSetup ( svc fleet . Service , logger kitlog . Logger , next http . Handler ) http . HandlerFunc {
2022-03-08 16:27:38 +00:00
rxOsquery := regexp . MustCompile ( ` ^/api/[^/]+/osquery ` )
2016-12-02 18:46:31 +00:00
return func ( w http . ResponseWriter , r * http . Request ) {
configRouter := http . NewServeMux ( )
2022-04-20 19:57:26 +00:00
srv := kithttp . NewServer (
Add read replica testing helpers and fix non-sso login bug (#4908)
not set on the INSERT.
- OUT: Only sets the ID on the passed session and returns it. (`CreatedAt`, `AccessedAt`, are not set.)
New version:
```go
func (ds *Datastore) NewSession(ctx context.Context, userID uint, sessionKey string) (*fleet.Session, error) {
sqlStatement := `
INSERT INTO sessions (
user_id,
` + "`key`" + `
)
VALUES(?,?)
`
result, err := ds.writer.ExecContext(ctx, sqlStatement, userID, sessionKey)
if err != nil {
return nil, ctxerr.Wrap(ctx, err, "inserting session")
}
id, _ := result.LastInsertId() // cannot fail with the mysql driver
return ds.sessionByID(ctx, ds.writer, uint(id))
}
```
- IN: Define arguments that are truly used when creating a session.
- OUT: Load and return the fleet.Session struct with all values set (using the `ds.writer` to support read replicas correctly).
PS: The new `NewSession` version mimics what we already do with other entities, like policies (`Datastore.NewGlobalPolicy`).
2022-04-04 23:52:05 +00:00
makeSetupEndpoint ( svc , logger ) ,
2016-12-02 18:46:31 +00:00
decodeSetupRequest ,
encodeResponse ,
2022-04-20 19:57:26 +00:00
)
// NOTE: support setup on both /v1/ and version-less, in the future /v1/
// will be dropped.
configRouter . Handle ( "/api/v1/setup" , srv )
configRouter . Handle ( "/api/setup" , srv )
2017-01-12 00:40:58 +00:00
// whitelist osqueryd endpoints
2022-03-08 16:27:38 +00:00
if rxOsquery . MatchString ( r . URL . Path ) {
2017-01-12 00:40:58 +00:00
next . ServeHTTP ( w , r )
return
}
2021-06-03 23:24:15 +00:00
requireSetup , err := svc . SetupRequired ( context . Background ( ) )
2017-02-09 18:43:45 +00:00
if err != nil {
logger . Log ( "msg" , "fetching setup info from db" , "err" , err )
w . WriteHeader ( http . StatusInternalServerError )
return
}
if requireSetup {
2016-12-02 18:46:31 +00:00
configRouter . ServeHTTP ( w , r )
2017-02-09 18:43:45 +00:00
return
2016-12-02 18:46:31 +00:00
}
2017-02-09 18:43:45 +00:00
next . ServeHTTP ( w , r )
2016-11-09 17:19:07 +00:00
}
}
2016-12-29 23:36:36 +00:00
// RedirectLoginToSetup detects if the setup endpoint should be used. If setup is required it redirect all
// frontend urls to /setup, otherwise the frontend router is used.
2021-06-06 22:07:29 +00:00
func RedirectLoginToSetup ( svc fleet . Service , logger kitlog . Logger , next http . Handler , urlPrefix string ) http . HandlerFunc {
2016-12-29 23:36:36 +00:00
return func ( w http . ResponseWriter , r * http . Request ) {
redirect := http . HandlerFunc ( func ( w http . ResponseWriter , r * http . Request ) {
2017-09-01 16:42:46 +00:00
if r . URL . Path == "/setup" {
2016-12-29 23:36:36 +00:00
next . ServeHTTP ( w , r )
return
}
newURL := r . URL
2019-10-16 23:40:45 +00:00
newURL . Path = urlPrefix + "/setup"
2016-12-29 23:36:36 +00:00
http . Redirect ( w , r , newURL . String ( ) , http . StatusTemporaryRedirect )
} )
2017-02-09 18:43:45 +00:00
2021-06-03 23:24:15 +00:00
setupRequired , err := svc . SetupRequired ( context . Background ( ) )
2017-02-09 18:43:45 +00:00
if err != nil {
2017-09-01 16:42:46 +00:00
logger . Log ( "msg" , "fetching setupinfo from db" , "err" , err )
2017-02-09 18:43:45 +00:00
w . WriteHeader ( http . StatusInternalServerError )
return
}
if setupRequired {
2016-12-29 23:36:36 +00:00
redirect . ServeHTTP ( w , r )
2017-02-09 18:43:45 +00:00
return
2016-12-29 23:36:36 +00:00
}
2019-10-16 23:40:45 +00:00
RedirectSetupToLogin ( svc , logger , next , urlPrefix ) . ServeHTTP ( w , r )
2016-11-09 17:19:07 +00:00
}
}
2017-09-01 16:42:46 +00:00
// RedirectSetupToLogin forces the /setup path to be redirected to login. This middleware is used after
2017-01-11 19:05:07 +00:00
// the app has been setup.
2021-06-06 22:07:29 +00:00
func RedirectSetupToLogin ( svc fleet . Service , logger kitlog . Logger , next http . Handler , urlPrefix string ) http . HandlerFunc {
2017-01-11 19:05:07 +00:00
return func ( w http . ResponseWriter , r * http . Request ) {
if r . URL . Path == "/setup" {
newURL := r . URL
2019-10-16 23:40:45 +00:00
newURL . Path = urlPrefix + "/login"
2017-01-11 19:05:07 +00:00
http . Redirect ( w , r , newURL . String ( ) , http . StatusTemporaryRedirect )
return
}
next . ServeHTTP ( w , r )
}
}
2023-01-16 20:06:30 +00:00
// RegisterAppleMDMProtocolServices registers the HTTP handlers that serve
// the MDM services to Apple devices.
func RegisterAppleMDMProtocolServices (
mux * http . ServeMux ,
2023-03-23 10:30:28 +00:00
scepConfig config . MDMConfig ,
2024-05-30 21:18:42 +00:00
mdmStorage fleet . MDMAppleStore ,
2023-01-31 14:46:01 +00:00
scepStorage scep_depot . Depot ,
2023-01-16 20:06:30 +00:00
logger kitlog . Logger ,
checkinAndCommandService nanomdm_service . CheckinAndCommandService ,
2024-03-15 18:20:15 +00:00
ddmService nanomdm_service . DeclarativeManagement ,
2024-12-20 21:40:23 +00:00
profileService nanomdm_service . ProfileService ,
2025-07-23 11:11:32 +00:00
serverURLPrefix string ,
Added missing OpenTelemetry instrumentation to several API endpoints. (#32960)
Fixes #32331
Manually tested all paths. `/test` path removed in
https://github.com/fleetdm/fleet/pull/32962
Also added support for sending errors to OpenTelemetry, like we do for
APM/Sentry.
# Checklist for submitter
- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files)
for more information.
## Testing
- [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 OpenTelemetry tracing across core HTTP endpoints (health,
version, assets, metrics, enroll/root, debug, Apple MDM, SCEP, SCIM)
with dynamic per-request route instrumentation.
* Enhanced error reporting to include OpenTelemetry spans/events with
contextual user/host attributes.
* **Tests**
* Added unit tests validating SCIM and error-handling telemetry, span
naming, and sensitive-data redaction.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-09-16 16:10:33 +00:00
fleetConfig config . FleetConfig ,
2023-01-16 20:06:30 +00:00
) error {
Added missing OpenTelemetry instrumentation to several API endpoints. (#32960)
Fixes #32331
Manually tested all paths. `/test` path removed in
https://github.com/fleetdm/fleet/pull/32962
Also added support for sending errors to OpenTelemetry, like we do for
APM/Sentry.
# Checklist for submitter
- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files)
for more information.
## Testing
- [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 OpenTelemetry tracing across core HTTP endpoints (health,
version, assets, metrics, enroll/root, debug, Apple MDM, SCEP, SCIM)
with dynamic per-request route instrumentation.
* Enhanced error reporting to include OpenTelemetry spans/events with
contextual user/host attributes.
* **Tests**
* Added unit tests validating SCIM and error-handling telemetry, span
naming, and sensitive-data redaction.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-09-16 16:10:33 +00:00
if err := registerSCEP ( mux , scepConfig , scepStorage , mdmStorage , logger , fleetConfig ) ; err != nil {
2023-01-16 20:06:30 +00:00
return fmt . Errorf ( "scep: %w" , err )
}
Added missing OpenTelemetry instrumentation to several API endpoints. (#32960)
Fixes #32331
Manually tested all paths. `/test` path removed in
https://github.com/fleetdm/fleet/pull/32962
Also added support for sending errors to OpenTelemetry, like we do for
APM/Sentry.
# Checklist for submitter
- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files)
for more information.
## Testing
- [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 OpenTelemetry tracing across core HTTP endpoints (health,
version, assets, metrics, enroll/root, debug, Apple MDM, SCEP, SCIM)
with dynamic per-request route instrumentation.
* Enhanced error reporting to include OpenTelemetry spans/events with
contextual user/host attributes.
* **Tests**
* Added unit tests validating SCIM and error-handling telemetry, span
naming, and sensitive-data redaction.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-09-16 16:10:33 +00:00
if err := registerMDM ( mux , mdmStorage , checkinAndCommandService , ddmService , profileService , logger , fleetConfig ) ; err != nil {
2023-01-16 20:06:30 +00:00
return fmt . Errorf ( "mdm: %w" , err )
}
Added missing OpenTelemetry instrumentation to several API endpoints. (#32960)
Fixes #32331
Manually tested all paths. `/test` path removed in
https://github.com/fleetdm/fleet/pull/32962
Also added support for sending errors to OpenTelemetry, like we do for
APM/Sentry.
# Checklist for submitter
- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files)
for more information.
## Testing
- [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 OpenTelemetry tracing across core HTTP endpoints (health,
version, assets, metrics, enroll/root, debug, Apple MDM, SCEP, SCIM)
with dynamic per-request route instrumentation.
* Enhanced error reporting to include OpenTelemetry spans/events with
contextual user/host attributes.
* **Tests**
* Added unit tests validating SCIM and error-handling telemetry, span
naming, and sensitive-data redaction.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-09-16 16:10:33 +00:00
if err := registerMDMServiceDiscovery ( mux , logger , serverURLPrefix , fleetConfig ) ; err != nil {
2025-07-23 11:11:32 +00:00
return fmt . Errorf ( "service discovery: %w" , err )
}
return nil
}
func registerMDMServiceDiscovery (
mux * http . ServeMux ,
logger kitlog . Logger ,
serverURLPrefix string ,
Added missing OpenTelemetry instrumentation to several API endpoints. (#32960)
Fixes #32331
Manually tested all paths. `/test` path removed in
https://github.com/fleetdm/fleet/pull/32962
Also added support for sending errors to OpenTelemetry, like we do for
APM/Sentry.
# Checklist for submitter
- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files)
for more information.
## Testing
- [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 OpenTelemetry tracing across core HTTP endpoints (health,
version, assets, metrics, enroll/root, debug, Apple MDM, SCEP, SCIM)
with dynamic per-request route instrumentation.
* Enhanced error reporting to include OpenTelemetry spans/events with
contextual user/host attributes.
* **Tests**
* Added unit tests validating SCIM and error-handling telemetry, span
naming, and sensitive-data redaction.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-09-16 16:10:33 +00:00
fleetConfig config . FleetConfig ,
2025-07-23 11:11:32 +00:00
) error {
serviceDiscoveryLogger := kitlog . With ( logger , "component" , "mdm-apple-service-discovery" )
fullMDMEnrollmentURL := fmt . Sprintf ( "%s%s" , serverURLPrefix , apple_mdm . AccountDrivenEnrollPath )
serviceDiscoveryHandler := http . HandlerFunc ( func ( w http . ResponseWriter , r * http . Request ) {
serviceDiscoveryLogger . Log ( "msg" , "serving MDM service discovery response" , "url" , fullMDMEnrollmentURL )
w . Header ( ) . Set ( "Content-Type" , "application/json" )
w . WriteHeader ( http . StatusOK )
_ , err := fmt . Fprintf ( w , ` { "Servers":[ { "Version": "mdm-byod", "BaseURL": "%s"}]} ` , fullMDMEnrollmentURL )
if err != nil {
serviceDiscoveryLogger . Log ( "err" , "error writing service discovery response" , "err" , err )
http . Error ( w , "Internal Server Error" , http . StatusInternalServerError )
}
} )
Added missing OpenTelemetry instrumentation to several API endpoints. (#32960)
Fixes #32331
Manually tested all paths. `/test` path removed in
https://github.com/fleetdm/fleet/pull/32962
Also added support for sending errors to OpenTelemetry, like we do for
APM/Sentry.
# Checklist for submitter
- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files)
for more information.
## Testing
- [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 OpenTelemetry tracing across core HTTP endpoints (health,
version, assets, metrics, enroll/root, debug, Apple MDM, SCEP, SCIM)
with dynamic per-request route instrumentation.
* Enhanced error reporting to include OpenTelemetry spans/events with
contextual user/host attributes.
* **Tests**
* Added unit tests validating SCIM and error-handling telemetry, span
naming, and sensitive-data redaction.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-09-16 16:10:33 +00:00
mux . Handle ( apple_mdm . ServiceDiscoveryPath , otel . WrapHandler ( serviceDiscoveryHandler , apple_mdm . ServiceDiscoveryPath , fleetConfig ) )
2023-01-16 20:06:30 +00:00
return nil
}
// registerSCEP registers the HTTP handler for SCEP service needed for enrollment to MDM.
// Returns the SCEP CA certificate that can be used by verifiers.
func registerSCEP (
mux * http . ServeMux ,
2023-03-23 10:30:28 +00:00
scepConfig config . MDMConfig ,
2023-01-31 14:46:01 +00:00
scepStorage scep_depot . Depot ,
2024-05-30 21:18:42 +00:00
mdmStorage fleet . MDMAppleStore ,
2023-01-16 20:06:30 +00:00
logger kitlog . Logger ,
Added missing OpenTelemetry instrumentation to several API endpoints. (#32960)
Fixes #32331
Manually tested all paths. `/test` path removed in
https://github.com/fleetdm/fleet/pull/32962
Also added support for sending errors to OpenTelemetry, like we do for
APM/Sentry.
# Checklist for submitter
- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files)
for more information.
## Testing
- [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 OpenTelemetry tracing across core HTTP endpoints (health,
version, assets, metrics, enroll/root, debug, Apple MDM, SCEP, SCIM)
with dynamic per-request route instrumentation.
* Enhanced error reporting to include OpenTelemetry spans/events with
contextual user/host attributes.
* **Tests**
* Added unit tests validating SCIM and error-handling telemetry, span
naming, and sensitive-data redaction.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-09-16 16:10:33 +00:00
fleetConfig config . FleetConfig ,
2023-01-16 20:06:30 +00:00
) error {
2024-09-27 12:04:11 +00:00
var signer scepserver . CSRSignerContext = scepserver . SignCSRAdapter ( scep_depot . NewSigner (
2023-01-16 20:06:30 +00:00
scepStorage ,
2023-03-23 10:30:28 +00:00
scep_depot . WithValidityDays ( scepConfig . AppleSCEPSignerValidityDays ) ,
scep_depot . WithAllowRenewalDays ( scepConfig . AppleSCEPSignerAllowRenewalDays ) ,
2024-09-27 12:04:11 +00:00
) )
2024-10-09 18:47:27 +00:00
assets , err := mdmStorage . GetAllMDMConfigAssetsByName ( context . Background ( ) , [ ] fleet . MDMAssetName { fleet . MDMAssetSCEPChallenge } , nil )
2024-06-03 21:33:52 +00:00
if err != nil {
return fmt . Errorf ( "retrieving SCEP challenge: %w" , err )
2023-01-16 20:06:30 +00:00
}
2024-06-03 21:33:52 +00:00
scepChallenge := string ( assets [ fleet . MDMAssetSCEPChallenge ] . Value )
2024-09-27 12:04:11 +00:00
signer = scepserver . StaticChallengeMiddleware ( scepChallenge , signer )
2024-05-30 21:18:42 +00:00
scepService := NewSCEPService (
mdmStorage ,
signer ,
kitlog . With ( logger , "component" , "mdm-apple-scep" ) ,
2023-01-16 20:06:30 +00:00
)
2024-05-30 21:18:42 +00:00
2023-01-16 20:06:30 +00:00
scepLogger := kitlog . With ( logger , "component" , "http-mdm-apple-scep" )
e := scepserver . MakeServerEndpoints ( scepService )
e . GetEndpoint = scepserver . EndpointLoggingMiddleware ( scepLogger ) ( e . GetEndpoint )
e . PostEndpoint = scepserver . EndpointLoggingMiddleware ( scepLogger ) ( e . PostEndpoint )
scepHandler := scepserver . MakeHTTPHandler ( e , scepService , scepLogger )
Added missing OpenTelemetry instrumentation to several API endpoints. (#32960)
Fixes #32331
Manually tested all paths. `/test` path removed in
https://github.com/fleetdm/fleet/pull/32962
Also added support for sending errors to OpenTelemetry, like we do for
APM/Sentry.
# Checklist for submitter
- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files)
for more information.
## Testing
- [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 OpenTelemetry tracing across core HTTP endpoints (health,
version, assets, metrics, enroll/root, debug, Apple MDM, SCEP, SCIM)
with dynamic per-request route instrumentation.
* Enhanced error reporting to include OpenTelemetry spans/events with
contextual user/host attributes.
* **Tests**
* Added unit tests validating SCIM and error-handling telemetry, span
naming, and sensitive-data redaction.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-09-16 16:10:33 +00:00
mux . Handle ( apple_mdm . SCEPPath , otel . WrapHandler ( scepHandler , apple_mdm . SCEPPath , fleetConfig ) )
2023-01-16 20:06:30 +00:00
return nil
}
2024-10-09 18:47:27 +00:00
func RegisterSCEPProxy (
rootMux * http . ServeMux ,
ds fleet . Datastore ,
logger kitlog . Logger ,
2025-03-14 17:16:51 +00:00
timeout * time . Duration ,
Added missing OpenTelemetry instrumentation to several API endpoints. (#32960)
Fixes #32331
Manually tested all paths. `/test` path removed in
https://github.com/fleetdm/fleet/pull/32962
Also added support for sending errors to OpenTelemetry, like we do for
APM/Sentry.
# Checklist for submitter
- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files)
for more information.
## Testing
- [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 OpenTelemetry tracing across core HTTP endpoints (health,
version, assets, metrics, enroll/root, debug, Apple MDM, SCEP, SCIM)
with dynamic per-request route instrumentation.
* Enhanced error reporting to include OpenTelemetry spans/events with
contextual user/host attributes.
* **Tests**
* Added unit tests validating SCIM and error-handling telemetry, span
naming, and sensitive-data redaction.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-09-16 16:10:33 +00:00
fleetConfig * config . FleetConfig ,
2024-10-09 18:47:27 +00:00
) error {
Added missing OpenTelemetry instrumentation to several API endpoints. (#32960)
Fixes #32331
Manually tested all paths. `/test` path removed in
https://github.com/fleetdm/fleet/pull/32962
Also added support for sending errors to OpenTelemetry, like we do for
APM/Sentry.
# Checklist for submitter
- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files)
for more information.
## Testing
- [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 OpenTelemetry tracing across core HTTP endpoints (health,
version, assets, metrics, enroll/root, debug, Apple MDM, SCEP, SCIM)
with dynamic per-request route instrumentation.
* Enhanced error reporting to include OpenTelemetry spans/events with
contextual user/host attributes.
* **Tests**
* Added unit tests validating SCIM and error-handling telemetry, span
naming, and sensitive-data redaction.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-09-16 16:10:33 +00:00
if fleetConfig == nil {
return errors . New ( "fleet config is nil" )
}
2024-10-09 18:47:27 +00:00
scepService := eeservice . NewSCEPProxyService (
ds ,
kitlog . With ( logger , "component" , "scep-proxy-service" ) ,
2025-03-14 17:16:51 +00:00
timeout ,
2024-10-09 18:47:27 +00:00
)
scepLogger := kitlog . With ( logger , "component" , "http-scep-proxy" )
e := scepserver . MakeServerEndpointsWithIdentifier ( scepService )
e . GetEndpoint = scepserver . EndpointLoggingMiddleware ( scepLogger ) ( e . GetEndpoint )
e . PostEndpoint = scepserver . EndpointLoggingMiddleware ( scepLogger ) ( e . PostEndpoint )
scepHandler := scepserver . MakeHTTPHandlerWithIdentifier ( e , apple_mdm . SCEPProxyPath , scepLogger )
Added missing OpenTelemetry instrumentation to several API endpoints. (#32960)
Fixes #32331
Manually tested all paths. `/test` path removed in
https://github.com/fleetdm/fleet/pull/32962
Also added support for sending errors to OpenTelemetry, like we do for
APM/Sentry.
# Checklist for submitter
- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files)
for more information.
## Testing
- [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 OpenTelemetry tracing across core HTTP endpoints (health,
version, assets, metrics, enroll/root, debug, Apple MDM, SCEP, SCIM)
with dynamic per-request route instrumentation.
* Enhanced error reporting to include OpenTelemetry spans/events with
contextual user/host attributes.
* **Tests**
* Added unit tests validating SCIM and error-handling telemetry, span
naming, and sensitive-data redaction.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-09-16 16:10:33 +00:00
// Not using OTEL dynamic wrapper so as not to expose {identifier} in the span name
scepHandler = otel . WrapHandler ( scepHandler , apple_mdm . SCEPProxyPath , * fleetConfig )
2024-10-09 18:47:27 +00:00
rootMux . Handle ( apple_mdm . SCEPProxyPath , scepHandler )
return nil
}
2023-01-16 20:06:30 +00:00
// NanoMDMLogger is a logger adapter for nanomdm.
type NanoMDMLogger struct {
logger kitlog . Logger
}
func NewNanoMDMLogger ( logger kitlog . Logger ) * NanoMDMLogger {
return & NanoMDMLogger {
logger : logger ,
}
}
func ( l * NanoMDMLogger ) Info ( keyvals ... interface { } ) {
level . Info ( l . logger ) . Log ( keyvals ... )
}
func ( l * NanoMDMLogger ) Debug ( keyvals ... interface { } ) {
level . Debug ( l . logger ) . Log ( keyvals ... )
}
func ( l * NanoMDMLogger ) With ( keyvals ... interface { } ) nanomdm_log . Logger {
newLogger := kitlog . With ( l . logger , keyvals ... )
return & NanoMDMLogger {
logger : newLogger ,
}
}
// registerMDM registers the HTTP handlers that serve core MDM services (like checking in for MDM commands).
func registerMDM (
mux * http . ServeMux ,
2024-05-30 21:18:42 +00:00
mdmStorage fleet . MDMAppleStore ,
2023-01-16 20:06:30 +00:00
checkinAndCommandService nanomdm_service . CheckinAndCommandService ,
2024-03-15 18:20:15 +00:00
ddmService nanomdm_service . DeclarativeManagement ,
2024-12-20 21:40:23 +00:00
profileService nanomdm_service . ProfileService ,
2023-01-16 20:06:30 +00:00
logger kitlog . Logger ,
Added missing OpenTelemetry instrumentation to several API endpoints. (#32960)
Fixes #32331
Manually tested all paths. `/test` path removed in
https://github.com/fleetdm/fleet/pull/32962
Also added support for sending errors to OpenTelemetry, like we do for
APM/Sentry.
# Checklist for submitter
- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files)
for more information.
## Testing
- [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 OpenTelemetry tracing across core HTTP endpoints (health,
version, assets, metrics, enroll/root, debug, Apple MDM, SCEP, SCIM)
with dynamic per-request route instrumentation.
* Enhanced error reporting to include OpenTelemetry spans/events with
contextual user/host attributes.
* **Tests**
* Added unit tests validating SCIM and error-handling telemetry, span
naming, and sensitive-data redaction.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-09-16 16:10:33 +00:00
fleetConfig config . FleetConfig ,
2023-01-16 20:06:30 +00:00
) error {
2024-05-30 21:18:42 +00:00
certVerifier := mdmcrypto . NewSCEPVerifier ( mdmStorage )
2023-01-16 20:06:30 +00:00
mdmLogger := NewNanoMDMLogger ( kitlog . With ( logger , "component" , "http-mdm-apple-mdm" ) )
// As usual, handlers are applied from bottom to top:
// 1. Extract and verify MDM signature.
// 2. Verify signer certificate with CA.
// 3. Verify new or enrolled certificate (certauth.CertAuth which wraps the MDM service).
// 4. Pass a copy of the request to Fleet middleware that ingests new hosts from pending MDM
// enrollments and updates the Fleet hosts table accordingly with the UDID and serial number of
// the device.
// 5. Run actual MDM service operation (checkin handler or command and results handler).
2024-12-20 21:40:23 +00:00
coreMDMService := nanomdm . New ( mdmStorage , nanomdm . WithLogger ( mdmLogger ) , nanomdm . WithDeclarativeManagement ( ddmService ) ,
2025-09-16 20:04:05 +00:00
nanomdm . WithProfileService ( profileService ) , nanomdm . WithUserAuthenticate ( checkinAndCommandService ) )
2023-03-27 18:43:01 +00:00
// NOTE: it is critical that the coreMDMService runs first, as the first
// service in the multi-service feature is run to completion _before_ running
// the other ones in parallel. This way, subsequent services have access to
// the result of the core service, e.g. the device is enrolled, etc.
2023-01-16 20:06:30 +00:00
var mdmService nanomdm_service . CheckinAndCommandService = multi . New ( mdmLogger , coreMDMService , checkinAndCommandService )
2025-03-28 21:33:22 +00:00
mdmService = certauth . New ( mdmService , mdmStorage , certauth . WithLogger ( mdmLogger . With ( "handler" , "cert-auth" ) ) )
2023-01-16 20:06:30 +00:00
var mdmHandler http . Handler = httpmdm . CheckinAndCommandHandler ( mdmService , mdmLogger . With ( "handler" , "checkin-command" ) )
2024-11-11 19:25:21 +00:00
verifyDisable , exists := os . LookupEnv ( "FLEET_MDM_APPLE_SCEP_VERIFY_DISABLE" )
if exists && ( strings . EqualFold ( verifyDisable , "true" ) || verifyDisable == "1" ) {
level . Info ( logger ) . Log ( "msg" ,
"disabling verification of macOS SCEP certificates as FLEET_MDM_APPLE_SCEP_VERIFY_DISABLE is set to true" )
} else {
mdmHandler = httpmdm . CertVerifyMiddleware ( mdmHandler , certVerifier , mdmLogger . With ( "handler" , "cert-verify" ) )
}
2024-11-20 17:47:11 +00:00
mdmHandler = httpmdm . CertExtractMdmSignatureMiddleware ( mdmHandler , httpmdm . MdmSignatureVerifierFunc ( cryptoutil . VerifyMdmSignature ) ,
httpmdm . SigLogWithLogger ( mdmLogger . With ( "handler" , "cert-extract" ) ) )
Added missing OpenTelemetry instrumentation to several API endpoints. (#32960)
Fixes #32331
Manually tested all paths. `/test` path removed in
https://github.com/fleetdm/fleet/pull/32962
Also added support for sending errors to OpenTelemetry, like we do for
APM/Sentry.
# Checklist for submitter
- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files)
for more information.
## Testing
- [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 OpenTelemetry tracing across core HTTP endpoints (health,
version, assets, metrics, enroll/root, debug, Apple MDM, SCEP, SCIM)
with dynamic per-request route instrumentation.
* Enhanced error reporting to include OpenTelemetry spans/events with
contextual user/host attributes.
* **Tests**
* Added unit tests validating SCIM and error-handling telemetry, span
naming, and sensitive-data redaction.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-09-16 16:10:33 +00:00
mux . Handle ( apple_mdm . MDMPath , otel . WrapHandler ( mdmHandler , apple_mdm . MDMPath , fleetConfig ) )
2023-01-16 20:06:30 +00:00
return nil
}
2024-11-22 15:56:36 +00:00
func WithMDMEnrollmentMiddleware ( svc fleet . Service , logger kitlog . Logger , next http . Handler ) http . HandlerFunc {
return func ( w http . ResponseWriter , r * http . Request ) {
2025-07-15 19:02:11 +00:00
if r . URL . Path != "/mdm/sso" && r . URL . Path != "/account_driven_enroll/sso" {
2025-05-19 18:29:46 +00:00
// TODO: redirects for non-SSO config web url?
2024-11-22 15:56:36 +00:00
next . ServeHTTP ( w , r )
return
}
// if x-apple-aspen-deviceinfo custom header is present, we need to check for minimum os version
di := r . Header . Get ( "x-apple-aspen-deviceinfo" )
if di != "" {
parsed , err := apple_mdm . ParseDeviceinfo ( di , false ) // FIXME: use verify=true when we have better parsing for various Apple certs (https://github.com/fleetdm/fleet/issues/20879)
if err != nil {
// just log the error and continue to next
level . Error ( logger ) . Log ( "msg" , "parsing x-apple-aspen-deviceinfo" , "err" , err )
next . ServeHTTP ( w , r )
return
}
2025-05-19 18:29:46 +00:00
// TODO: skip os version check if deviceinfo query param is present? or find another way
// to avoid polling the DB and Apple endpoint twice for each enrollment.
2024-11-22 15:56:36 +00:00
sur , err := svc . CheckMDMAppleEnrollmentWithMinimumOSVersion ( r . Context ( ) , parsed )
if err != nil {
// just log the error and continue to next
level . Error ( logger ) . Log ( "msg" , "checking minimum os version for mdm" , "err" , err )
next . ServeHTTP ( w , r )
return
}
if sur != nil {
w . Header ( ) . Set ( "Content-Type" , "application/json" )
w . WriteHeader ( http . StatusForbidden )
if err := json . NewEncoder ( w ) . Encode ( sur ) ; err != nil {
level . Error ( logger ) . Log ( "msg" , "failed to encode software update required" , "err" , err )
http . Redirect ( w , r , r . URL . String ( ) + "?error=true" , http . StatusSeeOther )
}
return
}
2025-05-19 18:29:46 +00:00
// TODO: Do non-Apple devices ever use this route? If so, we probably need to change the
// approach below so we don't endlessly redirect non-Apple clients to the same URL.
// if we get here, the minimum os version is satisfied, so we continue with SSO flow
q := r . URL . Query ( )
v , ok := q [ "deviceinfo" ]
if ! ok || len ( v ) == 0 {
// If the deviceinfo query param is empty, we add the deviceinfo to the URL and
// redirect.
//
// Note: We'll apply this redirect only if query params are empty because want to
// redirect to the same URL with added query params after parsing the x-apple-aspen-deviceinfo
// header. Whenever we see a request with any query params already present, we'll
// skip this step and just continue to the next handler.
newURL := * r . URL
q . Set ( "deviceinfo" , di )
newURL . RawQuery = q . Encode ( )
level . Info ( logger ) . Log ( "msg" , "handling mdm sso: redirect with deviceinfo" , "host_uuid" , parsed . UDID , "serial" , parsed . Serial )
http . Redirect ( w , r , newURL . String ( ) , http . StatusTemporaryRedirect )
return
}
if len ( v ) > 0 && v [ 0 ] != di {
// something is wrong, the device info in the query params does not match
// the one in the header, so we just log the error and continue to next
level . Error ( logger ) . Log ( "msg" , "device info in query params does not match header" , "header" , di , "query" , v [ 0 ] )
}
level . Info ( logger ) . Log ( "msg" , "handling mdm sso: proceed to next" , "host_uuid" , parsed . UDID , "serial" , parsed . Serial )
2024-11-22 15:56:36 +00:00
}
next . ServeHTTP ( w , r )
}
}