Files
Lucas Manuel Rodriguez 56763d13c1 Move fleet-mcp from tools/ to cmd/ (#49044)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** #43544. 

Moves `fleet-mcp` from `tools/fleet-mcp/` to `cmd/fleet-mcp/`. It is
becoming a production server used by customers, so it now lives under
`cmd/` alongside the other Fleet binaries.

Per the module strategy chosen for this move, it **remains a standalone
Go module** (keeps its own `go.mod`/`go.sum` and isolated deps such as
`mark3labs/mcp-go`, `logrus`, `gorilla/websocket`, `godotenv`) — the
root `github.com/fleetdm/fleet/v4` module is unchanged.

### What changed
- `git mv tools/fleet-mcp/ → cmd/fleet-mcp/` (history preserved as
renames).
- Updated all path references:
  - Root `Makefile` `update-go` module list.
- `.github/workflows/test-fleet-mcp.yml` — trigger paths,
`go-version-file`, `working-directory`.
  - `.github/dependabot.yml` — gomod directory.
  - `cmd/fleet-mcp/render.yaml` — `rootDir`.
- `cmd/fleet-mcp/README.md`, `Makefile`, `schema.go` — path
comments/links.
  - `articles/fleet-mcp.md` — README link.
  - Removed the `fleet-mcp/` row from `tools/README.md`.

### Follow-up (not in this PR)
- The Render service's Blueprint file path must be updated from
`tools/fleet-mcp/render.yaml` to `cmd/fleet-mcp/render.yaml` in the
Render dashboard.

## Testing
- `go build .` in `cmd/fleet-mcp` — OK
- `go test -race -count=1 ./...` — `ok fleet-mcp`

- [x] QA'd all new/changed functionality manually
2026-07-09 13:29:09 -03:00

24 lines
673 B
Go

package main
import (
"crypto/subtle"
"net/http"
)
// bearerAuthMiddleware rejects requests whose Authorization header does not
// match "Bearer <token>", returning 401 Unauthorized. The comparison uses
// crypto/subtle.ConstantTimeCompare to prevent timing side-channel attacks.
func bearerAuthMiddleware(token string, next http.Handler) http.Handler {
expected := []byte("Bearer " + token)
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
got := []byte(r.Header.Get("Authorization"))
if subtle.ConstantTimeCompare(got, expected) != 1 {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
next.ServeHTTP(w, r)
})
}