From c3bee53338e40f812b39133fd27e3802b0b4958d Mon Sep 17 00:00:00 2001 From: Martin Angers Date: Mon, 12 Jan 2026 10:03:01 -0500 Subject: [PATCH] Fix list applications managed and non-managed command uuid (#38162) --- server/mdm/apple/apple_mdm.go | 4 ++- server/service/integration_mdm_test.go | 38 ++++++++++++++++++++++---- 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/server/mdm/apple/apple_mdm.go b/server/mdm/apple/apple_mdm.go index 4177757a32..56af64aac9 100644 --- a/server/mdm/apple/apple_mdm.go +++ b/server/mdm/apple/apple_mdm.go @@ -1404,7 +1404,6 @@ func IOSiPadOSRefetch(ctx context.Context, ds fleet.Datastore, commander *MDMApp return nil } logger.Log("msg", "sending commands to refetch", "count", len(devices), "lookup-duration", time.Since(start)) - commandUUID := uuid.NewString() hostMDMCommands := make([]fleet.HostMDMCommand, 0, 3*len(devices)) installedAppsUUIDs := struct { @@ -1431,6 +1430,7 @@ func IOSiPadOSRefetch(ctx context.Context, ds fleet.Datastore, commander *MDMApp continue } + commandUUID := uuid.NewString() err = commander.InstalledApplicationList(ctx, uuids, fleet.RefetchAppsCommandUUIDPrefix+commandUUID, managedOnly) turnedOff, turnedOffError := turnOffMDMIfAPNSFailed(ctx, ds, err, logger, newActivityFn) if turnedOffError != nil { @@ -1453,6 +1453,7 @@ func IOSiPadOSRefetch(ctx context.Context, ds fleet.Datastore, commander *MDMApp } } if len(certsListUUIDs) > 0 { + commandUUID := uuid.NewString() err = commander.CertificateList(ctx, certsListUUIDs, fleet.RefetchCertsCommandUUIDPrefix+commandUUID) turnedOff, turnedOffError := turnOffMDMIfAPNSFailed(ctx, ds, err, logger, newActivityFn) if turnedOffError != nil { @@ -1475,6 +1476,7 @@ func IOSiPadOSRefetch(ctx context.Context, ds fleet.Datastore, commander *MDMApp } } if len(deviceInfoUUIDs) > 0 { + commandUUID := uuid.NewString() err := commander.DeviceInformation(ctx, deviceInfoUUIDs, fleet.RefetchDeviceCommandUUIDPrefix+commandUUID) turnedOff, turnedOffError := turnOffMDMIfAPNSFailed(ctx, ds, err, logger, newActivityFn) if turnedOffError != nil { diff --git a/server/service/integration_mdm_test.go b/server/service/integration_mdm_test.go index afe081ef50..ca6c5a0e1c 100644 --- a/server/service/integration_mdm_test.go +++ b/server/service/integration_mdm_test.go @@ -1446,6 +1446,7 @@ func (s *integrationMDMTestSuite) createAppleMobileHostThenEnrollMDM(platform st dbZeroTime := time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC) serialNumber := mdmtest.RandSerialNumber() fleetHost, err := s.ds.NewHost(ctx, &fleet.Host{ + UUID: uuid.NewString(), HardwareSerial: serialNumber, HardwareModel: model, Platform: platform, @@ -1465,6 +1466,7 @@ func (s *integrationMDMTestSuite) createAppleMobileHostThenEnrollMDM(platform st mdmDevice := mdmtest.NewTestMDMClientAppleDirect(mdmEnrollInfo, model) mdmDevice.SerialNumber = serialNumber + mdmDevice.UUID = fleetHost.UUID err = mdmDevice.Enroll() require.NoError(t, err) @@ -20198,15 +20200,15 @@ func (s *integrationMDMTestSuite) TestInstalledApplicationListCommandForBYODiDev {HostID: hostBYOD.ID, CommandType: fleet.RefetchDeviceCommandUUIDPrefix}, }, commands) - checkExpectedCommands := func(mdmClient *mdmtest.TestAppleMDMClient, managedOnly bool) { - var installedAppCount int + checkExpectedCommands := func(mdmClient *mdmtest.TestAppleMDMClient, managedOnly bool, wantAppListCount int) { + var installedAppListCount int cmd, err := mdmClient.Idle() require.NoError(t, err) for cmd != nil { var fullCmd micromdm.CommandPayload switch cmd.Command.RequestType { case "InstalledApplicationList": - installedAppCount++ + installedAppListCount++ require.NoError(t, plist.Unmarshal(cmd.Raw, &fullCmd)) require.NotNil(t, fullCmd.Command) require.NotNil(t, fullCmd.Command.InstalledApplicationList) @@ -20224,10 +20226,10 @@ func (s *integrationMDMTestSuite) TestInstalledApplicationListCommandForBYODiDev require.NoError(t, err) } } - require.Equal(t, 1, installedAppCount) + require.Equal(t, wantAppListCount, installedAppListCount) } - checkExpectedCommands(mdmClientBYOD, true) + checkExpectedCommands(mdmClientBYOD, true, 1) // create a company-owned ios host hostDEP, mdmClientDEP := s.createAppleMobileHostThenEnrollMDM("ios") @@ -20245,5 +20247,29 @@ func (s *integrationMDMTestSuite) TestInstalledApplicationListCommandForBYODiDev {HostID: hostDEP.ID, CommandType: fleet.RefetchDeviceCommandUUIDPrefix}, }, commands) - checkExpectedCommands(mdmClientDEP, false) + checkExpectedCommands(mdmClientDEP, false, 1) + + // run the cron-based refetch, will not do anything as the devices were just refetched + err = apple_mdm.IOSiPadOSRefetch(ctx, s.ds, s.mdmCommander, s.logger, func(ctx context.Context, user *fleet.User, act fleet.ActivityDetails) error { + return newActivity(ctx, user, act, s.ds, s.logger) + }) + require.NoError(t, err) + + checkExpectedCommands(mdmClientBYOD, true, 0) + checkExpectedCommands(mdmClientDEP, false, 0) + + // change the detail_updated_at of the devices to > 1h ago, and run the refetch again + hostBYOD.DetailUpdatedAt = time.Now().Add(-24 * time.Hour) + hostDEP.DetailUpdatedAt = time.Now().Add(-24 * time.Hour) + require.NoError(t, s.ds.UpdateHost(ctx, hostBYOD)) + require.NoError(t, s.ds.UpdateHost(ctx, hostDEP)) + + // run the cron-based refetch again, will enqueue the commands with the correct managed only flag + err = apple_mdm.IOSiPadOSRefetch(ctx, s.ds, s.mdmCommander, s.logger, func(ctx context.Context, user *fleet.User, act fleet.ActivityDetails) error { + return newActivity(ctx, user, act, s.ds, s.logger) + }) + require.NoError(t, err) + + checkExpectedCommands(mdmClientBYOD, true, 1) + checkExpectedCommands(mdmClientDEP, false, 1) }