diff --git a/changes/35613-android-profiles-pending b/changes/35613-android-profiles-pending new file mode 100644 index 0000000000..7117e8f64c --- /dev/null +++ b/changes/35613-android-profiles-pending @@ -0,0 +1 @@ +Updated Android MDM profiles to show up as pending on upload, the same as Apple MDM profiles. diff --git a/server/service/integration_android_certificate_templates_test.go b/server/service/integration_android_certificate_templates_test.go index faa7acb70f..63e7a61a90 100644 --- a/server/service/integration_android_certificate_templates_test.go +++ b/server/service/integration_android_certificate_templates_test.go @@ -138,7 +138,7 @@ func (s *integrationMDMTestSuite) createEnrolledAndroidHost(t *testing.T, ctx co AppliedPolicyID: ptr.String("1"), }, } - androidHostInput.SetNodeKey(enterpriseID) + androidHostInput.SetNodeKey("android/" + hostUUID) createdAndroidHost, err := s.ds.NewAndroidHost(ctx, androidHostInput) require.NoError(t, err) diff --git a/server/service/integration_mdm_profiles_test.go b/server/service/integration_mdm_profiles_test.go index 002e2d6d6a..8fc6bd196f 100644 --- a/server/service/integration_mdm_profiles_test.go +++ b/server/service/integration_mdm_profiles_test.go @@ -8691,3 +8691,49 @@ func (s *integrationMDMTestSuite) TestWindowsProfileRetry() { require.Len(t, cmds, 1) // only ack returned }) } + +func (s *integrationMDMTestSuite) TestHostMDMAndroidProfilesStatus() { + t := s.T() + ctx := context.Background() + s.setSkipWorkerJobs(t) + + testTeam, err := s.ds.NewTeam(ctx, &fleet.Team{Name: "TestTeam"}) + require.NoError(t, err) + + // Ensure MDM is turned on + appConfig, err := s.ds.AppConfig(ctx) + require.NoError(t, err) + appConfig.MDM.AndroidEnabledAndConfigured = true + err = s.ds.SaveAppConfig(ctx, appConfig) + require.NoError(t, err) + enterpriseID := s.enableAndroidMDM(t) + + s.createEnrolledAndroidHost(t, ctx, enterpriseID, &testTeam.ID, "host-1") + s.createEnrolledAndroidHost(t, ctx, enterpriseID, &testTeam.ID, "host-2") + + var hosts listHostsResponse + s.DoJSON("GET", "/api/latest/fleet/hosts", nil, http.StatusOK, &hosts) + assert.Len(t, hosts.Hosts, 2) + + bytes := []byte(`{ + "removeUserDisabled": false +}`) + + fields := make(map[string][]string) + fields["team_id"] = []string{fmt.Sprintf("%d", testTeam.ID)} + body, headers := generateNewProfileMultipartRequest(t, "remove-user-disabled.json", bytes, s.token, fields) + res := s.DoRawWithHeaders("POST", "/api/latest/fleet/configuration_profiles", body.Bytes(), http.StatusOK, headers) + require.NotNil(t, res) + + // profiles should be added with NULL status even before the cron job (s.awaitTriggerAndroidProfileSchedule(t)) + var profiles []fleet.HostMDMAndroidProfile + mysql.ExecAdhocSQL(t, s.ds, func(q sqlx.ExtContext) error { + err := sqlx.SelectContext(ctx, q, &profiles, "SELECT host_uuid, status, operation_type FROM host_mdm_android_profiles") + require.NoError(t, err) + return nil + }) + + require.Len(t, profiles, 2) + require.Nil(t, profiles[0].Status) + require.Nil(t, profiles[1].Status) +} diff --git a/server/service/mdm.go b/server/service/mdm.go index 6e8dc125ea..97fce5573d 100644 --- a/server/service/mdm.go +++ b/server/service/mdm.go @@ -1801,6 +1801,9 @@ func (svc *Service) NewMDMAndroidConfigProfile(ctx context.Context, teamID uint, } return nil, ctxerr.Wrap(ctx, err) } + if _, err := svc.ds.BulkSetPendingMDMHostProfiles(ctx, nil, nil, []string{newCP.ProfileUUID}, nil); err != nil { + return nil, ctxerr.Wrap(ctx, err, "bulk set pending host profiles") + } var ( actTeamID *uint diff --git a/server/service/mdm_test.go b/server/service/mdm_test.go index c057890468..772790eb13 100644 --- a/server/service/mdm_test.go +++ b/server/service/mdm_test.go @@ -2669,6 +2669,9 @@ func TestNewMDMProfilePremiumOnlyAndroid(t *testing.T) { ds.NewMDMAndroidConfigProfileFunc = func(ctx context.Context, cp fleet.MDMAndroidConfigProfile) (*fleet.MDMAndroidConfigProfile, error) { return &fleet.MDMAndroidConfigProfile{}, nil } + ds.BulkSetPendingMDMHostProfilesFunc = func(ctx context.Context, hostIDs, teamIDs []uint, profileUUIDs, hostUUIDs []string) (updates fleet.MDMProfilesUpdates, err error) { + return fleet.MDMProfilesUpdates{}, nil + } testCases := []struct { name string