improve table cleanup on unenrollment (#11075)

https://github.com/fleetdm/fleet/issues/10948
This commit is contained in:
Roberto Dip 2023-04-07 22:02:17 -03:00 committed by GitHub
parent c4775f4129
commit 34833d64a5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 87 additions and 40 deletions

View File

@ -776,12 +776,48 @@ func upsertMDMAppleHostLabelMembershipDB(ctx context.Context, tx sqlx.ExtContext
return nil
}
func (ds *Datastore) deleteMDMAppleProfilesForHost(ctx context.Context, tx sqlx.ExtContext, uuid string) error {
_, err := tx.ExecContext(ctx, `
DELETE FROM host_mdm_apple_profiles
WHERE host_uuid = ?`, uuid)
if err != nil {
return ctxerr.Wrap(ctx, err, "removing all profiles from host")
}
return nil
}
func (ds *Datastore) UpdateHostTablesOnMDMUnenroll(ctx context.Context, uuid string) error {
return ds.withTx(ctx, func(tx sqlx.ExtContext) error {
_, err := tx.ExecContext(ctx, `
var hostID uint
row := tx.QueryRowxContext(ctx, `SELECT id FROM hosts WHERE uuid = ?`, uuid)
err := row.Scan(&hostID)
if err != nil {
return ctxerr.Wrap(ctx, err, "getting host id from UUID")
}
_, err = tx.ExecContext(ctx, `
DELETE FROM host_mdm
WHERE host_id = (SELECT id FROM hosts WHERE uuid = ?)`, uuid)
return err
WHERE host_id = ?`, hostID)
if err != nil {
return ctxerr.Wrap(ctx, err, "removing host_mdm rows for host")
}
// Since the host is unenrolled, delete all profiles assigned to the
// host manually, the device won't Acknowledge any more requests (eg:
// to delete profiles) and profiles are automatically removed on
// unenrollment.
if err := ds.deleteMDMAppleProfilesForHost(ctx, tx, uuid); err != nil {
return ctxerr.Wrap(ctx, err, "deleting profiles for host")
}
_, err = tx.ExecContext(ctx, `
DELETE FROM host_disk_encryption_keys
WHERE host_id = ?`, hostID)
if err != nil {
return ctxerr.Wrap(ctx, err, "removing all profiles from host")
}
return nil
})
}
@ -1273,14 +1309,6 @@ func (ds *Datastore) BulkUpsertMDMAppleHostProfiles(ctx context.Context, payload
return err
}
func (ds *Datastore) DeleteMDMAppleProfilesForHost(ctx context.Context, hostUUID string) error {
_, err := ds.writer.ExecContext(ctx, `
DELETE FROM host_mdm_apple_profiles
WHERE host_uuid = ?
`, hostUUID)
return err
}
func (ds *Datastore) UpdateOrDeleteHostMDMAppleProfile(ctx context.Context, profile *fleet.HostMDMAppleProfile) error {
if profile.OperationType == fleet.MDMAppleOperationTypeRemove &&
profile.Status != nil && (*profile.Status == fleet.MDMAppleDeliveryApplied || profile.IgnoreMDMClientError()) {

View File

@ -727,6 +727,38 @@ func testUpdateHostTablesOnMDMUnenroll(t *testing.T, ds *Datastore) {
})
require.NoError(t, err)
profiles := []*fleet.MDMAppleConfigProfile{
configProfileForTest(t, "N1", "I1", "z"),
}
err = ds.BulkUpsertMDMAppleHostProfiles(ctx, []*fleet.MDMAppleBulkUpsertHostProfilePayload{
{
ProfileID: profiles[0].ProfileID,
ProfileIdentifier: profiles[0].Identifier,
ProfileName: profiles[0].Name,
HostUUID: testUUID,
Status: &fleet.MDMAppleDeliveryApplied,
OperationType: fleet.MDMAppleOperationTypeInstall,
CommandUUID: "command-uuid",
},
},
)
require.NoError(t, err)
hostProfs, err := ds.GetHostMDMProfiles(ctx, testUUID)
require.NoError(t, err)
require.Len(t, hostProfs, len(profiles))
var hostID uint
err = sqlx.GetContext(context.Background(), ds.reader, &hostID, `SELECT id FROM hosts WHERE uuid = ?`, testUUID)
require.NoError(t, err)
err = ds.SetOrUpdateHostDiskEncryptionKey(ctx, hostID, "asdf")
require.NoError(t, err)
key, err := ds.GetHostDiskEncryptionKey(ctx, hostID)
require.NoError(t, err)
require.NotNil(t, key)
// check that an entry in host_mdm exists
var count int
err = sqlx.GetContext(context.Background(), ds.reader, &count, `SELECT COUNT(*) FROM host_mdm WHERE host_id = (SELECT id FROM hosts WHERE uuid = ?)`, testUUID)
@ -739,6 +771,13 @@ func testUpdateHostTablesOnMDMUnenroll(t *testing.T, ds *Datastore) {
err = sqlx.GetContext(context.Background(), ds.reader, &count, `SELECT COUNT(*) FROM host_mdm WHERE host_id = ?`, testUUID)
require.NoError(t, err)
require.Equal(t, 0, count)
hostProfs, err = ds.GetHostMDMProfiles(ctx, testUUID)
require.NoError(t, err)
require.Empty(t, hostProfs)
key, err = ds.GetHostDiskEncryptionKey(ctx, hostID)
require.ErrorIs(t, err, sql.ErrNoRows)
require.Nil(t, key)
}
func testBatchSetMDMAppleProfiles(t *testing.T, ds *Datastore) {
@ -1421,7 +1460,10 @@ func testMDMAppleHostsProfilesStatus(t *testing.T, ds *Datastore) {
require.True(t, checkListHosts(fleet.MacOSSettingsStatusLatest, ptr.Uint(0), []*fleet.Host{}))
// hosts[6] deletes all its profiles
require.NoError(t, ds.DeleteMDMAppleProfilesForHost(ctx, hosts[6].UUID))
tx, err := ds.writer.BeginTxx(ctx, nil)
require.NoError(t, err)
require.NoError(t, ds.deleteMDMAppleProfilesForHost(ctx, tx, hosts[6].UUID))
require.NoError(t, tx.Commit())
pendingHosts := append(hosts[2:6:6], hosts[7:]...)
res, err = ds.GetMDMAppleHostsProfilesSummary(ctx, nil) // get summary for profiles with no team
require.NoError(t, err)
@ -1692,7 +1734,10 @@ func testDeleteMDMAppleProfilesForHost(t *testing.T, ds *Datastore) {
require.NoError(t, err)
require.Len(t, gotProfs, 1)
err = ds.DeleteMDMAppleProfilesForHost(ctx, h.UUID)
tx, err := ds.writer.BeginTxx(ctx, nil)
require.NoError(t, err)
require.NoError(t, ds.deleteMDMAppleProfilesForHost(ctx, tx, h.UUID))
require.NoError(t, tx.Commit())
require.NoError(t, err)
gotProfs, err = ds.GetHostMDMProfiles(ctx, h.UUID)
require.NoError(t, err)

View File

@ -845,9 +845,6 @@ type Datastore interface {
// and the status is "applied" (i.e. successfully removed).
UpdateOrDeleteHostMDMAppleProfile(ctx context.Context, profile *HostMDMAppleProfile) error
// DeleteMDMAppleProfilesForHost deletes all MDM profiles for a host
DeleteMDMAppleProfilesForHost(ctx context.Context, hostUUID string) error
// GetMDMAppleCommandRequest type returns the request type for the given command
GetMDMAppleCommandRequestType(ctx context.Context, commandUUID string) (string, error)

View File

@ -576,8 +576,6 @@ type GetMDMAppleProfilesContentsFunc func(ctx context.Context, profileIDs []uint
type UpdateOrDeleteHostMDMAppleProfileFunc func(ctx context.Context, profile *fleet.HostMDMAppleProfile) error
type DeleteMDMAppleProfilesForHostFunc func(ctx context.Context, hostUUID string) error
type GetMDMAppleCommandRequestTypeFunc func(ctx context.Context, commandUUID string) (string, error)
type GetMDMAppleHostsProfilesSummaryFunc func(ctx context.Context, teamID *uint) (*fleet.MDMAppleHostsProfilesSummary, error)
@ -1435,9 +1433,6 @@ type DataStore struct {
UpdateOrDeleteHostMDMAppleProfileFunc UpdateOrDeleteHostMDMAppleProfileFunc
UpdateOrDeleteHostMDMAppleProfileFuncInvoked bool
DeleteMDMAppleProfilesForHostFunc DeleteMDMAppleProfilesForHostFunc
DeleteMDMAppleProfilesForHostFuncInvoked bool
GetMDMAppleCommandRequestTypeFunc GetMDMAppleCommandRequestTypeFunc
GetMDMAppleCommandRequestTypeFuncInvoked bool
@ -3425,13 +3420,6 @@ func (s *DataStore) UpdateOrDeleteHostMDMAppleProfile(ctx context.Context, profi
return s.UpdateOrDeleteHostMDMAppleProfileFunc(ctx, profile)
}
func (s *DataStore) DeleteMDMAppleProfilesForHost(ctx context.Context, hostUUID string) error {
s.mu.Lock()
s.DeleteMDMAppleProfilesForHostFuncInvoked = true
s.mu.Unlock()
return s.DeleteMDMAppleProfilesForHostFunc(ctx, hostUUID)
}
func (s *DataStore) GetMDMAppleCommandRequestType(ctx context.Context, commandUUID string) (string, error) {
s.mu.Lock()
s.GetMDMAppleCommandRequestTypeFuncInvoked = true

View File

@ -1192,14 +1192,6 @@ func (svc *Service) EnqueueMDMAppleCommandRemoveEnrollmentProfile(ctx context.Co
return ctxerr.Wrap(ctx, err, "enqueuing mdm apple remove profile command")
}
// Since the host is unenrolled, delete all profiles assigned to the
// host manually, the device won't Acknowledge any more requests (eg:
// to delete profiles) and profiles are automatically removed on
// unenrollment.
if err := svc.ds.DeleteMDMAppleProfilesForHost(ctx, h.UUID); err != nil {
return ctxerr.Wrap(ctx, err, "removing all profiles from host")
}
if err := svc.ds.NewActivity(ctx, authz.UserFromContext(ctx), &fleet.ActivityTypeMDMUnenrolled{
HostSerial: h.HardwareSerial,
HostDisplayName: h.DisplayName(),
@ -1985,6 +1977,7 @@ func (svc *MDMAppleCheckinAndCommandService) CheckOut(r *mdm.Request, m *mdm.Che
if err != nil {
return err
}
if err := svc.ds.UpdateHostTablesOnMDMUnenroll(r.Context, m.UDID); err != nil {
return err
}

View File

@ -813,10 +813,6 @@ func TestMDMCommandAuthz(t *testing.T) {
return nil
}
ds.DeleteMDMAppleProfilesForHostFunc = func(ctx context.Context, hostUUID string) error {
return nil
}
var mdmEnabled atomic.Bool
ds.GetNanoMDMEnrollmentFunc = func(ctx context.Context, hostUUID string) (*fleet.NanoEnrollment, error) {
// This function is called twice during EnqueueMDMAppleCommandRemoveEnrollmentProfile.