Skip to content

Commit

Permalink
Fix issue when identical MDM commands are sent twice to the same devi…
Browse files Browse the repository at this point in the history
…ce when replica DB is being used.
  • Loading branch information
getvictor committed Jan 10, 2025
1 parent de53040 commit 7cd178e
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 1 deletion.
1 change: 1 addition & 0 deletions changes/24816-fix-double-mdm-commands
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix issue when identical MDM commands are sent twice to the same device when replica DB is being used.
2 changes: 1 addition & 1 deletion server/mdm/nanomdm/service/nanomdm/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ func (s *Service) CommandAndReportResults(r *mdm.Request, results *mdm.CommandRe
}
if results.Status != "Idle" {
// If the host is not idle, we use primary DB since we just wrote results of previous command.
ctxdb.RequirePrimary(r.Context, true)
r.Context = ctxdb.RequirePrimary(r.Context, true)
}
cmd, err := s.store.RetrieveNextCommand(r, results.Status == "NotNow")
if err != nil {
Expand Down
58 changes: 58 additions & 0 deletions server/mdm/nanomdm/service/nanomdm/service_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package nanomdm

import (
"context"
"testing"

"github.com/fleetdm/fleet/v4/server/contexts/ctxdb"
"github.com/fleetdm/fleet/v4/server/mdm/nanomdm/mdm"
mock "github.com/fleetdm/fleet/v4/server/mock/mdm"
"github.com/micromdm/nanolib/log"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestCommandAndReportResultsPrimaryDBUse(t *testing.T) {
ds := new(mock.MDMAppleStore)

enrollID := &mdm.EnrollID{
ID: "1",
Type: mdm.Device,
}
s := Service{
logger: log.NopLogger,
store: ds,
normalizer: func(e *mdm.Enrollment) *mdm.EnrollID {
return enrollID
},
}
ds.StoreCommandReportFunc = func(r *mdm.Request, report *mdm.CommandResults) error {
return nil
}
var primaryRequired bool
ds.RetrieveNextCommandFunc = func(r *mdm.Request, skipNotNow bool) (*mdm.CommandWithSubtype, error) {
assert.Equal(t, primaryRequired, ctxdb.IsPrimaryRequired(r.Context))
return nil, nil
}

mdmRequest := &mdm.Request{
Context: context.Background(),
}
mdmCommandResults := &mdm.CommandResults{
Status: "Idle",
}
// We don't use primary DB with "Idle" status because we don't update the status of existing commands
cmd, err := s.CommandAndReportResults(mdmRequest, mdmCommandResults)
require.NoError(t, err)
require.Nil(t, cmd)

// We use primary DB with non-"Idle" status
mdmCommandResults = &mdm.CommandResults{
Status: "Acknowledge",
}
primaryRequired = true
cmd, err = s.CommandAndReportResults(mdmRequest, mdmCommandResults)
require.NoError(t, err)
require.Nil(t, cmd)

}
2 changes: 2 additions & 0 deletions server/service/integration_mdm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11583,6 +11583,8 @@ func (s *integrationMDMTestSuite) TestVPPApps() {
// Simulate successful installation on the host
cmd, err = mdmClient.Acknowledge(cmd.CommandUUID)
require.NoError(t, err)
// No further commands expected
assert.Nil(t, cmd)

listResp = listHostsResponse{}
s.DoJSON("GET", "/api/latest/fleet/hosts", nil, http.StatusOK, &listResp, "software_status", "installed", "team_id",
Expand Down

0 comments on commit 7cd178e

Please sign in to comment.