diff --git a/changes/issue-9905-fix-panic-host-mdm-is-server b/changes/issue-9905-fix-panic-host-mdm-is-server new file mode 100644 index 0000000000..be255df17b --- /dev/null +++ b/changes/issue-9905-fix-panic-host-mdm-is-server @@ -0,0 +1 @@ +* Fixed a panic when loading information for a host enrolled in MDM and its `is_server` field is `NULL`. diff --git a/server/datastore/mysql/hosts.go b/server/datastore/mysql/hosts.go index b218315151..90a2290820 100644 --- a/server/datastore/mysql/hosts.go +++ b/server/datastore/mysql/hosts.go @@ -1274,7 +1274,7 @@ func (ds *Datastore) LoadHostByOrbitNodeKey(ctx context.Context, nodeKey string) hm.server_url, hm.installed_from_dep, hm.mdm_id, - hm.is_server, + COALESCE(hm.is_server, false) AS is_server, COALESCE(mdms.name, ?) AS name FROM hosts h @@ -2351,7 +2351,7 @@ func (ds *Datastore) SetOrUpdateHostDisksEncryption(ctx context.Context, hostID func (ds *Datastore) SetOrUpdateHostDiskEncryptionKey(ctx context.Context, hostID uint, encryptedBase64Key string) error { _, err := ds.writer.ExecContext(ctx, ` - INSERT INTO host_disk_encryption_keys (host_id, base64_encrypted) + INSERT INTO host_disk_encryption_keys (host_id, base64_encrypted) VALUES (?, ?) ON DUPLICATE KEY UPDATE /* if the key has changed, NULLify this value so it can be calculated again */ @@ -2455,7 +2455,7 @@ func (ds *Datastore) GetHostMDM(ctx context.Context, hostID uint) (*fleet.HostMD var hmdm fleet.HostMDM err := sqlx.GetContext(ctx, ds.reader, &hmdm, ` SELECT - hm.host_id, hm.enrolled, hm.server_url, hm.installed_from_dep, hm.mdm_id, hm.is_server, COALESCE(mdms.name, ?) AS name + hm.host_id, hm.enrolled, hm.server_url, hm.installed_from_dep, hm.mdm_id, COALESCE(hm.is_server, false) AS is_server, COALESCE(mdms.name, ?) AS name FROM host_mdm hm LEFT OUTER JOIN diff --git a/server/datastore/mysql/hosts_test.go b/server/datastore/mysql/hosts_test.go index ce8995ce59..69e7b1a41f 100644 --- a/server/datastore/mysql/hosts_test.go +++ b/server/datastore/mysql/hosts_test.go @@ -923,6 +923,17 @@ func testHostsUnenrollFromMDM(t *testing.T, ds *Datastore) { err = ds.SetOrUpdateMDMData(ctx, h2.ID, false, true, simpleMDM, true, "") require.NoError(t, err) + // force is_server to NULL for host 1 + ExecAdhocSQL(t, ds, func(q sqlx.ExtContext) error { + _, err := q.ExecContext(ctx, `UPDATE host_mdm SET is_server = NULL WHERE host_id = ?`, h.ID) + return err + }) + // GetHostMDM should still work and return false for is_server + hmdm, err := ds.GetHostMDM(ctx, h.ID) + require.NoError(t, err) + require.Equal(t, h.ID, hmdm.HostID) + require.False(t, hmdm.IsServer) + for _, hi := range []*fleet.Host{h, h2} { hmdm, err := ds.GetHostMDM(ctx, hi.ID) require.NoError(t, err) @@ -5980,6 +5991,17 @@ func testHostsLoadHostByOrbitNodeKey(t *testing.T, ds *Datastore) { require.Equal(t, hFleet.ID, loadFleet.MDMInfo.HostID) require.True(t, loadFleet.IsOsqueryEnrolled()) require.True(t, loadFleet.MDMInfo.IsPendingDEPFleetEnrollment()) + require.False(t, loadFleet.MDMInfo.IsServer) + + // force its is_server mdm field to NULL, should be same as false + ExecAdhocSQL(t, ds, func(q sqlx.ExtContext) error { + _, err := q.ExecContext(ctx, `UPDATE host_mdm SET is_server = NULL WHERE host_id = ?`, hFleet.ID) + return err + }) + loadFleet, err = ds.LoadHostByOrbitNodeKey(ctx, *hFleet.OrbitNodeKey) + require.NoError(t, err) + require.Equal(t, hFleet.ID, loadFleet.ID) + require.False(t, loadFleet.MDMInfo.IsServer) } func checkEncryptionKeyStatus(t *testing.T, ds *Datastore, hostID uint, expected *bool) {