diff --git a/changes/38785-windows-setup-experience-cancel b/changes/38785-windows-setup-experience-cancel new file mode 100644 index 0000000000..7fffb77759 --- /dev/null +++ b/changes/38785-windows-setup-experience-cancel @@ -0,0 +1 @@ +- Added `require_all_software_windows` setting to cancel the Windows setup experience if any software install fails during Autopilot enrollment, matching the existing macOS behavior. diff --git a/server/service/setup_experience.go b/server/service/setup_experience.go index cd26b8b717..00203aa7cd 100644 --- a/server/service/setup_experience.go +++ b/server/service/setup_experience.go @@ -238,22 +238,31 @@ func (svc *Service) IsAllSetupExperienceSoftwareRequired(ctx context.Context, ho } func isAllSetupExperienceSoftwareRequired(ctx context.Context, ds fleet.Datastore, host *fleet.Host) (bool, error) { + // Only macOS and Windows support canceling setup if software fails. + if host.Platform != "darwin" && host.Platform != "windows" { + return false, nil + } + teamID := host.TeamID - requireAllSoftware := false if teamID == nil || *teamID == 0 { ac, err := ds.AppConfig(ctx) if err != nil { return false, ctxerr.Wrap(ctx, err, "getting app config") } - requireAllSoftware = ac.MDM.MacOSSetup.RequireAllSoftware - } else { - team, err := ds.TeamLite(ctx, *teamID) - if err != nil { - return false, ctxerr.Wrap(ctx, err, "load team") + if host.Platform == "windows" { + return ac.MDM.MacOSSetup.RequireAllSoftwareWindows, nil } - requireAllSoftware = team.Config.MDM.MacOSSetup.RequireAllSoftware + return ac.MDM.MacOSSetup.RequireAllSoftware, nil } - return requireAllSoftware, nil + + team, err := ds.TeamLite(ctx, *teamID) + if err != nil { + return false, ctxerr.Wrap(ctx, err, "load team") + } + if host.Platform == "windows" { + return team.Config.MDM.MacOSSetup.RequireAllSoftwareWindows, nil + } + return team.Config.MDM.MacOSSetup.RequireAllSoftware, nil } func (svc *Service) MaybeCancelPendingSetupExperienceSteps(ctx context.Context, host *fleet.Host) error { @@ -261,8 +270,8 @@ func (svc *Service) MaybeCancelPendingSetupExperienceSteps(ctx context.Context, } func maybeCancelPendingSetupExperienceSteps(ctx context.Context, ds fleet.Datastore, host *fleet.Host, newActivityFn fleet.NewActivityFunc) error { - // If the host is not MacOS, we do nothing. - if host.Platform != "darwin" { + // Only macOS and Windows support canceling setup experience steps. + if host.Platform != "darwin" && host.Platform != "windows" { return nil } diff --git a/server/service/setup_experience_test.go b/server/service/setup_experience_test.go index c3d3daf828..4fd449063e 100644 --- a/server/service/setup_experience_test.go +++ b/server/service/setup_experience_test.go @@ -221,6 +221,79 @@ func TestSetupExperienceAuth(t *testing.T) { } } +func TestIsAllSetupExperienceSoftwareRequired(t *testing.T) { + ds := new(mock.Store) + + teamID := uint(1) + // Use different values for macOS vs Windows to ensure the correct field is read for each platform. + appCfg := &fleet.AppConfig{} + appCfg.MDM.MacOSSetup.RequireAllSoftware = true + appCfg.MDM.MacOSSetup.RequireAllSoftwareWindows = false + + ds.AppConfigFunc = func(ctx context.Context) (*fleet.AppConfig, error) { + return appCfg, nil + } + ds.TeamLiteFunc = func(ctx context.Context, tid uint) (*fleet.TeamLite, error) { + return &fleet.TeamLite{ + ID: tid, + Name: "team", + Config: fleet.TeamConfigLite{ + MDM: fleet.TeamMDM{ + MacOSSetup: fleet.MacOSSetup{ + RequireAllSoftware: false, + RequireAllSoftwareWindows: true, + }, + }, + }, + }, nil + } + + tests := []struct { + name string + host *fleet.Host + expected bool + }{ + { + name: "macOS host, no team, reads macOS global config (true)", + host: &fleet.Host{Platform: "darwin"}, + expected: true, + }, + { + name: "macOS host, with team, reads macOS team config (false)", + host: &fleet.Host{Platform: "darwin", TeamID: &teamID}, + expected: false, + }, + { + name: "windows host, no team, reads Windows global config (false)", + host: &fleet.Host{Platform: "windows"}, + expected: false, + }, + { + name: "windows host, with team, reads Windows team config (true)", + host: &fleet.Host{Platform: "windows", TeamID: &teamID}, + expected: true, + }, + { + name: "linux host returns false", + host: &fleet.Host{Platform: "ubuntu"}, + expected: false, + }, + { + name: "ios host returns false", + host: &fleet.Host{Platform: "ios"}, + expected: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result, err := isAllSetupExperienceSoftwareRequired(t.Context(), ds, tt.host) + require.NoError(t, err) + require.Equal(t, tt.expected, result) + }) + } +} + func TestMaybeUpdateSetupExperience(t *testing.T) { ds := new(mock.Store) // _, ctx := newTestService(t, ds, nil, nil, nil)