From 1de5599e8ea397cef7f2ce9f77908c0686aaa57f Mon Sep 17 00:00:00 2001 From: Zach Wasserman Date: Wed, 17 Jul 2024 13:35:45 -0700 Subject: [PATCH] Improvements to logging in mdmproxy (#20201) - Add --debug flag to log Fleet requests and responses - Add --log-skipped flag to disable logging most garbage requests by default --- tools/mdm/migration/mdmproxy/mdmproxy.go | 67 ++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 3 deletions(-) diff --git a/tools/mdm/migration/mdmproxy/mdmproxy.go b/tools/mdm/migration/mdmproxy/mdmproxy.go index b8c0be5fa706..9071879ec0bb 100644 --- a/tools/mdm/migration/mdmproxy/mdmproxy.go +++ b/tools/mdm/migration/mdmproxy/mdmproxy.go @@ -31,7 +31,21 @@ type mdmProxy struct { // mutex is used to sync reads/updates to the migrateUDIDs and migratePercentage mutex sync.RWMutex // token is used to authenticate updates to the migrateUDIDs and migratePercentage - token string + token string + debug bool + logSkipped bool +} + +func skipRequest(r *http.Request) bool { + // Throw out a bunch of common junk requests + return strings.Contains(r.URL.Path, ".php") || + strings.Contains(r.URL.Path, ".git") || + strings.Contains(r.URL.Path, ".yml") || + strings.Contains(r.URL.Path, ".txt") || + strings.Contains(r.URL.Path, ".py") || + strings.Contains(r.URL.Path, "wp-") || + strings.Contains(r.URL.Path, "private") || + (r.URL.Path == "/" && r.Method == http.MethodPost) } func (m *mdmProxy) handleProxy(w http.ResponseWriter, r *http.Request) { @@ -41,6 +55,14 @@ func (m *mdmProxy) handleProxy(w http.ResponseWriter, r *http.Request) { return } + if skipRequest(r) { + if m.logSkipped { + log.Printf("Forbidden skipped request: %s %s", r.Method, r.URL.String()) + } + http.Error(w, "Forbidden", http.StatusForbidden) + return + } + // Send all SCEP requests to the existing server if strings.Contains(r.URL.Path, "scep") { log.Printf("%s %s -> Existing (SCEP)", r.Method, r.URL.String()) @@ -53,7 +75,20 @@ func (m *mdmProxy) handleProxy(w http.ResponseWriter, r *http.Request) { log.Printf("%s %s -> Existing (API)", r.Method, r.URL.String()) m.existingProxy.ServeHTTP(w, r) return + } + + if r.URL.Path == "/" && r.Method == http.MethodGet { + log.Printf("%s %s -> Existing (Home)", r.Method, r.URL.String()) + m.existingProxy.ServeHTTP(w, r) + return + } + if !strings.HasPrefix(r.URL.Path, "/mdm") { + if m.logSkipped { + log.Printf("Forbidden non-mdm request: %s %s", r.Method, r.URL.String()) + } + http.Error(w, "Forbidden", http.StatusForbidden) + return } // Read the body of the request @@ -78,6 +113,9 @@ func (m *mdmProxy) handleProxy(w http.ResponseWriter, r *http.Request) { // Migrated UDIDs go to the Fleet server, otherwise requests go to the existing server. if udid != "" && m.isUDIDMigrated(udid) { log.Printf("%s %s (%s) -> Fleet", r.Method, r.URL.String(), udid) + if m.debug { + log.Printf("Fleet request: %s", string(body)) + } m.fleetProxy.ServeHTTP(w, r) } else { log.Printf("%s %s (%s) -> Existing", r.Method, r.URL.String(), udid) @@ -238,12 +276,29 @@ func makeExistingProxy(existingURL, existingDNSName string) *httputil.ReversePro return proxy } -func makeFleetProxy(fleetURL string) *httputil.ReverseProxy { +func makeFleetProxy(fleetURL string, debug bool) *httputil.ReverseProxy { targetURL, err := url.Parse(fleetURL) if err != nil { panic("failed to parse fleet-url: " + err.Error()) } proxy := httputil.NewSingleHostReverseProxy(targetURL) + if debug { + proxy.ModifyResponse = func(r *http.Response) error { + b, err := io.ReadAll(r.Body) + if err != nil { + return err + } + err = r.Body.Close() + if err != nil { + return err + } + r.Body = io.NopCloser(bytes.NewReader(b)) + + log.Println("Fleet response: ", string(b)) + + return nil + } + } return proxy } @@ -256,6 +311,8 @@ func main() { migratePercentage := flag.Int("migrate-percentage", 0, "Percentage of clients to migrate from existing MDM to Fleet") migrateUDIDs := flag.String("migrate-udids", "", "Space/newline-delimited list of UDIDs to migrate always") serverAddr := flag.String("server-address", ":8080", "Address for server to listen on") + debug := flag.Bool("debug", false, "Enable debug logging") + logSkipped := flag.Bool("log-skipped", false, "Log skipped requests (usually from web scanners)") flag.Parse() // Check required flags @@ -278,6 +335,8 @@ func main() { log.Printf("--existing-url set: %s", *existingURL) log.Printf("--existing-hostname set: %s", *existingHostname) log.Printf("--fleet-url set: %s", *fleetURL) + log.Printf("--debug set: %v", *debug) + log.Printf("--log-skipped set: %v", *logSkipped) if *authToken != "" { log.Printf("--auth-token set. Remote configuration enabled.") } else { @@ -292,7 +351,9 @@ func main() { migratePercentage: *migratePercentage, migrateUDIDs: udids, existingProxy: makeExistingProxy(*existingURL, *existingHostname), - fleetProxy: makeFleetProxy(*fleetURL), + fleetProxy: makeFleetProxy(*fleetURL, *debug), + debug: *debug, + logSkipped: *logSkipped, } mux := http.NewServeMux()