Fix sending of "install Fleetd" commands repeatedly on Azure-enrolled Windows devices (#18453)

This commit is contained in:
Martin Angers 2024-04-29 08:48:54 -04:00 committed by GitHub
parent 8eec8e5371
commit 26b83de925
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 102 additions and 24 deletions

View file

@ -0,0 +1 @@
* Fixed an issue on Windows hosts enrolled in MDM via Azure AD where the command to install Fleetd on the device was sent repeatedly, even though `fleetd` had been properly installed.

View file

@ -2680,13 +2680,13 @@ func (ds *Datastore) HostByIdentifier(ctx context.Context, identifier string) (*
COALESCE(hd.percent_disk_space_available, 0) as percent_disk_space_available,
COALESCE(hd.gigs_total_disk_space, 0) as gigs_total_disk_space,
COALESCE(hst.seen_time, h.created_at) AS seen_time,
COALESCE(hu.software_updated_at, h.created_at) AS software_updated_at
` + hostMDMSelect + `
COALESCE(hu.software_updated_at, h.created_at) AS software_updated_at
` + hostMDMSelect + `
FROM hosts h
LEFT JOIN host_seen_times hst ON (h.id = hst.host_id)
LEFT JOIN host_updates hu ON (h.id = hu.host_id)
LEFT JOIN host_updates hu ON (h.id = hu.host_id)
LEFT JOIN host_disks hd ON hd.host_id = h.id
` + hostMDMJoin + `
` + hostMDMJoin + `
WHERE ? IN (h.hostname, h.osquery_host_id, h.node_key, h.uuid, h.hardware_serial)
LIMIT 1
`
@ -3715,9 +3715,11 @@ func (ds *Datastore) GetHostOrbitInfo(ctx context.Context, hostID uint) (*fleet.
err := sqlx.GetContext(
ctx, ds.reader(ctx), &orbit, `
SELECT
scripts_enabled
version,
desktop_version,
scripts_enabled
FROM
host_orbit_info
host_orbit_info
WHERE host_id = ?`, hostID,
)
if err != nil {
@ -5037,7 +5039,7 @@ func (ds *Datastore) loadHostLite(ctx context.Context, id *uint, identifier *str
stmt := `
SELECT
h.id,
h.team_id,
h.team_id,
h.osquery_host_id,
h.node_key,
h.hostname,
@ -5048,7 +5050,7 @@ func (ds *Datastore) loadHostLite(ctx context.Context, id *uint, identifier *str
COALESCE(hst.seen_time, h.created_at) AS seen_time
FROM hosts h
LEFT JOIN host_seen_times hst ON (h.id = hst.host_id)
%s
%s
LIMIT 1
`
var (

View file

@ -361,7 +361,9 @@ type Host struct {
// HostOrbitInfo maps to the host_orbit_info table in the database, which maps to the orbit_info agent table.
type HostOrbitInfo struct {
ScriptsEnabled *bool `json:"scripts_enabled" db:"scripts_enabled"`
Version string `json:"version" db:"version"`
DesktopVersion *string `json:"desktop_version" db:"desktop_version"`
ScriptsEnabled *bool `json:"scripts_enabled" db:"scripts_enabled"`
}
// HostHealth contains a subset of Host data that indicates how healthy a Host is. For fields with

View file

@ -6069,22 +6069,79 @@ func (s *integrationMDMTestSuite) TestWindowsAutomaticEnrollmentCommands() {
d := mdmtest.NewTestMDMClientWindowsAutomatic(s.server.URL, azureMail)
require.NoError(t, d.Enroll())
cmds, err := d.StartManagementSession()
checkinAndAck := func(expectFleetdCmds bool) {
cmds, err := d.StartManagementSession()
require.NoError(t, err)
if !expectFleetdCmds {
// receives only the 2 status commands
require.Len(t, cmds, 2)
for _, c := range cmds {
require.Equal(t, "Status", c.Verb, c)
}
return
}
// 2 status + 2 commands to install fleetd
require.Len(t, cmds, 4)
var fleetdAddCmd, fleetdExecCmd fleet.ProtoCmdOperation
for _, c := range cmds {
switch c.Verb {
case "Add":
fleetdAddCmd = c
case "Exec":
fleetdExecCmd = c
}
}
require.Equal(t, syncml.FleetdWindowsInstallerGUID, fleetdAddCmd.Cmd.GetTargetURI())
require.Equal(t, syncml.FleetdWindowsInstallerGUID, fleetdExecCmd.Cmd.GetTargetURI())
// reply with success for both commands
msgID, err := d.GetCurrentMsgID()
require.NoError(t, err)
d.AppendResponse(fleet.SyncMLCmd{
XMLName: xml.Name{Local: fleet.CmdStatus},
MsgRef: &msgID,
CmdRef: &fleetdAddCmd.Cmd.CmdID.Value,
Cmd: &fleetdAddCmd.Verb,
Data: ptr.String("200"),
Items: nil,
CmdID: fleet.CmdID{Value: uuid.NewString()},
})
d.AppendResponse(fleet.SyncMLCmd{
XMLName: xml.Name{Local: fleet.CmdStatus},
MsgRef: &msgID,
CmdRef: &fleetdExecCmd.Cmd.CmdID.Value,
Cmd: &fleetdExecCmd.Verb,
Data: ptr.String("200"),
Items: nil,
CmdID: fleet.CmdID{Value: uuid.NewString()},
})
cmds, err = d.SendResponse()
require.NoError(t, err)
// the ack of the message should be the only returned command
require.Len(t, cmds, 1)
}
// start a management session, will receive the install fleetd commands
checkinAndAck(true)
// start a new management session again, Fleetd is not reported as installed
// so it receives the commands again
checkinAndAck(true)
// simulate fleetd installed and enrolled
host := createOrbitEnrolledHost(t, "windows", "h1", s.ds)
err = s.ds.UpdateMDMWindowsEnrollmentsHostUUID(ctx, host.UUID, d.DeviceID)
require.NoError(t, err)
err = s.ds.SetOrUpdateHostOrbitInfo(ctx, host.ID, "1.23", sql.NullString{}, sql.NullBool{})
require.NoError(t, err)
// 2 status + 2 commands to install fleetd
require.Len(t, cmds, 4)
var fleetdAddCmd, fleetdExecCmd fleet.ProtoCmdOperation
for _, c := range cmds {
switch c.Verb {
case "Add":
fleetdAddCmd = c
case "Exec":
fleetdExecCmd = c
}
}
require.Equal(t, syncml.FleetdWindowsInstallerGUID, fleetdAddCmd.Cmd.GetTargetURI())
require.Equal(t, syncml.FleetdWindowsInstallerGUID, fleetdExecCmd.Cmd.GetTargetURI())
// start a new management session again, Fleetd is reported as installed so
// it does not receive the commands
checkinAndAck(false)
}
func (s *integrationMDMTestSuite) TestValidManagementUnenrollRequest() {

View file

@ -1274,7 +1274,23 @@ func (svc *Service) isFleetdPresentOnDevice(ctx context.Context, deviceID string
// If user identity is a MS-MDM UPN it means that the device was enrolled through user-driven flow
// This means that fleetd might not be installed
if isValidUPN(enrolledDevice.MDMEnrollUserID) {
return false, nil
var isPresent bool
if enrolledDevice.HostUUID != "" {
host, err := svc.ds.HostLiteByIdentifier(ctx, enrolledDevice.HostUUID)
if err != nil && !fleet.IsNotFound(err) {
return false, ctxerr.Wrap(ctx, err, "get host lite by identifier")
}
if host != nil {
orbitInfo, err := svc.ds.GetHostOrbitInfo(ctx, host.ID)
if err != nil && !fleet.IsNotFound(err) {
return false, ctxerr.Wrap(ctx, err, "get host orbit info")
}
if orbitInfo != nil {
isPresent = orbitInfo.Version != ""
}
}
}
return isPresent, nil
}
// TODO: Add check here to determine if MDM DeviceID is connected with Smbios UUID present on