LM: Fix deleted iOS/iPadOS checking in does not update lost mode status (#34250)

<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #34203 

# Checklist for submitter

If some of the following don't apply, delete the relevant line.

- [x] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)

## Testing

- [x] Added/updated automated tests
- [x] QA'd all new/changed functionality manually
This commit is contained in:
Magnus Jensen
2025-10-15 17:24:40 -03:00
committed by GitHub
parent 3e7fde5fef
commit 8c4b5f9371
8 changed files with 185 additions and 5 deletions
+27
View File
@@ -7147,3 +7147,30 @@ WHERE
return &idp, nil
}
func (ds *Datastore) GetLatestAppleMDMCommandOfType(ctx context.Context, hostUUID string, commandType string) (*fleet.MDMCommand, error) {
const stmt = `
SELECT id as host_uuid, command_uuid, request_type FROM nano_view_queue WHERE id = ? AND request_type = ? ORDER BY created_at DESC LIMIT 1
`
var cmd fleet.MDMCommand
if err := sqlx.GetContext(ctx, ds.reader(ctx), &cmd, stmt, hostUUID, commandType); err != nil {
if err == sql.ErrNoRows {
return nil, notFound("MDMCommand")
}
return nil, ctxerr.Wrap(ctx, err, "get latest apple mdm command of type")
}
return &cmd, nil
}
func (ds *Datastore) SetLockCommandForLostModeCheckin(ctx context.Context, hostID uint, commandUUID string) error {
// We know we can insert here, as this is only called when processing a
// a new iphone/ipad checkin with lost mode enabled.
const stmt = `
INSERT INTO host_mdm_actions (host_id, lock_ref)
VALUES (?, ?)
`
_, err := ds.writer(ctx).ExecContext(ctx, stmt, hostID, commandUUID)
return ctxerr.Wrap(ctx, err, "set lock ref for lost mode checkin")
}
+70
View File
@@ -104,6 +104,8 @@ func TestMDMApple(t *testing.T) {
{"TestDeleteMDMAppleDeclarationWithPendingInstalls", testDeleteMDMAppleDeclarationWithPendingInstalls},
{"TestUpdateNanoMDMUserEnrollmentUsername", testUpdateNanoMDMUserEnrollmentUsername},
{"TestLockUnlockWipeIphone", testLockUnlockWipeIphone},
{"TestGetLatestAppleMDMCommandOfType", testGetLatestAppleMDMCommandOfType},
{"TestSetLockCommandForLostModeCheckin", testSetLockCommandForLostModeCheckin},
}
for _, c := range cases {
@@ -9483,3 +9485,71 @@ func testUpdateNanoMDMUserEnrollmentUsername(t *testing.T, ds *Datastore) {
require.Equal(t, nanoenroll_username, user1)
require.Equal(t, userUUID1, fetchedUserUUID1)
}
func testGetLatestAppleMDMCommandOfType(t *testing.T, ds *Datastore) {
ctx := t.Context()
// Fails if host does not have a record
_, err := ds.GetLatestAppleMDMCommandOfType(ctx, "non-existing-uuid", "DeviceLock")
require.Error(t, err)
require.True(t, errors.Is(err, sql.ErrNoRows))
// Nano enroll a single device
realHostUUID := uuid.NewString()
host := &fleet.Host{
UUID: realHostUUID,
HardwareSerial: "serial",
Platform: "darwin",
TeamID: nil,
}
nanoEnroll(t, ds, host, false)
// Insert one record
deviceLockCommandUUID := uuid.NewString()
requestType := "DeviceLock"
insertIntoNanoViewQueue(t, ds, host.UUID, deviceLockCommandUUID, requestType)
// Fails if host does exist but not request type
_, err = ds.GetLatestAppleMDMCommandOfType(ctx, host.UUID, "EnableLostMode")
require.Error(t, err)
require.True(t, errors.Is(err, sql.ErrNoRows))
// Succeeds if host and request type exist
cmd, err := ds.GetLatestAppleMDMCommandOfType(ctx, host.UUID, requestType)
require.NoError(t, err)
require.Equal(t, deviceLockCommandUUID, cmd.CommandUUID)
require.Equal(t, requestType, cmd.RequestType)
}
// insertIntoNanoViewQueue is a helper function that populates the entries that nano_view_queue is made up of.
func insertIntoNanoViewQueue(t *testing.T, ds *Datastore, hostUUID, commandUUID, requestType string) {
ctx := t.Context()
ExecAdhocSQL(t, ds, func(q sqlx.ExtContext) error {
// Insert into nano_commands
_, err := q.ExecContext(ctx, `INSERT INTO nano_commands (command_uuid, request_type, command, subtype) VALUES (?, ?, '<?xml', 'None')`, commandUUID, requestType)
require.NoError(t, err)
// Insert into nano_enrollment_queue
_, err = q.ExecContext(ctx, `INSERT INTO nano_enrollment_queue (id, command_uuid, active, priority) VALUES (?, ?, 1, 0)`, hostUUID, commandUUID)
require.NoError(t, err)
// Insert into nano_command_results
_, err = q.ExecContext(ctx, `INSERT INTO nano_command_results (id, command_uuid, status, result, not_now_tally) VALUES (?, ?, 'Acknowledged', '<?xml', 0)`, hostUUID, commandUUID)
return err
})
}
func testSetLockCommandForLostModeCheckin(t *testing.T, ds *Datastore) {
ctx := t.Context()
hostID := uint(1)
commandUUID := uuid.NewString()
// Insert successfully
err := ds.SetLockCommandForLostModeCheckin(ctx, hostID, commandUUID)
require.NoError(t, err)
// Fails if trying to insert on existing row
err = ds.SetLockCommandForLostModeCheckin(ctx, hostID, commandUUID)
require.Error(t, err)
}