From c8b1af7603e6bbd45c25ec5b282e4a062718928d Mon Sep 17 00:00:00 2001 From: Martin Angers Date: Tue, 11 Mar 2025 11:06:25 -0400 Subject: [PATCH] Android: fix BYOD enrollment page to get up-to-date MDM enabled status (#27011) --- cmd/fleet/serve.go | 5 +-- server/service/frontend.go | 19 ++++++---- server/service/frontend_test.go | 65 ++++++++++++++++++++++++--------- 3 files changed, 60 insertions(+), 29 deletions(-) diff --git a/cmd/fleet/serve.go b/cmd/fleet/serve.go index 0bfdb6e27c..ac71b63084 100644 --- a/cmd/fleet/serve.go +++ b/cmd/fleet/serve.go @@ -1081,13 +1081,10 @@ the way that the Fleet server works. frontendHandler = service.RedirectSetupToLogin(svc, logger, frontendHandler, config.Server.URLPrefix) } - // TODO: need a mechanism to check if android feature is enabled endUserEnrollOTAHandler = service.ServeEndUserEnrollOTA( svc, config.Server.URLPrefix, - appCfg.MDM.EnabledAndConfigured, - appCfg.MDM.AndroidEnabledAndConfigured, - os.Getenv("FLEET_DEV_ANDROID_ENABLED") == "1", + ds, logger, ) } diff --git a/server/service/frontend.go b/server/service/frontend.go index 14e3df981f..0feb6c7eeb 100644 --- a/server/service/frontend.go +++ b/server/service/frontend.go @@ -6,6 +6,7 @@ import ( "io" "net/http" "net/url" + "os" assetfs "github.com/elazarl/go-bindata-assetfs" "github.com/fleetdm/fleet/v4/server/bindata" @@ -76,15 +77,14 @@ func ServeFrontend(urlPrefix string, sandbox bool, logger log.Logger) http.Handl func ServeEndUserEnrollOTA( svc fleet.Service, urlPrefix string, - isMacMDMEnabled bool, - isAndroidMDMEnabled bool, - isAndroidFeatureEnabled bool, // TODO: remove android feature flag + ds fleet.Datastore, logger log.Logger, ) http.Handler { herr := func(w http.ResponseWriter, err string) { logger.Log("err", err) http.Error(w, err, http.StatusInternalServerError) } + androidFeatureEnabled := os.Getenv("FLEET_DEV_ANDROID_ENABLED") == "1" return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { endpoint_utils.WriteBrowserSecurityHeaders(w) @@ -93,12 +93,17 @@ func ServeEndUserEnrollOTA( herr(w, "setup required err: "+err.Error()) return } - if setupRequired { herr(w, "fleet instance not setup") return } + appCfg, err := ds.AppConfig(r.Context()) + if err != nil { + herr(w, "load appconfig err: "+err.Error()) + return + } + fs := newBinaryFileSystem("/frontend") file, err := fs.Open("templates/enroll-ota.html") if err != nil { @@ -132,9 +137,9 @@ func ServeEndUserEnrollOTA( }{ URLPrefix: urlPrefix, EnrollURL: enrollURL, - AndroidMDMEnabled: isAndroidMDMEnabled, - MacMDMEnabled: isMacMDMEnabled, - AndroidFeatureEnabled: isAndroidFeatureEnabled, + AndroidMDMEnabled: appCfg.MDM.AndroidEnabledAndConfigured, + MacMDMEnabled: appCfg.MDM.EnabledAndConfigured, + AndroidFeatureEnabled: androidFeatureEnabled, }); err != nil { herr(w, "execute react template: "+err.Error()) return diff --git a/server/service/frontend_test.go b/server/service/frontend_test.go index 0b3650f6c1..23e9b8c193 100644 --- a/server/service/frontend_test.go +++ b/server/service/frontend_test.go @@ -3,14 +3,17 @@ package service import ( "bytes" "context" + "fmt" "io" "net/http" "net/http/httptest" "os" "testing" + "github.com/fleetdm/fleet/v4/server/fleet" "github.com/fleetdm/fleet/v4/server/mock" "github.com/go-kit/log" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -53,26 +56,52 @@ func TestServeEndUserEnrollOTA(t *testing.T) { ds.HasUsersFunc = func(ctx context.Context) (bool, error) { return true, nil } + appCfg := &fleet.AppConfig{ + MDM: fleet.MDM{ + EnabledAndConfigured: false, + AndroidEnabledAndConfigured: false, + }, + } + ds.AppConfigFunc = func(ctx context.Context) (*fleet.AppConfig, error) { + return appCfg, nil + } + svc, _ := newTestService(t, ds, nil, nil) - logger := log.NewLogfmtLogger(os.Stdout) - h := ServeEndUserEnrollOTA(svc, "", true, true, true, logger) - ts := httptest.NewServer(h) - t.Cleanup(func() { - ts.Close() - }) + for _, enabled := range []bool{true, false} { + t.Run(fmt.Sprintf("MDM enabled: %t", enabled), func(t *testing.T) { + appCfg.MDM.EnabledAndConfigured = enabled + appCfg.MDM.AndroidEnabledAndConfigured = enabled + if enabled { + t.Setenv("FLEET_DEV_ANDROID_ENABLED", "1") + } else { + t.Setenv("FLEET_DEV_ANDROID_ENABLED", "0") + } - // assert html is returned - response, err := http.DefaultClient.Get(ts.URL + "?enroll_secret=foo") - require.NoError(t, err) - require.Equal(t, http.StatusOK, response.StatusCode) - require.Equal(t, response.Header.Get("Content-Type"), "text/html; charset=utf-8") + logger := log.NewLogfmtLogger(os.Stdout) + h := ServeEndUserEnrollOTA(svc, "", ds, logger) + ts := httptest.NewServer(h) + t.Cleanup(func() { + ts.Close() + }) - // assert it contains the content we expect - defer response.Body.Close() - bodyBytes, err := io.ReadAll(response.Body) - require.NoError(t, err) - bodyString := string(bodyBytes) - require.Contains(t, bodyString, "api/v1/fleet/enrollment_profiles/ota?enroll_secret=foo") - require.Contains(t, bodyString, "/api/v1/fleet/android_enterprise/enrollment_token") + // assert html is returned + response, err := http.DefaultClient.Get(ts.URL + "?enroll_secret=foo") + require.NoError(t, err) + require.Equal(t, http.StatusOK, response.StatusCode) + require.Equal(t, response.Header.Get("Content-Type"), "text/html; charset=utf-8") + assert.True(t, ds.AppConfigFuncInvoked) + + // assert it contains the content we expect + defer response.Body.Close() + bodyBytes, err := io.ReadAll(response.Body) + require.NoError(t, err) + bodyString := string(bodyBytes) + require.Contains(t, bodyString, "api/v1/fleet/enrollment_profiles/ota?enroll_secret=foo") + require.Contains(t, bodyString, "/api/v1/fleet/android_enterprise/enrollment_token") + require.Contains(t, bodyString, fmt.Sprintf(`const ANDROID_MDM_ENABLED = "%t" === "true";`, enabled)) + require.Contains(t, bodyString, fmt.Sprintf(`const MAC_MDM_ENABLED = "%t" == "true";`, enabled)) + require.Contains(t, bodyString, fmt.Sprintf(`const ANDROID_FEATURE_ENABLED = "%t" === "true";`, enabled)) + }) + } }