improve windows resending (#40365)

Improves windows resending
This commit is contained in:
Magnus Jensen
2026-02-24 09:10:07 -05:00
committed by GitHub
parent 6435fa6c68
commit 8d5be2f877
7 changed files with 71 additions and 17 deletions
+15 -6
View File
@@ -2472,23 +2472,32 @@ func (ds *Datastore) GetWindowsHostMDMCertificateProfile(ctx context.Context, ho
return &profile, nil
}
func (ds *Datastore) GetWindowsMDMCommandsForResending(ctx context.Context, failedCommandIds []string) ([]*fleet.MDMWindowsCommand, error) {
func (ds *Datastore) GetWindowsMDMCommandsForResending(ctx context.Context, deviceID string, failedCommandIds []string) ([]*fleet.MDMWindowsCommand, error) {
if len(failedCommandIds) == 0 {
return []*fleet.MDMWindowsCommand{}, nil
}
stmt := `SELECT command_uuid, raw_command, target_loc_uri, created_at, updated_at
FROM windows_mdm_commands WHERE`
stmt := `SELECT wmc.command_uuid, wmc.raw_command, wmc.target_loc_uri, wmc.created_at, wmc.updated_at
FROM windows_mdm_commands wmc INNER JOIN windows_mdm_command_queue wmcq ON wmcq.enrollment_id = (SELECT id from mdm_windows_enrollments WHERE mdm_device_id = ?) AND wmcq.command_uuid = wmc.command_uuid WHERE`
args := []any{}
args := []any{deviceID}
for idx, commandId := range failedCommandIds {
stmt += " raw_command LIKE ? OR "
args = append(args, "%"+commandId+"%")
if commandId == "" {
continue
}
stmt += " wmc.raw_command LIKE ? OR "
args = append(args, "%<CmdID>"+commandId+"</CmdID>%")
if idx == len(failedCommandIds)-1 {
stmt = strings.TrimSuffix(stmt, " OR ")
}
}
if len(args) == 1 {
// No valid command IDs were provided, return empty result to avoid returning all commands for the device.
return []*fleet.MDMWindowsCommand{}, nil
}
stmt += fmt.Sprintf(" ORDER BY created_at DESC LIMIT %d", len(failedCommandIds))
var commands []*fleet.MDMWindowsCommand
+6 -4
View File
@@ -3702,27 +3702,29 @@ func testGetWindowsMDMCommandsForResending(t *testing.T, ds *Datastore) {
dev := createMDMWindowsEnrollment(ctx, t, ds)
// No commands in windows_mdm_commands so doesn't matter what we put in
commands, err := ds.GetWindowsMDMCommandsForResending(ctx, []string{cmdUUID})
commands, err := ds.GetWindowsMDMCommandsForResending(ctx, dev.MDMDeviceID, []string{cmdUUID})
require.NoError(t, err)
require.Empty(t, commands)
// Insert a command
rawCommand := []byte(cmdUUID)
rawCommand := fmt.Appendf(nil, "<CmdID>%s</CmdID>", cmdUUID)
err = ds.mdmWindowsInsertCommandForHostsDB(ctx, ds.writer(ctx), []string{dev.HostUUID}, &fleet.MDMWindowsCommand{
CommandUUID: topLevelCmdUUID,
RawCommand: rawCommand,
})
require.NoError(t, err)
//
// Fetch command for resending
commands, err = ds.GetWindowsMDMCommandsForResending(ctx, []string{cmdUUID})
commands, err = ds.GetWindowsMDMCommandsForResending(ctx, dev.MDMDeviceID, []string{cmdUUID})
require.NoError(t, err)
require.Len(t, commands, 1)
assert.Equal(t, topLevelCmdUUID, commands[0].CommandUUID)
assert.Equal(t, rawCommand, commands[0].RawCommand)
// Check that we search raw body and not match on command_uuid
commands, err = ds.GetWindowsMDMCommandsForResending(ctx, []string{topLevelCmdUUID})
commands, err = ds.GetWindowsMDMCommandsForResending(ctx, dev.MDMDeviceID, []string{topLevelCmdUUID})
require.NoError(t, err)
require.Empty(t, commands)
}
+1 -1
View File
@@ -2682,7 +2682,7 @@ type Datastore interface {
// and need to be resent based on their command IDs.
//
// Returns a slice of MDMWindowsCommand pointers containing the commands to be resent.
GetWindowsMDMCommandsForResending(ctx context.Context, failedCommandIds []string) ([]*MDMWindowsCommand, error)
GetWindowsMDMCommandsForResending(ctx context.Context, deviceID string, failedCommandIds []string) ([]*MDMWindowsCommand, error)
// ResendWindowsMDMCommand marks the specified Windows MDM command for resend
// by inserting a new command entry, command queue, but also updates the host profile reference.
+3 -3
View File
@@ -1765,7 +1765,7 @@ type GetCurrentTimeFunc func(ctx context.Context) (time.Time, error)
type UpdateOrDeleteHostMDMWindowsProfileFunc func(ctx context.Context, profile *fleet.HostMDMWindowsProfile) error
type GetWindowsMDMCommandsForResendingFunc func(ctx context.Context, failedCommandIds []string) ([]*fleet.MDMWindowsCommand, error)
type GetWindowsMDMCommandsForResendingFunc func(ctx context.Context, deviceID string, failedCommandIds []string) ([]*fleet.MDMWindowsCommand, error)
type ResendWindowsMDMCommandFunc func(ctx context.Context, mdmDeviceId string, newCmd *fleet.MDMWindowsCommand, oldCmd *fleet.MDMWindowsCommand) error
@@ -10509,11 +10509,11 @@ func (s *DataStore) UpdateOrDeleteHostMDMWindowsProfile(ctx context.Context, pro
return s.UpdateOrDeleteHostMDMWindowsProfileFunc(ctx, profile)
}
func (s *DataStore) GetWindowsMDMCommandsForResending(ctx context.Context, failedCommandIds []string) ([]*fleet.MDMWindowsCommand, error) {
func (s *DataStore) GetWindowsMDMCommandsForResending(ctx context.Context, deviceID string, failedCommandIds []string) ([]*fleet.MDMWindowsCommand, error) {
s.mu.Lock()
s.GetWindowsMDMCommandsForResendingFuncInvoked = true
s.mu.Unlock()
return s.GetWindowsMDMCommandsForResendingFunc(ctx, failedCommandIds)
return s.GetWindowsMDMCommandsForResendingFunc(ctx, deviceID, failedCommandIds)
}
func (s *DataStore) ResendWindowsMDMCommand(ctx context.Context, mdmDeviceId string, newCmd *fleet.MDMWindowsCommand, oldCmd *fleet.MDMWindowsCommand) error {
@@ -8692,6 +8692,49 @@ func (s *integrationMDMTestSuite) TestWindowsProfileRetry() {
require.NoError(t, err)
require.Len(t, cmds, 1) // only ack returned
})
t.Run("Other hosts can not get all commands", func(t *testing.T) {
// Let's insert a command for the original host, with some random raw_command data
commandUUID := uuid.NewString()
mysql.ExecAdhocSQL(t, s.ds, func(q sqlx.ExtContext) error {
commandData := `<Add><!-- CmdID generated by Fleet --><CmdID>` + commandUUID + `</CmdID><Item><Target><LocURI>./BogusLocURI</LocURI></Target><Meta><Type xmlns="syncml:metinf">text/plain</Type><Format xmlns="syncml:metinf">bool</Format></Meta><Data>true</Data></Item></Add>`
_, err := q.ExecContext(ctx, `INSERT INTO windows_mdm_commands (command_uuid, raw_command, target_loc_uri) VALUES (?, ?, '')`, commandUUID, commandData)
require.NoError(t, err)
return nil
})
// Create another host and enroll in MDM
_, mdmDevice2 := createWindowsHostThenEnrollMDM(s.ds, s.server.URL, t)
// Start connection, and then reply with a missing CmdRef
cmds, err := mdmDevice2.StartManagementSession()
require.NoError(t, err)
msgID, err := mdmDevice2.GetCurrentMsgID()
require.NoError(t, err)
for _, cmd := range cmds {
if cmd.Verb == "Status" {
continue
}
}
syncCmd := fleet.SyncMLCmd{
XMLName: xml.Name{Local: fleet.CmdStatus},
MsgRef: &msgID,
Cmd: ptr.String("Add"),
CmdRef: ptr.String(""),
Data: ptr.String(syncml.CmdStatusAlreadyExists),
CmdID: fleet.CmdID{Value: uuid.NewString()},
}
mdmDevice2.AppendResponse(syncCmd)
cmds, err = mdmDevice2.SendResponse()
require.NoError(t, err)
require.Len(t, cmds, 1) // Only 1 status message
for _, cmd := range cmds {
if cmd.Verb != "Status" {
t.Errorf("Expected only Status command, got %s", cmd.Verb)
}
}
})
}
func (s *integrationMDMTestSuite) TestHostMDMAndroidProfilesStatus() {
+2 -2
View File
@@ -1743,7 +1743,7 @@ func (svc *Service) processIncomingMDMCmds(ctx context.Context, deviceID string,
// Iterate over the operations and process them
for _, protoCMD := range reqMsg.GetOrderedCmds() {
if protoCMD.Cmd.Data != nil && *protoCMD.Cmd.Data == "418" {
if protoCMD.Cmd.Data != nil && *protoCMD.Cmd.Data == "418" && protoCMD.Cmd.CmdRef != nil {
// 418 = Already exists, and indicate that an <Add> failed due to the item already existing on the device
// We need to re-issue a <Replace> command for this item
alreadyExistsCmdIDs = append(alreadyExistsCmdIDs, *protoCMD.Cmd.CmdRef)
@@ -1782,7 +1782,7 @@ func (svc *Service) processIncomingMDMCmds(ctx context.Context, deviceID string,
}
func handleResendingAlreadyExistsCommands(ctx context.Context, svc *Service, alreadyExistsCmdIDs []string, deviceID string) ([]string, error) {
commands, err := svc.ds.GetWindowsMDMCommandsForResending(ctx, alreadyExistsCmdIDs)
commands, err := svc.ds.GetWindowsMDMCommandsForResending(ctx, deviceID, alreadyExistsCmdIDs)
if err != nil {
return nil, fmt.Errorf("get commands for resending: %w", err)
}
+1 -1
View File
@@ -1044,7 +1044,7 @@ func TestRekeyWindowsDevice(t *testing.T) {
ds.MDMWindowsGetPendingCommandsFunc = func(ctx context.Context, deviceID string) ([]*fleet.MDMWindowsCommand, error) {
return []*fleet.MDMWindowsCommand{}, nil
}
ds.GetWindowsMDMCommandsForResendingFunc = func(ctx context.Context, failedCommandIds []string) ([]*fleet.MDMWindowsCommand, error) {
ds.GetWindowsMDMCommandsForResendingFunc = func(ctx context.Context, deviceID string, failedCommandIds []string) ([]*fleet.MDMWindowsCommand, error) {
return []*fleet.MDMWindowsCommand{}, nil
}