From 07332b2100e5d7f97f88d22200a94f0d9f9659b6 Mon Sep 17 00:00:00 2001 From: Roberto Dip Date: Sat, 8 Apr 2023 15:01:57 -0300 Subject: [PATCH 01/11] various profile fixes --- server/datastore/mysql/apple_mdm.go | 308 ++++++++++-------- .../20230408084104_AddChecksumToProfiles.go | 24 ++ ...230408084104_AddChecksumToProfiles_test.go | 20 ++ server/datastore/mysql/schema.sql | 6 +- server/fleet/apple_mdm.go | 2 + server/service/apple_mdm.go | 2 + 6 files changed, 230 insertions(+), 132 deletions(-) create mode 100644 server/datastore/mysql/migrations/tables/20230408084104_AddChecksumToProfiles.go create mode 100644 server/datastore/mysql/migrations/tables/20230408084104_AddChecksumToProfiles_test.go diff --git a/server/datastore/mysql/apple_mdm.go b/server/datastore/mysql/apple_mdm.go index af7a1cbdd91..96b713da6f5 100644 --- a/server/datastore/mysql/apple_mdm.go +++ b/server/datastore/mysql/apple_mdm.go @@ -1,7 +1,6 @@ package mysql import ( - "bytes" "context" "database/sql" "errors" @@ -22,8 +21,8 @@ import ( func (ds *Datastore) NewMDMAppleConfigProfile(ctx context.Context, cp fleet.MDMAppleConfigProfile) (*fleet.MDMAppleConfigProfile, error) { stmt := ` INSERT INTO - mdm_apple_configuration_profiles (team_id, identifier, name, mobileconfig) -VALUES (?, ?, ?, ?)` + mdm_apple_configuration_profiles (team_id, identifier, name, mobileconfig, checksum) +VALUES (?, ?, ?, ?, UNHEX(MD5(mobileconfig)))` var teamID uint if cp.TeamID != nil { @@ -174,13 +173,18 @@ SELECT profile_id, profile_name AS name, profile_identifier AS identifier, - status, + -- internally, a NULL status implies that the cron needs to pick up + -- this profile, for the user that difference doesn't exist, the + -- profile is effectively pending. This is consistent with all our + -- aggregation functions. + COALESCE(status, '%s') AS status, COALESCE(operation_type, '') AS operation_type, COALESCE(detail, '') AS detail FROM host_mdm_apple_profiles WHERE - host_uuid = ? AND NOT (operation_type = '%s' AND COALESCE(status, '') = '%s')`, + host_uuid = ? AND NOT (operation_type = '%s' AND status = '%s')`, + fleet.MDMAppleDeliveryPending, fleet.MDMAppleOperationTypeRemove, fleet.MDMAppleDeliveryApplied, ) @@ -894,7 +898,10 @@ INSERT INTO team_id, identifier, name, mobileconfig ) VALUES - ( ?, ?, ?, ? ) + ( ?, ?, ?, ?, UNHEX(MD5(mobileconfig)) ) +ON DUPLICATE KEY UPDATE + mobileconfig = VALUES(mobileconfig), + checksum = UNHEX(MD5(VALUES(mobileconfig))) ` // use a profile team id of 0 if no-team @@ -928,16 +935,12 @@ VALUES } } - // match the existing profiles to the incoming ones and keep the existing - // ones that have not changed + // figure out if we need to delete any profiles keepIdents := make([]string, 0, len(incomingIdents)) for _, p := range existingProfiles { if newP := incomingProfs[p.Identifier]; newP != nil { - if bytes.Equal(newP.Mobileconfig, p.Mobileconfig) { - // the profile has not changed, keep the existing one - keepIdents = append(keepIdents, p.Identifier) - delete(incomingProfs, p.Identifier) - } + keepIdents = append(keepIdents, p.Identifier) + delete(incomingProfs, p.Identifier) } } @@ -975,117 +978,97 @@ VALUES // (i.e. pass 0 in that case as part of the teamIDs slice). Only one of the // slice arguments can have values. func (ds *Datastore) BulkSetPendingMDMAppleHostProfiles(ctx context.Context, hostIDs, teamIDs, profileIDs []uint, hostUUIDs []string) error { - var countArgs int - if len(hostIDs) > 0 { - countArgs++ - } - if len(teamIDs) > 0 { - countArgs++ - } - if len(profileIDs) > 0 { - countArgs++ - } - if len(hostUUIDs) > 0 { - countArgs++ - } - if countArgs > 1 { - return errors.New("only one of hostIDs, teamIDs, profileIDs or hostUUIDs can be provided") - } - if countArgs == 0 { - return nil - } + return ds.withTx(ctx, func(tx sqlx.ExtContext) error { + var countArgs int + if len(hostIDs) > 0 { + countArgs++ + } + if len(teamIDs) > 0 { + countArgs++ + } + if len(profileIDs) > 0 { + countArgs++ + } + if len(hostUUIDs) > 0 { + countArgs++ + } + if countArgs > 1 { + return errors.New("only one of hostIDs, teamIDs, profileIDs or hostUUIDs can be provided") + } + if countArgs == 0 { + return nil + } - var ( - uuids []string - args []any - uuidStmt string - ) + var ( + uuids []string + args []any + uuidStmt string + ) - switch { - case len(hostUUIDs) > 0: - // no need to run a query to load host UUIDs, that's what we received - // directly. - uuids = hostUUIDs - - case len(hostIDs) > 0: - uuidStmt = `SELECT uuid FROM hosts WHERE id IN (?)` - args = append(args, hostIDs) - - case len(teamIDs) > 0: - uuidStmt = `SELECT uuid FROM hosts WHERE ` - if len(teamIDs) == 1 && teamIDs[0] == 0 { - uuidStmt += `team_id IS NULL` - } else { - uuidStmt += `team_id IN (?)` - args = append(args, teamIDs) - for _, tmID := range teamIDs { - if tmID == 0 { - uuidStmt += ` OR team_id IS NULL` - break + switch { + case len(hostUUIDs) > 0: + // no need to run a query to load host UUIDs, that's what we received + // directly. + uuids = hostUUIDs + + case len(hostIDs) > 0: + uuidStmt = `SELECT uuid FROM hosts WHERE id IN (?)` + args = append(args, hostIDs) + + case len(teamIDs) > 0: + uuidStmt = `SELECT uuid FROM hosts WHERE ` + if len(teamIDs) == 1 && teamIDs[0] == 0 { + uuidStmt += `team_id IS NULL` + } else { + uuidStmt += `team_id IN (?)` + args = append(args, teamIDs) + for _, tmID := range teamIDs { + if tmID == 0 { + uuidStmt += ` OR team_id IS NULL` + break + } } } - } - case len(profileIDs) > 0: - uuidStmt = ` + case len(profileIDs) > 0: + uuidStmt = ` SELECT DISTINCT h.uuid FROM hosts h JOIN mdm_apple_configuration_profiles macp ON h.team_id = macp.team_id OR (h.team_id IS NULL AND macp.team_id = 0) WHERE macp.profile_id IN (?)` - args = append(args, profileIDs) - } - - if len(uuids) == 0 { - uuidStmt, args, err := sqlx.In(uuidStmt, args...) - if err != nil { - return ctxerr.Wrap(ctx, err, "prepare query to load host UUIDs") + args = append(args, profileIDs) } - if err := sqlx.SelectContext(ctx, ds.writer, &uuids, uuidStmt, args...); err != nil { - return ctxerr.Wrap(ctx, err, "execute query to load host UUIDs") + + if len(uuids) == 0 { + uuidStmt, args, err := sqlx.In(uuidStmt, args...) + if err != nil { + return ctxerr.Wrap(ctx, err, "prepare query to load host UUIDs") + } + if err := sqlx.SelectContext(ctx, tx, &uuids, uuidStmt, args...); err != nil { + return ctxerr.Wrap(ctx, err, "execute query to load host UUIDs") + } } - } - if len(uuids) == 0 { - return nil - } + if len(uuids) == 0 { + return nil + } - const baseStmt = ` -INSERT INTO host_mdm_apple_profiles ( - profile_id, - host_uuid, - profile_identifier, - profile_name, - operation_type, - status, - command_uuid -) - -- NOTE: from https://dev.mysql.com/doc/refman/5.7/en/insert-on-duplicate.html - -- In an ON DUPLICATE KEY UPDATE clause: - -- References to columns from a UNION do not work reliably. To work - -- around this restriction, rewrite the UNION as a derived table so that its - -- rows can be treated as a single-table result set. - SELECT * FROM ( - -- profiles to install, i.e. those part of the host's team/no team. - -- Except for the SELECT list, filtering on specific target IDs - -- (host/team/profile) and ignoring hmap rows that are already - -- "install" and NULL status, this is the same as - -- ListMDMAppleProfilesToInstall. + const profilesToInstallStmt = ` SELECT ds.profile_id as profile_id, ds.host_uuid as host_uuid, ds.profile_identifier as profile_identifier, ds.profile_name as profile_name, - ? as operation_type, - NULL as status, - '' as command_uuid + ds.checksum as checksum FROM ( SELECT macp.profile_id, h.uuid as host_uuid, macp.identifier as profile_identifier, - macp.name as profile_name + macp.name as profile_name, + macp.checksum as checksum FROM mdm_apple_configuration_profiles macp JOIN hosts h ON h.team_id = macp.team_id OR (h.team_id IS NULL AND macp.team_id = 0) JOIN nano_enrollments ne ON ne.device_id = h.uuid @@ -1094,25 +1077,37 @@ INSERT INTO host_mdm_apple_profiles ( LEFT JOIN host_mdm_apple_profiles hmap ON hmap.profile_id = ds.profile_id AND hmap.host_uuid = ds.host_uuid WHERE + -- profile has been updated + ( hmap.checksum != ds.checksum ) OR -- profiles in A but not in B ( hmap.profile_id IS NULL AND hmap.host_uuid IS NULL ) OR -- profiles in A and B but with operation type "remove" - ( hmap.host_uuid IS NOT NULL AND ( hmap.operation_type = ? OR hmap.operation_type IS NULL ) ) + ( hmap.host_uuid IS NOT NULL AND ( hmap.operation_type = ? OR hmap.operation_type IS NULL ) )` - UNION + stmt, args, err := sqlx.In(profilesToInstallStmt, + uuids, fleet.MDMAppleOperationTypeRemove, + ) + if err != nil { + return ctxerr.Wrap(ctx, err, "building profiles to install statement") + } - -- profiles to remove, i.e. those not part of the host's team/no team. - -- Except for the SELECT list, filtering on specific target IDs and ignoring - -- hmap rows that are already "remove" in any status, this is the same - -- as ListMDMAppleProfilesToRemove. + var profilesToInstall []*fleet.MDMAppleProfilePayload + err = sqlx.SelectContext(ctx, tx, &profilesToInstall, stmt, args...) + if err != nil { + return ctxerr.Wrap(ctx, err, "bulk set pending profile status execute") + } + installIdentifiers := []string{} + for _, p := range profilesToInstall { + installIdentifiers = append(installIdentifiers, p.ProfileIdentifier) + } + + const profilesToRemoveStmt = ` SELECT hmap.profile_id as profile_id, hmap.host_uuid as host_uuid, hmap.profile_identifier as profile_identifier, hmap.profile_name as profile_name, - ? as operation_type, - NULL as status, - '' as command_uuid + hmap.checksum as checksum FROM ( SELECT h.uuid, macp.profile_id @@ -1129,26 +1124,71 @@ INSERT INTO host_mdm_apple_profiles ( AND ds.profile_id IS NULL AND ds.uuid IS NULL -- except "remove" operations in any state AND ( hmap.operation_type IS NULL OR hmap.operation_type != ? ) - ) AS dt + -- profiles that are being installed + AND hmap.profile_identifier NOT IN (?) + ` + stmt, args, err = sqlx.In(profilesToRemoveStmt, + uuids, uuids, fleet.MDMAppleOperationTypeRemove, installIdentifiers, + ) + if err != nil { + return ctxerr.Wrap(ctx, err, "building profiles to remove statement") + } + var profilesToRemove []*fleet.MDMAppleProfilePayload + err = sqlx.SelectContext(ctx, tx, &profilesToRemove, stmt, args...) + if err != nil { + return ctxerr.Wrap(ctx, err, "bulk set pending profile status execute") + } + + if len(profilesToInstall) == 0 && len(profilesToRemove) == 0 { + return nil + } + + // before doing the inserts, remove profiles with identifiers that will be sent again from the database + stmt, args, err = sqlx.In("DELETE FROM host_mdm_apple_profiles WHERE host_uuid IN (?) AND profile_identifier IN (?)", uuids, installIdentifiers) + if err != nil { + return ctxerr.Wrap(ctx, err, "building delete statement to remove unused profiles") + } + _, err = tx.ExecContext(ctx, stmt, args...) + if err != nil { + return ctxerr.Wrap(ctx, err, "bulk set pending profile status execute") + } + + var pargs []any + var psb strings.Builder + for _, p := range profilesToInstall { + pargs = append(pargs, p.ProfileID, p.HostUUID, p.ProfileIdentifier, p.ProfileName, p.Checksum, fleet.MDMAppleOperationTypeInstall, nil, "") + psb.WriteString("(?, ?, ?, ?, ?, ?, ?, ?),") + + } + for _, p := range profilesToRemove { + pargs = append(pargs, p.ProfileID, p.HostUUID, p.ProfileIdentifier, p.ProfileName, p.Checksum, fleet.MDMAppleOperationTypeRemove, nil, "") + psb.WriteString("(?, ?, ?, ?, ?, ?, ?, ?),") + + } + baseStmt := fmt.Sprintf(` +INSERT INTO host_mdm_apple_profiles ( + profile_id, + host_uuid, + profile_identifier, + profile_name, + checksum, + operation_type, + status, + command_uuid +) +VALUES %s ON DUPLICATE KEY UPDATE operation_type = VALUES(operation_type), status = VALUES(status), command_uuid = VALUES(command_uuid), + checksum = VALUES(checksum), detail = '' -` +`, strings.TrimSuffix(psb.String(), ",")) - stmt, args, err := sqlx.In(baseStmt, - // to install parameters: - fleet.MDMAppleOperationTypeInstall, uuids, fleet.MDMAppleOperationTypeRemove, - // to remove parameters: - fleet.MDMAppleOperationTypeRemove, uuids, uuids, fleet.MDMAppleOperationTypeRemove, - ) - if err != nil { - return ctxerr.Wrap(ctx, err, "bulk set pending profile status build args") - } - _, err = ds.writer.ExecContext(ctx, stmt, args...) - return ctxerr.Wrap(ctx, err, "bulk set pending profile status execute") + _, err = tx.ExecContext(ctx, baseStmt, pargs...) + return ctxerr.Wrap(ctx, err, "bulk set pending profile status execute") + }) } func (ds *Datastore) ListMDMAppleProfilesToInstall(ctx context.Context) ([]*fleet.MDMAppleProfilePayload, error) { @@ -1162,6 +1202,9 @@ func (ds *Datastore) ListMDMAppleProfilesToInstall(ctx context.Context) ([]*flee // // - profiles that are in A but not in B // + // - profiles which contents have changed, but their identifier are + // the same (by matching checksums) + // // - profiles that are in A and in B, but with an operation type of // "remove", regardless of the status. (technically, if status is NULL then // the profile should be already installed - it has not been queued for @@ -1178,13 +1221,14 @@ func (ds *Datastore) ListMDMAppleProfilesToInstall(ctx context.Context) ([]*flee // profile's content is edited, all relevant hosts will be marked as status // NULL so that it gets re-installed. query := ` - SELECT ds.profile_id, ds.host_uuid, ds.profile_identifier, ds.profile_name + SELECT ds.profile_id, ds.host_uuid, ds.profile_identifier, ds.profile_name, ds.checksum FROM ( SELECT macp.profile_id, h.uuid as host_uuid, macp.identifier as profile_identifier, - macp.name as profile_name + macp.name as profile_name, + macp.checksum as checksum FROM mdm_apple_configuration_profiles macp JOIN hosts h ON h.team_id = macp.team_id OR (h.team_id IS NULL AND macp.team_id = 0) JOIN nano_enrollments ne ON ne.device_id = h.uuid @@ -1193,6 +1237,8 @@ func (ds *Datastore) ListMDMAppleProfilesToInstall(ctx context.Context) ([]*flee LEFT JOIN host_mdm_apple_profiles hmap ON hmap.profile_id = ds.profile_id AND hmap.host_uuid = ds.host_uuid WHERE + -- profile has been updated + ( hmap.checksum != ds.checksum ) OR -- profiles in A but not in B ( hmap.profile_id IS NULL AND hmap.host_uuid IS NULL ) OR -- profiles in A and B but with operation type "remove" @@ -1223,7 +1269,7 @@ func (ds *Datastore) ListMDMAppleProfilesToRemove(ctx context.Context) ([]*fleet // processed by the ListMDMAppleProfilesToInstall method (since they are in // both, their desired state is necessarily to be installed). query := ` - SELECT hmap.profile_id, hmap.profile_identifier, hmap.profile_name, hmap.host_uuid + SELECT hmap.profile_id, hmap.profile_identifier, hmap.profile_name, hmap.host_uuid, hmap.checksum FROM ( SELECT h.uuid, macp.profile_id FROM mdm_apple_configuration_profiles macp @@ -1283,8 +1329,8 @@ func (ds *Datastore) BulkUpsertMDMAppleHostProfiles(ctx context.Context, payload var sb strings.Builder for _, p := range payload { - args = append(args, p.ProfileID, p.ProfileIdentifier, p.ProfileName, p.HostUUID, p.Status, p.OperationType, p.CommandUUID) - sb.WriteString("(?, ?, ?, ?, ?, ?, ?),") + args = append(args, p.ProfileID, p.ProfileIdentifier, p.ProfileName, p.HostUUID, p.Status, p.OperationType, p.CommandUUID, p.Checksum) + sb.WriteString("(?, ?, ?, ?, ?, ?, ?, ?),") } stmt := fmt.Sprintf(` @@ -1295,7 +1341,8 @@ func (ds *Datastore) BulkUpsertMDMAppleHostProfiles(ctx context.Context, payload host_uuid, status, operation_type, - command_uuid + command_uuid, + checksum ) VALUES %s ON DUPLICATE KEY UPDATE @@ -1516,15 +1563,16 @@ func (ds *Datastore) BulkUpsertMDMAppleConfigProfiles(ctx context.Context, paylo } args = append(args, teamID, cp.Identifier, cp.Name, cp.Mobileconfig) - sb.WriteString("(?, ?, ?, ?),") + sb.WriteString("(?, ?, ?, ?, UNHEX(MD5(mobileconfig))),") } stmt := fmt.Sprintf(` INSERT INTO - mdm_apple_configuration_profiles (team_id, identifier, name, mobileconfig) + mdm_apple_configuration_profiles (team_id, identifier, name, mobileconfig, checksum) VALUES %s ON DUPLICATE KEY UPDATE - mobileconfig = VALUES(mobileconfig)`, strings.TrimSuffix(sb.String(), ",")) + mobileconfig = VALUES(mobileconfig), + checksum = UNHEX(MD5(VALUES(mobileconfig)))`, strings.TrimSuffix(sb.String(), ",")) if _, err := ds.writer.ExecContext(ctx, stmt, args...); err != nil { return ctxerr.Wrapf(ctx, err, "upsert mdm config profiles") diff --git a/server/datastore/mysql/migrations/tables/20230408084104_AddChecksumToProfiles.go b/server/datastore/mysql/migrations/tables/20230408084104_AddChecksumToProfiles.go new file mode 100644 index 00000000000..1096ec485e6 --- /dev/null +++ b/server/datastore/mysql/migrations/tables/20230408084104_AddChecksumToProfiles.go @@ -0,0 +1,24 @@ +package tables + +import ( + "database/sql" + + "github.com/pkg/errors" +) + +func init() { + MigrationClient.AddMigration(Up_20230408084104, Down_20230408084104) +} + +func Up_20230408084104(tx *sql.Tx) error { + _, err := tx.Exec( + `ALTER TABLE mdm_apple_configuration_profiles ADD COLUMN checksum BINARY(16) NOT NULL; + ALTER TABLE host_mdm_apple_profiles ADD COLUMN checksum BINARY(16) NOT NULL; + UPDATE mdm_apple_configuration_profiles SET checksum = UNHEX(MD5(mobileconfig)); + UPDATE host_mdm_apple_profiles hmap SET checksum = (SELECT checksum FROM mdm_apple_configuration_profiles macp WHERE macp.profile_id = hmap.profile_id);`) + return errors.Wrap(err, "add checksum column") +} + +func Down_20230408084104(tx *sql.Tx) error { + return nil +} diff --git a/server/datastore/mysql/migrations/tables/20230408084104_AddChecksumToProfiles_test.go b/server/datastore/mysql/migrations/tables/20230408084104_AddChecksumToProfiles_test.go new file mode 100644 index 00000000000..68391f4b9ea --- /dev/null +++ b/server/datastore/mysql/migrations/tables/20230408084104_AddChecksumToProfiles_test.go @@ -0,0 +1,20 @@ +package tables + +import "testing" + +func TestUp_20230408084104(t *testing.T) { + db := applyUpToPrev(t) + + // + // Insert data to test the migration + // + // ... + + // Apply current migration. + applyNext(t, db) + + // + // Check data, insert new entries, e.g. to verify migration is safe. + // + // ... +} diff --git a/server/datastore/mysql/schema.sql b/server/datastore/mysql/schema.sql index 50d1542f0a9..ea77938cd8c 100644 --- a/server/datastore/mysql/schema.sql +++ b/server/datastore/mysql/schema.sql @@ -251,6 +251,7 @@ CREATE TABLE `host_mdm_apple_profiles` ( `detail` text COLLATE utf8mb4_unicode_ci, `command_uuid` varchar(127) COLLATE utf8mb4_unicode_ci NOT NULL, `profile_name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '', + `checksum` binary(16) NOT NULL, PRIMARY KEY (`host_uuid`,`profile_id`), KEY `status` (`status`), KEY `operation_type` (`operation_type`), @@ -496,6 +497,7 @@ CREATE TABLE `mdm_apple_configuration_profiles` ( `mobileconfig` blob NOT NULL, `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `checksum` binary(16) NOT NULL, PRIMARY KEY (`profile_id`), UNIQUE KEY `idx_mdm_apple_config_prof_team_identifier` (`team_id`,`identifier`), UNIQUE KEY `idx_mdm_apple_config_prof_team_name` (`team_id`,`name`) @@ -563,9 +565,9 @@ CREATE TABLE `migration_status_tables` ( `tstamp` timestamp NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `id` (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=179 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +) ENGINE=InnoDB AUTO_INCREMENT=180 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; /*!40101 SET character_set_client = @saved_cs_client */; -INSERT INTO `migration_status_tables` VALUES (1,0,1,'2020-01-01 01:01:01'),(2,20161118193812,1,'2020-01-01 01:01:01'),(3,20161118211713,1,'2020-01-01 01:01:01'),(4,20161118212436,1,'2020-01-01 01:01:01'),(5,20161118212515,1,'2020-01-01 01:01:01'),(6,20161118212528,1,'2020-01-01 01:01:01'),(7,20161118212538,1,'2020-01-01 01:01:01'),(8,20161118212549,1,'2020-01-01 01:01:01'),(9,20161118212557,1,'2020-01-01 01:01:01'),(10,20161118212604,1,'2020-01-01 01:01:01'),(11,20161118212613,1,'2020-01-01 01:01:01'),(12,20161118212621,1,'2020-01-01 01:01:01'),(13,20161118212630,1,'2020-01-01 01:01:01'),(14,20161118212641,1,'2020-01-01 01:01:01'),(15,20161118212649,1,'2020-01-01 01:01:01'),(16,20161118212656,1,'2020-01-01 01:01:01'),(17,20161118212758,1,'2020-01-01 01:01:01'),(18,20161128234849,1,'2020-01-01 01:01:01'),(19,20161230162221,1,'2020-01-01 01:01:01'),(20,20170104113816,1,'2020-01-01 01:01:01'),(21,20170105151732,1,'2020-01-01 01:01:01'),(22,20170108191242,1,'2020-01-01 01:01:01'),(23,20170109094020,1,'2020-01-01 01:01:01'),(24,20170109130438,1,'2020-01-01 01:01:01'),(25,20170110202752,1,'2020-01-01 01:01:01'),(26,20170111133013,1,'2020-01-01 01:01:01'),(27,20170117025759,1,'2020-01-01 01:01:01'),(28,20170118191001,1,'2020-01-01 01:01:01'),(29,20170119234632,1,'2020-01-01 01:01:01'),(30,20170124230432,1,'2020-01-01 01:01:01'),(31,20170127014618,1,'2020-01-01 01:01:01'),(32,20170131232841,1,'2020-01-01 01:01:01'),(33,20170223094154,1,'2020-01-01 01:01:01'),(34,20170306075207,1,'2020-01-01 01:01:01'),(35,20170309100733,1,'2020-01-01 01:01:01'),(36,20170331111922,1,'2020-01-01 01:01:01'),(37,20170502143928,1,'2020-01-01 01:01:01'),(38,20170504130602,1,'2020-01-01 01:01:01'),(39,20170509132100,1,'2020-01-01 01:01:01'),(40,20170519105647,1,'2020-01-01 01:01:01'),(41,20170519105648,1,'2020-01-01 01:01:01'),(42,20170831234300,1,'2020-01-01 01:01:01'),(43,20170831234301,1,'2020-01-01 01:01:01'),(44,20170831234303,1,'2020-01-01 01:01:01'),(45,20171116163618,1,'2020-01-01 01:01:01'),(46,20171219164727,1,'2020-01-01 01:01:01'),(47,20180620164811,1,'2020-01-01 01:01:01'),(48,20180620175054,1,'2020-01-01 01:01:01'),(49,20180620175055,1,'2020-01-01 01:01:01'),(50,20191010101639,1,'2020-01-01 01:01:01'),(51,20191010155147,1,'2020-01-01 01:01:01'),(52,20191220130734,1,'2020-01-01 01:01:01'),(53,20200311140000,1,'2020-01-01 01:01:01'),(54,20200405120000,1,'2020-01-01 01:01:01'),(55,20200407120000,1,'2020-01-01 01:01:01'),(56,20200420120000,1,'2020-01-01 01:01:01'),(57,20200504120000,1,'2020-01-01 01:01:01'),(58,20200512120000,1,'2020-01-01 01:01:01'),(59,20200707120000,1,'2020-01-01 01:01:01'),(60,20201011162341,1,'2020-01-01 01:01:01'),(61,20201021104586,1,'2020-01-01 01:01:01'),(62,20201102112520,1,'2020-01-01 01:01:01'),(63,20201208121729,1,'2020-01-01 01:01:01'),(64,20201215091637,1,'2020-01-01 01:01:01'),(65,20210119174155,1,'2020-01-01 01:01:01'),(66,20210326182902,1,'2020-01-01 01:01:01'),(67,20210421112652,1,'2020-01-01 01:01:01'),(68,20210506095025,1,'2020-01-01 01:01:01'),(69,20210513115729,1,'2020-01-01 01:01:01'),(70,20210526113559,1,'2020-01-01 01:01:01'),(71,20210601000001,1,'2020-01-01 01:01:01'),(72,20210601000002,1,'2020-01-01 01:01:01'),(73,20210601000003,1,'2020-01-01 01:01:01'),(74,20210601000004,1,'2020-01-01 01:01:01'),(75,20210601000005,1,'2020-01-01 01:01:01'),(76,20210601000006,1,'2020-01-01 01:01:01'),(77,20210601000007,1,'2020-01-01 01:01:01'),(78,20210601000008,1,'2020-01-01 01:01:01'),(79,20210606151329,1,'2020-01-01 01:01:01'),(80,20210616163757,1,'2020-01-01 01:01:01'),(81,20210617174723,1,'2020-01-01 01:01:01'),(82,20210622160235,1,'2020-01-01 01:01:01'),(83,20210623100031,1,'2020-01-01 01:01:01'),(84,20210623133615,1,'2020-01-01 01:01:01'),(85,20210708143152,1,'2020-01-01 01:01:01'),(86,20210709124443,1,'2020-01-01 01:01:01'),(87,20210712155608,1,'2020-01-01 01:01:01'),(88,20210714102108,1,'2020-01-01 01:01:01'),(89,20210719153709,1,'2020-01-01 01:01:01'),(90,20210721171531,1,'2020-01-01 01:01:01'),(91,20210723135713,1,'2020-01-01 01:01:01'),(92,20210802135933,1,'2020-01-01 01:01:01'),(93,20210806112844,1,'2020-01-01 01:01:01'),(94,20210810095603,1,'2020-01-01 01:01:01'),(95,20210811150223,1,'2020-01-01 01:01:01'),(96,20210818151827,1,'2020-01-01 01:01:01'),(97,20210818151828,1,'2020-01-01 01:01:01'),(98,20210818182258,1,'2020-01-01 01:01:01'),(99,20210819131107,1,'2020-01-01 01:01:01'),(100,20210819143446,1,'2020-01-01 01:01:01'),(101,20210903132338,1,'2020-01-01 01:01:01'),(102,20210915144307,1,'2020-01-01 01:01:01'),(103,20210920155130,1,'2020-01-01 01:01:01'),(104,20210927143115,1,'2020-01-01 01:01:01'),(105,20210927143116,1,'2020-01-01 01:01:01'),(106,20211013133706,1,'2020-01-01 01:01:01'),(107,20211013133707,1,'2020-01-01 01:01:01'),(108,20211102135149,1,'2020-01-01 01:01:01'),(109,20211109121546,1,'2020-01-01 01:01:01'),(110,20211110163320,1,'2020-01-01 01:01:01'),(111,20211116184029,1,'2020-01-01 01:01:01'),(112,20211116184030,1,'2020-01-01 01:01:01'),(113,20211202092042,1,'2020-01-01 01:01:01'),(114,20211202181033,1,'2020-01-01 01:01:01'),(115,20211207161856,1,'2020-01-01 01:01:01'),(116,20211216131203,1,'2020-01-01 01:01:01'),(117,20211221110132,1,'2020-01-01 01:01:01'),(118,20220107155700,1,'2020-01-01 01:01:01'),(119,20220125105650,1,'2020-01-01 01:01:01'),(120,20220201084510,1,'2020-01-01 01:01:01'),(121,20220208144830,1,'2020-01-01 01:01:01'),(122,20220208144831,1,'2020-01-01 01:01:01'),(123,20220215152203,1,'2020-01-01 01:01:01'),(124,20220223113157,1,'2020-01-01 01:01:01'),(125,20220307104655,1,'2020-01-01 01:01:01'),(126,20220309133956,1,'2020-01-01 01:01:01'),(127,20220316155700,1,'2020-01-01 01:01:01'),(128,20220323152301,1,'2020-01-01 01:01:01'),(129,20220330100659,1,'2020-01-01 01:01:01'),(130,20220404091216,1,'2020-01-01 01:01:01'),(131,20220419140750,1,'2020-01-01 01:01:01'),(132,20220428140039,1,'2020-01-01 01:01:01'),(133,20220503134048,1,'2020-01-01 01:01:01'),(134,20220524102918,1,'2020-01-01 01:01:01'),(135,20220526123327,1,'2020-01-01 01:01:01'),(136,20220526123328,1,'2020-01-01 01:01:01'),(137,20220526123329,1,'2020-01-01 01:01:01'),(138,20220608113128,1,'2020-01-01 01:01:01'),(139,20220627104817,1,'2020-01-01 01:01:01'),(140,20220704101843,1,'2020-01-01 01:01:01'),(141,20220708095046,1,'2020-01-01 01:01:01'),(142,20220713091130,1,'2020-01-01 01:01:01'),(143,20220802135510,1,'2020-01-01 01:01:01'),(144,20220818101352,1,'2020-01-01 01:01:01'),(145,20220822161445,1,'2020-01-01 01:01:01'),(146,20220831100036,1,'2020-01-01 01:01:01'),(147,20220831100151,1,'2020-01-01 01:01:01'),(148,20220908181826,1,'2020-01-01 01:01:01'),(149,20220914154915,1,'2020-01-01 01:01:01'),(150,20220915165115,1,'2020-01-01 01:01:01'),(151,20220915165116,1,'2020-01-01 01:01:01'),(152,20220928100158,1,'2020-01-01 01:01:01'),(153,20221014084130,1,'2020-01-01 01:01:01'),(154,20221027085019,1,'2020-01-01 01:01:01'),(155,20221101103952,1,'2020-01-01 01:01:01'),(156,20221104144401,1,'2020-01-01 01:01:01'),(157,20221109100749,1,'2020-01-01 01:01:01'),(158,20221115104546,1,'2020-01-01 01:01:01'),(159,20221130114928,1,'2020-01-01 01:01:01'),(160,20221205112142,1,'2020-01-01 01:01:01'),(161,20221216115820,1,'2020-01-01 01:01:01'),(162,20221220195934,1,'2020-01-01 01:01:01'),(163,20221220195935,1,'2020-01-01 01:01:01'),(164,20221223174807,1,'2020-01-01 01:01:01'),(165,20221227163855,1,'2020-01-01 01:01:01'),(166,20221227163856,1,'2020-01-01 01:01:01'),(167,20230202224725,1,'2020-01-01 01:01:01'),(168,20230206163608,1,'2020-01-01 01:01:01'),(169,20230214131519,1,'2020-01-01 01:01:01'),(170,20230303135738,1,'2020-01-01 01:01:01'),(171,20230313135301,1,'2020-01-01 01:01:01'),(172,20230313141819,1,'2020-01-01 01:01:01'),(173,20230315104937,1,'2020-01-01 01:01:01'),(174,20230317173844,1,'2020-01-01 01:01:01'),(175,20230320133602,1,'2020-01-01 01:01:01'),(176,20230330100011,1,'2020-01-01 01:01:01'),(177,20230330134823,1,'2020-01-01 01:01:01'),(178,20230405232025,1,'2020-01-01 01:01:01'); +INSERT INTO `migration_status_tables` VALUES (1,0,1,'2020-01-01 01:01:01'),(2,20161118193812,1,'2020-01-01 01:01:01'),(3,20161118211713,1,'2020-01-01 01:01:01'),(4,20161118212436,1,'2020-01-01 01:01:01'),(5,20161118212515,1,'2020-01-01 01:01:01'),(6,20161118212528,1,'2020-01-01 01:01:01'),(7,20161118212538,1,'2020-01-01 01:01:01'),(8,20161118212549,1,'2020-01-01 01:01:01'),(9,20161118212557,1,'2020-01-01 01:01:01'),(10,20161118212604,1,'2020-01-01 01:01:01'),(11,20161118212613,1,'2020-01-01 01:01:01'),(12,20161118212621,1,'2020-01-01 01:01:01'),(13,20161118212630,1,'2020-01-01 01:01:01'),(14,20161118212641,1,'2020-01-01 01:01:01'),(15,20161118212649,1,'2020-01-01 01:01:01'),(16,20161118212656,1,'2020-01-01 01:01:01'),(17,20161118212758,1,'2020-01-01 01:01:01'),(18,20161128234849,1,'2020-01-01 01:01:01'),(19,20161230162221,1,'2020-01-01 01:01:01'),(20,20170104113816,1,'2020-01-01 01:01:01'),(21,20170105151732,1,'2020-01-01 01:01:01'),(22,20170108191242,1,'2020-01-01 01:01:01'),(23,20170109094020,1,'2020-01-01 01:01:01'),(24,20170109130438,1,'2020-01-01 01:01:01'),(25,20170110202752,1,'2020-01-01 01:01:01'),(26,20170111133013,1,'2020-01-01 01:01:01'),(27,20170117025759,1,'2020-01-01 01:01:01'),(28,20170118191001,1,'2020-01-01 01:01:01'),(29,20170119234632,1,'2020-01-01 01:01:01'),(30,20170124230432,1,'2020-01-01 01:01:01'),(31,20170127014618,1,'2020-01-01 01:01:01'),(32,20170131232841,1,'2020-01-01 01:01:01'),(33,20170223094154,1,'2020-01-01 01:01:01'),(34,20170306075207,1,'2020-01-01 01:01:01'),(35,20170309100733,1,'2020-01-01 01:01:01'),(36,20170331111922,1,'2020-01-01 01:01:01'),(37,20170502143928,1,'2020-01-01 01:01:01'),(38,20170504130602,1,'2020-01-01 01:01:01'),(39,20170509132100,1,'2020-01-01 01:01:01'),(40,20170519105647,1,'2020-01-01 01:01:01'),(41,20170519105648,1,'2020-01-01 01:01:01'),(42,20170831234300,1,'2020-01-01 01:01:01'),(43,20170831234301,1,'2020-01-01 01:01:01'),(44,20170831234303,1,'2020-01-01 01:01:01'),(45,20171116163618,1,'2020-01-01 01:01:01'),(46,20171219164727,1,'2020-01-01 01:01:01'),(47,20180620164811,1,'2020-01-01 01:01:01'),(48,20180620175054,1,'2020-01-01 01:01:01'),(49,20180620175055,1,'2020-01-01 01:01:01'),(50,20191010101639,1,'2020-01-01 01:01:01'),(51,20191010155147,1,'2020-01-01 01:01:01'),(52,20191220130734,1,'2020-01-01 01:01:01'),(53,20200311140000,1,'2020-01-01 01:01:01'),(54,20200405120000,1,'2020-01-01 01:01:01'),(55,20200407120000,1,'2020-01-01 01:01:01'),(56,20200420120000,1,'2020-01-01 01:01:01'),(57,20200504120000,1,'2020-01-01 01:01:01'),(58,20200512120000,1,'2020-01-01 01:01:01'),(59,20200707120000,1,'2020-01-01 01:01:01'),(60,20201011162341,1,'2020-01-01 01:01:01'),(61,20201021104586,1,'2020-01-01 01:01:01'),(62,20201102112520,1,'2020-01-01 01:01:01'),(63,20201208121729,1,'2020-01-01 01:01:01'),(64,20201215091637,1,'2020-01-01 01:01:01'),(65,20210119174155,1,'2020-01-01 01:01:01'),(66,20210326182902,1,'2020-01-01 01:01:01'),(67,20210421112652,1,'2020-01-01 01:01:01'),(68,20210506095025,1,'2020-01-01 01:01:01'),(69,20210513115729,1,'2020-01-01 01:01:01'),(70,20210526113559,1,'2020-01-01 01:01:01'),(71,20210601000001,1,'2020-01-01 01:01:01'),(72,20210601000002,1,'2020-01-01 01:01:01'),(73,20210601000003,1,'2020-01-01 01:01:01'),(74,20210601000004,1,'2020-01-01 01:01:01'),(75,20210601000005,1,'2020-01-01 01:01:01'),(76,20210601000006,1,'2020-01-01 01:01:01'),(77,20210601000007,1,'2020-01-01 01:01:01'),(78,20210601000008,1,'2020-01-01 01:01:01'),(79,20210606151329,1,'2020-01-01 01:01:01'),(80,20210616163757,1,'2020-01-01 01:01:01'),(81,20210617174723,1,'2020-01-01 01:01:01'),(82,20210622160235,1,'2020-01-01 01:01:01'),(83,20210623100031,1,'2020-01-01 01:01:01'),(84,20210623133615,1,'2020-01-01 01:01:01'),(85,20210708143152,1,'2020-01-01 01:01:01'),(86,20210709124443,1,'2020-01-01 01:01:01'),(87,20210712155608,1,'2020-01-01 01:01:01'),(88,20210714102108,1,'2020-01-01 01:01:01'),(89,20210719153709,1,'2020-01-01 01:01:01'),(90,20210721171531,1,'2020-01-01 01:01:01'),(91,20210723135713,1,'2020-01-01 01:01:01'),(92,20210802135933,1,'2020-01-01 01:01:01'),(93,20210806112844,1,'2020-01-01 01:01:01'),(94,20210810095603,1,'2020-01-01 01:01:01'),(95,20210811150223,1,'2020-01-01 01:01:01'),(96,20210818151827,1,'2020-01-01 01:01:01'),(97,20210818151828,1,'2020-01-01 01:01:01'),(98,20210818182258,1,'2020-01-01 01:01:01'),(99,20210819131107,1,'2020-01-01 01:01:01'),(100,20210819143446,1,'2020-01-01 01:01:01'),(101,20210903132338,1,'2020-01-01 01:01:01'),(102,20210915144307,1,'2020-01-01 01:01:01'),(103,20210920155130,1,'2020-01-01 01:01:01'),(104,20210927143115,1,'2020-01-01 01:01:01'),(105,20210927143116,1,'2020-01-01 01:01:01'),(106,20211013133706,1,'2020-01-01 01:01:01'),(107,20211013133707,1,'2020-01-01 01:01:01'),(108,20211102135149,1,'2020-01-01 01:01:01'),(109,20211109121546,1,'2020-01-01 01:01:01'),(110,20211110163320,1,'2020-01-01 01:01:01'),(111,20211116184029,1,'2020-01-01 01:01:01'),(112,20211116184030,1,'2020-01-01 01:01:01'),(113,20211202092042,1,'2020-01-01 01:01:01'),(114,20211202181033,1,'2020-01-01 01:01:01'),(115,20211207161856,1,'2020-01-01 01:01:01'),(116,20211216131203,1,'2020-01-01 01:01:01'),(117,20211221110132,1,'2020-01-01 01:01:01'),(118,20220107155700,1,'2020-01-01 01:01:01'),(119,20220125105650,1,'2020-01-01 01:01:01'),(120,20220201084510,1,'2020-01-01 01:01:01'),(121,20220208144830,1,'2020-01-01 01:01:01'),(122,20220208144831,1,'2020-01-01 01:01:01'),(123,20220215152203,1,'2020-01-01 01:01:01'),(124,20220223113157,1,'2020-01-01 01:01:01'),(125,20220307104655,1,'2020-01-01 01:01:01'),(126,20220309133956,1,'2020-01-01 01:01:01'),(127,20220316155700,1,'2020-01-01 01:01:01'),(128,20220323152301,1,'2020-01-01 01:01:01'),(129,20220330100659,1,'2020-01-01 01:01:01'),(130,20220404091216,1,'2020-01-01 01:01:01'),(131,20220419140750,1,'2020-01-01 01:01:01'),(132,20220428140039,1,'2020-01-01 01:01:01'),(133,20220503134048,1,'2020-01-01 01:01:01'),(134,20220524102918,1,'2020-01-01 01:01:01'),(135,20220526123327,1,'2020-01-01 01:01:01'),(136,20220526123328,1,'2020-01-01 01:01:01'),(137,20220526123329,1,'2020-01-01 01:01:01'),(138,20220608113128,1,'2020-01-01 01:01:01'),(139,20220627104817,1,'2020-01-01 01:01:01'),(140,20220704101843,1,'2020-01-01 01:01:01'),(141,20220708095046,1,'2020-01-01 01:01:01'),(142,20220713091130,1,'2020-01-01 01:01:01'),(143,20220802135510,1,'2020-01-01 01:01:01'),(144,20220818101352,1,'2020-01-01 01:01:01'),(145,20220822161445,1,'2020-01-01 01:01:01'),(146,20220831100036,1,'2020-01-01 01:01:01'),(147,20220831100151,1,'2020-01-01 01:01:01'),(148,20220908181826,1,'2020-01-01 01:01:01'),(149,20220914154915,1,'2020-01-01 01:01:01'),(150,20220915165115,1,'2020-01-01 01:01:01'),(151,20220915165116,1,'2020-01-01 01:01:01'),(152,20220928100158,1,'2020-01-01 01:01:01'),(153,20221014084130,1,'2020-01-01 01:01:01'),(154,20221027085019,1,'2020-01-01 01:01:01'),(155,20221101103952,1,'2020-01-01 01:01:01'),(156,20221104144401,1,'2020-01-01 01:01:01'),(157,20221109100749,1,'2020-01-01 01:01:01'),(158,20221115104546,1,'2020-01-01 01:01:01'),(159,20221130114928,1,'2020-01-01 01:01:01'),(160,20221205112142,1,'2020-01-01 01:01:01'),(161,20221216115820,1,'2020-01-01 01:01:01'),(162,20221220195934,1,'2020-01-01 01:01:01'),(163,20221220195935,1,'2020-01-01 01:01:01'),(164,20221223174807,1,'2020-01-01 01:01:01'),(165,20221227163855,1,'2020-01-01 01:01:01'),(166,20221227163856,1,'2020-01-01 01:01:01'),(167,20230202224725,1,'2020-01-01 01:01:01'),(168,20230206163608,1,'2020-01-01 01:01:01'),(169,20230214131519,1,'2020-01-01 01:01:01'),(170,20230303135738,1,'2020-01-01 01:01:01'),(171,20230313135301,1,'2020-01-01 01:01:01'),(172,20230313141819,1,'2020-01-01 01:01:01'),(173,20230315104937,1,'2020-01-01 01:01:01'),(174,20230317173844,1,'2020-01-01 01:01:01'),(175,20230320133602,1,'2020-01-01 01:01:01'),(176,20230330100011,1,'2020-01-01 01:01:01'),(177,20230330134823,1,'2020-01-01 01:01:01'),(178,20230405232025,1,'2020-01-01 01:01:01'),(179,20230408084104,1,'2020-01-01 01:01:01'); /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `mobile_device_management_solutions` ( diff --git a/server/fleet/apple_mdm.go b/server/fleet/apple_mdm.go index e16294fab3d..38fc06f1ad8 100644 --- a/server/fleet/apple_mdm.go +++ b/server/fleet/apple_mdm.go @@ -355,6 +355,7 @@ type MDMAppleProfilePayload struct { ProfileIdentifier string `db:"profile_identifier"` ProfileName string `db:"profile_name"` HostUUID string `db:"host_uuid"` + Checksum []byte `db:"checksum"` } type MDMAppleBulkUpsertHostProfilePayload struct { @@ -365,6 +366,7 @@ type MDMAppleBulkUpsertHostProfilePayload struct { CommandUUID string OperationType MDMAppleOperationType Status *MDMAppleDeliveryStatus + Checksum []byte } // MDMAppleHostsProfilesSummary reports the number of hosts being managed with MDM configuration diff --git a/server/service/apple_mdm.go b/server/service/apple_mdm.go index 2b34b17d2fe..ee0dc28f879 100644 --- a/server/service/apple_mdm.go +++ b/server/service/apple_mdm.go @@ -2207,6 +2207,7 @@ func ReconcileProfiles( CommandUUID: target.cmdUUID, ProfileIdentifier: p.ProfileIdentifier, ProfileName: p.ProfileName, + Checksum: p.Checksum, }) } @@ -2229,6 +2230,7 @@ func ReconcileProfiles( CommandUUID: target.cmdUUID, ProfileIdentifier: p.ProfileIdentifier, ProfileName: p.ProfileName, + Checksum: p.Checksum, }) } From 532fc3616a4400f3fea57a75c73f249e56d71fa4 Mon Sep 17 00:00:00 2001 From: Roberto Dip Date: Sat, 8 Apr 2023 15:42:14 -0300 Subject: [PATCH 02/11] adjust reports --- server/datastore/mysql/apple_mdm.go | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/server/datastore/mysql/apple_mdm.go b/server/datastore/mysql/apple_mdm.go index 96b713da6f5..6374cbf82c2 100644 --- a/server/datastore/mysql/apple_mdm.go +++ b/server/datastore/mysql/apple_mdm.go @@ -183,9 +183,10 @@ SELECT FROM host_mdm_apple_profiles WHERE - host_uuid = ? AND NOT (operation_type = '%s' AND status = '%s')`, + host_uuid = ? AND NOT (operation_type = '%s' AND COALESCE(status, '%s') = '%s')`, fleet.MDMAppleDeliveryPending, fleet.MDMAppleOperationTypeRemove, + fleet.MDMAppleDeliveryPending, fleet.MDMAppleDeliveryApplied, ) @@ -1101,7 +1102,7 @@ WHERE installIdentifiers = append(installIdentifiers, p.ProfileIdentifier) } - const profilesToRemoveStmt = ` + profilesToRemoveStmt := ` SELECT hmap.profile_id as profile_id, hmap.host_uuid as host_uuid, @@ -1125,11 +1126,16 @@ WHERE -- except "remove" operations in any state AND ( hmap.operation_type IS NULL OR hmap.operation_type != ? ) -- profiles that are being installed - AND hmap.profile_identifier NOT IN (?) ` - stmt, args, err = sqlx.In(profilesToRemoveStmt, - uuids, uuids, fleet.MDMAppleOperationTypeRemove, installIdentifiers, - ) + + inArgs := []any{uuids, uuids, fleet.MDMAppleOperationTypeRemove} + if len(installIdentifiers) > 0 { + profilesToRemoveStmt += `AND hmap.profile_identifier NOT IN (?)` + inArgs = append(inArgs, installIdentifiers) + + } + + stmt, args, err = sqlx.In(profilesToRemoveStmt, inArgs...) if err != nil { return ctxerr.Wrap(ctx, err, "building profiles to remove statement") } From 2a0253ddd7540ccc89eb385648963f0713644eb5 Mon Sep 17 00:00:00 2001 From: Roberto Dip Date: Sat, 8 Apr 2023 17:25:21 -0300 Subject: [PATCH 03/11] right query building --- server/datastore/mysql/apple_mdm.go | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/server/datastore/mysql/apple_mdm.go b/server/datastore/mysql/apple_mdm.go index 6374cbf82c2..59ceaba2ca1 100644 --- a/server/datastore/mysql/apple_mdm.go +++ b/server/datastore/mysql/apple_mdm.go @@ -1098,8 +1098,13 @@ WHERE return ctxerr.Wrap(ctx, err, "bulk set pending profile status execute") } installIdentifiers := []string{} + identifierToHosts := map[string][]string{} for _, p := range profilesToInstall { installIdentifiers = append(installIdentifiers, p.ProfileIdentifier) + if _, ok := identifierToHosts[p.ProfileIdentifier]; !ok { + identifierToHosts[p.ProfileIdentifier] = []string{} + } + identifierToHosts[p.ProfileIdentifier] = append(identifierToHosts[p.ProfileIdentifier], p.HostUUID) } profilesToRemoveStmt := ` @@ -1150,11 +1155,16 @@ WHERE } // before doing the inserts, remove profiles with identifiers that will be sent again from the database - stmt, args, err = sqlx.In("DELETE FROM host_mdm_apple_profiles WHERE host_uuid IN (?) AND profile_identifier IN (?)", uuids, installIdentifiers) - if err != nil { - return ctxerr.Wrap(ctx, err, "building delete statement to remove unused profiles") + var dargs []any + var dsb strings.Builder + for identifier, hostUUIDs := range identifierToHosts { + for _, hostUUID := range hostUUIDs { + dargs = append(dargs, hostUUID, identifier) + dsb.WriteString("(?,?),") + } } - _, err = tx.ExecContext(ctx, stmt, args...) + stmt = fmt.Sprintf(`DELETE FROM host_mdm_apple_profiles WHERE (host_uuid, profile_identifier) IN(%s)`, strings.TrimSuffix(dsb.String(), ",")) + _, err = tx.ExecContext(ctx, stmt, dargs...) if err != nil { return ctxerr.Wrap(ctx, err, "bulk set pending profile status execute") } From de5056e90077afe5f974a7faf60bdb1e2a00f807 Mon Sep 17 00:00:00 2001 From: Roberto Dip Date: Sat, 8 Apr 2023 18:27:13 -0300 Subject: [PATCH 04/11] fixes --- server/datastore/mysql/apple_mdm.go | 4 ++-- server/fleet/apple_mdm.go | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/server/datastore/mysql/apple_mdm.go b/server/datastore/mysql/apple_mdm.go index 59ceaba2ca1..37a5b81abb6 100644 --- a/server/datastore/mysql/apple_mdm.go +++ b/server/datastore/mysql/apple_mdm.go @@ -896,11 +896,12 @@ WHERE const insertNewOrEditedProfile = ` INSERT INTO mdm_apple_configuration_profiles ( - team_id, identifier, name, mobileconfig + team_id, identifier, name, mobileconfig, checksum ) VALUES ( ?, ?, ?, ?, UNHEX(MD5(mobileconfig)) ) ON DUPLICATE KEY UPDATE + name = VALUES(name), mobileconfig = VALUES(mobileconfig), checksum = UNHEX(MD5(VALUES(mobileconfig))) ` @@ -941,7 +942,6 @@ ON DUPLICATE KEY UPDATE for _, p := range existingProfiles { if newP := incomingProfs[p.Identifier]; newP != nil { keepIdents = append(keepIdents, p.Identifier) - delete(incomingProfs, p.Identifier) } } diff --git a/server/fleet/apple_mdm.go b/server/fleet/apple_mdm.go index 38fc06f1ad8..8a4b502bcc0 100644 --- a/server/fleet/apple_mdm.go +++ b/server/fleet/apple_mdm.go @@ -296,8 +296,10 @@ type MDMAppleConfigProfile struct { // Mobileconfig is the byte slice corresponding to the XML property list (i.e. plist) // representation of the configuration profile. It must be XML or PKCS7 parseable. Mobileconfig mobileconfig.Mobileconfig `db:"mobileconfig" json:"-"` - CreatedAt time.Time `db:"created_at" json:"created_at"` - UpdatedAt time.Time `db:"updated_at" json:"updated_at"` + // Checksum is an MD5 hash of the Mobileconfig bytes + Checksum []byte `db:"checksum" json:"-"` + CreatedAt time.Time `db:"created_at" json:"created_at"` + UpdatedAt time.Time `db:"updated_at" json:"updated_at"` } func NewMDMAppleConfigProfile(raw []byte, teamID *uint) (*MDMAppleConfigProfile, error) { From 5c0557c28197e61627304edaef6ef60b9c8113f2 Mon Sep 17 00:00:00 2001 From: Roberto Dip Date: Sat, 8 Apr 2023 19:24:29 -0300 Subject: [PATCH 05/11] fix bugs and a bunch of tests --- server/datastore/mysql/apple_mdm.go | 26 +-- server/datastore/mysql/apple_mdm_test.go | 261 ++++++++++++----------- server/datastore/mysql/hosts_test.go | 4 +- server/datastore/mysql/labels_test.go | 2 + server/service/integration_mdm_test.go | 2 + 5 files changed, 162 insertions(+), 133 deletions(-) diff --git a/server/datastore/mysql/apple_mdm.go b/server/datastore/mysql/apple_mdm.go index 37a5b81abb6..dd100cae7f8 100644 --- a/server/datastore/mysql/apple_mdm.go +++ b/server/datastore/mysql/apple_mdm.go @@ -1154,19 +1154,21 @@ WHERE return nil } - // before doing the inserts, remove profiles with identifiers that will be sent again from the database - var dargs []any - var dsb strings.Builder - for identifier, hostUUIDs := range identifierToHosts { - for _, hostUUID := range hostUUIDs { - dargs = append(dargs, hostUUID, identifier) - dsb.WriteString("(?,?),") + // before doing the inserts, remove profiles with identifiers that will be re-sent + if len(profilesToInstall) > 0 { + var dargs []any + var dsb strings.Builder + for identifier, hostUUIDs := range identifierToHosts { + for _, hostUUID := range hostUUIDs { + dargs = append(dargs, hostUUID, identifier) + dsb.WriteString("(?,?),") + } + } + stmt = fmt.Sprintf(`DELETE FROM host_mdm_apple_profiles WHERE (host_uuid, profile_identifier) IN(%s)`, strings.TrimSuffix(dsb.String(), ",")) + _, err = tx.ExecContext(ctx, stmt, dargs...) + if err != nil { + return ctxerr.Wrap(ctx, err, "bulk set pending profile status execute") } - } - stmt = fmt.Sprintf(`DELETE FROM host_mdm_apple_profiles WHERE (host_uuid, profile_identifier) IN(%s)`, strings.TrimSuffix(dsb.String(), ",")) - _, err = tx.ExecContext(ctx, stmt, dargs...) - if err != nil { - return ctxerr.Wrap(ctx, err, "bulk set pending profile status execute") } var pargs []any diff --git a/server/datastore/mysql/apple_mdm_test.go b/server/datastore/mysql/apple_mdm_test.go index 662a3fb89a3..80a94dc16c8 100644 --- a/server/datastore/mysql/apple_mdm_test.go +++ b/server/datastore/mysql/apple_mdm_test.go @@ -2,6 +2,7 @@ package mysql import ( "context" + "crypto/md5" "crypto/sha256" "database/sql" "fmt" @@ -740,6 +741,7 @@ func testUpdateHostTablesOnMDMUnenroll(t *testing.T, ds *Datastore) { Status: &fleet.MDMAppleDeliveryApplied, OperationType: fleet.MDMAppleOperationTypeInstall, CommandUUID: "command-uuid", + Checksum: []byte("csum"), }, }, ) @@ -854,7 +856,7 @@ func testBatchSetMDMAppleProfiles(t *testing.T, ds *Datastore) { }, nil, []*fleet.MDMAppleConfigProfile{ configProfileForTest(t, "N2", "I1", "b"), }) - require.NotEqual(t, mNoTm["I1"], mNoTmb["I1"]) + require.Equal(t, mNoTm["I1"], mNoTmb["I1"]) // apply edited profile (by content only), unchanged profile and new profile // for tm1 @@ -867,8 +869,8 @@ func testBatchSetMDMAppleProfiles(t *testing.T, ds *Datastore) { withTeamID(configProfileForTest(t, "N2", "I2", "b"), 1), withTeamID(configProfileForTest(t, "N3", "I3", "c"), 1), }) - // identifier for N1-I1 is changed - require.NotEqual(t, mTm1b["I1"], mTm1c["I1"]) + // identifier for N1-I1 is unchanged + require.Equal(t, mTm1b["I1"], mTm1c["I1"]) // identifier for N2-I2 is unchanged require.Equal(t, mTm1b["I2"], mTm1c["I2"]) @@ -937,12 +939,24 @@ func configProfileForTest(t *testing.T, name, identifier, uuid string) *fleet.MD `, name, identifier, uuid)) cp, err := fleet.NewMDMAppleConfigProfile(prof, nil) + sum := md5.Sum(prof) + cp.Checksum = sum[:] require.NoError(t, err) return cp } func testMDMAppleProfileManagement(t *testing.T, ds *Datastore) { ctx := context.Background() + + matchProfiles := func(want, got []*fleet.MDMAppleProfilePayload) { + // match only the fields we care about + for _, p := range got { + require.NotEmpty(t, p.Checksum) + p.Checksum = nil + } + require.ElementsMatch(t, want, got) + } + globalProfiles := []*fleet.MDMAppleConfigProfile{ configProfileForTest(t, "N1", "I1", "z"), configProfileForTest(t, "N2", "I2", "b"), @@ -1004,7 +1018,7 @@ func testMDMAppleProfileManagement(t *testing.T, ds *Datastore) { // global profiles to install on the newly added host profiles, err = ds.ListMDMAppleProfilesToInstall(ctx) require.NoError(t, err) - require.ElementsMatch(t, []*fleet.MDMAppleProfilePayload{ + matchProfiles([]*fleet.MDMAppleProfilePayload{ {ProfileID: globalPfs[0].ProfileID, ProfileIdentifier: globalPfs[0].Identifier, ProfileName: globalPfs[0].Name, HostUUID: "test-uuid-1"}, {ProfileID: globalPfs[1].ProfileID, ProfileIdentifier: globalPfs[1].Identifier, ProfileName: globalPfs[1].Name, HostUUID: "test-uuid-1"}, {ProfileID: globalPfs[2].ProfileID, ProfileIdentifier: globalPfs[2].Identifier, ProfileName: globalPfs[2].Name, HostUUID: "test-uuid-1"}, @@ -1027,17 +1041,18 @@ func testMDMAppleProfileManagement(t *testing.T, ds *Datastore) { // still the same profiles to assign as there are no profiles for team 1 profiles, err = ds.ListMDMAppleProfilesToInstall(ctx) require.NoError(t, err) - require.ElementsMatch(t, []*fleet.MDMAppleProfilePayload{ + matchProfiles([]*fleet.MDMAppleProfilePayload{ {ProfileID: globalPfs[0].ProfileID, ProfileIdentifier: globalPfs[0].Identifier, ProfileName: globalPfs[0].Name, HostUUID: "test-uuid-1"}, {ProfileID: globalPfs[1].ProfileID, ProfileIdentifier: globalPfs[1].Identifier, ProfileName: globalPfs[1].Name, HostUUID: "test-uuid-1"}, {ProfileID: globalPfs[2].ProfileID, ProfileIdentifier: globalPfs[2].Identifier, ProfileName: globalPfs[2].Name, HostUUID: "test-uuid-1"}, }, profiles) // assign profiles to team 1 - err = ds.BatchSetMDMAppleProfiles(ctx, &team.ID, []*fleet.MDMAppleConfigProfile{ + teamProfiles := []*fleet.MDMAppleConfigProfile{ configProfileForTest(t, "N4", "I4", "x"), configProfileForTest(t, "N5", "I5", "y"), - }) + } + err = ds.BatchSetMDMAppleProfiles(ctx, &team.ID, teamProfiles) require.NoError(t, err) globalPfs, err = ds.ListMDMAppleConfigProfiles(ctx, ptr.Uint(0)) @@ -1050,7 +1065,7 @@ func testMDMAppleProfileManagement(t *testing.T, ds *Datastore) { // new profiles, this time for the new host belonging to team 1 profiles, err = ds.ListMDMAppleProfilesToInstall(ctx) require.NoError(t, err) - require.ElementsMatch(t, []*fleet.MDMAppleProfilePayload{ + matchProfiles([]*fleet.MDMAppleProfilePayload{ {ProfileID: globalPfs[0].ProfileID, ProfileIdentifier: globalPfs[0].Identifier, ProfileName: globalPfs[0].Name, HostUUID: "test-uuid-1"}, {ProfileID: globalPfs[1].ProfileID, ProfileIdentifier: globalPfs[1].Identifier, ProfileName: globalPfs[1].Name, HostUUID: "test-uuid-1"}, {ProfileID: globalPfs[2].ProfileID, ProfileIdentifier: globalPfs[2].Identifier, ProfileName: globalPfs[2].Name, HostUUID: "test-uuid-1"}, @@ -1073,7 +1088,7 @@ func testMDMAppleProfileManagement(t *testing.T, ds *Datastore) { // more profiles, this time for both global hosts and the team profiles, err = ds.ListMDMAppleProfilesToInstall(ctx) require.NoError(t, err) - require.ElementsMatch(t, []*fleet.MDMAppleProfilePayload{ + matchProfiles([]*fleet.MDMAppleProfilePayload{ {ProfileID: globalPfs[0].ProfileID, ProfileIdentifier: globalPfs[0].Identifier, ProfileName: globalPfs[0].Name, HostUUID: "test-uuid-1"}, {ProfileID: globalPfs[1].ProfileID, ProfileIdentifier: globalPfs[1].Identifier, ProfileName: globalPfs[1].Name, HostUUID: "test-uuid-1"}, {ProfileID: globalPfs[2].ProfileID, ProfileIdentifier: globalPfs[2].Identifier, ProfileName: globalPfs[2].Name, HostUUID: "test-uuid-1"}, @@ -1091,6 +1106,7 @@ func testMDMAppleProfileManagement(t *testing.T, ds *Datastore) { ProfileID: globalPfs[0].ProfileID, ProfileIdentifier: globalPfs[0].Identifier, ProfileName: globalPfs[0].Name, + Checksum: globalProfiles[0].Checksum, HostUUID: "test-uuid-1", Status: &fleet.MDMAppleDeliveryApplied, OperationType: fleet.MDMAppleOperationTypeInstall, @@ -1100,6 +1116,7 @@ func testMDMAppleProfileManagement(t *testing.T, ds *Datastore) { ProfileID: globalPfs[0].ProfileID, ProfileIdentifier: globalPfs[0].Identifier, ProfileName: globalPfs[0].Name, + Checksum: globalProfiles[0].Checksum, HostUUID: "test-uuid-3", Status: &fleet.MDMAppleDeliveryApplied, OperationType: fleet.MDMAppleOperationTypeInstall, @@ -1109,6 +1126,7 @@ func testMDMAppleProfileManagement(t *testing.T, ds *Datastore) { ProfileID: globalPfs[1].ProfileID, ProfileIdentifier: globalPfs[1].Identifier, ProfileName: globalPfs[1].Name, + Checksum: globalProfiles[1].Checksum, HostUUID: "test-uuid-1", Status: &fleet.MDMAppleDeliveryApplied, OperationType: fleet.MDMAppleOperationTypeInstall, @@ -1118,6 +1136,7 @@ func testMDMAppleProfileManagement(t *testing.T, ds *Datastore) { ProfileID: globalPfs[1].ProfileID, ProfileIdentifier: globalPfs[1].Identifier, ProfileName: globalPfs[1].Name, + Checksum: globalProfiles[1].Checksum, HostUUID: "test-uuid-3", Status: &fleet.MDMAppleDeliveryApplied, OperationType: fleet.MDMAppleOperationTypeInstall, @@ -1127,6 +1146,7 @@ func testMDMAppleProfileManagement(t *testing.T, ds *Datastore) { ProfileID: globalPfs[2].ProfileID, ProfileIdentifier: globalPfs[2].Identifier, ProfileName: globalPfs[2].Name, + Checksum: globalProfiles[2].Checksum, HostUUID: "test-uuid-1", Status: &fleet.MDMAppleDeliveryApplied, OperationType: fleet.MDMAppleOperationTypeInstall, @@ -1136,6 +1156,7 @@ func testMDMAppleProfileManagement(t *testing.T, ds *Datastore) { ProfileID: globalPfs[2].ProfileID, ProfileIdentifier: globalPfs[2].Identifier, ProfileName: globalPfs[2].Name, + Checksum: globalProfiles[2].Checksum, HostUUID: "test-uuid-3", Status: &fleet.MDMAppleDeliveryApplied, OperationType: fleet.MDMAppleOperationTypeInstall, @@ -1145,6 +1166,7 @@ func testMDMAppleProfileManagement(t *testing.T, ds *Datastore) { ProfileID: teamPfs[0].ProfileID, ProfileIdentifier: teamPfs[0].Identifier, ProfileName: teamPfs[0].Name, + Checksum: teamProfiles[0].Checksum, HostUUID: "test-uuid-2", Status: &fleet.MDMAppleDeliveryApplied, OperationType: fleet.MDMAppleOperationTypeInstall, @@ -1154,6 +1176,7 @@ func testMDMAppleProfileManagement(t *testing.T, ds *Datastore) { ProfileID: teamPfs[1].ProfileID, ProfileIdentifier: teamPfs[1].Identifier, ProfileName: teamPfs[1].Name, + Checksum: teamProfiles[1].Checksum, HostUUID: "test-uuid-2", Status: &fleet.MDMAppleDeliveryApplied, OperationType: fleet.MDMAppleOperationTypeInstall, @@ -1180,7 +1203,7 @@ func testMDMAppleProfileManagement(t *testing.T, ds *Datastore) { // profiles to be added for host1 are now related to the team profiles, err = ds.ListMDMAppleProfilesToInstall(ctx) require.NoError(t, err) - require.ElementsMatch(t, []*fleet.MDMAppleProfilePayload{ + matchProfiles([]*fleet.MDMAppleProfilePayload{ {ProfileID: teamPfs[0].ProfileID, ProfileIdentifier: teamPfs[0].Identifier, ProfileName: teamPfs[0].Name, HostUUID: "test-uuid-1"}, {ProfileID: teamPfs[1].ProfileID, ProfileIdentifier: teamPfs[1].Identifier, ProfileName: teamPfs[1].Name, HostUUID: "test-uuid-1"}, }, profiles) @@ -1188,7 +1211,7 @@ func testMDMAppleProfileManagement(t *testing.T, ds *Datastore) { // profiles to be removed includes host1's old profiles toRemove, err = ds.ListMDMAppleProfilesToRemove(ctx) require.NoError(t, err) - require.ElementsMatch(t, []*fleet.MDMAppleProfilePayload{ + matchProfiles([]*fleet.MDMAppleProfilePayload{ {ProfileID: globalPfs[0].ProfileID, ProfileIdentifier: globalPfs[0].Identifier, ProfileName: globalPfs[0].Name, HostUUID: "test-uuid-1"}, {ProfileID: globalPfs[1].ProfileID, ProfileIdentifier: globalPfs[1].Identifier, ProfileName: globalPfs[1].Name, HostUUID: "test-uuid-1"}, {ProfileID: globalPfs[2].ProfileID, ProfileIdentifier: globalPfs[2].Identifier, ProfileName: globalPfs[2].Name, HostUUID: "test-uuid-1"}, @@ -1350,6 +1373,7 @@ func upsertHostCPs( CommandUUID: "", OperationType: opType, Status: status, + Checksum: []byte("csum"), } upserts = append(upserts, &payload) } @@ -1679,6 +1703,7 @@ func testIgnoreMDMClientError(t *testing.T, ds *Datastore) { CommandUUID: "c2", OperationType: fleet.MDMAppleOperationTypeRemove, Status: &fleet.MDMAppleDeliveryPending, + Checksum: []byte("csum"), }})) cps, err = ds.GetHostMDMProfiles(ctx, "h2") require.NoError(t, err) @@ -1728,6 +1753,7 @@ func testDeleteMDMAppleProfilesForHost(t *testing.T, ds *Datastore) { CommandUUID: "c1", OperationType: fleet.MDMAppleOperationTypeRemove, Status: &fleet.MDMAppleDeliveryPending, + Checksum: []byte("csum"), }})) gotProfs, err := ds.GetHostMDMProfiles(ctx, h.UUID) @@ -2026,19 +2052,19 @@ func testBulkSetPendingMDMAppleHostProfiles(t *testing.T, ds *Datastore) { require.NoError(t, err) assertHostProfiles(map[*fleet.Host][]fleet.HostMDMAppleProfile{ enrolledHosts[0]: { - {ProfileID: globalProfiles[0].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, - {ProfileID: globalProfiles[1].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, - {ProfileID: globalProfiles[2].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: globalProfiles[0].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: globalProfiles[1].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: globalProfiles[2].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, }, enrolledHosts[1]: { - {ProfileID: globalProfiles[0].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, - {ProfileID: globalProfiles[1].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, - {ProfileID: globalProfiles[2].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: globalProfiles[0].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: globalProfiles[1].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: globalProfiles[2].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, }, enrolledHosts[2]: { - {ProfileID: globalProfiles[0].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, - {ProfileID: globalProfiles[1].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, - {ProfileID: globalProfiles[2].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: globalProfiles[0].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: globalProfiles[1].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: globalProfiles[2].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, }, unenrolledHost: {}, linuxHost: {}, @@ -2067,19 +2093,19 @@ func testBulkSetPendingMDMAppleHostProfiles(t *testing.T, ds *Datastore) { require.NoError(t, err) assertHostProfiles(map[*fleet.Host][]fleet.HostMDMAppleProfile{ enrolledHosts[0]: { - {ProfileID: globalProfiles[0].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeRemove}, - {ProfileID: globalProfiles[1].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeRemove}, - {ProfileID: globalProfiles[2].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeRemove}, + {ProfileID: globalProfiles[0].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeRemove}, + {ProfileID: globalProfiles[1].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeRemove}, + {ProfileID: globalProfiles[2].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeRemove}, }, enrolledHosts[1]: { - {ProfileID: globalProfiles[0].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, - {ProfileID: globalProfiles[1].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, - {ProfileID: globalProfiles[2].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: globalProfiles[0].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: globalProfiles[1].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: globalProfiles[2].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, }, enrolledHosts[2]: { - {ProfileID: globalProfiles[0].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, - {ProfileID: globalProfiles[1].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, - {ProfileID: globalProfiles[2].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: globalProfiles[0].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: globalProfiles[1].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: globalProfiles[2].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, }, unenrolledHost: {}, linuxHost: {}, @@ -2108,19 +2134,19 @@ func testBulkSetPendingMDMAppleHostProfiles(t *testing.T, ds *Datastore) { require.NoError(t, err) assertHostProfiles(map[*fleet.Host][]fleet.HostMDMAppleProfile{ enrolledHosts[0]: { - {ProfileID: globalProfiles[0].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeRemove}, - {ProfileID: globalProfiles[1].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeRemove}, - {ProfileID: globalProfiles[2].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeRemove}, + {ProfileID: globalProfiles[0].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeRemove}, + {ProfileID: globalProfiles[1].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeRemove}, + {ProfileID: globalProfiles[2].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeRemove}, }, enrolledHosts[1]: { - {ProfileID: globalProfiles[0].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeRemove}, - {ProfileID: globalProfiles[1].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeRemove}, - {ProfileID: globalProfiles[2].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeRemove}, + {ProfileID: globalProfiles[0].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeRemove}, + {ProfileID: globalProfiles[1].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeRemove}, + {ProfileID: globalProfiles[2].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeRemove}, }, enrolledHosts[2]: { - {ProfileID: globalProfiles[0].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, - {ProfileID: globalProfiles[1].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, - {ProfileID: globalProfiles[2].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: globalProfiles[0].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: globalProfiles[1].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: globalProfiles[2].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, }, unenrolledHost: {}, linuxHost: {}, @@ -2152,21 +2178,21 @@ func testBulkSetPendingMDMAppleHostProfiles(t *testing.T, ds *Datastore) { require.NoError(t, err) assertHostProfiles(map[*fleet.Host][]fleet.HostMDMAppleProfile{ enrolledHosts[0]: { - {ProfileID: globalProfiles[0].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeRemove}, - {ProfileID: globalProfiles[1].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeRemove}, - {ProfileID: globalProfiles[2].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeRemove}, - {ProfileID: tm1Profiles[0].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, - {ProfileID: tm1Profiles[1].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: globalProfiles[0].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeRemove}, + {ProfileID: globalProfiles[1].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeRemove}, + {ProfileID: globalProfiles[2].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeRemove}, + {ProfileID: tm1Profiles[0].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: tm1Profiles[1].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, }, enrolledHosts[1]: { - {ProfileID: globalProfiles[0].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeRemove}, - {ProfileID: globalProfiles[1].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeRemove}, - {ProfileID: globalProfiles[2].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeRemove}, + {ProfileID: globalProfiles[0].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeRemove}, + {ProfileID: globalProfiles[1].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeRemove}, + {ProfileID: globalProfiles[2].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeRemove}, }, enrolledHosts[2]: { - {ProfileID: globalProfiles[0].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, - {ProfileID: globalProfiles[1].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, - {ProfileID: globalProfiles[2].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: globalProfiles[0].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: globalProfiles[1].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: globalProfiles[2].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, }, unenrolledHost: {}, linuxHost: {}, @@ -2178,11 +2204,11 @@ func testBulkSetPendingMDMAppleHostProfiles(t *testing.T, ds *Datastore) { // all rows in this test since we don't have command uuids. err = ds.BulkUpsertMDMAppleHostProfiles(ctx, []*fleet.MDMAppleBulkUpsertHostProfilePayload{ {HostUUID: enrolledHosts[0].UUID, ProfileID: globalProfiles[0].ProfileID, - Status: &fleet.MDMAppleDeliveryApplied, OperationType: fleet.MDMAppleOperationTypeRemove}, + Status: &fleet.MDMAppleDeliveryApplied, OperationType: fleet.MDMAppleOperationTypeRemove, Checksum: []byte("csum")}, {HostUUID: enrolledHosts[0].UUID, ProfileID: globalProfiles[1].ProfileID, - Status: &fleet.MDMAppleDeliveryApplied, OperationType: fleet.MDMAppleOperationTypeRemove}, + Status: &fleet.MDMAppleDeliveryApplied, OperationType: fleet.MDMAppleOperationTypeRemove, Checksum: []byte("csum")}, {HostUUID: enrolledHosts[0].UUID, ProfileID: globalProfiles[2].ProfileID, - Status: &fleet.MDMAppleDeliveryFailed, OperationType: fleet.MDMAppleOperationTypeRemove}, + Status: &fleet.MDMAppleDeliveryFailed, OperationType: fleet.MDMAppleOperationTypeRemove, Checksum: []byte("csum")}, }) require.NoError(t, err) @@ -2203,19 +2229,19 @@ func testBulkSetPendingMDMAppleHostProfiles(t *testing.T, ds *Datastore) { assertHostProfiles(map[*fleet.Host][]fleet.HostMDMAppleProfile{ enrolledHosts[0]: { {ProfileID: globalProfiles[2].ProfileID, Status: &fleet.MDMAppleDeliveryFailed, OperationType: fleet.MDMAppleOperationTypeRemove}, - {ProfileID: tm1Profiles[0].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeRemove}, - {ProfileID: newTm1Profiles[0].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, - {ProfileID: newTm1Profiles[1].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: tm1Profiles[0].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeRemove}, + {ProfileID: newTm1Profiles[0].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: newTm1Profiles[1].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, }, enrolledHosts[1]: { - {ProfileID: globalProfiles[0].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeRemove}, - {ProfileID: globalProfiles[1].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeRemove}, - {ProfileID: globalProfiles[2].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeRemove}, + {ProfileID: globalProfiles[0].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeRemove}, + {ProfileID: globalProfiles[1].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeRemove}, + {ProfileID: globalProfiles[2].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeRemove}, }, enrolledHosts[2]: { - {ProfileID: globalProfiles[0].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, - {ProfileID: globalProfiles[1].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, - {ProfileID: globalProfiles[2].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: globalProfiles[0].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: globalProfiles[1].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: globalProfiles[2].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, }, unenrolledHost: {}, linuxHost: {}, @@ -2242,20 +2268,19 @@ func testBulkSetPendingMDMAppleHostProfiles(t *testing.T, ds *Datastore) { assertHostProfiles(map[*fleet.Host][]fleet.HostMDMAppleProfile{ enrolledHosts[0]: { {ProfileID: globalProfiles[2].ProfileID, Status: &fleet.MDMAppleDeliveryFailed, OperationType: fleet.MDMAppleOperationTypeRemove}, - {ProfileID: tm1Profiles[0].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeRemove}, - {ProfileID: newTm1Profiles[0].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, - {ProfileID: newTm1Profiles[1].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, - {ProfileID: newTm1Profiles[2].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: newTm1Profiles[0].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: newTm1Profiles[1].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: newTm1Profiles[2].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, }, enrolledHosts[1]: { - {ProfileID: globalProfiles[0].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeRemove}, - {ProfileID: globalProfiles[1].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeRemove}, - {ProfileID: globalProfiles[2].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeRemove}, + {ProfileID: globalProfiles[0].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeRemove}, + {ProfileID: globalProfiles[1].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeRemove}, + {ProfileID: globalProfiles[2].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeRemove}, }, enrolledHosts[2]: { - {ProfileID: globalProfiles[0].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, - {ProfileID: globalProfiles[1].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, - {ProfileID: globalProfiles[2].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: globalProfiles[0].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: globalProfiles[1].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: globalProfiles[2].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, }, unenrolledHost: {}, linuxHost: {}, @@ -2279,21 +2304,20 @@ func testBulkSetPendingMDMAppleHostProfiles(t *testing.T, ds *Datastore) { assertHostProfiles(map[*fleet.Host][]fleet.HostMDMAppleProfile{ enrolledHosts[0]: { {ProfileID: globalProfiles[2].ProfileID, Status: &fleet.MDMAppleDeliveryFailed, OperationType: fleet.MDMAppleOperationTypeRemove}, - {ProfileID: tm1Profiles[0].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeRemove}, - {ProfileID: newTm1Profiles[0].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, - {ProfileID: newTm1Profiles[1].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, - {ProfileID: newTm1Profiles[2].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: newTm1Profiles[0].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: newTm1Profiles[1].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: newTm1Profiles[2].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, }, enrolledHosts[1]: { - {ProfileID: globalProfiles[0].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeRemove}, - {ProfileID: globalProfiles[1].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeRemove}, - {ProfileID: globalProfiles[2].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeRemove}, + {ProfileID: globalProfiles[0].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeRemove}, + {ProfileID: globalProfiles[1].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeRemove}, + {ProfileID: globalProfiles[2].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeRemove}, }, enrolledHosts[2]: { - {ProfileID: globalProfiles[0].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeRemove}, - {ProfileID: newGlobalProfiles[0].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, - {ProfileID: newGlobalProfiles[1].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, - {ProfileID: newGlobalProfiles[2].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: globalProfiles[0].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeRemove}, + {ProfileID: newGlobalProfiles[0].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: newGlobalProfiles[1].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: newGlobalProfiles[2].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, }, unenrolledHost: {}, linuxHost: {}, @@ -2318,22 +2342,21 @@ func testBulkSetPendingMDMAppleHostProfiles(t *testing.T, ds *Datastore) { assertHostProfiles(map[*fleet.Host][]fleet.HostMDMAppleProfile{ enrolledHosts[0]: { {ProfileID: globalProfiles[2].ProfileID, Status: &fleet.MDMAppleDeliveryFailed, OperationType: fleet.MDMAppleOperationTypeRemove}, - {ProfileID: tm1Profiles[0].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeRemove}, - {ProfileID: newTm1Profiles[0].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, - {ProfileID: newTm1Profiles[1].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, - {ProfileID: newTm1Profiles[2].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: newTm1Profiles[0].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: newTm1Profiles[1].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: newTm1Profiles[2].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, }, enrolledHosts[1]: { - {ProfileID: globalProfiles[0].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeRemove}, - {ProfileID: globalProfiles[1].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeRemove}, - {ProfileID: globalProfiles[2].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeRemove}, + {ProfileID: globalProfiles[0].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeRemove}, + {ProfileID: globalProfiles[1].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeRemove}, + {ProfileID: globalProfiles[2].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeRemove}, }, enrolledHosts[2]: { - {ProfileID: globalProfiles[0].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeRemove}, - {ProfileID: newGlobalProfiles[0].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, - {ProfileID: newGlobalProfiles[1].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, - {ProfileID: newGlobalProfiles[2].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, - {ProfileID: newGlobalProfiles[3].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: globalProfiles[0].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeRemove}, + {ProfileID: newGlobalProfiles[0].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: newGlobalProfiles[1].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: newGlobalProfiles[2].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: newGlobalProfiles[3].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, }, unenrolledHost: {}, linuxHost: {}, @@ -2355,23 +2378,22 @@ func testBulkSetPendingMDMAppleHostProfiles(t *testing.T, ds *Datastore) { assertHostProfiles(map[*fleet.Host][]fleet.HostMDMAppleProfile{ enrolledHosts[0]: { {ProfileID: globalProfiles[2].ProfileID, Status: &fleet.MDMAppleDeliveryFailed, OperationType: fleet.MDMAppleOperationTypeRemove}, - {ProfileID: tm1Profiles[0].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeRemove}, - {ProfileID: newTm1Profiles[0].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, - {ProfileID: newTm1Profiles[1].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, - {ProfileID: newTm1Profiles[2].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: newTm1Profiles[0].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: newTm1Profiles[1].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: newTm1Profiles[2].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, }, enrolledHosts[1]: { - {ProfileID: globalProfiles[0].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeRemove}, - {ProfileID: globalProfiles[1].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeRemove}, - {ProfileID: globalProfiles[2].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeRemove}, - {ProfileID: tm2Profiles[0].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: globalProfiles[0].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeRemove}, + {ProfileID: globalProfiles[1].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeRemove}, + {ProfileID: globalProfiles[2].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeRemove}, + {ProfileID: tm2Profiles[0].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, }, enrolledHosts[2]: { - {ProfileID: globalProfiles[0].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeRemove}, - {ProfileID: newGlobalProfiles[0].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, - {ProfileID: newGlobalProfiles[1].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, - {ProfileID: newGlobalProfiles[2].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, - {ProfileID: newGlobalProfiles[3].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: globalProfiles[0].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeRemove}, + {ProfileID: newGlobalProfiles[0].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: newGlobalProfiles[1].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: newGlobalProfiles[2].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: newGlobalProfiles[3].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, }, unenrolledHost: {}, linuxHost: {}, @@ -2383,23 +2405,22 @@ func testBulkSetPendingMDMAppleHostProfiles(t *testing.T, ds *Datastore) { assertHostProfiles(map[*fleet.Host][]fleet.HostMDMAppleProfile{ enrolledHosts[0]: { {ProfileID: globalProfiles[2].ProfileID, Status: &fleet.MDMAppleDeliveryFailed, OperationType: fleet.MDMAppleOperationTypeRemove}, - {ProfileID: tm1Profiles[0].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeRemove}, - {ProfileID: newTm1Profiles[0].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, - {ProfileID: newTm1Profiles[1].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, - {ProfileID: newTm1Profiles[2].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: newTm1Profiles[0].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: newTm1Profiles[1].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: newTm1Profiles[2].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, }, enrolledHosts[1]: { - {ProfileID: globalProfiles[0].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeRemove}, - {ProfileID: globalProfiles[1].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeRemove}, - {ProfileID: globalProfiles[2].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeRemove}, - {ProfileID: tm2Profiles[0].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: globalProfiles[0].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeRemove}, + {ProfileID: globalProfiles[1].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeRemove}, + {ProfileID: globalProfiles[2].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeRemove}, + {ProfileID: tm2Profiles[0].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, }, enrolledHosts[2]: { - {ProfileID: globalProfiles[0].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeRemove}, - {ProfileID: newGlobalProfiles[0].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, - {ProfileID: newGlobalProfiles[1].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, - {ProfileID: newGlobalProfiles[2].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, - {ProfileID: newGlobalProfiles[3].ProfileID, Status: nil, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: globalProfiles[0].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeRemove}, + {ProfileID: newGlobalProfiles[0].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: newGlobalProfiles[1].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: newGlobalProfiles[2].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: newGlobalProfiles[3].ProfileID, Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall}, }, unenrolledHost: {}, linuxHost: {}, diff --git a/server/datastore/mysql/hosts_test.go b/server/datastore/mysql/hosts_test.go index 019b3d4d557..f54208d8792 100644 --- a/server/datastore/mysql/hosts_test.go +++ b/server/datastore/mysql/hosts_test.go @@ -712,6 +712,7 @@ func testHostListOptionsTeamFilter(t *testing.T, ds *Datastore) { CommandUUID: "command-uuid-1", OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryApplied, + Checksum: []byte("csum"), }, })) listHostsCheckCount(t, ds, userFilter, fleet.HostListOptions{TeamFilter: &team1.ID, MacOSSettingsFilter: fleet.MacOSSettingsStatusLatest}, 1) // hosts[0] @@ -729,6 +730,7 @@ func testHostListOptionsTeamFilter(t *testing.T, ds *Datastore) { CommandUUID: "command-uuid-2", OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryApplied, + Checksum: []byte("csum"), }, })) listHostsCheckCount(t, ds, userFilter, fleet.HostListOptions{TeamFilter: &team1.ID, MacOSSettingsFilter: fleet.MacOSSettingsStatusLatest}, 1) // hosts[0] @@ -5523,7 +5525,7 @@ func testHostsDeleteHosts(t *testing.T, ds *Datastore) { prof, err := ds.NewMDMAppleConfigProfile(context.Background(), *configProfileForTest(t, "N1", "I1", "U1")) require.NoError(t, err) err = ds.BulkUpsertMDMAppleHostProfiles(context.Background(), []*fleet.MDMAppleBulkUpsertHostProfilePayload{ - {ProfileID: prof.ProfileID, ProfileIdentifier: prof.Identifier, ProfileName: prof.Name, HostUUID: host.UUID, OperationType: fleet.MDMAppleOperationTypeInstall}, + {ProfileID: prof.ProfileID, ProfileIdentifier: prof.Identifier, ProfileName: prof.Name, HostUUID: host.UUID, OperationType: fleet.MDMAppleOperationTypeInstall, Checksum: []byte("csum")}, }) require.NoError(t, err) diff --git a/server/datastore/mysql/labels_test.go b/server/datastore/mysql/labels_test.go index b134d09c791..00b33f96083 100644 --- a/server/datastore/mysql/labels_test.go +++ b/server/datastore/mysql/labels_test.go @@ -485,6 +485,7 @@ func testLabelsListHostsInLabelAndTeamFilter(deferred bool, t *testing.T, db *Da CommandUUID: "command-uuid-1", OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryApplied, + Checksum: []byte("csum"), }, })) listHostsInLabelCheckCount(t, db, userFilter, l1.ID, fleet.HostListOptions{TeamFilter: &team1.ID, MacOSSettingsFilter: fleet.MacOSSettingsStatusLatest}, 1) // h1 @@ -502,6 +503,7 @@ func testLabelsListHostsInLabelAndTeamFilter(deferred bool, t *testing.T, db *Da CommandUUID: "command-uuid-2", OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryApplied, + Checksum: []byte("csum"), }, })) listHostsInLabelCheckCount(t, db, userFilter, l1.ID, fleet.HostListOptions{TeamFilter: &team1.ID, MacOSSettingsFilter: fleet.MacOSSettingsStatusLatest}, 1) // h1 diff --git a/server/service/integration_mdm_test.go b/server/service/integration_mdm_test.go index 24a77f4e044..39c2731b7e9 100644 --- a/server/service/integration_mdm_test.go +++ b/server/service/integration_mdm_test.go @@ -913,6 +913,7 @@ func (s *integrationMDMTestSuite) TestMDMAppleGetEncryptionKey() { CommandUUID: hostCmdUUID, OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryApplied, + Checksum: []byte("csum"), }, }) require.NoError(t, err) @@ -1442,6 +1443,7 @@ func (s *integrationMDMTestSuite) TestMDMAppleDiskEncryptionAggregate() { CommandUUID: hostCmdUUID, OperationType: operationType, Status: status, + Checksum: []byte("csum"), }, }) require.NoError(t, err) From 559edd38d15b6e3b74b668384f706ad7b93f4c52 Mon Sep 17 00:00:00 2001 From: Roberto Dip Date: Sat, 8 Apr 2023 19:45:46 -0300 Subject: [PATCH 06/11] port changes from sarah's branch --- ee/server/service/teams.go | 18 ++++++++ server/datastore/mysql/apple_mdm.go | 68 +++++++++++++++++++++++++++++ server/datastore/mysql/hosts.go | 4 ++ server/fleet/datastore.go | 2 + server/mock/datastore_mock.go | 12 +++++ 5 files changed, 104 insertions(+) diff --git a/ee/server/service/teams.go b/ee/server/service/teams.go index 35acae7c0d7..155c0dd78dd 100644 --- a/ee/server/service/teams.go +++ b/ee/server/service/teams.go @@ -391,6 +391,24 @@ func (svc *Service) DeleteTeam(ctx context.Context, teamID uint) error { return ctxerr.Wrap(ctx, err, "bulk set pending host profiles") } + vc, ok := viewer.FromContext(ctx) + if !ok { + return fleet.ErrNoContext + } + filter := fleet.TeamFilter{User: vc.User, IncludeObserver: true} + hosts, err := svc.ds.ListHosts(ctx, filter, fleet.HostListOptions{TeamFilter: &teamID}) + if err != nil { + return ctxerr.Wrap(ctx, err, "list hosts for reconcile profiles on team change") + } + hostIDs := make([]uint, 0, len(hosts)) + for _, host := range hosts { + hostIDs = append(hostIDs, host.ID) + } + + if err := svc.ds.CleanupDiskEncryptionKeysOnTeamChange(ctx, hostIDs, ptr.Uint(0)); err != nil { + return ctxerr.Wrap(ctx, err, "reconcile profiles on team change cleanup disk encryption keys") + } + logging.WithExtras(ctx, "id", teamID) if err := svc.ds.NewActivity( diff --git a/server/datastore/mysql/apple_mdm.go b/server/datastore/mysql/apple_mdm.go index dd100cae7f8..bfefc6c79ca 100644 --- a/server/datastore/mysql/apple_mdm.go +++ b/server/datastore/mysql/apple_mdm.go @@ -1653,3 +1653,71 @@ func (ds *Datastore) GetMDMAppleBootstrapPackageMeta(ctx context.Context, teamID } return &bp, nil } + +func (ds *Datastore) CleanupDiskEncryptionKeysOnTeamChange(ctx context.Context, hostIDs []uint, newTeamID *uint) error { + return ds.withTx(ctx, func(tx sqlx.ExtContext) error { + return cleanupDiskEncryptionKeysOnTeamChangeDB(ctx, tx, hostIDs, newTeamID) + }) +} + +func cleanupDiskEncryptionKeysOnTeamChangeDB(ctx context.Context, tx sqlx.ExtContext, hostIDs []uint, newTeamID *uint) error { + _, err := getMDMAppleConfigProfileByTeamAndIdentifierDB(ctx, tx, newTeamID, mobileconfig.FleetFileVaultPayloadIdentifier) + if err != nil { + if fleet.IsNotFound(err) { + // the new team does not have a filevault profile so we need to delete the existing ones + if err := bulkDeleteHostDiskEncryptionKeysDB(ctx, tx, hostIDs); err != nil { + return ctxerr.Wrap(ctx, err, "reconcile filevault profiles on team change bulk delete host disk encryption keys") + } + } else { + return ctxerr.Wrap(ctx, err, "reconcile filevault profiles on team change get profile") + } + } + return nil +} + +func getMDMAppleConfigProfileByTeamAndIdentifierDB(ctx context.Context, tx sqlx.QueryerContext, teamID *uint, profileIdentifier string) (*fleet.MDMAppleConfigProfile, error) { + if teamID == nil { + teamID = ptr.Uint(0) + } + + stmt := ` +SELECT + profile_id, + team_id, + name, + identifier, + mobileconfig, + created_at, + updated_at +FROM + mdm_apple_configuration_profiles +WHERE + team_id=? AND identifier=?` + + var profile fleet.MDMAppleConfigProfile + err := sqlx.GetContext(ctx, tx, &profile, stmt, teamID, profileIdentifier) + if err != nil { + if err == sql.ErrNoRows { + return &fleet.MDMAppleConfigProfile{}, ctxerr.Wrap(ctx, notFound("MDMAppleConfigProfile").WithName(profileIdentifier)) + } + return &fleet.MDMAppleConfigProfile{}, ctxerr.Wrap(ctx, err, "get mdm apple config profile by team and identifier") + } + return &profile, nil +} + +func bulkDeleteHostDiskEncryptionKeysDB(ctx context.Context, tx sqlx.ExtContext, hostIDs []uint) error { + if len(hostIDs) == 0 { + return nil + } + + query, args, err := sqlx.In( + "DELETE FROM host_disk_encryption_keys WHERE host_id IN (?)", + hostIDs, + ) + if err != nil { + return ctxerr.Wrap(ctx, err, "building query") + } + + _, err = tx.ExecContext(ctx, query, args...) + return err +} diff --git a/server/datastore/mysql/hosts.go b/server/datastore/mysql/hosts.go index 66600b31cf7..d4d0629907f 100644 --- a/server/datastore/mysql/hosts.go +++ b/server/datastore/mysql/hosts.go @@ -1945,6 +1945,10 @@ func (ds *Datastore) AddHostsToTeam(ctx context.Context, teamID *uint, hostIDs [ return ctxerr.Wrap(ctx, err, "exec AddHostsToTeam") } + if err := cleanupDiskEncryptionKeysOnTeamChangeDB(ctx, tx, hostIDs, teamID); err != nil { + return ctxerr.Wrap(ctx, err, "AddHostsToTeam cleanup disk encryption keys") + } + return nil }) } diff --git a/server/fleet/datastore.go b/server/fleet/datastore.go index e9ad086f267..4ce734f8048 100644 --- a/server/fleet/datastore.go +++ b/server/fleet/datastore.go @@ -756,6 +756,8 @@ type Datastore interface { // GetHostMDMProfiles returns the MDM profile information for the specified host UUID. GetHostMDMProfiles(ctx context.Context, hostUUID string) ([]HostMDMAppleProfile, error) + CleanupDiskEncryptionKeysOnTeamChange(ctx context.Context, hostIDs []uint, newTeamID *uint) error + // NewMDMAppleEnrollmentProfile creates and returns new enrollment profile. // Such enrollment profiles allow devices to enroll to Fleet MDM. NewMDMAppleEnrollmentProfile(ctx context.Context, enrollmentPayload MDMAppleEnrollmentProfilePayload) (*MDMAppleEnrollmentProfile, error) diff --git a/server/mock/datastore_mock.go b/server/mock/datastore_mock.go index 411bca7354b..d50f5a27943 100644 --- a/server/mock/datastore_mock.go +++ b/server/mock/datastore_mock.go @@ -530,6 +530,8 @@ type DeleteMDMAppleConfigProfileByTeamAndIdentifierFunc func(ctx context.Context type GetHostMDMProfilesFunc func(ctx context.Context, hostUUID string) ([]fleet.HostMDMAppleProfile, error) +type CleanupDiskEncryptionKeysOnTeamChangeFunc func(ctx context.Context, hostIDs []uint, newTeamID *uint) error + type NewMDMAppleEnrollmentProfileFunc func(ctx context.Context, enrollmentPayload fleet.MDMAppleEnrollmentProfilePayload) (*fleet.MDMAppleEnrollmentProfile, error) type GetMDMAppleEnrollmentProfileByTokenFunc func(ctx context.Context, token string) (*fleet.MDMAppleEnrollmentProfile, error) @@ -1364,6 +1366,9 @@ type DataStore struct { GetHostMDMProfilesFunc GetHostMDMProfilesFunc GetHostMDMProfilesFuncInvoked bool + CleanupDiskEncryptionKeysOnTeamChangeFunc CleanupDiskEncryptionKeysOnTeamChangeFunc + CleanupDiskEncryptionKeysOnTeamChangeFuncInvoked bool + NewMDMAppleEnrollmentProfileFunc NewMDMAppleEnrollmentProfileFunc NewMDMAppleEnrollmentProfileFuncInvoked bool @@ -3259,6 +3264,13 @@ func (s *DataStore) GetHostMDMProfiles(ctx context.Context, hostUUID string) ([] return s.GetHostMDMProfilesFunc(ctx, hostUUID) } +func (s *DataStore) CleanupDiskEncryptionKeysOnTeamChange(ctx context.Context, hostIDs []uint, newTeamID *uint) error { + s.mu.Lock() + s.CleanupDiskEncryptionKeysOnTeamChangeFuncInvoked = true + s.mu.Unlock() + return s.CleanupDiskEncryptionKeysOnTeamChangeFunc(ctx, hostIDs, newTeamID) +} + func (s *DataStore) NewMDMAppleEnrollmentProfile(ctx context.Context, enrollmentPayload fleet.MDMAppleEnrollmentProfilePayload) (*fleet.MDMAppleEnrollmentProfile, error) { s.mu.Lock() s.NewMDMAppleEnrollmentProfileFuncInvoked = true From fb27fc10098b61c568048509e0b134e452b189ad Mon Sep 17 00:00:00 2001 From: Roberto Dip Date: Sat, 8 Apr 2023 20:01:29 -0300 Subject: [PATCH 07/11] fix integration tests --- server/service/integration_mdm_test.go | 142 +++++++++++++------------ 1 file changed, 73 insertions(+), 69 deletions(-) diff --git a/server/service/integration_mdm_test.go b/server/service/integration_mdm_test.go index 39c2731b7e9..4d95fbbf0d6 100644 --- a/server/service/integration_mdm_test.go +++ b/server/service/integration_mdm_test.go @@ -1014,6 +1014,22 @@ func (s *integrationMDMTestSuite) TestMDMAppleGetEncryptionKey() { ) } + team, err := s.ds.NewTeam(context.Background(), &fleet.Team{ + ID: 4827, + Name: "team1_" + t.Name(), + Description: "desc team1_" + t.Name(), + }) + require.NoError(t, err) + + // enable disk encryption on the team so the key is not deleted when the host is added + teamSpecs := applyTeamSpecsRequest{Specs: []*fleet.TeamSpec{{ + Name: "team1_" + t.Name(), + MDM: fleet.TeamSpecMDM{ + MacOSSettings: map[string]interface{}{"enable_disk_encryption": true}, + }, + }}} + s.Do("POST", "/api/latest/fleet/spec/teams", teamSpecs, http.StatusOK) + // we're about to mess up with the token, make sure to set it to the // default value when the test ends currToken := s.token @@ -1042,12 +1058,6 @@ func (s *integrationMDMTestSuite) TestMDMAppleGetEncryptionKey() { checkDecryptableKey(u) // add the host to a team - team, err := s.ds.NewTeam(context.Background(), &fleet.Team{ - ID: 4827, - Name: "team1_" + t.Name(), - Description: "desc team1_" + t.Name(), - }) - require.NoError(t, err) err = s.ds.AddHostsToTeam(ctx, &team.ID, []uint{host.ID}) require.NoError(t, err) @@ -2121,12 +2131,12 @@ func (s *integrationMDMTestSuite) TestHostMDMProfilesStatus() { require.Nil(t, h2.TeamID) s.assertHostConfigProfiles(map[*fleet.Host][]fleet.HostMDMAppleProfile{ h1: { - {Identifier: "G1", OperationType: fleet.MDMAppleOperationTypeInstall, Status: nil}, - {Identifier: "G2", OperationType: fleet.MDMAppleOperationTypeInstall, Status: nil}, + {Identifier: "G1", OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryPending}, + {Identifier: "G2", OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryPending}, }, h2: { - {Identifier: "G1", OperationType: fleet.MDMAppleOperationTypeInstall, Status: nil}, - {Identifier: "G2", OperationType: fleet.MDMAppleOperationTypeInstall, Status: nil}, + {Identifier: "G1", OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryPending}, + {Identifier: "G2", OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryPending}, }, }) @@ -2139,12 +2149,12 @@ func (s *integrationMDMTestSuite) TestHostMDMProfilesStatus() { require.Equal(t, tm1.ID, *h4.TeamID) s.assertHostConfigProfiles(map[*fleet.Host][]fleet.HostMDMAppleProfile{ h3: { - {Identifier: "T1.1", OperationType: fleet.MDMAppleOperationTypeInstall, Status: nil}, - {Identifier: "T1.2", OperationType: fleet.MDMAppleOperationTypeInstall, Status: nil}, + {Identifier: "T1.1", OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryPending}, + {Identifier: "T1.2", OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryPending}, }, h4: { - {Identifier: "T1.1", OperationType: fleet.MDMAppleOperationTypeInstall, Status: nil}, - {Identifier: "T1.2", OperationType: fleet.MDMAppleOperationTypeInstall, Status: nil}, + {Identifier: "T1.1", OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryPending}, + {Identifier: "T1.2", OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryPending}, }, }) @@ -2157,11 +2167,10 @@ func (s *integrationMDMTestSuite) TestHostMDMProfilesStatus() { addHostsToTeamRequest{TeamID: &tm2.ID, HostIDs: []uint{h1.ID}}, http.StatusOK, &moveHostResp) s.assertHostConfigProfiles(map[*fleet.Host][]fleet.HostMDMAppleProfile{ h1: { - {Identifier: "G1", OperationType: fleet.MDMAppleOperationTypeRemove, Status: nil}, - {Identifier: "G2", OperationType: fleet.MDMAppleOperationTypeRemove, Status: nil}, - {Identifier: "T2.1", OperationType: fleet.MDMAppleOperationTypeInstall, Status: nil}, - {Identifier: mobileconfig.FleetdConfigPayloadIdentifier, OperationType: fleet.MDMAppleOperationTypeInstall, Status: nil}, - {Identifier: mobileconfig.FleetdConfigPayloadIdentifier, OperationType: fleet.MDMAppleOperationTypeRemove, Status: nil}, + {Identifier: "G1", OperationType: fleet.MDMAppleOperationTypeRemove, Status: &fleet.MDMAppleDeliveryPending}, + {Identifier: "G2", OperationType: fleet.MDMAppleOperationTypeRemove, Status: &fleet.MDMAppleDeliveryPending}, + {Identifier: "T2.1", OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryPending}, + {Identifier: mobileconfig.FleetdConfigPayloadIdentifier, OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryPending}, }, h2: { {Identifier: "G1", OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryApplied}, @@ -2175,11 +2184,10 @@ func (s *integrationMDMTestSuite) TestHostMDMProfilesStatus() { addHostsToTeamRequest{TeamID: &tm2.ID, HostIDs: []uint{h3.ID}}, http.StatusOK, &moveHostResp) s.assertHostConfigProfiles(map[*fleet.Host][]fleet.HostMDMAppleProfile{ h3: { - {Identifier: "T1.1", OperationType: fleet.MDMAppleOperationTypeRemove, Status: nil}, - {Identifier: "T1.2", OperationType: fleet.MDMAppleOperationTypeRemove, Status: nil}, - {Identifier: "T2.1", OperationType: fleet.MDMAppleOperationTypeInstall, Status: nil}, - {Identifier: mobileconfig.FleetdConfigPayloadIdentifier, OperationType: fleet.MDMAppleOperationTypeRemove, Status: nil}, - {Identifier: mobileconfig.FleetdConfigPayloadIdentifier, OperationType: fleet.MDMAppleOperationTypeInstall, Status: nil}, + {Identifier: "T1.1", OperationType: fleet.MDMAppleOperationTypeRemove, Status: &fleet.MDMAppleDeliveryPending}, + {Identifier: "T1.2", OperationType: fleet.MDMAppleOperationTypeRemove, Status: &fleet.MDMAppleDeliveryPending}, + {Identifier: "T2.1", OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryPending}, + {Identifier: mobileconfig.FleetdConfigPayloadIdentifier, OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryPending}, }, h4: { {Identifier: "T1.1", OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryApplied}, @@ -2193,19 +2201,17 @@ func (s *integrationMDMTestSuite) TestHostMDMProfilesStatus() { addHostsToTeamRequest{TeamID: nil, HostIDs: []uint{h4.ID}}, http.StatusOK, &moveHostResp) s.assertHostConfigProfiles(map[*fleet.Host][]fleet.HostMDMAppleProfile{ h3: { - {Identifier: "T1.1", OperationType: fleet.MDMAppleOperationTypeRemove, Status: nil}, - {Identifier: "T1.2", OperationType: fleet.MDMAppleOperationTypeRemove, Status: nil}, - {Identifier: "T2.1", OperationType: fleet.MDMAppleOperationTypeInstall, Status: nil}, - {Identifier: mobileconfig.FleetdConfigPayloadIdentifier, OperationType: fleet.MDMAppleOperationTypeRemove, Status: nil}, - {Identifier: mobileconfig.FleetdConfigPayloadIdentifier, OperationType: fleet.MDMAppleOperationTypeInstall, Status: nil}, + {Identifier: "T1.1", OperationType: fleet.MDMAppleOperationTypeRemove, Status: &fleet.MDMAppleDeliveryPending}, + {Identifier: "T1.2", OperationType: fleet.MDMAppleOperationTypeRemove, Status: &fleet.MDMAppleDeliveryPending}, + {Identifier: "T2.1", OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryPending}, + {Identifier: mobileconfig.FleetdConfigPayloadIdentifier, OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryPending}, }, h4: { - {Identifier: "T1.1", OperationType: fleet.MDMAppleOperationTypeRemove, Status: nil}, - {Identifier: "T1.2", OperationType: fleet.MDMAppleOperationTypeRemove, Status: nil}, - {Identifier: "G1", OperationType: fleet.MDMAppleOperationTypeInstall, Status: nil}, - {Identifier: "G2", OperationType: fleet.MDMAppleOperationTypeInstall, Status: nil}, - {Identifier: mobileconfig.FleetdConfigPayloadIdentifier, OperationType: fleet.MDMAppleOperationTypeRemove, Status: nil}, - {Identifier: mobileconfig.FleetdConfigPayloadIdentifier, OperationType: fleet.MDMAppleOperationTypeInstall, Status: nil}, + {Identifier: "T1.1", OperationType: fleet.MDMAppleOperationTypeRemove, Status: &fleet.MDMAppleDeliveryPending}, + {Identifier: "T1.2", OperationType: fleet.MDMAppleOperationTypeRemove, Status: &fleet.MDMAppleDeliveryPending}, + {Identifier: "G1", OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryPending}, + {Identifier: "G2", OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryPending}, + {Identifier: mobileconfig.FleetdConfigPayloadIdentifier, OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryPending}, }, }) @@ -2221,12 +2227,12 @@ func (s *integrationMDMTestSuite) TestHostMDMProfilesStatus() { {Identifier: "G1", OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryApplied}, {Identifier: "G2", OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryApplied}, {Identifier: mobileconfig.FleetdConfigPayloadIdentifier, OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryApplied}, - {Identifier: "G3", OperationType: fleet.MDMAppleOperationTypeInstall, Status: nil}, + {Identifier: "G3", OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryPending}, }, h4: { {Identifier: "G1", OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryApplied}, {Identifier: "G2", OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryApplied}, - {Identifier: "G3", OperationType: fleet.MDMAppleOperationTypeInstall, Status: nil}, + {Identifier: "G3", OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryPending}, {Identifier: mobileconfig.FleetdConfigPayloadIdentifier, OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryApplied}, }, }) @@ -2238,12 +2244,12 @@ func (s *integrationMDMTestSuite) TestHostMDMProfilesStatus() { s.assertHostConfigProfiles(map[*fleet.Host][]fleet.HostMDMAppleProfile{ h1: { {Identifier: "T2.1", OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryApplied}, - {Identifier: "T2.2", OperationType: fleet.MDMAppleOperationTypeInstall, Status: nil}, + {Identifier: "T2.2", OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryPending}, {Identifier: mobileconfig.FleetdConfigPayloadIdentifier, OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryApplied}, }, h3: { {Identifier: "T2.1", OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryApplied}, - {Identifier: "T2.2", OperationType: fleet.MDMAppleOperationTypeInstall, Status: nil}, + {Identifier: "T2.2", OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryPending}, {Identifier: mobileconfig.FleetdConfigPayloadIdentifier, OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryApplied}, }, }) @@ -2267,13 +2273,13 @@ func (s *integrationMDMTestSuite) TestHostMDMProfilesStatus() { deleteMDMAppleConfigProfileRequest{}, http.StatusOK, &delProfResp) s.assertHostConfigProfiles(map[*fleet.Host][]fleet.HostMDMAppleProfile{ h2: { - {Identifier: "G1", OperationType: fleet.MDMAppleOperationTypeRemove, Status: nil}, + {Identifier: "G1", OperationType: fleet.MDMAppleOperationTypeRemove, Status: &fleet.MDMAppleDeliveryPending}, {Identifier: "G2", OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryApplied}, {Identifier: "G3", OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryApplied}, {Identifier: mobileconfig.FleetdConfigPayloadIdentifier, OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryApplied}, }, h4: { - {Identifier: "G1", OperationType: fleet.MDMAppleOperationTypeRemove, Status: nil}, + {Identifier: "G1", OperationType: fleet.MDMAppleOperationTypeRemove, Status: &fleet.MDMAppleDeliveryPending}, {Identifier: "G2", OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryApplied}, {Identifier: "G3", OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryApplied}, {Identifier: mobileconfig.FleetdConfigPayloadIdentifier, OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryApplied}, @@ -2295,12 +2301,12 @@ func (s *integrationMDMTestSuite) TestHostMDMProfilesStatus() { deleteMDMAppleConfigProfileRequest{}, http.StatusOK, &delProfResp) s.assertHostConfigProfiles(map[*fleet.Host][]fleet.HostMDMAppleProfile{ h1: { - {Identifier: "T2.1", OperationType: fleet.MDMAppleOperationTypeRemove, Status: nil}, + {Identifier: "T2.1", OperationType: fleet.MDMAppleOperationTypeRemove, Status: &fleet.MDMAppleDeliveryPending}, {Identifier: "T2.2", OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryApplied}, {Identifier: mobileconfig.FleetdConfigPayloadIdentifier, OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryApplied}, }, h3: { - {Identifier: "T2.1", OperationType: fleet.MDMAppleOperationTypeRemove, Status: nil}, + {Identifier: "T2.1", OperationType: fleet.MDMAppleOperationTypeRemove, Status: &fleet.MDMAppleDeliveryPending}, {Identifier: "T2.2", OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryApplied}, {Identifier: mobileconfig.FleetdConfigPayloadIdentifier, OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryApplied}, }, @@ -2323,17 +2329,17 @@ func (s *integrationMDMTestSuite) TestHostMDMProfilesStatus() { s.assertHostConfigProfiles(map[*fleet.Host][]fleet.HostMDMAppleProfile{ h2: { - {Identifier: "G2", OperationType: fleet.MDMAppleOperationTypeRemove, Status: nil}, - {Identifier: "G2b", OperationType: fleet.MDMAppleOperationTypeInstall, Status: nil}, - {Identifier: "G3", OperationType: fleet.MDMAppleOperationTypeRemove, Status: nil}, - {Identifier: "G4", OperationType: fleet.MDMAppleOperationTypeInstall, Status: nil}, + {Identifier: "G2", OperationType: fleet.MDMAppleOperationTypeRemove, Status: &fleet.MDMAppleDeliveryPending}, + {Identifier: "G2b", OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryPending}, + {Identifier: "G3", OperationType: fleet.MDMAppleOperationTypeRemove, Status: &fleet.MDMAppleDeliveryPending}, + {Identifier: "G4", OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryPending}, {Identifier: mobileconfig.FleetdConfigPayloadIdentifier, OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryApplied}, }, h4: { - {Identifier: "G2", OperationType: fleet.MDMAppleOperationTypeRemove, Status: nil}, - {Identifier: "G2b", OperationType: fleet.MDMAppleOperationTypeInstall, Status: nil}, - {Identifier: "G3", OperationType: fleet.MDMAppleOperationTypeRemove, Status: nil}, - {Identifier: "G4", OperationType: fleet.MDMAppleOperationTypeInstall, Status: nil}, + {Identifier: "G2", OperationType: fleet.MDMAppleOperationTypeRemove, Status: &fleet.MDMAppleDeliveryPending}, + {Identifier: "G2b", OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryPending}, + {Identifier: "G3", OperationType: fleet.MDMAppleOperationTypeRemove, Status: &fleet.MDMAppleDeliveryPending}, + {Identifier: "G4", OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryPending}, {Identifier: mobileconfig.FleetdConfigPayloadIdentifier, OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryApplied}, }, }) @@ -2350,15 +2356,15 @@ func (s *integrationMDMTestSuite) TestHostMDMProfilesStatus() { }, http.StatusNoContent, "team_id", fmt.Sprint(tm2.ID)) s.assertHostConfigProfiles(map[*fleet.Host][]fleet.HostMDMAppleProfile{ h1: { - {Identifier: "T2.2", OperationType: fleet.MDMAppleOperationTypeRemove, Status: nil}, - {Identifier: "T2.2b", OperationType: fleet.MDMAppleOperationTypeInstall, Status: nil}, - {Identifier: "T2.3", OperationType: fleet.MDMAppleOperationTypeInstall, Status: nil}, + {Identifier: "T2.2", OperationType: fleet.MDMAppleOperationTypeRemove, Status: &fleet.MDMAppleDeliveryPending}, + {Identifier: "T2.2b", OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryPending}, + {Identifier: "T2.3", OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryPending}, {Identifier: mobileconfig.FleetdConfigPayloadIdentifier, OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryApplied}, }, h3: { - {Identifier: "T2.2", OperationType: fleet.MDMAppleOperationTypeRemove, Status: nil}, - {Identifier: "T2.2b", OperationType: fleet.MDMAppleOperationTypeInstall, Status: nil}, - {Identifier: "T2.3", OperationType: fleet.MDMAppleOperationTypeInstall, Status: nil}, + {Identifier: "T2.2", OperationType: fleet.MDMAppleOperationTypeRemove, Status: &fleet.MDMAppleDeliveryPending}, + {Identifier: "T2.2b", OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryPending}, + {Identifier: "T2.3", OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryPending}, {Identifier: mobileconfig.FleetdConfigPayloadIdentifier, OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryApplied}, }, }) @@ -2414,20 +2420,18 @@ func (s *integrationMDMTestSuite) TestHostMDMProfilesStatus() { s.Do("DELETE", fmt.Sprintf("/api/latest/fleet/teams/%d", tm2.ID), nil, http.StatusOK) s.assertHostConfigProfiles(map[*fleet.Host][]fleet.HostMDMAppleProfile{ h1: { - {Identifier: "T2.2b", OperationType: fleet.MDMAppleOperationTypeRemove, Status: nil}, - {Identifier: "T2.3", OperationType: fleet.MDMAppleOperationTypeRemove, Status: nil}, - {Identifier: "G2b", OperationType: fleet.MDMAppleOperationTypeInstall, Status: nil}, - {Identifier: "G4", OperationType: fleet.MDMAppleOperationTypeInstall, Status: nil}, - {Identifier: mobileconfig.FleetdConfigPayloadIdentifier, OperationType: fleet.MDMAppleOperationTypeRemove, Status: nil}, - {Identifier: mobileconfig.FleetdConfigPayloadIdentifier, OperationType: fleet.MDMAppleOperationTypeInstall, Status: nil}, + {Identifier: "T2.2b", OperationType: fleet.MDMAppleOperationTypeRemove, Status: &fleet.MDMAppleDeliveryPending}, + {Identifier: "T2.3", OperationType: fleet.MDMAppleOperationTypeRemove, Status: &fleet.MDMAppleDeliveryPending}, + {Identifier: "G2b", OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryPending}, + {Identifier: "G4", OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryPending}, + {Identifier: mobileconfig.FleetdConfigPayloadIdentifier, OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryPending}, }, h3: { - {Identifier: "T2.2b", OperationType: fleet.MDMAppleOperationTypeRemove, Status: nil}, - {Identifier: "T2.3", OperationType: fleet.MDMAppleOperationTypeRemove, Status: nil}, - {Identifier: "G2b", OperationType: fleet.MDMAppleOperationTypeInstall, Status: nil}, - {Identifier: "G4", OperationType: fleet.MDMAppleOperationTypeInstall, Status: nil}, - {Identifier: mobileconfig.FleetdConfigPayloadIdentifier, OperationType: fleet.MDMAppleOperationTypeRemove, Status: nil}, - {Identifier: mobileconfig.FleetdConfigPayloadIdentifier, OperationType: fleet.MDMAppleOperationTypeInstall, Status: nil}, + {Identifier: "T2.2b", OperationType: fleet.MDMAppleOperationTypeRemove, Status: &fleet.MDMAppleDeliveryPending}, + {Identifier: "T2.3", OperationType: fleet.MDMAppleOperationTypeRemove, Status: &fleet.MDMAppleDeliveryPending}, + {Identifier: "G2b", OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryPending}, + {Identifier: "G4", OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryPending}, + {Identifier: mobileconfig.FleetdConfigPayloadIdentifier, OperationType: fleet.MDMAppleOperationTypeInstall, Status: &fleet.MDMAppleDeliveryPending}, }, }) From a79acc806c9346cdd4ed9ee4deed4c25642d3497 Mon Sep 17 00:00:00 2001 From: Roberto Dip Date: Sat, 8 Apr 2023 20:40:16 -0300 Subject: [PATCH 08/11] last test fixes --- server/datastore/mysql/apple_mdm_test.go | 1 + server/service/teams_test.go | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/server/datastore/mysql/apple_mdm_test.go b/server/datastore/mysql/apple_mdm_test.go index 80a94dc16c8..963f697888b 100644 --- a/server/datastore/mysql/apple_mdm_test.go +++ b/server/datastore/mysql/apple_mdm_test.go @@ -1673,6 +1673,7 @@ func testIgnoreMDMClientError(t *testing.T, ds *Datastore) { CommandUUID: "c1", OperationType: fleet.MDMAppleOperationTypeRemove, Status: &fleet.MDMAppleDeliveryPending, + Checksum: []byte("csum"), }})) cps, err := ds.GetHostMDMProfiles(ctx, "h1") require.NoError(t, err) diff --git a/server/service/teams_test.go b/server/service/teams_test.go index 7630256ca34..8fec36b03b1 100644 --- a/server/service/teams_test.go +++ b/server/service/teams_test.go @@ -52,6 +52,13 @@ func TestTeamAuth(t *testing.T) { ds.BulkSetPendingMDMAppleHostProfilesFunc = func(ctx context.Context, hids, tids, pids []uint, uuids []string) error { return nil } + ds.ListHostsFunc = func(ctx context.Context, filter fleet.TeamFilter, opt fleet.HostListOptions) ([]*fleet.Host, error) { + return []*fleet.Host{}, nil + } + ds.CleanupDiskEncryptionKeysOnTeamChangeFunc = func(ctx context.Context, hostIDs []uint, newTeamID *uint) error { + return nil + } + ds.TeamByNameFunc = func(ctx context.Context, name string) (*fleet.Team, error) { switch name { case "team1": From de95d11f10ca8136f7f60dad8b9384ba19b91911 Mon Sep 17 00:00:00 2001 From: Roberto Dip Date: Sat, 8 Apr 2023 20:51:21 -0300 Subject: [PATCH 09/11] add missing migration tests --- ...230408084104_AddChecksumToProfiles_test.go | 87 ++++++++++++++++--- 1 file changed, 77 insertions(+), 10 deletions(-) diff --git a/server/datastore/mysql/migrations/tables/20230408084104_AddChecksumToProfiles_test.go b/server/datastore/mysql/migrations/tables/20230408084104_AddChecksumToProfiles_test.go index 68391f4b9ea..6ef326b3530 100644 --- a/server/datastore/mysql/migrations/tables/20230408084104_AddChecksumToProfiles_test.go +++ b/server/datastore/mysql/migrations/tables/20230408084104_AddChecksumToProfiles_test.go @@ -1,20 +1,87 @@ package tables -import "testing" +import ( + "crypto/md5" + "fmt" + "testing" + + "github.com/stretchr/testify/require" +) func TestUp_20230408084104(t *testing.T) { db := applyUpToPrev(t) + stmt := ` +INSERT INTO + mdm_apple_configuration_profiles (team_id, identifier, name, mobileconfig) +VALUES (?, ?, ?, ?)` + + mcBytes := []byte(` + + + + PayloadContent + + PayloadDisplayName + TestPayloadName + PayloadIdentifier + TestPayloadIdentifier + PayloadType + Configuration + PayloadUUID + TestPayloadUUID + PayloadVersion + 1 + + +`) + + r, err := db.Exec(stmt, 0, "TestPayloadIdentifier", "TestPayloadName", mcBytes) + profileID, _ := r.LastInsertId() + require.NoError(t, err) + + var ( + identifier string + mobileconfig []byte + ) + err = db.QueryRow(`SELECT identifier, mobileconfig FROM mdm_apple_configuration_profiles WHERE name = ? AND team_id = ?`, "TestPayloadName", 0).Scan(&identifier, &mobileconfig) + require.NoError(t, err) + require.Equal(t, "TestPayloadIdentifier", identifier) + require.Equal(t, mcBytes, mobileconfig) + + var status []string + err = db.Select(&status, `SELECT status FROM mdm_apple_delivery_status`) + require.NoError(t, err) + require.ElementsMatch(t, []string{"failed", "applied", "pending"}, status) - // - // Insert data to test the migration - // - // ... + var opTypes []string + err = db.Select(&opTypes, `SELECT operation_type FROM mdm_apple_operation_types`) + require.NoError(t, err) + require.ElementsMatch(t, []string{"install", "remove"}, opTypes) - // Apply current migration. + _, err = db.Exec(` + INSERT INTO nano_commands (command_uuid, request_type, command) + VALUES ('command-uuid', 'foo', ' Date: Sat, 8 Apr 2023 21:03:44 -0300 Subject: [PATCH 10/11] lint --- server/datastore/mysql/apple_mdm_test.go | 4 ++-- .../tables/20230408084104_AddChecksumToProfiles_test.go | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/server/datastore/mysql/apple_mdm_test.go b/server/datastore/mysql/apple_mdm_test.go index 963f697888b..ee4c9a9155c 100644 --- a/server/datastore/mysql/apple_mdm_test.go +++ b/server/datastore/mysql/apple_mdm_test.go @@ -2,7 +2,7 @@ package mysql import ( "context" - "crypto/md5" + "crypto/md5" // nolint:gosec // used only to hash for efficient comparisons "crypto/sha256" "database/sql" "fmt" @@ -939,7 +939,7 @@ func configProfileForTest(t *testing.T, name, identifier, uuid string) *fleet.MD `, name, identifier, uuid)) cp, err := fleet.NewMDMAppleConfigProfile(prof, nil) - sum := md5.Sum(prof) + sum := md5.Sum(prof) // nolint:gosec // used only to hash for efficient comparisons cp.Checksum = sum[:] require.NoError(t, err) return cp diff --git a/server/datastore/mysql/migrations/tables/20230408084104_AddChecksumToProfiles_test.go b/server/datastore/mysql/migrations/tables/20230408084104_AddChecksumToProfiles_test.go index 6ef326b3530..9c75397dcc3 100644 --- a/server/datastore/mysql/migrations/tables/20230408084104_AddChecksumToProfiles_test.go +++ b/server/datastore/mysql/migrations/tables/20230408084104_AddChecksumToProfiles_test.go @@ -1,7 +1,7 @@ package tables import ( - "crypto/md5" + "crypto/md5" // nolint:gosec // used only to hash for efficient comparisons "fmt" "testing" @@ -78,10 +78,10 @@ VALUES (?, ?, ?, ?)` var checksum []byte err = db.QueryRow(`SELECT checksum FROM mdm_apple_configuration_profiles WHERE name = ? AND team_id = ?`, "TestPayloadName", 0).Scan(&checksum) require.NoError(t, err) - require.Equal(t, fmt.Sprintf("%x", md5.Sum(mcBytes)), fmt.Sprintf("%x", checksum)) + require.Equal(t, fmt.Sprintf("%x", md5.Sum(mcBytes)), fmt.Sprintf("%x", checksum)) // nolint:gosec // used only to hash for efficient comparisons err = db.QueryRow(`SELECT checksum FROM host_mdm_apple_profiles WHERE profile_id = ?`, profileID).Scan(&checksum) require.NoError(t, err) - require.Equal(t, fmt.Sprintf("%x", md5.Sum(mcBytes)), fmt.Sprintf("%x", checksum)) + require.Equal(t, fmt.Sprintf("%x", md5.Sum(mcBytes)), fmt.Sprintf("%x", checksum)) // nolint:gosec // used only to hash for efficient comparisons } From 6b1ddeff20f47070a70b6c18d40731ca3df9153d Mon Sep 17 00:00:00 2001 From: Roberto Dip Date: Sat, 8 Apr 2023 23:03:00 -0300 Subject: [PATCH 11/11] fetch hosts before deleting team --- ee/server/service/teams.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ee/server/service/teams.go b/ee/server/service/teams.go index 155c0dd78dd..b1ac0d92f4f 100644 --- a/ee/server/service/teams.go +++ b/ee/server/service/teams.go @@ -383,14 +383,6 @@ func (svc *Service) DeleteTeam(ctx context.Context, teamID uint) error { } name := team.Name - if err := svc.ds.DeleteTeam(ctx, teamID); err != nil { - return err - } - // team id 0 is provided since the team's hosts are now part of no team - if err := svc.ds.BulkSetPendingMDMAppleHostProfiles(ctx, nil, []uint{0}, nil, nil); err != nil { - return ctxerr.Wrap(ctx, err, "bulk set pending host profiles") - } - vc, ok := viewer.FromContext(ctx) if !ok { return fleet.ErrNoContext @@ -405,6 +397,14 @@ func (svc *Service) DeleteTeam(ctx context.Context, teamID uint) error { hostIDs = append(hostIDs, host.ID) } + if err := svc.ds.DeleteTeam(ctx, teamID); err != nil { + return err + } + // team id 0 is provided since the team's hosts are now part of no team + if err := svc.ds.BulkSetPendingMDMAppleHostProfiles(ctx, nil, []uint{0}, nil, nil); err != nil { + return ctxerr.Wrap(ctx, err, "bulk set pending host profiles") + } + if err := svc.ds.CleanupDiskEncryptionKeysOnTeamChange(ctx, hostIDs, ptr.Uint(0)); err != nil { return ctxerr.Wrap(ctx, err, "reconcile profiles on team change cleanup disk encryption keys") }