diff --git a/changes/42651-continuous-policy-automations b/changes/42651-continuous-policy-automations new file mode 100644 index 0000000000..add18f6ac6 --- /dev/null +++ b/changes/42651-continuous-policy-automations @@ -0,0 +1,2 @@ +- Added `continuous_automations_enabled` to team policies. When enabled, software and script automations run on every failing policy result instead of only on the host's first failure or a pass→fail transition. +- Surfaced `continuous_automations_enabled` in GitOps YAML (read and generated by `fleetctl generate-gitops`). diff --git a/cmd/fleetctl/fleetctl/api_test.go b/cmd/fleetctl/fleetctl/api_test.go index 371e2186d2..a36df8b238 100644 --- a/cmd/fleetctl/fleetctl/api_test.go +++ b/cmd/fleetctl/fleetctl/api_test.go @@ -74,6 +74,7 @@ func TestRunApiCommand(t *testing.T) { "calendar_events_enabled": false, "conditional_access_enabled": false, "type": "dynamic", + "continuous_automations_enabled": false, "created_at": "0001-01-01T00:00:00Z", "updated_at": "0001-01-01T00:00:00Z", "passing_host_count": 0, diff --git a/cmd/fleetctl/fleetctl/generate_gitops.go b/cmd/fleetctl/fleetctl/generate_gitops.go index cb4e7a99e0..0d7c47d7bc 100644 --- a/cmd/fleetctl/fleetctl/generate_gitops.go +++ b/cmd/fleetctl/fleetctl/generate_gitops.go @@ -1591,13 +1591,14 @@ func (cmd *GenerateGitopsCommand) generatePolicies(teamId *uint, filePath string result := make([]map[string]interface{}, len(policies)) for i, policy := range policies { policySpec := map[string]interface{}{ - jsonFieldName(t, "Name"): policy.Name, - jsonFieldName(t, "Description"): policy.Description, - jsonFieldName(t, "Resolution"): policy.Resolution, - jsonFieldName(t, "Platform"): policy.Platform, - jsonFieldName(t, "Critical"): policy.Critical, - jsonFieldName(t, "CalendarEventsEnabled"): policy.CalendarEventsEnabled, - jsonFieldName(t, "ConditionalAccessEnabled"): policy.ConditionalAccessEnabled, + jsonFieldName(t, "Name"): policy.Name, + jsonFieldName(t, "Description"): policy.Description, + jsonFieldName(t, "Resolution"): policy.Resolution, + jsonFieldName(t, "Platform"): policy.Platform, + jsonFieldName(t, "Critical"): policy.Critical, + jsonFieldName(t, "CalendarEventsEnabled"): policy.CalendarEventsEnabled, + jsonFieldName(t, "ConditionalAccessEnabled"): policy.ConditionalAccessEnabled, + jsonFieldName(t, "ContinuousAutomationsEnabled"): policy.ContinuousAutomationsEnabled, } if policy.Type == fleet.PolicyTypeDynamic { diff --git a/cmd/fleetctl/fleetctl/testdata/expectedHostDetailResponseJson.json b/cmd/fleetctl/fleetctl/testdata/expectedHostDetailResponseJson.json index 4383a1f6e5..4c58ed7960 100644 --- a/cmd/fleetctl/fleetctl/testdata/expectedHostDetailResponseJson.json +++ b/cmd/fleetctl/fleetctl/testdata/expectedHostDetailResponseJson.json @@ -68,6 +68,7 @@ "author_name": "Alice", "calendar_events_enabled": true, "conditional_access_enabled": false, + "continuous_automations_enabled": false, "created_at": "0001-01-01T00:00:00Z", "critical": false, "description": "Some description", @@ -88,6 +89,7 @@ "author_name": "Alice", "calendar_events_enabled": false, "conditional_access_enabled": false, + "continuous_automations_enabled": false, "created_at": "0001-01-01T00:00:00Z", "critical": false, "description": "", diff --git a/cmd/fleetctl/fleetctl/testdata/expectedHostDetailResponseYaml.yml b/cmd/fleetctl/fleetctl/testdata/expectedHostDetailResponseYaml.yml index 3a7ba2eb50..94124d5684 100644 --- a/cmd/fleetctl/fleetctl/testdata/expectedHostDetailResponseYaml.yml +++ b/cmd/fleetctl/fleetctl/testdata/expectedHostDetailResponseYaml.yml @@ -66,6 +66,7 @@ spec: author_name: Alice calendar_events_enabled: true conditional_access_enabled: false + continuous_automations_enabled: false created_at: "0001-01-01T00:00:00Z" critical: false description: Some description @@ -84,6 +85,7 @@ spec: author_name: Alice calendar_events_enabled: false conditional_access_enabled: false + continuous_automations_enabled: false created_at: "0001-01-01T00:00:00Z" critical: false description: "" diff --git a/cmd/fleetctl/fleetctl/testdata/generateGitops/expectedGlobalPolicies.yaml b/cmd/fleetctl/fleetctl/testdata/generateGitops/expectedGlobalPolicies.yaml index 078059853e..bb8295257f 100644 --- a/cmd/fleetctl/fleetctl/testdata/generateGitops/expectedGlobalPolicies.yaml +++ b/cmd/fleetctl/fleetctl/testdata/generateGitops/expectedGlobalPolicies.yaml @@ -1,5 +1,6 @@ - calendar_events_enabled: false conditional_access_enabled: true + continuous_automations_enabled: false critical: false description: This is a global policy install_software: @@ -15,6 +16,7 @@ webhooks_and_tickets_enabled: false - calendar_events_enabled: false conditional_access_enabled: false + continuous_automations_enabled: false critical: false description: This is a global policy with include_all scope labels_include_all: diff --git a/cmd/fleetctl/fleetctl/testdata/generateGitops/expectedTeamPolicies.yaml b/cmd/fleetctl/fleetctl/testdata/generateGitops/expectedTeamPolicies.yaml index 5a91f39277..81b02e1f00 100644 --- a/cmd/fleetctl/fleetctl/testdata/generateGitops/expectedTeamPolicies.yaml +++ b/cmd/fleetctl/fleetctl/testdata/generateGitops/expectedTeamPolicies.yaml @@ -1,4 +1,5 @@ - calendar_events_enabled: false + continuous_automations_enabled: false critical: false description: This is a team policy name: Team Policy @@ -12,6 +13,7 @@ conditional_access_bypass_enabled: true webhooks_and_tickets_enabled: false - calendar_events_enabled: false + continuous_automations_enabled: false critical: false description: This is a team patch policy name: Team patch policy @@ -25,6 +27,7 @@ webhooks_and_tickets_enabled: false - calendar_events_enabled: false conditional_access_enabled: false + continuous_automations_enabled: false critical: false description: This is a team policy with VPP app automation install_software: diff --git a/cmd/fleetctl/fleetctl/testdata/generateGitops/test_dir_free/default.yml b/cmd/fleetctl/fleetctl/testdata/generateGitops/test_dir_free/default.yml index bfd0d3c954..ab5f9b4dee 100644 --- a/cmd/fleetctl/fleetctl/testdata/generateGitops/test_dir_free/default.yml +++ b/cmd/fleetctl/fleetctl/testdata/generateGitops/test_dir_free/default.yml @@ -185,6 +185,7 @@ org_settings: policies: - calendar_events_enabled: false conditional_access_enabled: true + continuous_automations_enabled: false critical: false description: This is a global policy install_software: @@ -200,6 +201,7 @@ policies: webhooks_and_tickets_enabled: false - calendar_events_enabled: false conditional_access_enabled: false + continuous_automations_enabled: false critical: false description: This is a global policy with include_all scope name: Global Policy Include All diff --git a/cmd/fleetctl/fleetctl/testdata/generateGitops/test_dir_premium/default.yml b/cmd/fleetctl/fleetctl/testdata/generateGitops/test_dir_premium/default.yml index b1ac5a7fa6..5087400488 100644 --- a/cmd/fleetctl/fleetctl/testdata/generateGitops/test_dir_premium/default.yml +++ b/cmd/fleetctl/fleetctl/testdata/generateGitops/test_dir_premium/default.yml @@ -181,6 +181,7 @@ org_settings: policies: - calendar_events_enabled: false conditional_access_enabled: true + continuous_automations_enabled: false critical: false description: This is a global policy install_software: @@ -196,6 +197,7 @@ policies: webhooks_and_tickets_enabled: false - calendar_events_enabled: false conditional_access_enabled: false + continuous_automations_enabled: false critical: false description: This is a global policy with include_all scope labels_include_all: diff --git a/cmd/fleetctl/fleetctl/testdata/generateGitops/test_dir_premium/fleets/team-a-thumbsup.yml b/cmd/fleetctl/fleetctl/testdata/generateGitops/test_dir_premium/fleets/team-a-thumbsup.yml index 58478e252e..a6acf2408d 100644 --- a/cmd/fleetctl/fleetctl/testdata/generateGitops/test_dir_premium/fleets/team-a-thumbsup.yml +++ b/cmd/fleetctl/fleetctl/testdata/generateGitops/test_dir_premium/fleets/team-a-thumbsup.yml @@ -53,6 +53,7 @@ name: "Team A 👍" policies: - calendar_events_enabled: false conditional_access_enabled: true + continuous_automations_enabled: false critical: false description: This is a team policy name: Team Policy @@ -63,6 +64,7 @@ policies: webhooks_and_tickets_enabled: true - calendar_events_enabled: false conditional_access_enabled: true + continuous_automations_enabled: false critical: false description: This is a team patch policy fleet_maintained_app_slug: foo/darwin @@ -73,6 +75,7 @@ policies: webhooks_and_tickets_enabled: true - calendar_events_enabled: false conditional_access_enabled: false + continuous_automations_enabled: false critical: false description: This is a team policy with VPP app automation install_software: @@ -85,6 +88,7 @@ policies: webhooks_and_tickets_enabled: true - calendar_events_enabled: false conditional_access_enabled: false + continuous_automations_enabled: false critical: false description: This is a team policy with FMA install automation install_software: @@ -97,6 +101,7 @@ policies: webhooks_and_tickets_enabled: false - calendar_events_enabled: false conditional_access_enabled: false + continuous_automations_enabled: false critical: false description: This is a team policy with custom package install automation install_software: diff --git a/cmd/fleetctl/fleetctl/testdata/generateGitops/test_dir_premium/fleets/unassigned.yml b/cmd/fleetctl/fleetctl/testdata/generateGitops/test_dir_premium/fleets/unassigned.yml index f747b48729..e382a73ef4 100644 --- a/cmd/fleetctl/fleetctl/testdata/generateGitops/test_dir_premium/fleets/unassigned.yml +++ b/cmd/fleetctl/fleetctl/testdata/generateGitops/test_dir_premium/fleets/unassigned.yml @@ -36,6 +36,7 @@ name: Unassigned policies: - calendar_events_enabled: false conditional_access_enabled: true + continuous_automations_enabled: false critical: false description: This is a team policy name: Team Policy @@ -46,6 +47,7 @@ policies: webhooks_and_tickets_enabled: true - calendar_events_enabled: false conditional_access_enabled: true + continuous_automations_enabled: false critical: false description: This is a team patch policy fleet_maintained_app_slug: foo/darwin @@ -56,6 +58,7 @@ policies: webhooks_and_tickets_enabled: true - calendar_events_enabled: false conditional_access_enabled: false + continuous_automations_enabled: false critical: false description: This is a team policy with VPP app automation install_software: diff --git a/server/datastore/mysql/migrations/tables/20260522195237_AddContinuousAutomationsEnabledToPolicies.go b/server/datastore/mysql/migrations/tables/20260522195237_AddContinuousAutomationsEnabledToPolicies.go new file mode 100644 index 0000000000..bdfc809c24 --- /dev/null +++ b/server/datastore/mysql/migrations/tables/20260522195237_AddContinuousAutomationsEnabledToPolicies.go @@ -0,0 +1,28 @@ +package tables + +import ( + "database/sql" + "fmt" +) + +func init() { + MigrationClient.AddMigration(Up_20260522195237, Down_20260522195237) +} + +func Up_20260522195237(tx *sql.Tx) error { + if columnExists(tx, "policies", "continuous_automations_enabled") { + return nil + } + if _, err := tx.Exec(` + ALTER TABLE policies + ADD COLUMN continuous_automations_enabled TINYINT(1) NOT NULL DEFAULT 0, + ALGORITHM=INSTANT + `); err != nil { + return fmt.Errorf("add continuous_automations_enabled to policies: %w", err) + } + return nil +} + +func Down_20260522195237(tx *sql.Tx) error { + return nil +} diff --git a/server/datastore/mysql/migrations/tables/20260522195237_AddContinuousAutomationsEnabledToPolicies_test.go b/server/datastore/mysql/migrations/tables/20260522195237_AddContinuousAutomationsEnabledToPolicies_test.go new file mode 100644 index 0000000000..b768f85760 --- /dev/null +++ b/server/datastore/mysql/migrations/tables/20260522195237_AddContinuousAutomationsEnabledToPolicies_test.go @@ -0,0 +1,42 @@ +package tables + +import ( + "context" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestUp_20260522195237(t *testing.T) { + db := applyUpToPrev(t) + + policy1 := execNoErrLastID( + t, db, "INSERT INTO policies (name, query, description, checksum) VALUES (?,?,?,?)", + "policy1", "", "", "checksum1", + ) + + applyNext(t, db) + + var policyCheck []struct { + ID int64 `db:"id"` + ContinuousAutomationsEnabled bool `db:"continuous_automations_enabled"` + } + err := db.SelectContext(context.Background(), &policyCheck, `SELECT id, continuous_automations_enabled FROM policies WHERE id = ?`, policy1) + require.NoError(t, err) + require.Len(t, policyCheck, 1) + assert.Equal(t, policy1, policyCheck[0].ID) + assert.False(t, policyCheck[0].ContinuousAutomationsEnabled) + + policy2 := execNoErrLastID( + t, db, "INSERT INTO policies (name, query, description, checksum, continuous_automations_enabled) VALUES (?,?,?,?,?)", + "policy2", "", "", "checksum2", 1, + ) + + policyCheck = nil + err = db.SelectContext(context.Background(), &policyCheck, `SELECT id, continuous_automations_enabled FROM policies WHERE id = ?`, policy2) + require.NoError(t, err) + require.Len(t, policyCheck, 1) + assert.Equal(t, policy2, policyCheck[0].ID) + assert.True(t, policyCheck[0].ContinuousAutomationsEnabled) +} diff --git a/server/datastore/mysql/policies.go b/server/datastore/mysql/policies.go index d7f31f9b7a..3d2dd8d577 100644 --- a/server/datastore/mysql/policies.go +++ b/server/datastore/mysql/policies.go @@ -39,7 +39,7 @@ const policyCols = ` p.author_id, p.platforms, p.created_at, p.updated_at, p.critical, p.calendar_events_enabled, p.software_installer_id, p.script_id, p.vpp_apps_teams_id, p.conditional_access_enabled, p.type, - p.patch_software_title_id + p.patch_software_title_id, p.continuous_automations_enabled ` const ( @@ -393,11 +393,12 @@ func savePolicy(ctx context.Context, db sqlx.ExtContext, logger *slog.Logger, p SET name = ?, query = ?, description = ?, resolution = ?, platforms = ?, critical = ?, calendar_events_enabled = ?, software_installer_id = ?, script_id = ?, vpp_apps_teams_id = ?, - conditional_access_enabled = ?, checksum = ` + policiesChecksumComputedColumn() + ` + conditional_access_enabled = ?, continuous_automations_enabled = ?, + checksum = ` + policiesChecksumComputedColumn() + ` WHERE id = ? ` result, err := db.ExecContext( - ctx, updateStmt, p.Name, p.Query, p.Description, p.Resolution, p.Platform, p.Critical, p.CalendarEventsEnabled, p.SoftwareInstallerID, p.ScriptID, p.VPPAppsTeamsID, p.ConditionalAccessEnabled, p.ID, + ctx, updateStmt, p.Name, p.Query, p.Description, p.Resolution, p.Platform, p.Critical, p.CalendarEventsEnabled, p.SoftwareInstallerID, p.ScriptID, p.VPPAppsTeamsID, p.ConditionalAccessEnabled, p.ContinuousAutomationsEnabled, p.ID, ) if err != nil { return ctxerr.Wrap(ctx, err, "updating policy") @@ -424,6 +425,33 @@ func savePolicy(ctx context.Context, db sqlx.ExtContext, logger *slog.Logger, p ) } +// ResetPolicyAutomationRetryAttemptsForHost marks all prior script and software +// install attempts on this host (across the given policies) as "old sequence" by +// setting attempt_number=0. The retry gate counts attempt_number > 0 OR NULL, so +// after this reset the next attempt restarts the sequence at 1. +func (ds *Datastore) ResetPolicyAutomationRetryAttemptsForHost(ctx context.Context, hostID uint, policyIDs []uint) error { + if len(policyIDs) == 0 { + return nil + } + return ds.withRetryTxx(ctx, func(tx sqlx.ExtContext) error { + q, args, err := sqlx.In(resetScriptAttemptsStmt, hostID, policyIDs) + if err != nil { + return ctxerr.Wrap(ctx, err, "building reset host script attempts query") + } + if _, err := tx.ExecContext(ctx, q, args...); err != nil { + return ctxerr.Wrap(ctx, err, "reset host script attempts") + } + q, args, err = sqlx.In(resetInstallAttemptsStmt, hostID, policyIDs) + if err != nil { + return ctxerr.Wrap(ctx, err, "building reset host install attempts query") + } + if _, err := tx.ExecContext(ctx, q, args...); err != nil { + return ctxerr.Wrap(ctx, err, "reset host install attempts") + } + return nil + }) +} + // resetPolicyAutomationAttempts resets all attempt numbers for script and software install executions // associated with the given policy. func resetPolicyAutomationAttempts(ctx context.Context, db sqlx.ExecerContext, policyID uint) error { @@ -1167,13 +1195,13 @@ func newTeamPolicy(ctx context.Context, db sqlx.ExtContext, teamID uint, authorI name, query, description, team_id, resolution, author_id, platforms, critical, calendar_events_enabled, software_installer_id, script_id, vpp_apps_teams_id, conditional_access_enabled, checksum, - type, patch_software_title_id - ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, %s, ?, ?)`, + type, patch_software_title_id, continuous_automations_enabled + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, %s, ?, ?, ?)`, policiesChecksumComputedColumn(), ), nameUnicode, args.Query, args.Description, teamID, args.Resolution, authorID, args.Platform, args.Critical, args.CalendarEventsEnabled, args.SoftwareInstallerID, args.ScriptID, args.VPPAppsTeamsID, - args.ConditionalAccessEnabled, args.Type, args.PatchSoftwareTitleID, + args.ConditionalAccessEnabled, args.Type, args.PatchSoftwareTitleID, args.ContinuousAutomationsEnabled, ) switch { case err == nil: @@ -1465,8 +1493,9 @@ func (ds *Datastore) ApplyPolicySpecs(ctx context.Context, authorID uint, specs conditional_access_enabled, checksum, type, - patch_software_title_id - ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, %s, ?, ?) + patch_software_title_id, + continuous_automations_enabled + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, %s, ?, ?, ?) ON DUPLICATE KEY UPDATE query = VALUES(query), description = VALUES(description), @@ -1480,7 +1509,8 @@ func (ds *Datastore) ApplyPolicySpecs(ctx context.Context, authorID uint, specs script_id = VALUES(script_id), conditional_access_enabled = VALUES(conditional_access_enabled), type = VALUES(type), - patch_software_title_id = VALUES(patch_software_title_id) + patch_software_title_id = VALUES(patch_software_title_id), + continuous_automations_enabled = VALUES(continuous_automations_enabled) `, policiesChecksumComputedColumn(), ) for teamID, teamPolicySpecs := range teamIDToPolicies { @@ -1546,7 +1576,7 @@ func (ds *Datastore) ApplyPolicySpecs(ctx context.Context, authorID uint, specs query, spec.Name, spec.Query, spec.Description, authorID, spec.Resolution, teamID, spec.Platform, spec.Critical, spec.CalendarEventsEnabled, softwareInstallerID, vppAppsTeamsID, scriptID, spec.ConditionalAccessEnabled, - spec.Type, patchSoftwareTitleIDArg, + spec.Type, patchSoftwareTitleIDArg, spec.ContinuousAutomationsEnabled, ) if err != nil { return ctxerr.Wrap(ctx, err, "exec ApplyPolicySpecs insert") @@ -2521,7 +2551,7 @@ func (ds *Datastore) GetPoliciesWithAssociatedInstaller(ctx context.Context, tea if len(policyIDs) == 0 { return nil, nil } - query := `SELECT id, software_installer_id FROM policies WHERE team_id = ? AND software_installer_id IS NOT NULL AND id IN (?);` + query := `SELECT id, software_installer_id, continuous_automations_enabled FROM policies WHERE team_id = ? AND software_installer_id IS NOT NULL AND id IN (?);` query, args, err := sqlx.In(query, teamID, policyIDs) if err != nil { return nil, ctxerr.Wrapf(ctx, err, "build sqlx.In for get policies with associated installer") @@ -2537,7 +2567,7 @@ func (ds *Datastore) GetPoliciesWithAssociatedVPP(ctx context.Context, teamID ui if len(policyIDs) == 0 { return nil, nil } - query := `SELECT p.id, vat.adam_id, vat.platform FROM policies p JOIN vpp_apps_teams vat ON vat.id = p.vpp_apps_teams_id WHERE p.team_id = ? AND p.id IN (?);` + query := `SELECT p.id, vat.adam_id, vat.platform, p.continuous_automations_enabled FROM policies p JOIN vpp_apps_teams vat ON vat.id = p.vpp_apps_teams_id WHERE p.team_id = ? AND p.id IN (?);` query, args, err := sqlx.In(query, teamID, policyIDs) if err != nil { return nil, ctxerr.Wrapf(ctx, err, "build sqlx.In for get policies with associated installer") @@ -2553,7 +2583,7 @@ func (ds *Datastore) GetPoliciesWithAssociatedScript(ctx context.Context, teamID if len(policyIDs) == 0 { return nil, nil } - query := `SELECT id, script_id FROM policies WHERE team_id = ? AND script_id IS NOT NULL AND id IN (?);` + query := `SELECT id, script_id, continuous_automations_enabled FROM policies WHERE team_id = ? AND script_id IS NOT NULL AND id IN (?);` query, args, err := sqlx.In(query, teamID, policyIDs) if err != nil { return nil, ctxerr.Wrapf(ctx, err, "build sqlx.In for get policies with associated script") diff --git a/server/datastore/mysql/schema.sql b/server/datastore/mysql/schema.sql index edaead1a82..d843009cc1 100644 --- a/server/datastore/mysql/schema.sql +++ b/server/datastore/mysql/schema.sql @@ -1992,9 +1992,9 @@ CREATE TABLE `migration_status_tables` ( `is_applied` tinyint(1) NOT NULL, `tstamp` timestamp NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`) -) /*!50100 TABLESPACE `innodb_system` */ ENGINE=InnoDB AUTO_INCREMENT=531 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +) /*!50100 TABLESPACE `innodb_system` */ ENGINE=InnoDB AUTO_INCREMENT=532 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'),(179,20230408084104,1,'2020-01-01 01:01:01'),(180,20230411102858,1,'2020-01-01 01:01:01'),(181,20230421155932,1,'2020-01-01 01:01:01'),(182,20230425082126,1,'2020-01-01 01:01:01'),(183,20230425105727,1,'2020-01-01 01:01:01'),(184,20230501154913,1,'2020-01-01 01:01:01'),(185,20230503101418,1,'2020-01-01 01:01:01'),(186,20230515144206,1,'2020-01-01 01:01:01'),(187,20230517140952,1,'2020-01-01 01:01:01'),(188,20230517152807,1,'2020-01-01 01:01:01'),(189,20230518114155,1,'2020-01-01 01:01:01'),(190,20230520153236,1,'2020-01-01 01:01:01'),(191,20230525151159,1,'2020-01-01 01:01:01'),(192,20230530122103,1,'2020-01-01 01:01:01'),(193,20230602111827,1,'2020-01-01 01:01:01'),(194,20230608103123,1,'2020-01-01 01:01:01'),(195,20230629140529,1,'2020-01-01 01:01:01'),(196,20230629140530,1,'2020-01-01 01:01:01'),(197,20230711144622,1,'2020-01-01 01:01:01'),(198,20230721135421,1,'2020-01-01 01:01:01'),(199,20230721161508,1,'2020-01-01 01:01:01'),(200,20230726115701,1,'2020-01-01 01:01:01'),(201,20230807100822,1,'2020-01-01 01:01:01'),(202,20230814150442,1,'2020-01-01 01:01:01'),(203,20230823122728,1,'2020-01-01 01:01:01'),(204,20230906152143,1,'2020-01-01 01:01:01'),(205,20230911163618,1,'2020-01-01 01:01:01'),(206,20230912101759,1,'2020-01-01 01:01:01'),(207,20230915101341,1,'2020-01-01 01:01:01'),(208,20230918132351,1,'2020-01-01 01:01:01'),(209,20231004144339,1,'2020-01-01 01:01:01'),(210,20231009094541,1,'2020-01-01 01:01:01'),(211,20231009094542,1,'2020-01-01 01:01:01'),(212,20231009094543,1,'2020-01-01 01:01:01'),(213,20231009094544,1,'2020-01-01 01:01:01'),(214,20231016091915,1,'2020-01-01 01:01:01'),(215,20231024174135,1,'2020-01-01 01:01:01'),(216,20231025120016,1,'2020-01-01 01:01:01'),(217,20231025160156,1,'2020-01-01 01:01:01'),(218,20231031165350,1,'2020-01-01 01:01:01'),(219,20231106144110,1,'2020-01-01 01:01:01'),(220,20231107130934,1,'2020-01-01 01:01:01'),(221,20231109115838,1,'2020-01-01 01:01:01'),(222,20231121054530,1,'2020-01-01 01:01:01'),(223,20231122101320,1,'2020-01-01 01:01:01'),(224,20231130132828,1,'2020-01-01 01:01:01'),(225,20231130132931,1,'2020-01-01 01:01:01'),(226,20231204155427,1,'2020-01-01 01:01:01'),(227,20231206142340,1,'2020-01-01 01:01:01'),(228,20231207102320,1,'2020-01-01 01:01:01'),(229,20231207102321,1,'2020-01-01 01:01:01'),(230,20231207133731,1,'2020-01-01 01:01:01'),(231,20231212094238,1,'2020-01-01 01:01:01'),(232,20231212095734,1,'2020-01-01 01:01:01'),(233,20231212161121,1,'2020-01-01 01:01:01'),(234,20231215122713,1,'2020-01-01 01:01:01'),(235,20231219143041,1,'2020-01-01 01:01:01'),(236,20231224070653,1,'2020-01-01 01:01:01'),(237,20240110134315,1,'2020-01-01 01:01:01'),(238,20240119091637,1,'2020-01-01 01:01:01'),(239,20240126020642,1,'2020-01-01 01:01:01'),(240,20240126020643,1,'2020-01-01 01:01:01'),(241,20240129162819,1,'2020-01-01 01:01:01'),(242,20240130115133,1,'2020-01-01 01:01:01'),(243,20240131083822,1,'2020-01-01 01:01:01'),(244,20240205095928,1,'2020-01-01 01:01:01'),(245,20240205121956,1,'2020-01-01 01:01:01'),(246,20240209110212,1,'2020-01-01 01:01:01'),(247,20240212111533,1,'2020-01-01 01:01:01'),(248,20240221112844,1,'2020-01-01 01:01:01'),(249,20240222073518,1,'2020-01-01 01:01:01'),(250,20240222135115,1,'2020-01-01 01:01:01'),(251,20240226082255,1,'2020-01-01 01:01:01'),(252,20240228082706,1,'2020-01-01 01:01:01'),(253,20240301173035,1,'2020-01-01 01:01:01'),(254,20240302111134,1,'2020-01-01 01:01:01'),(255,20240312103753,1,'2020-01-01 01:01:01'),(256,20240313143416,1,'2020-01-01 01:01:01'),(257,20240314085226,1,'2020-01-01 01:01:01'),(258,20240314151747,1,'2020-01-01 01:01:01'),(259,20240320145650,1,'2020-01-01 01:01:01'),(260,20240327115530,1,'2020-01-01 01:01:01'),(261,20240327115617,1,'2020-01-01 01:01:01'),(262,20240408085837,1,'2020-01-01 01:01:01'),(263,20240415104633,1,'2020-01-01 01:01:01'),(264,20240430111727,1,'2020-01-01 01:01:01'),(265,20240515200020,1,'2020-01-01 01:01:01'),(266,20240521143023,1,'2020-01-01 01:01:01'),(267,20240521143024,1,'2020-01-01 01:01:01'),(268,20240601174138,1,'2020-01-01 01:01:01'),(269,20240607133721,1,'2020-01-01 01:01:01'),(270,20240612150059,1,'2020-01-01 01:01:01'),(271,20240613162201,1,'2020-01-01 01:01:01'),(272,20240613172616,1,'2020-01-01 01:01:01'),(273,20240618142419,1,'2020-01-01 01:01:01'),(274,20240625093543,1,'2020-01-01 01:01:01'),(275,20240626195531,1,'2020-01-01 01:01:01'),(276,20240702123921,1,'2020-01-01 01:01:01'),(277,20240703154849,1,'2020-01-01 01:01:01'),(278,20240707134035,1,'2020-01-01 01:01:01'),(279,20240707134036,1,'2020-01-01 01:01:01'),(280,20240709124958,1,'2020-01-01 01:01:01'),(281,20240709132642,1,'2020-01-01 01:01:01'),(282,20240709183940,1,'2020-01-01 01:01:01'),(283,20240710155623,1,'2020-01-01 01:01:01'),(284,20240723102712,1,'2020-01-01 01:01:01'),(285,20240725152735,1,'2020-01-01 01:01:01'),(286,20240725182118,1,'2020-01-01 01:01:01'),(287,20240726100517,1,'2020-01-01 01:01:01'),(288,20240730171504,1,'2020-01-01 01:01:01'),(289,20240730174056,1,'2020-01-01 01:01:01'),(290,20240730215453,1,'2020-01-01 01:01:01'),(291,20240730374423,1,'2020-01-01 01:01:01'),(292,20240801115359,1,'2020-01-01 01:01:01'),(293,20240802101043,1,'2020-01-01 01:01:01'),(294,20240802113716,1,'2020-01-01 01:01:01'),(295,20240814135330,1,'2020-01-01 01:01:01'),(296,20240815000000,1,'2020-01-01 01:01:01'),(297,20240815000001,1,'2020-01-01 01:01:01'),(298,20240816103247,1,'2020-01-01 01:01:01'),(299,20240820091218,1,'2020-01-01 01:01:01'),(300,20240826111228,1,'2020-01-01 01:01:01'),(301,20240826160025,1,'2020-01-01 01:01:01'),(302,20240829165448,1,'2020-01-01 01:01:01'),(303,20240829165605,1,'2020-01-01 01:01:01'),(304,20240829165715,1,'2020-01-01 01:01:01'),(305,20240829165930,1,'2020-01-01 01:01:01'),(306,20240829170023,1,'2020-01-01 01:01:01'),(307,20240829170033,1,'2020-01-01 01:01:01'),(308,20240829170044,1,'2020-01-01 01:01:01'),(309,20240905105135,1,'2020-01-01 01:01:01'),(310,20240905140514,1,'2020-01-01 01:01:01'),(311,20240905200000,1,'2020-01-01 01:01:01'),(312,20240905200001,1,'2020-01-01 01:01:01'),(313,20241002104104,1,'2020-01-01 01:01:01'),(314,20241002104105,1,'2020-01-01 01:01:01'),(315,20241002104106,1,'2020-01-01 01:01:01'),(316,20241002210000,1,'2020-01-01 01:01:01'),(317,20241003145349,1,'2020-01-01 01:01:01'),(318,20241004005000,1,'2020-01-01 01:01:01'),(319,20241008083925,1,'2020-01-01 01:01:01'),(320,20241009090010,1,'2020-01-01 01:01:01'),(321,20241017163402,1,'2020-01-01 01:01:01'),(322,20241021224359,1,'2020-01-01 01:01:01'),(323,20241022140321,1,'2020-01-01 01:01:01'),(324,20241025111236,1,'2020-01-01 01:01:01'),(325,20241025112748,1,'2020-01-01 01:01:01'),(326,20241025141855,1,'2020-01-01 01:01:01'),(327,20241110152839,1,'2020-01-01 01:01:01'),(328,20241110152840,1,'2020-01-01 01:01:01'),(329,20241110152841,1,'2020-01-01 01:01:01'),(330,20241116233322,1,'2020-01-01 01:01:01'),(331,20241122171434,1,'2020-01-01 01:01:01'),(332,20241125150614,1,'2020-01-01 01:01:01'),(333,20241203125346,1,'2020-01-01 01:01:01'),(334,20241203130032,1,'2020-01-01 01:01:01'),(335,20241205122800,1,'2020-01-01 01:01:01'),(336,20241209164540,1,'2020-01-01 01:01:01'),(337,20241210140021,1,'2020-01-01 01:01:01'),(338,20241219180042,1,'2020-01-01 01:01:01'),(339,20241220100000,1,'2020-01-01 01:01:01'),(340,20241220114903,1,'2020-01-01 01:01:01'),(341,20241220114904,1,'2020-01-01 01:01:01'),(342,20241224000000,1,'2020-01-01 01:01:01'),(343,20241230000000,1,'2020-01-01 01:01:01'),(344,20241231112624,1,'2020-01-01 01:01:01'),(345,20250102121439,1,'2020-01-01 01:01:01'),(346,20250121094045,1,'2020-01-01 01:01:01'),(347,20250121094500,1,'2020-01-01 01:01:01'),(348,20250121094600,1,'2020-01-01 01:01:01'),(349,20250121094700,1,'2020-01-01 01:01:01'),(350,20250124194347,1,'2020-01-01 01:01:01'),(351,20250127162751,1,'2020-01-01 01:01:01'),(352,20250213104005,1,'2020-01-01 01:01:01'),(353,20250214205657,1,'2020-01-01 01:01:01'),(354,20250217093329,1,'2020-01-01 01:01:01'),(355,20250219090511,1,'2020-01-01 01:01:01'),(356,20250219100000,1,'2020-01-01 01:01:01'),(357,20250219142401,1,'2020-01-01 01:01:01'),(358,20250224184002,1,'2020-01-01 01:01:01'),(359,20250225085436,1,'2020-01-01 01:01:01'),(360,20250226000000,1,'2020-01-01 01:01:01'),(361,20250226153445,1,'2020-01-01 01:01:01'),(362,20250304162702,1,'2020-01-01 01:01:01'),(363,20250306144233,1,'2020-01-01 01:01:01'),(364,20250313163430,1,'2020-01-01 01:01:01'),(365,20250317130944,1,'2020-01-01 01:01:01'),(366,20250318165922,1,'2020-01-01 01:01:01'),(367,20250320132525,1,'2020-01-01 01:01:01'),(368,20250320200000,1,'2020-01-01 01:01:01'),(369,20250326161930,1,'2020-01-01 01:01:01'),(370,20250326161931,1,'2020-01-01 01:01:01'),(371,20250331042354,1,'2020-01-01 01:01:01'),(372,20250331154206,1,'2020-01-01 01:01:01'),(373,20250401155831,1,'2020-01-01 01:01:01'),(374,20250408133233,1,'2020-01-01 01:01:01'),(375,20250410104321,1,'2020-01-01 01:01:01'),(376,20250421085116,1,'2020-01-01 01:01:01'),(377,20250422095806,1,'2020-01-01 01:01:01'),(378,20250424153059,1,'2020-01-01 01:01:01'),(379,20250430103833,1,'2020-01-01 01:01:01'),(380,20250430112622,1,'2020-01-01 01:01:01'),(381,20250501162727,1,'2020-01-01 01:01:01'),(382,20250502154517,1,'2020-01-01 01:01:01'),(383,20250502222222,1,'2020-01-01 01:01:01'),(384,20250507170845,1,'2020-01-01 01:01:01'),(385,20250513162912,1,'2020-01-01 01:01:01'),(386,20250519161614,1,'2020-01-01 01:01:01'),(387,20250519170000,1,'2020-01-01 01:01:01'),(388,20250520153848,1,'2020-01-01 01:01:01'),(389,20250528115932,1,'2020-01-01 01:01:01'),(390,20250529102706,1,'2020-01-01 01:01:01'),(391,20250603105558,1,'2020-01-01 01:01:01'),(392,20250609102714,1,'2020-01-01 01:01:01'),(393,20250609112613,1,'2020-01-01 01:01:01'),(394,20250613103810,1,'2020-01-01 01:01:01'),(395,20250616193950,1,'2020-01-01 01:01:01'),(396,20250624140757,1,'2020-01-01 01:01:01'),(397,20250626130239,1,'2020-01-01 01:01:01'),(398,20250629131032,1,'2020-01-01 01:01:01'),(399,20250701155654,1,'2020-01-01 01:01:01'),(400,20250707095725,1,'2020-01-01 01:01:01'),(401,20250716152435,1,'2020-01-01 01:01:01'),(402,20250718091828,1,'2020-01-01 01:01:01'),(403,20250728122229,1,'2020-01-01 01:01:01'),(404,20250731122715,1,'2020-01-01 01:01:01'),(405,20250731151000,1,'2020-01-01 01:01:01'),(406,20250803000000,1,'2020-01-01 01:01:01'),(407,20250805083116,1,'2020-01-01 01:01:01'),(408,20250807140441,1,'2020-01-01 01:01:01'),(409,20250808000000,1,'2020-01-01 01:01:01'),(410,20250811155036,1,'2020-01-01 01:01:01'),(411,20250813205039,1,'2020-01-01 01:01:01'),(412,20250814123333,1,'2020-01-01 01:01:01'),(413,20250815130115,1,'2020-01-01 01:01:01'),(414,20250816115553,1,'2020-01-01 01:01:01'),(415,20250817154557,1,'2020-01-01 01:01:01'),(416,20250825113751,1,'2020-01-01 01:01:01'),(417,20250827113140,1,'2020-01-01 01:01:01'),(418,20250828120836,1,'2020-01-01 01:01:01'),(419,20250902112642,1,'2020-01-01 01:01:01'),(420,20250904091745,1,'2020-01-01 01:01:01'),(421,20250905090000,1,'2020-01-01 01:01:01'),(422,20250922083056,1,'2020-01-01 01:01:01'),(423,20250923120000,1,'2020-01-01 01:01:01'),(424,20250926123048,1,'2020-01-01 01:01:01'),(425,20251015103505,1,'2020-01-01 01:01:01'),(426,20251015103600,1,'2020-01-01 01:01:01'),(427,20251015103700,1,'2020-01-01 01:01:01'),(428,20251015103800,1,'2020-01-01 01:01:01'),(429,20251015103900,1,'2020-01-01 01:01:01'),(430,20251028140000,1,'2020-01-01 01:01:01'),(431,20251028140100,1,'2020-01-01 01:01:01'),(432,20251028140110,1,'2020-01-01 01:01:01'),(433,20251028140200,1,'2020-01-01 01:01:01'),(434,20251028140300,1,'2020-01-01 01:01:01'),(435,20251028140400,1,'2020-01-01 01:01:01'),(436,20251031154558,1,'2020-01-01 01:01:01'),(437,20251103160848,1,'2020-01-01 01:01:01'),(438,20251104112849,1,'2020-01-01 01:01:01'),(439,20251106000000,1,'2020-01-01 01:01:01'),(440,20251107164629,1,'2020-01-01 01:01:01'),(441,20251107170854,1,'2020-01-01 01:01:01'),(442,20251110172137,1,'2020-01-01 01:01:01'),(443,20251111153133,1,'2020-01-01 01:01:01'),(444,20251117020000,1,'2020-01-01 01:01:01'),(445,20251117020100,1,'2020-01-01 01:01:01'),(446,20251117020200,1,'2020-01-01 01:01:01'),(447,20251121100000,1,'2020-01-01 01:01:01'),(448,20251121124239,1,'2020-01-01 01:01:01'),(449,20251124090450,1,'2020-01-01 01:01:01'),(450,20251124135808,1,'2020-01-01 01:01:01'),(451,20251124140138,1,'2020-01-01 01:01:01'),(452,20251124162948,1,'2020-01-01 01:01:01'),(453,20251127113559,1,'2020-01-01 01:01:01'),(454,20251202162232,1,'2020-01-01 01:01:01'),(455,20251203170808,1,'2020-01-01 01:01:01'),(456,20251207050413,1,'2020-01-01 01:01:01'),(457,20251208215800,1,'2020-01-01 01:01:01'),(458,20251209221730,1,'2020-01-01 01:01:01'),(459,20251209221850,1,'2020-01-01 01:01:01'),(460,20251215163721,1,'2020-01-01 01:01:01'),(461,20251217000000,1,'2020-01-01 01:01:01'),(462,20251217120000,1,'2020-01-01 01:01:01'),(463,20251229000000,1,'2020-01-01 01:01:01'),(464,20251229000010,1,'2020-01-01 01:01:01'),(465,20251229000020,1,'2020-01-01 01:01:01'),(466,20260106000000,1,'2020-01-01 01:01:01'),(467,20260108200708,1,'2020-01-01 01:01:01'),(468,20260108214732,1,'2020-01-01 01:01:01'),(469,20260109231821,1,'2020-01-01 01:01:01'),(470,20260113012054,1,'2020-01-01 01:01:01'),(471,20260124200020,1,'2020-01-01 01:01:01'),(472,20260126150840,1,'2020-01-01 01:01:01'),(473,20260126210724,1,'2020-01-01 01:01:01'),(474,20260202151756,1,'2020-01-01 01:01:01'),(475,20260205184907,1,'2020-01-01 01:01:01'),(476,20260210151544,1,'2020-01-01 01:01:01'),(477,20260210155109,1,'2020-01-01 01:01:01'),(478,20260210181120,1,'2020-01-01 01:01:01'),(479,20260211200153,1,'2020-01-01 01:01:01'),(480,20260217141240,1,'2020-01-01 01:01:01'),(481,20260217200906,1,'2020-01-01 01:01:01'),(482,20260218175704,1,'2020-01-01 01:01:01'),(483,20260314120000,1,'2020-01-01 01:01:01'),(484,20260316120000,1,'2020-01-01 01:01:01'),(485,20260316120001,1,'2020-01-01 01:01:01'),(486,20260316120002,1,'2020-01-01 01:01:01'),(487,20260316120003,1,'2020-01-01 01:01:01'),(488,20260316120004,1,'2020-01-01 01:01:01'),(489,20260316120005,1,'2020-01-01 01:01:01'),(490,20260316120006,1,'2020-01-01 01:01:01'),(491,20260316120007,1,'2020-01-01 01:01:01'),(492,20260316120008,1,'2020-01-01 01:01:01'),(493,20260316120009,1,'2020-01-01 01:01:01'),(494,20260316120010,1,'2020-01-01 01:01:01'),(495,20260317120000,1,'2020-01-01 01:01:01'),(496,20260318184559,1,'2020-01-01 01:01:01'),(497,20260319120000,1,'2020-01-01 01:01:01'),(498,20260323144117,1,'2020-01-01 01:01:01'),(499,20260324161944,1,'2020-01-01 01:01:01'),(500,20260324223334,1,'2020-01-01 01:01:01'),(501,20260326131501,1,'2020-01-01 01:01:01'),(502,20260326210603,1,'2020-01-01 01:01:01'),(503,20260331000000,1,'2020-01-01 01:01:01'),(504,20260401153000,1,'2020-01-01 01:01:01'),(505,20260401153001,1,'2020-01-01 01:01:01'),(506,20260401153503,1,'2020-01-01 01:01:01'),(507,20260403120000,1,'2020-01-01 01:01:01'),(508,20260409153713,1,'2020-01-01 01:01:01'),(509,20260409153714,1,'2020-01-01 01:01:01'),(510,20260409153715,1,'2020-01-01 01:01:01'),(511,20260409153716,1,'2020-01-01 01:01:01'),(512,20260409153717,1,'2020-01-01 01:01:01'),(513,20260409183610,1,'2020-01-01 01:01:01'),(514,20260410173222,1,'2020-01-01 01:01:01'),(515,20260422181702,1,'2020-01-01 01:01:01'),(516,20260423161823,1,'2020-01-01 01:01:01'),(517,20260423161824,1,'2020-01-01 01:01:01'),(518,20260518194422,1,'2020-01-01 01:01:01'),(519,20260522195224,1,'2020-01-01 01:01:01'),(520,20260522195225,1,'2020-01-01 01:01:01'),(521,20260522195226,1,'2020-01-01 01:01:01'),(522,20260522195227,1,'2020-01-01 01:01:01'),(523,20260522195229,1,'2020-01-01 01:01:01'),(524,20260522195230,1,'2020-01-01 01:01:01'),(525,20260522195231,1,'2020-01-01 01:01:01'),(526,20260522195232,1,'2020-01-01 01:01:01'),(527,20260522195233,1,'2020-01-01 01:01:01'),(528,20260522195234,1,'2020-01-01 01:01:01'),(529,20260522195235,1,'2020-01-01 01:01:01'),(530,20260522195236,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'),(180,20230411102858,1,'2020-01-01 01:01:01'),(181,20230421155932,1,'2020-01-01 01:01:01'),(182,20230425082126,1,'2020-01-01 01:01:01'),(183,20230425105727,1,'2020-01-01 01:01:01'),(184,20230501154913,1,'2020-01-01 01:01:01'),(185,20230503101418,1,'2020-01-01 01:01:01'),(186,20230515144206,1,'2020-01-01 01:01:01'),(187,20230517140952,1,'2020-01-01 01:01:01'),(188,20230517152807,1,'2020-01-01 01:01:01'),(189,20230518114155,1,'2020-01-01 01:01:01'),(190,20230520153236,1,'2020-01-01 01:01:01'),(191,20230525151159,1,'2020-01-01 01:01:01'),(192,20230530122103,1,'2020-01-01 01:01:01'),(193,20230602111827,1,'2020-01-01 01:01:01'),(194,20230608103123,1,'2020-01-01 01:01:01'),(195,20230629140529,1,'2020-01-01 01:01:01'),(196,20230629140530,1,'2020-01-01 01:01:01'),(197,20230711144622,1,'2020-01-01 01:01:01'),(198,20230721135421,1,'2020-01-01 01:01:01'),(199,20230721161508,1,'2020-01-01 01:01:01'),(200,20230726115701,1,'2020-01-01 01:01:01'),(201,20230807100822,1,'2020-01-01 01:01:01'),(202,20230814150442,1,'2020-01-01 01:01:01'),(203,20230823122728,1,'2020-01-01 01:01:01'),(204,20230906152143,1,'2020-01-01 01:01:01'),(205,20230911163618,1,'2020-01-01 01:01:01'),(206,20230912101759,1,'2020-01-01 01:01:01'),(207,20230915101341,1,'2020-01-01 01:01:01'),(208,20230918132351,1,'2020-01-01 01:01:01'),(209,20231004144339,1,'2020-01-01 01:01:01'),(210,20231009094541,1,'2020-01-01 01:01:01'),(211,20231009094542,1,'2020-01-01 01:01:01'),(212,20231009094543,1,'2020-01-01 01:01:01'),(213,20231009094544,1,'2020-01-01 01:01:01'),(214,20231016091915,1,'2020-01-01 01:01:01'),(215,20231024174135,1,'2020-01-01 01:01:01'),(216,20231025120016,1,'2020-01-01 01:01:01'),(217,20231025160156,1,'2020-01-01 01:01:01'),(218,20231031165350,1,'2020-01-01 01:01:01'),(219,20231106144110,1,'2020-01-01 01:01:01'),(220,20231107130934,1,'2020-01-01 01:01:01'),(221,20231109115838,1,'2020-01-01 01:01:01'),(222,20231121054530,1,'2020-01-01 01:01:01'),(223,20231122101320,1,'2020-01-01 01:01:01'),(224,20231130132828,1,'2020-01-01 01:01:01'),(225,20231130132931,1,'2020-01-01 01:01:01'),(226,20231204155427,1,'2020-01-01 01:01:01'),(227,20231206142340,1,'2020-01-01 01:01:01'),(228,20231207102320,1,'2020-01-01 01:01:01'),(229,20231207102321,1,'2020-01-01 01:01:01'),(230,20231207133731,1,'2020-01-01 01:01:01'),(231,20231212094238,1,'2020-01-01 01:01:01'),(232,20231212095734,1,'2020-01-01 01:01:01'),(233,20231212161121,1,'2020-01-01 01:01:01'),(234,20231215122713,1,'2020-01-01 01:01:01'),(235,20231219143041,1,'2020-01-01 01:01:01'),(236,20231224070653,1,'2020-01-01 01:01:01'),(237,20240110134315,1,'2020-01-01 01:01:01'),(238,20240119091637,1,'2020-01-01 01:01:01'),(239,20240126020642,1,'2020-01-01 01:01:01'),(240,20240126020643,1,'2020-01-01 01:01:01'),(241,20240129162819,1,'2020-01-01 01:01:01'),(242,20240130115133,1,'2020-01-01 01:01:01'),(243,20240131083822,1,'2020-01-01 01:01:01'),(244,20240205095928,1,'2020-01-01 01:01:01'),(245,20240205121956,1,'2020-01-01 01:01:01'),(246,20240209110212,1,'2020-01-01 01:01:01'),(247,20240212111533,1,'2020-01-01 01:01:01'),(248,20240221112844,1,'2020-01-01 01:01:01'),(249,20240222073518,1,'2020-01-01 01:01:01'),(250,20240222135115,1,'2020-01-01 01:01:01'),(251,20240226082255,1,'2020-01-01 01:01:01'),(252,20240228082706,1,'2020-01-01 01:01:01'),(253,20240301173035,1,'2020-01-01 01:01:01'),(254,20240302111134,1,'2020-01-01 01:01:01'),(255,20240312103753,1,'2020-01-01 01:01:01'),(256,20240313143416,1,'2020-01-01 01:01:01'),(257,20240314085226,1,'2020-01-01 01:01:01'),(258,20240314151747,1,'2020-01-01 01:01:01'),(259,20240320145650,1,'2020-01-01 01:01:01'),(260,20240327115530,1,'2020-01-01 01:01:01'),(261,20240327115617,1,'2020-01-01 01:01:01'),(262,20240408085837,1,'2020-01-01 01:01:01'),(263,20240415104633,1,'2020-01-01 01:01:01'),(264,20240430111727,1,'2020-01-01 01:01:01'),(265,20240515200020,1,'2020-01-01 01:01:01'),(266,20240521143023,1,'2020-01-01 01:01:01'),(267,20240521143024,1,'2020-01-01 01:01:01'),(268,20240601174138,1,'2020-01-01 01:01:01'),(269,20240607133721,1,'2020-01-01 01:01:01'),(270,20240612150059,1,'2020-01-01 01:01:01'),(271,20240613162201,1,'2020-01-01 01:01:01'),(272,20240613172616,1,'2020-01-01 01:01:01'),(273,20240618142419,1,'2020-01-01 01:01:01'),(274,20240625093543,1,'2020-01-01 01:01:01'),(275,20240626195531,1,'2020-01-01 01:01:01'),(276,20240702123921,1,'2020-01-01 01:01:01'),(277,20240703154849,1,'2020-01-01 01:01:01'),(278,20240707134035,1,'2020-01-01 01:01:01'),(279,20240707134036,1,'2020-01-01 01:01:01'),(280,20240709124958,1,'2020-01-01 01:01:01'),(281,20240709132642,1,'2020-01-01 01:01:01'),(282,20240709183940,1,'2020-01-01 01:01:01'),(283,20240710155623,1,'2020-01-01 01:01:01'),(284,20240723102712,1,'2020-01-01 01:01:01'),(285,20240725152735,1,'2020-01-01 01:01:01'),(286,20240725182118,1,'2020-01-01 01:01:01'),(287,20240726100517,1,'2020-01-01 01:01:01'),(288,20240730171504,1,'2020-01-01 01:01:01'),(289,20240730174056,1,'2020-01-01 01:01:01'),(290,20240730215453,1,'2020-01-01 01:01:01'),(291,20240730374423,1,'2020-01-01 01:01:01'),(292,20240801115359,1,'2020-01-01 01:01:01'),(293,20240802101043,1,'2020-01-01 01:01:01'),(294,20240802113716,1,'2020-01-01 01:01:01'),(295,20240814135330,1,'2020-01-01 01:01:01'),(296,20240815000000,1,'2020-01-01 01:01:01'),(297,20240815000001,1,'2020-01-01 01:01:01'),(298,20240816103247,1,'2020-01-01 01:01:01'),(299,20240820091218,1,'2020-01-01 01:01:01'),(300,20240826111228,1,'2020-01-01 01:01:01'),(301,20240826160025,1,'2020-01-01 01:01:01'),(302,20240829165448,1,'2020-01-01 01:01:01'),(303,20240829165605,1,'2020-01-01 01:01:01'),(304,20240829165715,1,'2020-01-01 01:01:01'),(305,20240829165930,1,'2020-01-01 01:01:01'),(306,20240829170023,1,'2020-01-01 01:01:01'),(307,20240829170033,1,'2020-01-01 01:01:01'),(308,20240829170044,1,'2020-01-01 01:01:01'),(309,20240905105135,1,'2020-01-01 01:01:01'),(310,20240905140514,1,'2020-01-01 01:01:01'),(311,20240905200000,1,'2020-01-01 01:01:01'),(312,20240905200001,1,'2020-01-01 01:01:01'),(313,20241002104104,1,'2020-01-01 01:01:01'),(314,20241002104105,1,'2020-01-01 01:01:01'),(315,20241002104106,1,'2020-01-01 01:01:01'),(316,20241002210000,1,'2020-01-01 01:01:01'),(317,20241003145349,1,'2020-01-01 01:01:01'),(318,20241004005000,1,'2020-01-01 01:01:01'),(319,20241008083925,1,'2020-01-01 01:01:01'),(320,20241009090010,1,'2020-01-01 01:01:01'),(321,20241017163402,1,'2020-01-01 01:01:01'),(322,20241021224359,1,'2020-01-01 01:01:01'),(323,20241022140321,1,'2020-01-01 01:01:01'),(324,20241025111236,1,'2020-01-01 01:01:01'),(325,20241025112748,1,'2020-01-01 01:01:01'),(326,20241025141855,1,'2020-01-01 01:01:01'),(327,20241110152839,1,'2020-01-01 01:01:01'),(328,20241110152840,1,'2020-01-01 01:01:01'),(329,20241110152841,1,'2020-01-01 01:01:01'),(330,20241116233322,1,'2020-01-01 01:01:01'),(331,20241122171434,1,'2020-01-01 01:01:01'),(332,20241125150614,1,'2020-01-01 01:01:01'),(333,20241203125346,1,'2020-01-01 01:01:01'),(334,20241203130032,1,'2020-01-01 01:01:01'),(335,20241205122800,1,'2020-01-01 01:01:01'),(336,20241209164540,1,'2020-01-01 01:01:01'),(337,20241210140021,1,'2020-01-01 01:01:01'),(338,20241219180042,1,'2020-01-01 01:01:01'),(339,20241220100000,1,'2020-01-01 01:01:01'),(340,20241220114903,1,'2020-01-01 01:01:01'),(341,20241220114904,1,'2020-01-01 01:01:01'),(342,20241224000000,1,'2020-01-01 01:01:01'),(343,20241230000000,1,'2020-01-01 01:01:01'),(344,20241231112624,1,'2020-01-01 01:01:01'),(345,20250102121439,1,'2020-01-01 01:01:01'),(346,20250121094045,1,'2020-01-01 01:01:01'),(347,20250121094500,1,'2020-01-01 01:01:01'),(348,20250121094600,1,'2020-01-01 01:01:01'),(349,20250121094700,1,'2020-01-01 01:01:01'),(350,20250124194347,1,'2020-01-01 01:01:01'),(351,20250127162751,1,'2020-01-01 01:01:01'),(352,20250213104005,1,'2020-01-01 01:01:01'),(353,20250214205657,1,'2020-01-01 01:01:01'),(354,20250217093329,1,'2020-01-01 01:01:01'),(355,20250219090511,1,'2020-01-01 01:01:01'),(356,20250219100000,1,'2020-01-01 01:01:01'),(357,20250219142401,1,'2020-01-01 01:01:01'),(358,20250224184002,1,'2020-01-01 01:01:01'),(359,20250225085436,1,'2020-01-01 01:01:01'),(360,20250226000000,1,'2020-01-01 01:01:01'),(361,20250226153445,1,'2020-01-01 01:01:01'),(362,20250304162702,1,'2020-01-01 01:01:01'),(363,20250306144233,1,'2020-01-01 01:01:01'),(364,20250313163430,1,'2020-01-01 01:01:01'),(365,20250317130944,1,'2020-01-01 01:01:01'),(366,20250318165922,1,'2020-01-01 01:01:01'),(367,20250320132525,1,'2020-01-01 01:01:01'),(368,20250320200000,1,'2020-01-01 01:01:01'),(369,20250326161930,1,'2020-01-01 01:01:01'),(370,20250326161931,1,'2020-01-01 01:01:01'),(371,20250331042354,1,'2020-01-01 01:01:01'),(372,20250331154206,1,'2020-01-01 01:01:01'),(373,20250401155831,1,'2020-01-01 01:01:01'),(374,20250408133233,1,'2020-01-01 01:01:01'),(375,20250410104321,1,'2020-01-01 01:01:01'),(376,20250421085116,1,'2020-01-01 01:01:01'),(377,20250422095806,1,'2020-01-01 01:01:01'),(378,20250424153059,1,'2020-01-01 01:01:01'),(379,20250430103833,1,'2020-01-01 01:01:01'),(380,20250430112622,1,'2020-01-01 01:01:01'),(381,20250501162727,1,'2020-01-01 01:01:01'),(382,20250502154517,1,'2020-01-01 01:01:01'),(383,20250502222222,1,'2020-01-01 01:01:01'),(384,20250507170845,1,'2020-01-01 01:01:01'),(385,20250513162912,1,'2020-01-01 01:01:01'),(386,20250519161614,1,'2020-01-01 01:01:01'),(387,20250519170000,1,'2020-01-01 01:01:01'),(388,20250520153848,1,'2020-01-01 01:01:01'),(389,20250528115932,1,'2020-01-01 01:01:01'),(390,20250529102706,1,'2020-01-01 01:01:01'),(391,20250603105558,1,'2020-01-01 01:01:01'),(392,20250609102714,1,'2020-01-01 01:01:01'),(393,20250609112613,1,'2020-01-01 01:01:01'),(394,20250613103810,1,'2020-01-01 01:01:01'),(395,20250616193950,1,'2020-01-01 01:01:01'),(396,20250624140757,1,'2020-01-01 01:01:01'),(397,20250626130239,1,'2020-01-01 01:01:01'),(398,20250629131032,1,'2020-01-01 01:01:01'),(399,20250701155654,1,'2020-01-01 01:01:01'),(400,20250707095725,1,'2020-01-01 01:01:01'),(401,20250716152435,1,'2020-01-01 01:01:01'),(402,20250718091828,1,'2020-01-01 01:01:01'),(403,20250728122229,1,'2020-01-01 01:01:01'),(404,20250731122715,1,'2020-01-01 01:01:01'),(405,20250731151000,1,'2020-01-01 01:01:01'),(406,20250803000000,1,'2020-01-01 01:01:01'),(407,20250805083116,1,'2020-01-01 01:01:01'),(408,20250807140441,1,'2020-01-01 01:01:01'),(409,20250808000000,1,'2020-01-01 01:01:01'),(410,20250811155036,1,'2020-01-01 01:01:01'),(411,20250813205039,1,'2020-01-01 01:01:01'),(412,20250814123333,1,'2020-01-01 01:01:01'),(413,20250815130115,1,'2020-01-01 01:01:01'),(414,20250816115553,1,'2020-01-01 01:01:01'),(415,20250817154557,1,'2020-01-01 01:01:01'),(416,20250825113751,1,'2020-01-01 01:01:01'),(417,20250827113140,1,'2020-01-01 01:01:01'),(418,20250828120836,1,'2020-01-01 01:01:01'),(419,20250902112642,1,'2020-01-01 01:01:01'),(420,20250904091745,1,'2020-01-01 01:01:01'),(421,20250905090000,1,'2020-01-01 01:01:01'),(422,20250922083056,1,'2020-01-01 01:01:01'),(423,20250923120000,1,'2020-01-01 01:01:01'),(424,20250926123048,1,'2020-01-01 01:01:01'),(425,20251015103505,1,'2020-01-01 01:01:01'),(426,20251015103600,1,'2020-01-01 01:01:01'),(427,20251015103700,1,'2020-01-01 01:01:01'),(428,20251015103800,1,'2020-01-01 01:01:01'),(429,20251015103900,1,'2020-01-01 01:01:01'),(430,20251028140000,1,'2020-01-01 01:01:01'),(431,20251028140100,1,'2020-01-01 01:01:01'),(432,20251028140110,1,'2020-01-01 01:01:01'),(433,20251028140200,1,'2020-01-01 01:01:01'),(434,20251028140300,1,'2020-01-01 01:01:01'),(435,20251028140400,1,'2020-01-01 01:01:01'),(436,20251031154558,1,'2020-01-01 01:01:01'),(437,20251103160848,1,'2020-01-01 01:01:01'),(438,20251104112849,1,'2020-01-01 01:01:01'),(439,20251106000000,1,'2020-01-01 01:01:01'),(440,20251107164629,1,'2020-01-01 01:01:01'),(441,20251107170854,1,'2020-01-01 01:01:01'),(442,20251110172137,1,'2020-01-01 01:01:01'),(443,20251111153133,1,'2020-01-01 01:01:01'),(444,20251117020000,1,'2020-01-01 01:01:01'),(445,20251117020100,1,'2020-01-01 01:01:01'),(446,20251117020200,1,'2020-01-01 01:01:01'),(447,20251121100000,1,'2020-01-01 01:01:01'),(448,20251121124239,1,'2020-01-01 01:01:01'),(449,20251124090450,1,'2020-01-01 01:01:01'),(450,20251124135808,1,'2020-01-01 01:01:01'),(451,20251124140138,1,'2020-01-01 01:01:01'),(452,20251124162948,1,'2020-01-01 01:01:01'),(453,20251127113559,1,'2020-01-01 01:01:01'),(454,20251202162232,1,'2020-01-01 01:01:01'),(455,20251203170808,1,'2020-01-01 01:01:01'),(456,20251207050413,1,'2020-01-01 01:01:01'),(457,20251208215800,1,'2020-01-01 01:01:01'),(458,20251209221730,1,'2020-01-01 01:01:01'),(459,20251209221850,1,'2020-01-01 01:01:01'),(460,20251215163721,1,'2020-01-01 01:01:01'),(461,20251217000000,1,'2020-01-01 01:01:01'),(462,20251217120000,1,'2020-01-01 01:01:01'),(463,20251229000000,1,'2020-01-01 01:01:01'),(464,20251229000010,1,'2020-01-01 01:01:01'),(465,20251229000020,1,'2020-01-01 01:01:01'),(466,20260106000000,1,'2020-01-01 01:01:01'),(467,20260108200708,1,'2020-01-01 01:01:01'),(468,20260108214732,1,'2020-01-01 01:01:01'),(469,20260109231821,1,'2020-01-01 01:01:01'),(470,20260113012054,1,'2020-01-01 01:01:01'),(471,20260124200020,1,'2020-01-01 01:01:01'),(472,20260126150840,1,'2020-01-01 01:01:01'),(473,20260126210724,1,'2020-01-01 01:01:01'),(474,20260202151756,1,'2020-01-01 01:01:01'),(475,20260205184907,1,'2020-01-01 01:01:01'),(476,20260210151544,1,'2020-01-01 01:01:01'),(477,20260210155109,1,'2020-01-01 01:01:01'),(478,20260210181120,1,'2020-01-01 01:01:01'),(479,20260211200153,1,'2020-01-01 01:01:01'),(480,20260217141240,1,'2020-01-01 01:01:01'),(481,20260217200906,1,'2020-01-01 01:01:01'),(482,20260218175704,1,'2020-01-01 01:01:01'),(483,20260314120000,1,'2020-01-01 01:01:01'),(484,20260316120000,1,'2020-01-01 01:01:01'),(485,20260316120001,1,'2020-01-01 01:01:01'),(486,20260316120002,1,'2020-01-01 01:01:01'),(487,20260316120003,1,'2020-01-01 01:01:01'),(488,20260316120004,1,'2020-01-01 01:01:01'),(489,20260316120005,1,'2020-01-01 01:01:01'),(490,20260316120006,1,'2020-01-01 01:01:01'),(491,20260316120007,1,'2020-01-01 01:01:01'),(492,20260316120008,1,'2020-01-01 01:01:01'),(493,20260316120009,1,'2020-01-01 01:01:01'),(494,20260316120010,1,'2020-01-01 01:01:01'),(495,20260317120000,1,'2020-01-01 01:01:01'),(496,20260318184559,1,'2020-01-01 01:01:01'),(497,20260319120000,1,'2020-01-01 01:01:01'),(498,20260323144117,1,'2020-01-01 01:01:01'),(499,20260324161944,1,'2020-01-01 01:01:01'),(500,20260324223334,1,'2020-01-01 01:01:01'),(501,20260326131501,1,'2020-01-01 01:01:01'),(502,20260326210603,1,'2020-01-01 01:01:01'),(503,20260331000000,1,'2020-01-01 01:01:01'),(504,20260401153000,1,'2020-01-01 01:01:01'),(505,20260401153001,1,'2020-01-01 01:01:01'),(506,20260401153503,1,'2020-01-01 01:01:01'),(507,20260403120000,1,'2020-01-01 01:01:01'),(508,20260409153713,1,'2020-01-01 01:01:01'),(509,20260409153714,1,'2020-01-01 01:01:01'),(510,20260409153715,1,'2020-01-01 01:01:01'),(511,20260409153716,1,'2020-01-01 01:01:01'),(512,20260409153717,1,'2020-01-01 01:01:01'),(513,20260409183610,1,'2020-01-01 01:01:01'),(514,20260410173222,1,'2020-01-01 01:01:01'),(515,20260422181702,1,'2020-01-01 01:01:01'),(516,20260423161823,1,'2020-01-01 01:01:01'),(517,20260423161824,1,'2020-01-01 01:01:01'),(518,20260518194422,1,'2020-01-01 01:01:01'),(519,20260522195224,1,'2020-01-01 01:01:01'),(520,20260522195225,1,'2020-01-01 01:01:01'),(521,20260522195226,1,'2020-01-01 01:01:01'),(522,20260522195227,1,'2020-01-01 01:01:01'),(523,20260522195229,1,'2020-01-01 01:01:01'),(524,20260522195230,1,'2020-01-01 01:01:01'),(525,20260522195231,1,'2020-01-01 01:01:01'),(526,20260522195232,1,'2020-01-01 01:01:01'),(527,20260522195233,1,'2020-01-01 01:01:01'),(528,20260522195234,1,'2020-01-01 01:01:01'),(529,20260522195235,1,'2020-01-01 01:01:01'),(530,20260522195236,1,'2020-01-01 01:01:01'),(531,20260522195237,1,'2020-01-01 01:01:01'); /*!40101 SET @saved_cs_client = @@character_set_client */; /*!50503 SET character_set_client = utf8mb4 */; CREATE TABLE `mobile_device_management_solutions` ( @@ -2377,6 +2377,7 @@ CREATE TABLE `policies` ( `type` enum('dynamic','patch') COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'dynamic', `patch_software_title_id` int unsigned DEFAULT NULL, `needs_full_membership_cleanup` tinyint(1) NOT NULL DEFAULT '0', + `continuous_automations_enabled` tinyint(1) NOT NULL DEFAULT '0', PRIMARY KEY (`id`), UNIQUE KEY `idx_policies_checksum` (`checksum`), UNIQUE KEY `idx_team_id_patch_software_title_id` (`team_id`,`patch_software_title_id`), diff --git a/server/fleet/api_policies.go b/server/fleet/api_policies.go index 2bc772f047..e81cf15b76 100644 --- a/server/fleet/api_policies.go +++ b/server/fleet/api_policies.go @@ -150,23 +150,24 @@ func (r AutofillPoliciesResponse) Error() error { return r.Err } ///////////////////////////////////////////////////////////////////////////////// type TeamPolicyRequest struct { - TeamID uint `url:"fleet_id"` - QueryID *uint `json:"query_id" renameto:"report_id"` - Query string `json:"query"` - Name string `json:"name"` - Description string `json:"description"` - Resolution string `json:"resolution"` - Platform string `json:"platform"` - Critical bool `json:"critical" premium:"true"` - CalendarEventsEnabled bool `json:"calendar_events_enabled"` - SoftwareTitleID *uint `json:"software_title_id"` - ScriptID *uint `json:"script_id"` - LabelsIncludeAny []string `json:"labels_include_any"` - LabelsIncludeAll []string `json:"labels_include_all" premium:"true"` - LabelsExcludeAny []string `json:"labels_exclude_any"` - ConditionalAccessEnabled bool `json:"conditional_access_enabled"` - Type *string `json:"type"` - PatchSoftwareTitleID *uint `json:"patch_software_title_id"` + TeamID uint `url:"fleet_id"` + QueryID *uint `json:"query_id" renameto:"report_id"` + Query string `json:"query"` + Name string `json:"name"` + Description string `json:"description"` + Resolution string `json:"resolution"` + Platform string `json:"platform"` + Critical bool `json:"critical" premium:"true"` + CalendarEventsEnabled bool `json:"calendar_events_enabled"` + SoftwareTitleID *uint `json:"software_title_id"` + ScriptID *uint `json:"script_id"` + LabelsIncludeAny []string `json:"labels_include_any"` + LabelsIncludeAll []string `json:"labels_include_all" premium:"true"` + LabelsExcludeAny []string `json:"labels_exclude_any"` + ConditionalAccessEnabled bool `json:"conditional_access_enabled"` + ContinuousAutomationsEnabled bool `json:"continuous_automations_enabled" premium:"true"` + Type *string `json:"type"` + PatchSoftwareTitleID *uint `json:"patch_software_title_id"` } type TeamPolicyResponse struct { diff --git a/server/fleet/datastore.go b/server/fleet/datastore.go index 076dab9265..9c6a8c5c9f 100644 --- a/server/fleet/datastore.go +++ b/server/fleet/datastore.go @@ -933,6 +933,13 @@ type Datastore interface { // GetPoliciesWithAssociatedVPP returns team policies that have an associated VPP app GetPoliciesWithAssociatedVPP(ctx context.Context, teamID uint, policyIDs []uint) ([]PolicyVPPData, error) GetPoliciesWithAssociatedScript(ctx context.Context, teamID uint, policyIDs []uint) ([]PolicyScriptData, error) + // ResetPolicyAutomationRetryAttemptsForHost marks all prior policy automation + // script/install attempts on this host as "old sequence" (attempt_number=0) + // for the given policies. Used when continuous_automations_enabled triggers + // a new automation run while the policy is still failing, so that the new + // attempt restarts the retry sequence at 1 instead of inheriting the cap + // from the previous sequence. + ResetPolicyAutomationRetryAttemptsForHost(ctx context.Context, hostID uint, policyIDs []uint) error GetCalendarPolicies(ctx context.Context, teamID uint) ([]PolicyCalendarData, error) // GetPoliciesForConditionalAccess returns the team policies that are configured for "Conditional access". GetPoliciesForConditionalAccess(ctx context.Context, teamID uint, platform string) ([]uint, error) diff --git a/server/fleet/policies.go b/server/fleet/policies.go index cff3052ac7..db09ceabd0 100644 --- a/server/fleet/policies.go +++ b/server/fleet/policies.go @@ -65,6 +65,12 @@ type PolicyPayload struct { // // Only applies to team policies with the patch type. PatchSoftwareTitleID *uint + + // ContinuousAutomationsEnabled indicates whether software/script automations + // should run on every failing policy result, not just on pass→fail transitions. + // + // Only applies to team policies. + ContinuousAutomationsEnabled bool } // NewTeamPolicyPayload holds data for team policy creation. @@ -110,6 +116,9 @@ type NewTeamPolicyPayload struct { Type *string // PatchSoftwareTitleID is the title id of the Fleet maintained app checked by a patch policy. PatchSoftwareTitleID *uint + // ContinuousAutomationsEnabled indicates whether software/script automations + // should run on every failing policy result, not just on pass→fail transitions. + ContinuousAutomationsEnabled bool } var ( @@ -282,6 +291,11 @@ type ModifyPolicyPayload struct { // // Only applies to team policies. ConditionalAccessEnabled *bool `json:"conditional_access_enabled" premium:"true"` + // ContinuousAutomationsEnabled indicates whether software/script automations + // should run on every failing policy result, not just on pass→fail transitions. + // + // Only applies to team policies. + ContinuousAutomationsEnabled *bool `json:"continuous_automations_enabled" premium:"true"` // Type is the policy type. It is 'dynamic' by default and 'patch' for patch policies. Type string `json:"-"` @@ -379,6 +393,12 @@ type PolicyData struct { // Only applies to team policies with the patch type. PatchSoftwareTitleID *uint `json:"-" db:"patch_software_title_id"` + // ContinuousAutomationsEnabled indicates whether software/script automations + // should run on every failing policy result, not just on pass→fail transitions. + // + // Only applies to team policies. + ContinuousAutomationsEnabled bool `json:"continuous_automations_enabled" db:"continuous_automations_enabled"` + UpdateCreateTimestamps } @@ -422,19 +442,22 @@ type PolicyCalendarData struct { } type PolicySoftwareInstallerData struct { - ID uint `db:"id"` - InstallerID uint `db:"software_installer_id"` + ID uint `db:"id"` + InstallerID uint `db:"software_installer_id"` + ContinuousAutomationsEnabled bool `db:"continuous_automations_enabled"` } type PolicyVPPData struct { - ID uint `db:"id"` - AdamID string `db:"adam_id"` - Platform InstallableDevicePlatform `db:"platform"` + ID uint `db:"id"` + AdamID string `db:"adam_id"` + Platform InstallableDevicePlatform `db:"platform"` + ContinuousAutomationsEnabled bool `db:"continuous_automations_enabled"` } type PolicyScriptData struct { - ID uint `db:"id"` - ScriptID uint `db:"script_id"` + ID uint `db:"id"` + ScriptID uint `db:"script_id"` + ContinuousAutomationsEnabled bool `db:"continuous_automations_enabled"` } // PolicyLite is a stripped down version of the policy. @@ -504,6 +527,11 @@ type PolicySpec struct { // // Only applies to team policies. ConditionalAccessEnabled bool `json:"conditional_access_enabled"` + // ContinuousAutomationsEnabled indicates whether software/script automations + // should run on every failing policy result, not just on pass→fail transitions. + // + // Only applies to team policies. + ContinuousAutomationsEnabled bool `json:"continuous_automations_enabled"` Type string `json:"type"` FleetMaintainedAppSlug string `json:"fleet_maintained_app_slug"` diff --git a/server/mock/datastore_mock.go b/server/mock/datastore_mock.go index 5747999518..baf3882102 100644 --- a/server/mock/datastore_mock.go +++ b/server/mock/datastore_mock.go @@ -677,6 +677,8 @@ type GetPoliciesWithAssociatedVPPFunc func(ctx context.Context, teamID uint, pol type GetPoliciesWithAssociatedScriptFunc func(ctx context.Context, teamID uint, policyIDs []uint) ([]fleet.PolicyScriptData, error) +type ResetPolicyAutomationRetryAttemptsForHostFunc func(ctx context.Context, hostID uint, policyIDs []uint) error + type GetCalendarPoliciesFunc func(ctx context.Context, teamID uint) ([]fleet.PolicyCalendarData, error) type GetPoliciesForConditionalAccessFunc func(ctx context.Context, teamID uint, platform string) ([]uint, error) @@ -2985,6 +2987,9 @@ type DataStore struct { GetPoliciesWithAssociatedScriptFunc GetPoliciesWithAssociatedScriptFunc GetPoliciesWithAssociatedScriptFuncInvoked bool + ResetPolicyAutomationRetryAttemptsForHostFunc ResetPolicyAutomationRetryAttemptsForHostFunc + ResetPolicyAutomationRetryAttemptsForHostFuncInvoked bool + GetCalendarPoliciesFunc GetCalendarPoliciesFunc GetCalendarPoliciesFuncInvoked bool @@ -7266,6 +7271,13 @@ func (s *DataStore) GetPoliciesWithAssociatedScript(ctx context.Context, teamID return s.GetPoliciesWithAssociatedScriptFunc(ctx, teamID, policyIDs) } +func (s *DataStore) ResetPolicyAutomationRetryAttemptsForHost(ctx context.Context, hostID uint, policyIDs []uint) error { + s.mu.Lock() + s.ResetPolicyAutomationRetryAttemptsForHostFuncInvoked = true + s.mu.Unlock() + return s.ResetPolicyAutomationRetryAttemptsForHostFunc(ctx, hostID, policyIDs) +} + func (s *DataStore) GetCalendarPolicies(ctx context.Context, teamID uint) ([]fleet.PolicyCalendarData, error) { s.mu.Lock() s.GetCalendarPoliciesFuncInvoked = true diff --git a/server/service/global_policies.go b/server/service/global_policies.go index 66aaeb1766..6ce37d85de 100644 --- a/server/service/global_policies.go +++ b/server/service/global_policies.go @@ -234,7 +234,10 @@ func (svc Service) removeGlobalPoliciesFromWebhookConfig(ctx context.Context, id // Modify ///////////////////////////////////////////////////////////////////////////////// -const errPolicyAllFleetsForConditionalAccess = "\"All fleets\" policy cannot have conditional_access_enabled set" +const ( + errPolicyAllFleetsForConditionalAccess = "\"All fleets\" policy cannot have conditional_access_enabled set" + errPolicyAllFleetsForContinuousAutomations = "\"All fleets\" policy cannot have continuous_automations_enabled set" +) func modifyGlobalPolicyEndpoint(ctx context.Context, request interface{}, svc fleet.Service) (fleet.Errorer, error) { req := request.(*fleet.ModifyGlobalPolicyRequest) @@ -456,6 +459,12 @@ func (svc *Service) ApplyPolicySpecs(ctx context.Context, policies []*fleet.Poli }) } + if policy.Team == "" && policy.ContinuousAutomationsEnabled { + return ctxerr.Wrap(ctx, &fleet.BadRequestError{ + Message: fmt.Sprintf("policy spec payload verification: %s", errPolicyAllFleetsForContinuousAutomations), + }) + } + if err := policy.Verify(); err != nil { return ctxerr.Wrap(ctx, &fleet.BadRequestError{ Message: fmt.Sprintf("policy spec payload verification: %s", err), @@ -467,6 +476,11 @@ func (svc *Service) ApplyPolicySpecs(ctx context.Context, policies []*fleet.Poli return fleet.ErrMissingLicense } + // ContinuousAutomationsEnabled is premium-only. + if policy.ContinuousAutomationsEnabled && !license.IsPremium(ctx) { + return fleet.ErrMissingLicense + } + // Make sure any applied labels exist. labels := slices.Concat(policy.LabelsIncludeAny, policy.LabelsIncludeAll, policy.LabelsExcludeAny) if len(labels) > 0 { diff --git a/server/service/integration_enterprise_test.go b/server/service/integration_enterprise_test.go index de0df59d4e..6e69c4054c 100644 --- a/server/service/integration_enterprise_test.go +++ b/server/service/integration_enterprise_test.go @@ -61,7 +61,6 @@ import ( microsoft_mdm "github.com/fleetdm/fleet/v4/server/mdm/microsoft" mdmtest "github.com/fleetdm/fleet/v4/server/mdm/testing_utils" "github.com/fleetdm/fleet/v4/server/policies" - "github.com/fleetdm/fleet/v4/server/ptr" "github.com/fleetdm/fleet/v4/server/pubsub" commonCalendar "github.com/fleetdm/fleet/v4/server/service/calendar" "github.com/fleetdm/fleet/v4/server/service/conditional_access_microsoft_proxy" @@ -299,7 +298,7 @@ func (s *integrationEnterpriseTestSuite) TestTeamSpecs() { require.Equal(t, fleet.Features{ EnableHostUsers: false, EnableSoftwareInventory: false, - AdditionalQueries: ptr.RawMessage(json.RawMessage(`{"foo": "bar"}`)), + AdditionalQueries: new(json.RawMessage(`{"foo": "bar"}`)), HistoricalData: fleet.HistoricalDataSettings{Uptime: true, Vulnerabilities: true}, }, team.Config.Features) require.Equal(t, fleet.TeamMDM{ @@ -1123,8 +1122,8 @@ func (s *integrationEnterpriseTestSuite) TestTeamLabels() { LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now(), - OsqueryHostID: ptr.String(t.Name() + "_global_host"), - NodeKey: ptr.String(t.Name() + "_global_host"), + OsqueryHostID: new(t.Name() + "_global_host"), + NodeKey: new(t.Name() + "_global_host"), UUID: t.Name() + "_global_host", Hostname: t.Name() + "_global_host.local", Platform: "darwin", @@ -1242,7 +1241,7 @@ func (s *integrationEnterpriseTestSuite) TestTeamSchedule() { gsParams := teamScheduleQueryRequest{ScheduledQueryPayload: fleet.ScheduledQueryPayload{ QueryID: &qr.ID, - Interval: ptr.Uint(42), + Interval: new(uint(42)), }} r := teamScheduleQueryResponse{} s.DoJSON("POST", fmt.Sprintf("/api/latest/fleet/teams/%d/schedule", team1.ID), gsParams, http.StatusOK, &r) @@ -1256,7 +1255,7 @@ func (s *integrationEnterpriseTestSuite) TestTeamSchedule() { id := ts.Scheduled[0].ID modifyResp := modifyTeamScheduleResponse{} - modifyParams := modifyTeamScheduleRequest{ScheduledQueryPayload: fleet.ScheduledQueryPayload{Interval: ptr.Uint(55)}} + modifyParams := modifyTeamScheduleRequest{ScheduledQueryPayload: fleet.ScheduledQueryPayload{Interval: new(uint(55))}} s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/teams/%d/schedule/%d", team1.ID, id), modifyParams, http.StatusOK, &modifyResp) // just to satisfy my paranoia, wanted to make sure the contents of the json would work @@ -1449,7 +1448,7 @@ func (s *integrationEnterpriseTestSuite) TestListTeamPoliciesAutomationTypeSoftw // Create a patch policy patchPolicy := fleet.TeamPolicyResponse{} s.DoJSON("POST", fmt.Sprintf("/api/latest/fleet/fleets/%d/policies", team.ID), fleet.TeamPolicyRequest{ - Type: ptr.String("patch"), + Type: new("patch"), PatchSoftwareTitleID: &dummyTitleID, }, http.StatusOK, &patchPolicy) require.NotNil(t, patchPolicy.Policy.PatchSoftware) @@ -1631,8 +1630,8 @@ func (s *integrationEnterpriseTestSuite) TestTeamQueries() { // create global query params := fleet.QueryPayload{ - Name: ptr.String("global1"), - Query: ptr.String("select * from time;"), + Name: new("global1"), + Query: new("select * from time;"), } var createQueryResp fleet.CreateQueryResponse s.DoJSON("POST", "/api/latest/fleet/queries", ¶ms, http.StatusOK, &createQueryResp) @@ -1640,9 +1639,9 @@ func (s *integrationEnterpriseTestSuite) TestTeamQueries() { // create team query params = fleet.QueryPayload{ - Name: ptr.String("team1"), - Query: ptr.String("select * from time;"), - TeamID: ptr.Uint(team1.ID), + Name: new("team1"), + Query: new("select * from time;"), + TeamID: new(team1.ID), } createQueryResp = fleet.CreateQueryResponse{} s.DoJSON("POST", "/api/latest/fleet/queries", ¶ms, http.StatusOK, &createQueryResp) @@ -1841,7 +1840,7 @@ func (s *integrationEnterpriseTestSuite) TestAvailableTeams() { user := &fleet.User{ Name: "Available Teams User", Email: "available@example.com", - GlobalRole: ptr.String("observer"), + GlobalRole: new("observer"), } err = user.SetPassword(test.GoodPassword, 10, 10) require.Nil(t, err) @@ -1852,7 +1851,7 @@ func (s *integrationEnterpriseTestSuite) TestAvailableTeams() { var getResp getUserResponse s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/users/%d", user.ID), nil, http.StatusOK, &getResp) assert.Equal(t, user.ID, getResp.User.ID) - assert.Equal(t, ptr.String("observer"), getResp.User.GlobalRole) + assert.Equal(t, new("observer"), getResp.User.GlobalRole) assert.Len(t, getResp.User.Teams, 0) // teams is empty if user has a global role assert.Len(t, getResp.AvailableTeams, 1) // available teams includes all teams if user has a global role assert.Equal(t, getResp.AvailableTeams[0].Name, "Available Team") @@ -1961,7 +1960,7 @@ func (s *integrationEnterpriseTestSuite) TestTeamEndpoints() { paddedTeamID := tmResp.Team.ID // rename with leading/trailing whitespace — name should be trimmed - s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/teams/%d", paddedTeamID), fleet.TeamPayload{Name: ptr.String(" Renamed Padded ")}, http.StatusOK, &tmResp) + s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/teams/%d", paddedTeamID), fleet.TeamPayload{Name: new(" Renamed Padded ")}, http.StatusOK, &tmResp) require.Equal(t, "Renamed Padded", tmResp.Team.Name) // case-only self-rename is allowed (the team's own id is excluded from @@ -1988,8 +1987,8 @@ func (s *integrationEnterpriseTestSuite) TestTeamEndpoints() { // create a team with invalid host expiry window team4 := &fleet.TeamPayload{ - Name: ptr.String(name + "invalid host_expiry_window"), - Description: ptr.String("Team4 description"), + Name: new(name + "invalid host_expiry_window"), + Description: new("Team4 description"), Secrets: []*fleet.EnrollSecret{{Secret: "TEAM4"}}, HostExpirySettings: &fleet.HostExpirySettings{ HostExpiryEnabled: true, @@ -2084,14 +2083,14 @@ func (s *integrationEnterpriseTestSuite) TestTeamEndpoints() { s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/teams/%d", tm1ID), modifyExpiry, http.StatusUnprocessableEntity, &tmResp) // try to rename to reserved names - r = s.Do("PATCH", fmt.Sprintf("/api/latest/fleet/teams/%d", tm1ID), fleet.TeamPayload{Name: ptr.String("no TEAM")}, http.StatusUnprocessableEntity) + r = s.Do("PATCH", fmt.Sprintf("/api/latest/fleet/teams/%d", tm1ID), fleet.TeamPayload{Name: new("no TEAM")}, http.StatusUnprocessableEntity) require.Contains(t, extractServerErrorText(r.Body), `is a reserved fleet name`) - r = s.Do("PATCH", fmt.Sprintf("/api/latest/fleet/teams/%d", tm1ID), fleet.TeamPayload{Name: ptr.String("ALL teAMs")}, http.StatusUnprocessableEntity) + r = s.Do("PATCH", fmt.Sprintf("/api/latest/fleet/teams/%d", tm1ID), fleet.TeamPayload{Name: new("ALL teAMs")}, http.StatusUnprocessableEntity) require.Contains(t, extractServerErrorText(r.Body), `is a reserved fleet name`) // try to rename to a whitespace-only name - r = s.Do("PATCH", fmt.Sprintf("/api/latest/fleet/teams/%d", tm1ID), fleet.TeamPayload{Name: ptr.String(" ")}, http.StatusUnprocessableEntity) + r = s.Do("PATCH", fmt.Sprintf("/api/latest/fleet/teams/%d", tm1ID), fleet.TeamPayload{Name: new(" ")}, http.StatusUnprocessableEntity) require.Contains(t, extractServerErrorText(r.Body), `may not be empty`) // Modify team's calendar config @@ -2122,7 +2121,7 @@ func (s *integrationEnterpriseTestSuite) TestTeamEndpoints() { user := &fleet.User{ Name: "Team User", Email: "user@example.com", - GlobalRole: ptr.String("observer"), + GlobalRole: new("observer"), } require.NoError(t, user.SetPassword(test.GoodPassword, 10, 10)) user, err := s.ds.NewUser(context.Background(), user) @@ -2306,12 +2305,12 @@ func (s *integrationEnterpriseTestSuite) TestTeamSecretsAreObfuscated() { global_obs := &fleet.User{ Name: "Global Obs", Email: "global_obs@example.com", - GlobalRole: ptr.String(fleet.RoleObserver), + GlobalRole: new(fleet.RoleObserver), } global_obs_plus := &fleet.User{ Name: "Global Obs+", Email: "global_obs_plus@example.com", - GlobalRole: ptr.String(fleet.RoleObserverPlus), + GlobalRole: new(fleet.RoleObserverPlus), } team_obs := &fleet.User{ Name: "Team Obs", @@ -2568,7 +2567,7 @@ func (s *integrationEnterpriseTestSuite) TestExternalIntegrationsTeamConfig() { // update the team with an unrelated field, should not change integrations tmResp = teamResponse{} s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/teams/%d", team.ID), fleet.TeamPayload{ - Description: ptr.String("team-desc"), + Description: new("team-desc"), }, http.StatusOK, &tmResp) require.Len(t, tmResp.Team.Config.Integrations.Jira, 1) require.Equal(t, "team-desc", tmResp.Team.Description) @@ -2781,7 +2780,7 @@ func (s *integrationEnterpriseTestSuite) TestExternalIntegrationsTeamConfig() { // update the team with an unrelated field, should not change integrations tmResp = teamResponse{} s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/teams/%d", team.ID), fleet.TeamPayload{ - Description: ptr.String("team-desc-2"), + Description: new("team-desc-2"), }, http.StatusOK, &tmResp) require.Len(t, tmResp.Team.Config.Integrations.Zendesk, 2) require.Equal(t, "team-desc-2", tmResp.Team.Description) @@ -3123,7 +3122,7 @@ func (s *integrationEnterpriseTestSuite) TestNoTeamFailingPolicyWebhookTrigger() LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now(), - NodeKey: ptr.String("no-team-host-key"), + NodeKey: new("no-team-host-key"), UUID: "no-team-host-uuid", Hostname: "no-team-host", PrimaryIP: "192.168.1.100", @@ -3179,9 +3178,9 @@ func (s *integrationEnterpriseTestSuite) TestNoTeamFailingPolicyWebhookTrigger() // Record policy results - all fail err = s.ds.RecordPolicyQueryExecutions(ctx, host, map[uint]*bool{ - noTeamPol1.ID: ptr.Bool(false), // Fails and is in webhook config - noTeamPol2.ID: ptr.Bool(false), // Fails and is in webhook config - noTeamPol3.ID: ptr.Bool(false), // Fails but NOT in webhook config + noTeamPol1.ID: new(false), // Fails and is in webhook config + noTeamPol2.ID: new(false), // Fails and is in webhook config + noTeamPol3.ID: new(false), // Fails but NOT in webhook config }, time.Now(), false, nil) require.NoError(t, err) @@ -3599,7 +3598,7 @@ func (s *integrationEnterpriseTestSuite) listRecentExceptionActivities(activityT func (s *integrationEnterpriseTestSuite) assertAppleOSUpdatesDeclaration(teamID *uint, profileName string, expected *fleet.AppleOSUpdateSettings) { t := s.T() if teamID == nil { - teamID = ptr.Uint(0) + teamID = new(uint(0)) } var declUUID string @@ -4043,8 +4042,8 @@ func (s *integrationEnterpriseTestSuite) TestLinuxDiskEncryption() { LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now(), - NodeKey: ptr.String(strings.ReplaceAll(t.Name(), "/", "_") + "3"), - OsqueryHostID: ptr.String(strings.ReplaceAll(t.Name(), "/", "_") + "3"), + NodeKey: new(strings.ReplaceAll(t.Name(), "/", "_") + "3"), + OsqueryHostID: new(strings.ReplaceAll(t.Name(), "/", "_") + "3"), UUID: t.Name() + "3", Hostname: t.Name() + "foo3.local", PrimaryIP: "192.168.1.3", @@ -4058,14 +4057,14 @@ func (s *integrationEnterpriseTestSuite) TestLinuxDiskEncryption() { team, err := s.ds.NewTeam(context.Background(), &fleet.Team{Name: "A team"}) require.NoError(t, err) - teamID := ptr.Uint(team.ID) + teamID := new(team.ID) teamHost, err := s.ds.NewHost(context.Background(), &fleet.Host{ DetailUpdatedAt: time.Now(), LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now(), - NodeKey: ptr.String(strings.ReplaceAll(t.Name(), "/", "_") + "2"), - OsqueryHostID: ptr.String(strings.ReplaceAll(t.Name(), "/", "_") + "2"), + NodeKey: new(strings.ReplaceAll(t.Name(), "/", "_") + "2"), + OsqueryHostID: new(strings.ReplaceAll(t.Name(), "/", "_") + "2"), UUID: t.Name() + "2", Hostname: t.Name() + "foo2.local", PrimaryIP: "192.168.1.2", @@ -4162,7 +4161,7 @@ func (s *integrationEnterpriseTestSuite) TestLinuxDiskEncryption() { }, http.StatusNoContent) // upload LUKS data - keySlot := ptr.Uint(1) + keySlot := new(uint(1)) s.Do("POST", "/api/fleet/orbit/luks_data", fleet.OrbitPostLUKSRequest{ OrbitNodeKey: *noTeamHost.OrbitNodeKey, Passphrase: "whale makes pail rise", @@ -4203,7 +4202,7 @@ func (s *integrationEnterpriseTestSuite) TestLinuxDiskEncryption() { require.Equal(t, fleet.MDMDiskEncryptionSummary{ActionRequired: fleet.MDMPlatformsCounts{Linux: 1}}, *summary.MDMDiskEncryptionSummary) // upload LUKS data (no error, and no trigger, first this time) - keySlot = ptr.Uint(3) + keySlot = new(uint(3)) s.Do("POST", "/api/fleet/orbit/luks_data", fleet.OrbitPostLUKSRequest{ // #nosec G101 - test data OrbitNodeKey: *teamHost.OrbitNodeKey, Passphrase: "the mome raths outgrabe", @@ -5074,11 +5073,11 @@ func (s *integrationEnterpriseTestSuite) TestInvitedUserMFA() { // create valid invite createInviteReq := createInviteRequest{InvitePayload: fleet.InvitePayload{ - Email: ptr.String("some@email.com"), - Name: ptr.String("some name"), + Email: new("some@email.com"), + Name: new("some name"), GlobalRole: null.StringFrom(fleet.RoleAdmin), - MFAEnabled: ptr.Bool(true), - SSOEnabled: ptr.Bool(true), + MFAEnabled: new(true), + SSOEnabled: new(true), }} createInviteResp := createInviteResponse{} s.DoJSON("POST", "/api/latest/fleet/invites", createInviteReq, http.StatusConflict, &createInviteResp) @@ -5100,25 +5099,25 @@ func (s *integrationEnterpriseTestSuite) TestInvitedUserMFA() { var createFromInviteResp createUserResponse s.DoJSON("POST", "/api/latest/fleet/users", fleet.UserPayload{ - Name: ptr.String("Full Name"), - Password: ptr.String(test.GoodPassword), - Email: ptr.String(inv.Email), - InviteToken: ptr.String(inv.Token), + Name: new("Full Name"), + Password: new(test.GoodPassword), + Email: new(inv.Email), + InviteToken: new(inv.Token), }, http.StatusOK, &createFromInviteResp) require.True(t, createFromInviteResp.User.MFAEnabled) // create an invite with SSO, swap to MFA createInviteReq = createInviteRequest{InvitePayload: fleet.InvitePayload{ - Email: ptr.String("a@b.d"), - Name: ptr.String("some other name"), + Email: new("a@b.d"), + Name: new("some other name"), GlobalRole: null.StringFrom(fleet.RoleAdmin), - SSOEnabled: ptr.Bool(true), + SSOEnabled: new(true), }} s.DoJSON("POST", "/api/latest/fleet/invites", createInviteReq, http.StatusOK, &createInviteResp) validInvite = *createInviteResp.Invite var updateInviteResp updateInviteResponse s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/invites/%d", validInvite.ID), updateInviteRequest{ - InvitePayload: fleet.InvitePayload{MFAEnabled: ptr.Bool(true), SSOEnabled: ptr.Bool(false)}, + InvitePayload: fleet.InvitePayload{MFAEnabled: new(true), SSOEnabled: new(false)}, }, http.StatusOK, &updateInviteResp) require.True(t, updateInviteResp.Invite.MFAEnabled) } @@ -5191,7 +5190,7 @@ func (s *integrationEnterpriseTestSuite) TestSSOJITProvisioning() { // Test that roles are not updated for an existing user when SSO attributes are not set. // Change role to global admin first. - user.GlobalRole = ptr.String("admin") + user.GlobalRole = new("admin") err = s.ds.SaveUser(context.Background(), user) require.NoError(t, err) // Login should NOT change the role to the default (global observer) because SSO attributes @@ -5221,7 +5220,7 @@ func (s *integrationEnterpriseTestSuite) TestSSOJITProvisioning() { user3, err = s.ds.UserByEmail(context.Background(), "sso_user_3_global_admin@example.com") require.NoError(t, err) require.Equal(t, "sso_user_3_global_admin@example.com", user3.Email) - user3.GlobalRole = ptr.String("maintainer") + user3.GlobalRole = new("maintainer") err = s.ds.SaveUser(context.Background(), user3) require.NoError(t, err) @@ -5343,8 +5342,8 @@ func (s *integrationEnterpriseTestSuite) TestDistributedReadWithFeatures() { LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now().Add(-1 * time.Minute), - OsqueryHostID: ptr.String(t.Name()), - NodeKey: ptr.String(t.Name()), + OsqueryHostID: new(t.Name()), + NodeKey: new(t.Name()), UUID: uuid.New().String(), Hostname: fmt.Sprintf("%sfoo.local", t.Name()), Platform: "darwin", @@ -5388,8 +5387,8 @@ func (s *integrationEnterpriseTestSuite) TestListHosts() { LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now().Add(-1 * time.Minute), - OsqueryHostID: ptr.String(t.Name()), - NodeKey: ptr.String(t.Name()), + OsqueryHostID: new(t.Name()), + NodeKey: new(t.Name()), UUID: uuid.New().String(), Hostname: fmt.Sprintf("%sfoo.local", t.Name()), Platform: "darwin", @@ -5400,8 +5399,8 @@ func (s *integrationEnterpriseTestSuite) TestListHosts() { LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now().Add(-1 * time.Minute), - OsqueryHostID: ptr.String(t.Name() + "2"), - NodeKey: ptr.String(t.Name() + "2"), + OsqueryHostID: new(t.Name() + "2"), + NodeKey: new(t.Name() + "2"), UUID: uuid.New().String(), Hostname: fmt.Sprintf("%sbar.local", t.Name()), Platform: "linux", @@ -5412,8 +5411,8 @@ func (s *integrationEnterpriseTestSuite) TestListHosts() { LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now().Add(-1 * time.Minute), - OsqueryHostID: ptr.String(t.Name() + "3"), - NodeKey: ptr.String(t.Name() + "3"), + OsqueryHostID: new(t.Name() + "3"), + NodeKey: new(t.Name() + "3"), UUID: uuid.New().String(), Hostname: fmt.Sprintf("%sbaz.local", t.Name()), Platform: "windows", @@ -5423,7 +5422,7 @@ func (s *integrationEnterpriseTestSuite) TestListHosts() { // set disk space information for some hosts (none provided for host3) require.NoError(t, s.ds.SetOrUpdateHostDisksSpace(context.Background(), host1.ID, 10.0, 2.0, 500.0, nil)) - require.NoError(t, s.ds.SetOrUpdateHostDisksSpace(context.Background(), host2.ID, 32.0, 4.0, 1000.0, ptr.Float64(1200.0))) + require.NoError(t, s.ds.SetOrUpdateHostDisksSpace(context.Background(), host2.ID, 32.0, 4.0, 1000.0, new(float64(1200.0)))) var resp listHostsResponse s.DoJSON("GET", "/api/latest/fleet/hosts", nil, http.StatusOK, &resp) @@ -5433,7 +5432,7 @@ func (s *integrationEnterpriseTestSuite) TestListHosts() { require.NoError(t, err) for _, h := range resp.Hosts { err = s.ds.RecordLabelQueryExecutions( - context.Background(), h.Host, map[uint]*bool{allHostsLabel.ID: ptr.Bool(true)}, time.Now(), false, + context.Background(), h.Host, map[uint]*bool{allHostsLabel.ID: new(true)}, time.Now(), false, ) require.NoError(t, err) } @@ -5540,9 +5539,9 @@ func (s *integrationEnterpriseTestSuite) TestListHosts() { vulnMeta := []fleet.CVEMeta{{ CVE: "cve-123-123-123", - CVSSScore: ptr.Float64(9.8), - EPSSProbability: ptr.Float64(0.5), - CISAKnownExploit: ptr.Bool(true), + CVSSScore: new(float64(9.8)), + EPSSProbability: new(float64(0.5)), + CISAKnownExploit: new(true), Published: &now, Description: "a long description of the cve", }} @@ -5649,8 +5648,8 @@ func (s *integrationEnterpriseTestSuite) TestListHostsSoftwareVersionOnDifferent LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now(), - OsqueryHostID: ptr.String(t.Name() + "h1"), - NodeKey: ptr.String(t.Name() + "h1"), + OsqueryHostID: new(t.Name() + "h1"), + NodeKey: new(t.Name() + "h1"), UUID: uuid.New().String(), Hostname: t.Name() + "h1.local", Platform: "darwin", @@ -5663,8 +5662,8 @@ func (s *integrationEnterpriseTestSuite) TestListHostsSoftwareVersionOnDifferent LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now(), - OsqueryHostID: ptr.String(t.Name() + "h2"), - NodeKey: ptr.String(t.Name() + "h2"), + OsqueryHostID: new(t.Name() + "h2"), + NodeKey: new(t.Name() + "h2"), UUID: uuid.New().String(), Hostname: t.Name() + "h2.local", Platform: "darwin", @@ -5735,11 +5734,11 @@ func (s *integrationEnterpriseTestSuite) TestHostHealth() { host, err := s.ds.NewHost(context.Background(), &fleet.Host{ DetailUpdatedAt: time.Now(), - OsqueryHostID: ptr.String(t.Name() + "hostid1"), + OsqueryHostID: new(t.Name() + "hostid1"), LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now(), - NodeKey: ptr.String(t.Name() + "nodekey1"), + NodeKey: new(t.Name() + "nodekey1"), UUID: t.Name() + "uuid1", Hostname: t.Name() + "foo.local", PrimaryIP: "192.168.1.1", @@ -5747,7 +5746,7 @@ func (s *integrationEnterpriseTestSuite) TestHostHealth() { OSVersion: "Mac OS X 10.14.6", Platform: "darwin", CPUType: "cpuType", - TeamID: ptr.Uint(team.ID), + TeamID: new(team.ID), }) require.NoError(t, err) require.NotNil(t, host) @@ -5793,18 +5792,18 @@ func (s *integrationEnterpriseTestSuite) TestHostHealth() { assert.NotNil(t, hh.HostHealth) assert.Equal(t, host.OSVersion, hh.HostHealth.OsVersion) assert.Equal(t, 2, hh.HostHealth.FailingPoliciesCount) - assert.Equal(t, ptr.Int(1), hh.HostHealth.FailingCriticalPoliciesCount) + assert.Equal(t, new(int(1)), hh.HostHealth.FailingCriticalPoliciesCount) assert.Contains(t, hh.HostHealth.FailingPolicies, &fleet.HostHealthFailingPolicy{ ID: failingTeamPolicy.ID, Name: failingTeamPolicy.Name, Resolution: failingTeamPolicy.Resolution, - Critical: ptr.Bool(true), + Critical: new(true), }) assert.Contains(t, hh.HostHealth.FailingPolicies, &fleet.HostHealthFailingPolicy{ ID: failingGlobalPolicy.ID, Name: failingGlobalPolicy.Name, Resolution: failingGlobalPolicy.Resolution, - Critical: ptr.Bool(false), + Critical: new(false), }) } @@ -5827,8 +5826,8 @@ func (s *integrationEnterpriseTestSuite) TestListVulnerabilities() { LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now(), - NodeKey: ptr.String(strings.ReplaceAll(t.Name(), "/", "_") + "2"), - OsqueryHostID: ptr.String(strings.ReplaceAll(t.Name(), "/", "_") + "2"), + NodeKey: new(strings.ReplaceAll(t.Name(), "/", "_") + "2"), + OsqueryHostID: new(strings.ReplaceAll(t.Name(), "/", "_") + "2"), UUID: t.Name() + "2", Hostname: t.Name() + "foo2.local", PrimaryIP: "192.168.1.2", @@ -5858,7 +5857,7 @@ func (s *integrationEnterpriseTestSuite) TestListVulnerabilities() { _, err = s.ds.InsertOSVulnerability(context.Background(), fleet.OSVulnerability{ OSID: os.ID, CVE: "CVE-2021-1234", - ResolvedInVersion: ptr.String("10.0.19043.2013"), + ResolvedInVersion: new("10.0.19043.2013"), }, fleet.MSRCSource) require.NoError(t, err) @@ -5879,18 +5878,18 @@ func (s *integrationEnterpriseTestSuite) TestListVulnerabilities() { err = s.ds.InsertCVEMeta(context.Background(), []fleet.CVEMeta{ { CVE: "CVE-2021-1234", - CVSSScore: ptr.Float64(7.5), - EPSSProbability: ptr.Float64(0.5), - CISAKnownExploit: ptr.Bool(true), - Published: ptr.Time(mockTime), + CVSSScore: new(float64(7.5)), + EPSSProbability: new(float64(0.5)), + CISAKnownExploit: new(true), + Published: new(mockTime), Description: "Test CVE 2021-1234", }, { CVE: "CVE-2021-1235", - CVSSScore: ptr.Float64(5.4), - EPSSProbability: ptr.Float64(0.6), - CISAKnownExploit: ptr.Bool(false), - Published: ptr.Time(mockTime), + CVSSScore: new(float64(5.4)), + EPSSProbability: new(float64(0.6)), + CISAKnownExploit: new(false), + Published: new(mockTime), Description: "Test CVE 2021-1235", }, }) @@ -5917,11 +5916,11 @@ func (s *integrationEnterpriseTestSuite) TestListVulnerabilities() { DetailsLink: "https://nvd.nist.gov/vuln/detail/CVE-2021-1234", CVE: fleet.CVE{ CVE: "CVE-2021-1234", - CVSSScore: ptr.Float64Ptr(7.5), - EPSSProbability: ptr.Float64Ptr(0.5), - CISAKnownExploit: ptr.BoolPtr(true), - CVEPublished: ptr.TimePtr(mockTime), - Description: ptr.StringPtr("Test CVE 2021-1234"), + CVSSScore: new(new(7.5)), + EPSSProbability: new(new(0.5)), + CISAKnownExploit: new(new(true)), + CVEPublished: new(new(mockTime)), + Description: new(new("Test CVE 2021-1234")), }, }, "CVE-2021-1235": { @@ -5929,11 +5928,11 @@ func (s *integrationEnterpriseTestSuite) TestListVulnerabilities() { DetailsLink: "https://nvd.nist.gov/vuln/detail/CVE-2021-1235", CVE: fleet.CVE{ CVE: "CVE-2021-1235", - CVSSScore: ptr.Float64Ptr(5.4), - EPSSProbability: ptr.Float64Ptr(0.6), - CISAKnownExploit: ptr.BoolPtr(false), - CVEPublished: ptr.TimePtr(mockTime), - Description: ptr.StringPtr("Test CVE 2021-1235"), + CVSSScore: new(new(5.4)), + EPSSProbability: new(new(0.6)), + CISAKnownExploit: new(new(false)), + CVEPublished: new(new(mockTime)), + Description: new(new("Test CVE 2021-1235")), }, }, } @@ -5984,11 +5983,11 @@ func (s *integrationEnterpriseTestSuite) TestListVulnerabilities() { require.Equal(t, "CVE-2021-1234", gResp.Vulnerability.CVE.CVE) require.Equal(t, uint(1), gResp.Vulnerability.HostsCount) require.Equal(t, "https://nvd.nist.gov/vuln/detail/CVE-2021-1234", gResp.Vulnerability.DetailsLink) - require.Equal(t, ptr.StringPtr("Test CVE 2021-1234"), gResp.Vulnerability.Description) - require.Equal(t, ptr.Float64Ptr(7.5), gResp.Vulnerability.CVSSScore) - require.Equal(t, ptr.BoolPtr(true), gResp.Vulnerability.CISAKnownExploit) - require.Equal(t, ptr.Float64Ptr(0.5), gResp.Vulnerability.EPSSProbability) - require.Equal(t, ptr.TimePtr(mockTime), gResp.Vulnerability.CVEPublished) + require.Equal(t, new(new("Test CVE 2021-1234")), gResp.Vulnerability.Description) + require.Equal(t, new(new(7.5)), gResp.Vulnerability.CVSSScore) + require.Equal(t, new(new(true)), gResp.Vulnerability.CISAKnownExploit) + require.Equal(t, new(new(0.5)), gResp.Vulnerability.EPSSProbability) + require.Equal(t, new(new(mockTime)), gResp.Vulnerability.CVEPublished) require.Len(t, gResp.OSVersions, 1) require.Equal(t, "Windows 11 Enterprise 22H2 10.0.19042.1234", gResp.OSVersions[0].Name) require.Equal(t, "Windows 11 Enterprise 22H2", gResp.OSVersions[0].NameOnly) @@ -6046,10 +6045,10 @@ func (s *integrationEnterpriseTestSuite) TestOSVersions() { vulnMeta := []fleet.CVEMeta{ { CVE: "CVE-2021-1234", - CVSSScore: ptr.Float64(5.4), - EPSSProbability: ptr.Float64(0.5), - CISAKnownExploit: ptr.Bool(true), - Published: ptr.Time(time.Date(2021, 1, 1, 0, 0, 0, 0, time.UTC)), + CVSSScore: new(float64(5.4)), + EPSSProbability: new(float64(0.5)), + CISAKnownExploit: new(true), + Published: new(time.Date(2021, 1, 1, 0, 0, 0, 0, time.UTC)), Description: "a long description of the cve", }, } @@ -6088,7 +6087,7 @@ func (s *integrationEnterpriseTestSuite) TestOSVersions() { s.DoJSON( "POST", "/api/latest/fleet/teams", createTeamRequest{ TeamPayload: fleet.TeamPayload{ - Name: ptr.String("os_versions_team"), + Name: new("os_versions_team"), }, }, http.StatusOK, &tr, ) @@ -6226,7 +6225,7 @@ func (s *integrationEnterpriseTestSuite) TestMDMNotConfiguredEndpoints() { case route.method == "PATCH" && (route.path == "/api/latest/fleet/setup_experience" || route.path == "/api/latest/fleet/mdm/apple/setup"): // These routes don't require MDM if you're only changing end-user auth, so we'll set something else to check. - params = fleet.MDMAppleSetupPayload{EnableReleaseDeviceManually: ptr.Bool(true)} + params = fleet.MDMAppleSetupPayload{EnableReleaseDeviceManually: new(true)} } var res *http.Response @@ -6251,7 +6250,7 @@ func (s *integrationEnterpriseTestSuite) TestMDMNotConfiguredEndpoints() { s.Do("POST", "/api/latest/fleet/mdm/apple/dep/key_pair", nil, http.StatusOK) // setting enable release device manually requires MDM - res := s.Do("PATCH", "/api/v1/fleet/setup_experience", fleet.MDMAppleSetupPayload{EnableReleaseDeviceManually: ptr.Bool(true)}, http.StatusBadRequest) + res := s.Do("PATCH", "/api/v1/fleet/setup_experience", fleet.MDMAppleSetupPayload{EnableReleaseDeviceManually: new(true)}, http.StatusBadRequest) errMsg := extractServerErrorText(res.Body) require.Contains(t, errMsg, fleet.ErrMDMNotConfigured.Error()) @@ -6262,7 +6261,7 @@ func (s *integrationEnterpriseTestSuite) TestMDMNotConfiguredEndpoints() { require.Contains(t, errMsg, `Couldn't update setup_experience because MDM features aren't turned on in Fleet.`) // setting end-user auth does NOT require MDM - s.Do("PATCH", "/api/v1/fleet/setup_experience", fleet.MDMAppleSetupPayload{EnableEndUserAuthentication: ptr.Bool(false)}, http.StatusNoContent) + s.Do("PATCH", "/api/v1/fleet/setup_experience", fleet.MDMAppleSetupPayload{EnableEndUserAuthentication: new(false)}, http.StatusNoContent) } func (s *integrationEnterpriseTestSuite) TestGlobalPolicyCreateReadPatch() { @@ -6310,12 +6309,12 @@ func (s *integrationEnterpriseTestSuite) TestGlobalPolicyCreateReadPatch() { patchPol1Req := &fleet.ModifyGlobalPolicyRequest{ ModifyPolicyPayload: fleet.ModifyPolicyPayload{ - Name: ptr.String("newName1"), - Query: ptr.String("newQuery"), - Description: ptr.String("newDescription"), - Resolution: ptr.String("newResolution"), - Platform: ptr.String("windows"), - Critical: ptr.Bool(false), + Name: new("newName1"), + Query: new("newQuery"), + Description: new("newDescription"), + Resolution: new("newResolution"), + Platform: new("windows"), + Critical: new(false), }, } patchPol1 := &fleet.ModifyGlobalPolicyResponse{} @@ -6324,12 +6323,12 @@ func (s *integrationEnterpriseTestSuite) TestGlobalPolicyCreateReadPatch() { patchPol2Req := &fleet.ModifyGlobalPolicyRequest{ ModifyPolicyPayload: fleet.ModifyPolicyPayload{ - Name: ptr.String("newName2"), - Query: ptr.String("newQuery"), - Description: ptr.String("newDescription"), - Resolution: ptr.String("newResolution"), - Platform: ptr.String("windows"), - Critical: ptr.Bool(true), + Name: new("newName2"), + Query: new("newQuery"), + Description: new("newDescription"), + Resolution: new("newResolution"), + Platform: new("windows"), + Critical: new(true), }, } patchPol2 := &fleet.ModifyGlobalPolicyResponse{} @@ -6398,13 +6397,13 @@ func (s *integrationEnterpriseTestSuite) TestTeamPolicyCreateReadPatch() { patchPol1Req := &fleet.ModifyTeamPolicyRequest{ ModifyPolicyPayload: fleet.ModifyPolicyPayload{ - Name: ptr.String("newName1"), - Query: ptr.String("newQuery"), - Description: ptr.String("newDescription"), - Resolution: ptr.String("newResolution"), - Platform: ptr.String("windows"), - Critical: ptr.Bool(false), - CalendarEventsEnabled: ptr.Bool(false), + Name: new("newName1"), + Query: new("newQuery"), + Description: new("newDescription"), + Resolution: new("newResolution"), + Platform: new("windows"), + Critical: new(false), + CalendarEventsEnabled: new(false), }, } patchPol1 := &fleet.ModifyTeamPolicyResponse{} @@ -6413,13 +6412,13 @@ func (s *integrationEnterpriseTestSuite) TestTeamPolicyCreateReadPatch() { patchPol2Req := &fleet.ModifyTeamPolicyRequest{ ModifyPolicyPayload: fleet.ModifyPolicyPayload{ - Name: ptr.String("newName2"), - Query: ptr.String("newQuery"), - Description: ptr.String("newDescription"), - Resolution: ptr.String("newResolution"), - Platform: ptr.String("windows"), - Critical: ptr.Bool(true), - CalendarEventsEnabled: ptr.Bool(true), + Name: new("newName2"), + Query: new("newQuery"), + Description: new("newDescription"), + Resolution: new("newResolution"), + Platform: new("windows"), + Critical: new(true), + CalendarEventsEnabled: new(true), }, } patchPol2 := &fleet.ModifyTeamPolicyResponse{} @@ -6499,9 +6498,9 @@ func (s *integrationEnterpriseTestSuite) TestResetAutomation() { require.NoError(s.T(), err) err = s.ds.RecordPolicyQueryExecutions(ctx, h1, map[uint]*bool{ - createPol1.Policy.ID: ptr.Bool(false), - createPol2.Policy.ID: ptr.Bool(false), - createPol3.Policy.ID: ptr.Bool(false), // This policy is not activated for automation in config. + createPol1.Policy.ID: new(false), + createPol2.Policy.ID: new(false), + createPol3.Policy.ID: new(false), // This policy is not activated for automation in config. }, time.Now(), false, nil) require.NoError(s.T(), err) @@ -6572,8 +6571,8 @@ func createHostAndDeviceToken(t *testing.T, ds *mysql.Datastore, token string) * LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now().Add(-1 * time.Minute), - OsqueryHostID: ptr.String(t.Name()), - NodeKey: ptr.String(t.Name()), + OsqueryHostID: new(t.Name()), + NodeKey: new(t.Name()), UUID: uuid.New().String(), Hostname: fmt.Sprintf("%sfoo.local", t.Name()), HardwareSerial: uuid.New().String(), @@ -6610,7 +6609,7 @@ func (s *integrationEnterpriseTestSuite) TestListSoftware() { LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now(), - NodeKey: ptr.String(t.Name() + "1"), + NodeKey: new(t.Name() + "1"), UUID: t.Name() + "1", Hostname: t.Name() + "foo.local", PrimaryIP: "192.168.1.1", @@ -6635,7 +6634,7 @@ func (s *integrationEnterpriseTestSuite) TestListSoftware() { ctx, fleet.SoftwareVulnerability{ SoftwareID: bar.ID, CVE: "cve-123", - ResolvedInVersion: ptr.String("1.2.3"), + ResolvedInVersion: new("1.2.3"), }, fleet.NVDSource, ) require.NoError(t, err) @@ -6643,9 +6642,9 @@ func (s *integrationEnterpriseTestSuite) TestListSoftware() { require.NoError(t, s.ds.InsertCVEMeta(ctx, []fleet.CVEMeta{{ CVE: "cve-123", - CVSSScore: ptr.Float64(5.4), - EPSSProbability: ptr.Float64(0.5), - CISAKnownExploit: ptr.Bool(true), + CVSSScore: new(float64(5.4)), + EPSSProbability: new(float64(0.5)), + CISAKnownExploit: new(true), Published: &now, Description: "a long description of the cve", }})) @@ -6672,12 +6671,12 @@ func (s *integrationEnterpriseTestSuite) TestListSoftware() { require.Empty(t, fooPayload.Vulnerabilities) require.Len(t, barPayload.Vulnerabilities, 1) require.Equal(t, barPayload.Vulnerabilities[0].CVE, "cve-123") - require.NotNil(t, barPayload.Vulnerabilities[0].CVSSScore, ptr.Float64Ptr(5.4)) - require.NotNil(t, barPayload.Vulnerabilities[0].EPSSProbability, ptr.Float64Ptr(0.5)) - require.NotNil(t, barPayload.Vulnerabilities[0].CISAKnownExploit, ptr.BoolPtr(true)) - require.Equal(t, barPayload.Vulnerabilities[0].CVEPublished, ptr.TimePtr(now)) - require.Equal(t, barPayload.Vulnerabilities[0].Description, ptr.StringPtr("a long description of the cve")) - require.Equal(t, barPayload.Vulnerabilities[0].ResolvedInVersion, ptr.StringPtr("1.2.3")) + require.NotNil(t, barPayload.Vulnerabilities[0].CVSSScore, new(new(5.4))) + require.NotNil(t, barPayload.Vulnerabilities[0].EPSSProbability, new(new(0.5))) + require.NotNil(t, barPayload.Vulnerabilities[0].CISAKnownExploit, new(new(true))) + require.Equal(t, barPayload.Vulnerabilities[0].CVEPublished, new(new(now))) + require.Equal(t, barPayload.Vulnerabilities[0].Description, new(new("a long description of the cve"))) + require.Equal(t, barPayload.Vulnerabilities[0].ResolvedInVersion, new(new("1.2.3"))) var respVersions listSoftwareVersionsResponse s.DoJSON("GET", "/api/latest/fleet/software/versions", nil, http.StatusOK, &respVersions) @@ -6698,12 +6697,12 @@ func (s *integrationEnterpriseTestSuite) TestListSoftware() { require.Empty(t, fooPayload.Vulnerabilities) require.Len(t, barPayload.Vulnerabilities, 1) require.Equal(t, barPayload.Vulnerabilities[0].CVE, "cve-123") - require.NotNil(t, barPayload.Vulnerabilities[0].CVSSScore, ptr.Float64Ptr(5.4)) - require.NotNil(t, barPayload.Vulnerabilities[0].EPSSProbability, ptr.Float64Ptr(0.5)) - require.NotNil(t, barPayload.Vulnerabilities[0].CISAKnownExploit, ptr.BoolPtr(true)) - require.Equal(t, barPayload.Vulnerabilities[0].CVEPublished, ptr.TimePtr(now)) - require.Equal(t, barPayload.Vulnerabilities[0].Description, ptr.StringPtr("a long description of the cve")) - require.Equal(t, barPayload.Vulnerabilities[0].ResolvedInVersion, ptr.StringPtr("1.2.3")) + require.NotNil(t, barPayload.Vulnerabilities[0].CVSSScore, new(new(5.4))) + require.NotNil(t, barPayload.Vulnerabilities[0].EPSSProbability, new(new(0.5))) + require.NotNil(t, barPayload.Vulnerabilities[0].CISAKnownExploit, new(new(true))) + require.Equal(t, barPayload.Vulnerabilities[0].CVEPublished, new(new(now))) + require.Equal(t, barPayload.Vulnerabilities[0].Description, new(new("a long description of the cve"))) + require.Equal(t, barPayload.Vulnerabilities[0].ResolvedInVersion, new(new("1.2.3"))) // vulnerable param required when using vulnerability filters respVersions = listSoftwareVersionsResponse{} @@ -6859,7 +6858,7 @@ func (s *integrationEnterpriseTestSuite) TestGitOpsUserActions() { admin, err := s.ds.UserByEmail(ctx, "admin1@example.com") require.NoError(t, err) h1, err := s.ds.NewHost(ctx, &fleet.Host{ - NodeKey: ptr.String(t.Name() + "1"), + NodeKey: new(t.Name() + "1"), UUID: t.Name() + "1", Hostname: strings.ReplaceAll(t.Name()+"foo.local", "/", "_"), }) @@ -6877,14 +6876,14 @@ func (s *integrationEnterpriseTestSuite) TestGitOpsUserActions() { }) require.NoError(t, err) team1Host, err := s.ds.NewHost(ctx, &fleet.Host{ - NodeKey: ptr.String(t.Name() + "2"), + NodeKey: new(t.Name() + "2"), UUID: t.Name() + "2", Hostname: strings.ReplaceAll(t.Name()+"zoo.local", "/", "_"), TeamID: &t1.ID, }) require.NoError(t, err) globalHost, err := s.ds.NewHost(ctx, &fleet.Host{ - NodeKey: ptr.String(t.Name() + "3"), + NodeKey: new(t.Name() + "3"), UUID: t.Name() + "3", Hostname: strings.ReplaceAll(t.Name()+"global.local", "/", "_"), }) @@ -6912,8 +6911,8 @@ func (s *integrationEnterpriseTestSuite) TestGitOpsUserActions() { var userPackID uint s.DoJSON("POST", "/api/latest/fleet/packs", createPackRequest{ PackPayload: fleet.PackPayload{ - Name: ptr.String("Foobar"), - Disabled: ptr.Bool(false), + Name: new("Foobar"), + Disabled: new(false), }, }, http.StatusOK, &cpar) userPackID = cpar.Pack.Pack.ID @@ -6921,10 +6920,10 @@ func (s *integrationEnterpriseTestSuite) TestGitOpsUserActions() { cur := createUserResponse{} s.DoJSON("POST", "/api/latest/fleet/users/admin", createUserRequest{ UserPayload: fleet.UserPayload{ - Email: ptr.String("foo42@example.com"), - Password: ptr.String("p4ssw0rd.123"), - Name: ptr.String("foo42"), - GlobalRole: ptr.String("maintainer"), + Email: new("foo42@example.com"), + Password: new("p4ssw0rd.123"), + Name: new("foo42"), + GlobalRole: new("maintainer"), }, }, http.StatusOK, &cur) maintainer := cur.User @@ -6946,7 +6945,7 @@ func (s *integrationEnterpriseTestSuite) TestGitOpsUserActions() { u := &fleet.User{ Name: "GitOps", Email: "gitops1@example.com", - GlobalRole: ptr.String(fleet.RoleGitOps), + GlobalRole: new(fleet.RoleGitOps), } require.NoError(t, u.SetPassword(test.GoodPassword, 10, 10)) _, err = s.ds.NewUser(context.Background(), u) @@ -7040,7 +7039,7 @@ func (s *integrationEnterpriseTestSuite) TestGitOpsUserActions() { // Attempt to modify a label, should allow. s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/labels/%d", clr.Label.ID), fleet.ModifyLabelRequest{ ModifyLabelPayload: fleet.ModifyLabelPayload{ - Name: ptr.String("foo2"), + Name: new("foo2"), }, }, http.StatusOK, &fleet.ModifyLabelResponse{}) @@ -7106,7 +7105,7 @@ func (s *integrationEnterpriseTestSuite) TestGitOpsUserActions() { // Attempt to run live queries asynchronously (saved query), should fail. s.DoJSON("POST", "/api/latest/fleet/queries/run", createDistributedQueryCampaignRequest{ - QueryID: ptr.Uint(q1.ID), + QueryID: new(q1.ID), Selected: fleet.HostTargets{ HostIDs: []uint{h1.ID}, }, @@ -7116,37 +7115,37 @@ func (s *integrationEnterpriseTestSuite) TestGitOpsUserActions() { cqr := fleet.CreateQueryResponse{} s.DoJSON("POST", "/api/latest/fleet/queries", fleet.CreateQueryRequest{ QueryPayload: fleet.QueryPayload{ - Name: ptr.String("foo4"), - Query: ptr.String("SELECT * from osquery_info;"), + Name: new("foo4"), + Query: new("SELECT * from osquery_info;"), }, }, http.StatusOK, &cqr) cqr2 := fleet.CreateQueryResponse{} s.DoJSON("POST", "/api/latest/fleet/queries", fleet.CreateQueryRequest{ QueryPayload: fleet.QueryPayload{ - Name: ptr.String("foo5"), - Query: ptr.String("SELECT * from os_version;"), + Name: new("foo5"), + Query: new("SELECT * from os_version;"), }, }, http.StatusOK, &cqr2) cqr3 := fleet.CreateQueryResponse{} s.DoJSON("POST", "/api/latest/fleet/queries", fleet.CreateQueryRequest{ QueryPayload: fleet.QueryPayload{ - Name: ptr.String("foo6"), - Query: ptr.String("SELECT * from processes;"), + Name: new("foo6"), + Query: new("SELECT * from processes;"), }, }, http.StatusOK, &cqr3) cqr4 := fleet.CreateQueryResponse{} s.DoJSON("POST", "/api/latest/fleet/queries", fleet.CreateQueryRequest{ QueryPayload: fleet.QueryPayload{ - Name: ptr.String("foo7"), - Query: ptr.String("SELECT * from managed_policies;"), + Name: new("foo7"), + Query: new("SELECT * from managed_policies;"), }, }, http.StatusOK, &cqr4) // Attempt to edit queries, should allow. s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/queries/%d", cqr.Query.ID), fleet.ModifyQueryRequest{ QueryPayload: fleet.QueryPayload{ - Name: ptr.String("foo4"), - Query: ptr.String("SELECT * FROM system_info;"), + Name: new("foo4"), + Query: new("SELECT * FROM system_info;"), }, }, http.StatusOK, &fleet.ModifyQueryResponse{}) @@ -7172,7 +7171,7 @@ func (s *integrationEnterpriseTestSuite) TestGitOpsUserActions() { // Attempt to edit a scheduled query in the global schedule, should allow. s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/packs/schedule/%d", sqr.Scheduled.ID), fleet.ModifyScheduledQueryRequest{ ScheduledQueryPayload: fleet.ScheduledQueryPayload{ - Interval: ptr.Uint(30), + Interval: new(uint(30)), }, }, http.StatusOK, &fleet.ScheduleQueryResponse{}) @@ -7186,14 +7185,14 @@ func (s *integrationEnterpriseTestSuite) TestGitOpsUserActions() { cpr := createPackResponse{} s.DoJSON("POST", "/api/latest/fleet/packs", createPackRequest{ PackPayload: fleet.PackPayload{ - Name: ptr.String("foo8"), + Name: new("foo8"), }, }, http.StatusOK, &cpr) // Attempt to edit a pack, should allow. s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/packs/%d", cpr.Pack.ID), modifyPackRequest{ PackPayload: fleet.PackPayload{ - Name: ptr.String("foo9"), + Name: new("foo9"), }, }, http.StatusOK, &modifyPackResponse{}) @@ -7215,7 +7214,7 @@ func (s *integrationEnterpriseTestSuite) TestGitOpsUserActions() { mgplr := fleet.ModifyGlobalPolicyResponse{} s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/policies/%d", gplr.Policy.ID), fleet.ModifyGlobalPolicyRequest{ ModifyPolicyPayload: fleet.ModifyPolicyPayload{ - Query: ptr.String("SELECT * from plist WHERE path = 'foo';"), + Query: new("SELECT * from plist WHERE path = 'foo';"), }, }, http.StatusOK, &mgplr) @@ -7241,7 +7240,7 @@ func (s *integrationEnterpriseTestSuite) TestGitOpsUserActions() { mtplr := fleet.ModifyTeamPolicyResponse{} s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/teams/%d/policies/%d", t1.ID, tplr.Policy.ID), fleet.ModifyTeamPolicyRequest{ ModifyPolicyPayload: fleet.ModifyPolicyPayload{ - Query: ptr.String("SELECT * from file WHERE path = 'foo';"), + Query: new("SELECT * from file WHERE path = 'foo';"), }, }, http.StatusOK, &mtplr) @@ -7259,16 +7258,16 @@ func (s *integrationEnterpriseTestSuite) TestGitOpsUserActions() { // Attempt to create a user, should fail. s.DoJSON("POST", "/api/latest/fleet/users/admin", createUserRequest{ UserPayload: fleet.UserPayload{ - Email: ptr.String("foo10@example.com"), - Name: ptr.String("foo10"), - GlobalRole: ptr.String("admin"), + Email: new("foo10@example.com"), + Name: new("foo10"), + GlobalRole: new("admin"), }, }, http.StatusForbidden, &createUserResponse{}) // Attempt to modify a user, should fail. s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/users/%d", admin.ID), modifyUserRequest{ UserPayload: fleet.UserPayload{ - GlobalRole: ptr.String("observer"), + GlobalRole: new("observer"), }, }, http.StatusForbidden, &modifyUserResponse{}) @@ -7302,14 +7301,14 @@ func (s *integrationEnterpriseTestSuite) TestGitOpsUserActions() { tr := teamResponse{} s.DoJSON("POST", "/api/latest/fleet/teams", createTeamRequest{ TeamPayload: fleet.TeamPayload{ - Name: ptr.String("foo11"), + Name: new("foo11"), }, }, http.StatusOK, &tr) // Attempt to edit a team, should allow. s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/teams/%d", tr.Team.ID), modifyTeamRequest{ TeamPayload: fleet.TeamPayload{ - Name: ptr.String("foo12"), + Name: new("foo12"), }, }, http.StatusOK, &teamResponse{}) @@ -7339,7 +7338,7 @@ func (s *integrationEnterpriseTestSuite) TestGitOpsUserActions() { }, { Secret: "foo500", - TeamID: ptr.Uint(t1.ID), + TeamID: new(t1.ID), }, }, }, @@ -7383,8 +7382,8 @@ func (s *integrationEnterpriseTestSuite) TestGitOpsUserActions() { tcqr := fleet.CreateQueryResponse{} s.DoJSON("POST", "/api/latest/fleet/queries", fleet.CreateQueryRequest{ QueryPayload: fleet.QueryPayload{ - Name: ptr.String("foo600"), - Query: ptr.String("SELECT * from orbit_info;"), + Name: new("foo600"), + Query: new("SELECT * from orbit_info;"), }, }, http.StatusForbidden, &tcqr) @@ -7392,8 +7391,8 @@ func (s *integrationEnterpriseTestSuite) TestGitOpsUserActions() { tcqr = fleet.CreateQueryResponse{} s.DoJSON("POST", "/api/latest/fleet/queries", fleet.CreateQueryRequest{ QueryPayload: fleet.QueryPayload{ - Name: ptr.String("foo600"), - Query: ptr.String("SELECT * from orbit_info;"), + Name: new("foo600"), + Query: new("SELECT * from orbit_info;"), TeamID: &t1.ID, }, }, http.StatusOK, &tcqr) @@ -7401,8 +7400,8 @@ func (s *integrationEnterpriseTestSuite) TestGitOpsUserActions() { // Attempt to edit own query, should allow. s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/queries/%d", tcqr.Query.ID), fleet.ModifyQueryRequest{ QueryPayload: fleet.QueryPayload{ - Name: ptr.String("foo4"), - Query: ptr.String("SELECT * FROM system_info;"), + Name: new("foo4"), + Query: new("SELECT * FROM system_info;"), }, }, http.StatusOK, &fleet.ModifyQueryResponse{}) @@ -7412,8 +7411,8 @@ func (s *integrationEnterpriseTestSuite) TestGitOpsUserActions() { // Attempt to edit query created by somebody else, should fail. s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/queries/%d", cqr4.Query.ID), fleet.ModifyQueryRequest{ QueryPayload: fleet.QueryPayload{ - Name: ptr.String("foo4"), - Query: ptr.String("SELECT * FROM system_info;"), + Name: new("foo4"), + Query: new("SELECT * FROM system_info;"), }, }, http.StatusForbidden, &fleet.ModifyQueryResponse{}) @@ -7444,8 +7443,8 @@ func (s *integrationEnterpriseTestSuite) TestGitOpsUserActions() { cqrt1 := fleet.CreateQueryResponse{} s.DoJSON("POST", "/api/latest/fleet/queries", fleet.CreateQueryRequest{ QueryPayload: fleet.QueryPayload{ - Name: ptr.String("foo8"), - Query: ptr.String("SELECT * from managed_policies;"), + Name: new("foo8"), + Query: new("SELECT * from managed_policies;"), TeamID: &t1.ID, }, }, http.StatusOK, &cqrt1) @@ -7453,8 +7452,8 @@ func (s *integrationEnterpriseTestSuite) TestGitOpsUserActions() { // Add a schedule with the deprecated APIs (by referencing a global query). s.DoJSON("POST", fmt.Sprintf("/api/latest/fleet/teams/%d/schedule", t1.ID), teamScheduleQueryRequest{ ScheduledQueryPayload: fleet.ScheduledQueryPayload{ - QueryID: ptr.Uint(q1.ID), - Interval: ptr.Uint(60), + QueryID: new(q1.ID), + Interval: new(uint(60)), }, }, http.StatusOK, &ttsqr) @@ -7498,14 +7497,14 @@ func (s *integrationEnterpriseTestSuite) TestGitOpsUserActions() { // Attempt to edit a team policy, should allow. s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/teams/%d/policies/%d", t1.ID, ttplr.Policy.ID), fleet.ModifyTeamPolicyRequest{ ModifyPolicyPayload: fleet.ModifyPolicyPayload{ - Query: ptr.String("SELECT * from file WHERE path = 'foobar';"), + Query: new("SELECT * from file WHERE path = 'foobar';"), }, }, http.StatusOK, &fleet.ModifyTeamPolicyResponse{}) // Attempt to edit another team's policy, should fail. s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/teams/%d/policies/%d", t2.ID, t2p.ID), fleet.ModifyTeamPolicyRequest{ ModifyPolicyPayload: fleet.ModifyPolicyPayload{ - Query: ptr.String("SELECT * from file WHERE path = 'foobar';"), + Query: new("SELECT * from file WHERE path = 'foobar';"), }, }, http.StatusForbidden, &fleet.ModifyTeamPolicyResponse{}) @@ -7526,14 +7525,14 @@ func (s *integrationEnterpriseTestSuite) TestGitOpsUserActions() { // Attempt to edit own team, should allow. s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/teams/%d", t1.ID), modifyTeamRequest{ TeamPayload: fleet.TeamPayload{ - Name: ptr.String("foo123456"), + Name: new("foo123456"), }, }, http.StatusOK, &teamResponse{}) // Attempt to edit another team, should fail. s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/teams/%d", t2.ID), modifyTeamRequest{ TeamPayload: fleet.TeamPayload{ - Name: ptr.String("foo123456"), + Name: new("foo123456"), }, }, http.StatusForbidden, &teamResponse{}) @@ -7971,8 +7970,8 @@ func (s *integrationEnterpriseTestSuite) TestRunHostScript() { LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now().Add(-time.Minute), - OsqueryHostID: ptr.String("plain-osquery-host"), - NodeKey: ptr.String("plain-osquery-host"), + OsqueryHostID: new("plain-osquery-host"), + NodeKey: new("plain-osquery-host"), UUID: uuid.New().String(), Hostname: fmt.Sprintf("%s.local", "plain-osquery-host"), HardwareSerial: uuid.New().String(), @@ -8337,12 +8336,12 @@ func (s *integrationEnterpriseTestSuite) TestRunHostSavedScript() { s.DoJSON("POST", "/api/latest/fleet/scripts/run", fleet.HostScriptRequestPayload{HostID: host.ID + 100, ScriptID: &savedNoTmScript.ID}, http.StatusNotFound, &runResp) // attempt to run with both script contents and id - res := s.Do("POST", "/api/latest/fleet/scripts/run", fleet.HostScriptRequestPayload{HostID: host.ID, ScriptContents: "echo", ScriptID: ptr.Uint(savedTmScript.ID + 999)}, http.StatusUnprocessableEntity) + res := s.Do("POST", "/api/latest/fleet/scripts/run", fleet.HostScriptRequestPayload{HostID: host.ID, ScriptContents: "echo", ScriptID: new(savedTmScript.ID + 999)}, http.StatusUnprocessableEntity) errMsg := extractServerErrorText(res.Body) require.Contains(t, errMsg, `Only one of 'script_id' or 'script_contents' is allowed.`) // attempt to run with unknown script id - res = s.Do("POST", "/api/latest/fleet/scripts/run", fleet.HostScriptRequestPayload{HostID: host.ID, ScriptID: ptr.Uint(savedTmScript.ID + 999)}, http.StatusNotFound) + res = s.Do("POST", "/api/latest/fleet/scripts/run", fleet.HostScriptRequestPayload{HostID: host.ID, ScriptID: new(savedTmScript.ID + 999)}, http.StatusNotFound) errMsg = extractServerErrorText(res.Body) require.Contains(t, errMsg, `No script exists for the provided "script_id".`) @@ -8430,7 +8429,7 @@ func (s *integrationEnterpriseTestSuite) TestRunHostSavedScript() { require.Contains(t, runSyncResp.Message, fleet.RunScriptHostTimeoutErrMsg) // attempt to run sync with both script contents and script id - res = s.Do("POST", "/api/latest/fleet/scripts/run/sync", fleet.HostScriptRequestPayload{HostID: host.ID, ScriptContents: "echo", ScriptID: ptr.Uint(savedTmScript.ID + 999)}, http.StatusUnprocessableEntity) + res = s.Do("POST", "/api/latest/fleet/scripts/run/sync", fleet.HostScriptRequestPayload{HostID: host.ID, ScriptContents: "echo", ScriptID: new(savedTmScript.ID + 999)}, http.StatusUnprocessableEntity) errMsg = extractServerErrorText(res.Body) require.Contains(t, errMsg, `Only one of 'script_id' or 'script_contents' is allowed.`) @@ -8444,11 +8443,11 @@ func (s *integrationEnterpriseTestSuite) TestRunHostSavedScript() { require.Contains(t, errMsg, `Only one of 'script_contents' or 'script_name' is allowed.`) // attempt to run sync with both script id and script name - res = s.Do("POST", "/api/latest/fleet/scripts/run/sync", fleet.HostScriptRequestPayload{HostID: host.ID, ScriptID: ptr.Uint(savedTmScript.ID + 999), ScriptName: savedTmScript.Name}, http.StatusUnprocessableEntity) + res = s.Do("POST", "/api/latest/fleet/scripts/run/sync", fleet.HostScriptRequestPayload{HostID: host.ID, ScriptID: new(savedTmScript.ID + 999), ScriptName: savedTmScript.Name}, http.StatusUnprocessableEntity) errMsg = extractServerErrorText(res.Body) require.Contains(t, errMsg, `Only one of 'script_id' or 'script_name' is allowed.`) - res = s.Do("POST", "/api/latest/fleet/scripts/run", fleet.HostScriptRequestPayload{HostID: host.ID, ScriptID: ptr.Uint(savedTmScript.ID + 999), ScriptName: savedTmScript.Name}, http.StatusUnprocessableEntity) + res = s.Do("POST", "/api/latest/fleet/scripts/run", fleet.HostScriptRequestPayload{HostID: host.ID, ScriptID: new(savedTmScript.ID + 999), ScriptName: savedTmScript.Name}, http.StatusUnprocessableEntity) errMsg = extractServerErrorText(res.Body) require.Contains(t, errMsg, `Only one of 'script_id' or 'script_name' is allowed.`) @@ -8462,11 +8461,11 @@ func (s *integrationEnterpriseTestSuite) TestRunHostSavedScript() { require.Contains(t, errMsg, `Only one of 'script_contents' or 'team_id' is allowed.`) // attempt to run sync with both script id and team id - res = s.Do("POST", "/api/latest/fleet/scripts/run/sync", fleet.HostScriptRequestPayload{HostID: host.ID, ScriptID: ptr.Uint(savedTmScript.ID + 999), TeamID: 1}, http.StatusUnprocessableEntity) + res = s.Do("POST", "/api/latest/fleet/scripts/run/sync", fleet.HostScriptRequestPayload{HostID: host.ID, ScriptID: new(savedTmScript.ID + 999), TeamID: 1}, http.StatusUnprocessableEntity) errMsg = extractServerErrorText(res.Body) require.Contains(t, errMsg, `Only one of 'script_id' or 'team_id' is allowed.`) - res = s.Do("POST", "/api/latest/fleet/scripts/run", fleet.HostScriptRequestPayload{HostID: host.ID, ScriptID: ptr.Uint(savedTmScript.ID + 999), TeamID: 1}, http.StatusUnprocessableEntity) + res = s.Do("POST", "/api/latest/fleet/scripts/run", fleet.HostScriptRequestPayload{HostID: host.ID, ScriptID: new(savedTmScript.ID + 999), TeamID: 1}, http.StatusUnprocessableEntity) errMsg = extractServerErrorText(res.Body) require.Contains(t, errMsg, `Only one of 'script_id' or 'team_id' is allowed.`) @@ -8567,8 +8566,8 @@ func (s *integrationEnterpriseTestSuite) TestRunHostSavedScript() { LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now().Add(-time.Minute), - OsqueryHostID: ptr.String("plain-osquery-host-2"), - NodeKey: ptr.String("plain-osquery-host-2"), + OsqueryHostID: new("plain-osquery-host-2"), + NodeKey: new("plain-osquery-host-2"), UUID: uuid.New().String(), Hostname: fmt.Sprintf("%s.local", "plain-osquery-host-2"), HardwareSerial: uuid.New().String(), @@ -8663,19 +8662,19 @@ func (s *integrationEnterpriseTestSuite) TestOrbitConfigExtensions() { // orbitDarwinClient is member of 'All hosts' and 'Zoobar' labels. err = s.ds.RecordLabelQueryExecutions(ctx, orbitDarwinClient, map[uint]*bool{ - allHostsLabel.ID: ptr.Bool(true), - zoobarLabel.ID: ptr.Bool(true), + allHostsLabel.ID: new(true), + zoobarLabel.ID: new(true), }, time.Now(), false) require.NoError(t, err) // orbitLinuxClient is member of 'All hosts' and 'Foobar' labels. err = s.ds.RecordLabelQueryExecutions(ctx, orbitLinuxClient, map[uint]*bool{ - allHostsLabel.ID: ptr.Bool(true), - foobarLabel.ID: ptr.Bool(true), + allHostsLabel.ID: new(true), + foobarLabel.ID: new(true), }, time.Now(), false) require.NoError(t, err) // orbitWindowsClient is member of the 'All hosts' label only. err = s.ds.RecordLabelQueryExecutions(ctx, orbitWindowsClient, map[uint]*bool{ - allHostsLabel.ID: ptr.Bool(true), + allHostsLabel.ID: new(true), }, time.Now(), false) require.NoError(t, err) @@ -8760,7 +8759,7 @@ func (s *integrationEnterpriseTestSuite) TestOrbitConfigExtensions() { // orbitDarwinClient is now also a member of the 'Foobar' label. err = s.ds.RecordLabelQueryExecutions(ctx, orbitDarwinClient, map[uint]*bool{ - foobarLabel.ID: ptr.Bool(true), + foobarLabel.ID: new(true), }, time.Now(), false) require.NoError(t, err) @@ -9163,8 +9162,8 @@ func (s *integrationEnterpriseTestSuite) TestHostScriptDetails() { LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now().Add(-1 * time.Minute), - OsqueryHostID: ptr.String("host0"), - NodeKey: ptr.String("host0"), + OsqueryHostID: new("host0"), + NodeKey: new("host0"), UUID: uuid.New().String(), Hostname: "host0", Platform: "darwin", @@ -9177,8 +9176,8 @@ func (s *integrationEnterpriseTestSuite) TestHostScriptDetails() { LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now().Add(-1 * time.Minute), - OsqueryHostID: ptr.String("host1"), - NodeKey: ptr.String("host1"), + OsqueryHostID: new("host1"), + NodeKey: new("host1"), UUID: uuid.New().String(), Hostname: "host1", Platform: "darwin", @@ -9192,8 +9191,8 @@ func (s *integrationEnterpriseTestSuite) TestHostScriptDetails() { LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now().Add(-1 * time.Minute), - OsqueryHostID: ptr.String("host2"), - NodeKey: ptr.String("host2"), + OsqueryHostID: new("host2"), + NodeKey: new("host2"), UUID: uuid.New().String(), Hostname: "host2", Platform: "darwin", @@ -9207,8 +9206,8 @@ func (s *integrationEnterpriseTestSuite) TestHostScriptDetails() { LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now().Add(-1 * time.Minute), - OsqueryHostID: ptr.String("host3"), - NodeKey: ptr.String("host3"), + OsqueryHostID: new("host3"), + NodeKey: new("host3"), UUID: uuid.New().String(), Hostname: "host3", Platform: "windows", @@ -9222,8 +9221,8 @@ func (s *integrationEnterpriseTestSuite) TestHostScriptDetails() { LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now().Add(-1 * time.Minute), - OsqueryHostID: ptr.String("host4"), - NodeKey: ptr.String("host4"), + OsqueryHostID: new("host4"), + NodeKey: new("host4"), UUID: uuid.New().String(), Hostname: "host4", Platform: "ubuntu", @@ -9237,8 +9236,8 @@ func (s *integrationEnterpriseTestSuite) TestHostScriptDetails() { LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now().Add(-1 * time.Minute), - OsqueryHostID: ptr.String("host5"), - NodeKey: ptr.String("host5"), + OsqueryHostID: new("host5"), + NodeKey: new("host5"), UUID: uuid.New().String(), Hostname: "host5", Platform: "chrome", @@ -9303,8 +9302,8 @@ VALUES } // insert some ad hoc script results, these are never included in the host script details - insertResults(t, host0.ID, &fleet.Script{Name: "ad hoc script", ScriptContents: "echo foo"}, now, "ad-hoc-0", ptr.Int64(0)) - insertResults(t, host1.ID, &fleet.Script{Name: "ad hoc script", ScriptContents: "echo foo"}, now.Add(-1*time.Hour), "ad-hoc-1", ptr.Int64(1)) + insertResults(t, host0.ID, &fleet.Script{Name: "ad hoc script", ScriptContents: "echo foo"}, now, "ad-hoc-0", new(int64(0))) + insertResults(t, host1.ID, &fleet.Script{Name: "ad hoc script", ScriptContents: "echo foo"}, now.Add(-1*time.Hour), "ad-hoc-1", new(int64(1))) t.Run("no team", func(t *testing.T) { noTeamScripts, _, err := s.ds.ListScripts(ctx, nil, fleet.ListOptions{}) @@ -9312,12 +9311,12 @@ VALUES require.Len(t, noTeamScripts, 5) // insert saved script results for host0 - insertResults(t, host0.ID, noTeamScripts[0], now, "exec0-0", ptr.Int64(0)) // expect status ran - insertResults(t, host0.ID, noTeamScripts[1], now.Add(-1*time.Hour), "exec0-1", ptr.Int64(1)) // expect status error - insertResults(t, host0.ID, noTeamScripts[2], now.Add(-2*time.Hour), "exec0-2", nil) // expect status pending + insertResults(t, host0.ID, noTeamScripts[0], now, "exec0-0", new(int64(0))) // expect status ran + insertResults(t, host0.ID, noTeamScripts[1], now.Add(-1*time.Hour), "exec0-1", new(int64(1))) // expect status error + insertResults(t, host0.ID, noTeamScripts[2], now.Add(-2*time.Hour), "exec0-2", nil) // expect status pending // insert some ad hoc script results, these are never included in the host script details - insertResults(t, host0.ID, &fleet.Script{Name: "ad hoc script", ScriptContents: "echo foo"}, now.Add(-3*time.Hour), "exec0-3", ptr.Int64(0)) + insertResults(t, host0.ID, &fleet.Script{Name: "ad hoc script", ScriptContents: "echo foo"}, now.Add(-3*time.Hour), "exec0-3", new(int64(0))) // check host script details, should include all no team scripts var resp fleet.GetHostScriptDetailsResponse @@ -9359,7 +9358,7 @@ VALUES require.Len(t, tm1Scripts, 5) // insert results for host1 - insertResults(t, host1.ID, tm1Scripts[0], now, "exec1-0", ptr.Int64(0)) // expect status ran + insertResults(t, host1.ID, tm1Scripts[0], now, "exec1-0", new(int64(0))) // expect status ran // check host script details, should match team 1 var resp fleet.GetHostScriptDetailsResponse @@ -9560,9 +9559,9 @@ VALUES }, { name: "script-timeout", - exitCode: ptr.Int64(-1), + exitCode: new(int64(-1)), executedAt: now.Add(-1 * time.Hour), - expected: fleet.HostScriptTimeoutMessage(ptr.Int(int(scripts.MaxHostExecutionTime.Seconds()))), + expected: fleet.HostScriptTimeoutMessage(new(int(scripts.MaxHostExecutionTime.Seconds()))), }, { name: "pending", @@ -9572,19 +9571,19 @@ VALUES }, { name: "success", - exitCode: ptr.Int64(0), + exitCode: new(int64(0)), executedAt: now.Add(-1 * time.Hour), expected: "", }, { name: "error", - exitCode: ptr.Int64(1), + exitCode: new(int64(1)), executedAt: now.Add(-1 * time.Hour), expected: "", }, { name: "disabled", - exitCode: ptr.Int64(-2), + exitCode: new(int64(-2)), executedAt: now.Add(-1 * time.Hour), expected: fleet.RunScriptDisabledErrMsg, }, @@ -9856,8 +9855,8 @@ func (s *integrationEnterpriseTestSuite) TestBatchApplyScriptsEndpoints() { } func (s *integrationEnterpriseTestSuite) TestTeamConfigDetailQueriesOverrides() { - ctx := context.Background() t := s.T() + ctx := context.Background() teamName := t.Name() + "team1" team := &fleet.Team{ @@ -9893,8 +9892,8 @@ func (s *integrationEnterpriseTestSuite) TestTeamConfigDetailQueriesOverrides() LabelUpdatedAt: time.Now().Add(-10 * time.Hour), PolicyUpdatedAt: time.Now().Add(-10 * time.Hour), SeenTime: time.Now().Add(-1 * time.Minute), - OsqueryHostID: ptr.String(t.Name()), - NodeKey: ptr.String(t.Name()), + OsqueryHostID: new(t.Name()), + NodeKey: new(t.Name()), UUID: uuid.New().String(), Hostname: fmt.Sprintf("%sfoo.local", t.Name()), Platform: "linux", @@ -9986,8 +9985,8 @@ func (s *integrationEnterpriseTestSuite) TestTeamConfigHistoricalDataGitOps() { } func (s *integrationEnterpriseTestSuite) TestAllSoftwareTitles() { - ctx := context.Background() t := s.T() + ctx := context.Background() softwareTitleListResultsMatch := func(want, got []fleet.SoftwareTitleListResult) { // compare only the fields we care about @@ -10065,8 +10064,8 @@ func (s *integrationEnterpriseTestSuite) TestAllSoftwareTitles() { LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now().Add(-1 * time.Minute), - OsqueryHostID: ptr.String(t.Name()), - NodeKey: ptr.String(t.Name()), + OsqueryHostID: new(t.Name()), + NodeKey: new(t.Name()), UUID: uuid.New().String(), Hostname: fmt.Sprintf("%sfoo.local", t.Name()), Platform: "darwin", @@ -10078,8 +10077,8 @@ func (s *integrationEnterpriseTestSuite) TestAllSoftwareTitles() { LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now().Add(-1 * time.Minute), - OsqueryHostID: ptr.String(t.Name() + "tm"), - NodeKey: ptr.String(t.Name() + "tm"), + OsqueryHostID: new(t.Name() + "tm"), + NodeKey: new(t.Name() + "tm"), UUID: uuid.New().String(), Hostname: fmt.Sprintf("%sfoo.local", t.Name()+"tm"), Platform: "linux", @@ -10136,8 +10135,8 @@ func (s *integrationEnterpriseTestSuite) TestAllSoftwareTitles() { err = s.ds.InsertCVEMeta(context.Background(), []fleet.CVEMeta{ { CVE: "cve-123-123-132", - CVSSScore: ptr.Float64(7.8), - CISAKnownExploit: ptr.Bool(true), + CVSSScore: new(float64(7.8)), + CISAKnownExploit: new(true), }, }) require.NoError(t, err) @@ -10666,8 +10665,8 @@ func (s *integrationEnterpriseTestSuite) TestAllSoftwareTitles() { VersionsCount: 2, HostsCount: 2, Versions: []fleet.SoftwareVersion{ - {Version: "0.0.1", Vulnerabilities: nil, HostsCount: ptr.Uint(2)}, - {Version: "0.0.3", Vulnerabilities: nil, HostsCount: ptr.Uint(1)}, + {Version: "0.0.1", Vulnerabilities: nil, HostsCount: new(uint(2))}, + {Version: "0.0.3", Vulnerabilities: nil, HostsCount: new(uint(1))}, }, }, }, []fleet.SoftwareTitle{*stResp.SoftwareTitle}) @@ -10686,7 +10685,7 @@ func (s *integrationEnterpriseTestSuite) TestAllSoftwareTitles() { VersionsCount: 1, HostsCount: 1, Versions: []fleet.SoftwareVersion{ - {Version: "0.0.1", Vulnerabilities: nil, HostsCount: ptr.Uint(1)}, + {Version: "0.0.1", Vulnerabilities: nil, HostsCount: new(uint(1))}, }, }, }, []fleet.SoftwareTitle{*stResp.SoftwareTitle}, @@ -10716,7 +10715,7 @@ func (s *integrationEnterpriseTestSuite) TestAllSoftwareTitles() { { Version: "0.0.4", Vulnerabilities: &fleet.SliceString{"cve-123-123-132"}, - HostsCount: ptr.Uint(1), + HostsCount: new(uint(1)), }, }, }, @@ -10774,7 +10773,7 @@ func (s *integrationEnterpriseTestSuite) TestAllSoftwareTitles() { { Version: "0.0.4", Vulnerabilities: &fleet.SliceString{"cve-123-123-132"}, - HostsCount: ptr.Uint(1), + HostsCount: new(uint(1)), }, }, }, @@ -10848,7 +10847,7 @@ func (s *integrationEnterpriseTestSuite) TestAllSoftwareTitles() { InstallScript: "install", Filename: "vim.deb", SelfService: true, - TeamID: ptr.Uint(0), + TeamID: new(uint(0)), AutomaticInstall: true, Platform: "linux", } @@ -10979,8 +10978,8 @@ func (s *integrationEnterpriseTestSuite) TestAllSoftwareTitles() { } func (s *integrationEnterpriseTestSuite) TestLockUnlockWipeWindowsLinux() { - ctx := context.Background() t := s.T() + ctx := context.Background() // create a Windows and a Linux hosts winHost := createOrbitEnrolledHost(t, "windows", "win_lock_unlock", s.ds) @@ -11112,8 +11111,8 @@ func (s *integrationEnterpriseTestSuite) createHosts(t *testing.T, platforms ... LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now().Add(-time.Duration(i) * time.Minute), - OsqueryHostID: ptr.String(fmt.Sprintf("%s%d", t.Name(), i)), - NodeKey: ptr.String(fmt.Sprintf("%s%d", t.Name(), i)), + OsqueryHostID: new(fmt.Sprintf("%s%d", t.Name(), i)), + NodeKey: new(fmt.Sprintf("%s%d", t.Name(), i)), UUID: uuid.New().String(), Hostname: fmt.Sprintf("%sfoo.local%d", t.Name(), i), Platform: platform, @@ -11133,8 +11132,8 @@ func (s *integrationEnterpriseTestSuite) TestSoftwareAuth() { LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now().Add(-1 * time.Minute), - OsqueryHostID: ptr.String(t.Name()), - NodeKey: ptr.String(t.Name()), + OsqueryHostID: new(t.Name()), + NodeKey: new(t.Name()), UUID: uuid.New().String(), Hostname: fmt.Sprintf("%sfoo.local", t.Name()), Platform: "darwin", @@ -11146,8 +11145,8 @@ func (s *integrationEnterpriseTestSuite) TestSoftwareAuth() { LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now().Add(-1 * time.Minute), - OsqueryHostID: ptr.String(t.Name() + "tm"), - NodeKey: ptr.String(t.Name() + "tm"), + OsqueryHostID: new(t.Name() + "tm"), + NodeKey: new(t.Name() + "tm"), UUID: uuid.New().String(), Hostname: fmt.Sprintf("%sfoo.local", t.Name()+"tm"), Platform: "linux", @@ -11248,7 +11247,7 @@ func (s *integrationEnterpriseTestSuite) TestSoftwareAuth() { Password: &test.GoodPassword, Name: &uu.Email, Teams: uu.Teams, - AdminForcedPasswordReset: ptr.Bool(false), + AdminForcedPasswordReset: new(false), }, }, http.StatusOK, &cur) extraTestUsers[k] = *cur.User @@ -11512,8 +11511,8 @@ func genDistributedReqWithPolicyResults(host *fleet.Host, policyResults map[uint } func (s *integrationEnterpriseTestSuite) TestCalendarEvents() { - ctx := context.Background() t := s.T() + ctx := context.Background() t.Cleanup(func() { calendar.ClearMockEvents() calendar.ClearMockChannels() @@ -11540,8 +11539,8 @@ func (s *integrationEnterpriseTestSuite) TestCalendarEvents() { LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now().Add(-1 * time.Minute), - OsqueryHostID: ptr.String(t.Name() + name), - NodeKey: ptr.String(t.Name() + name), + OsqueryHostID: new(t.Name() + name), + NodeKey: new(t.Name() + name), UUID: uuid.New().String(), Hostname: fmt.Sprintf("%s.%s.local", name, t.Name()), Platform: "darwin", @@ -11603,8 +11602,8 @@ func (s *integrationEnterpriseTestSuite) TestCalendarEvents() { s.DoJSON("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( host1Team1, map[uint]*bool{ - team1Policy1Calendar.ID: ptr.Bool(false), - team1Policy2.ID: ptr.Bool(true), + team1Policy1Calendar.ID: new(false), + team1Policy2.ID: new(true), globalPolicy.ID: nil, }, ), http.StatusOK, &distributedResp) @@ -11613,8 +11612,8 @@ func (s *integrationEnterpriseTestSuite) TestCalendarEvents() { s.DoJSON("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( host2Team1, map[uint]*bool{ - team1Policy1Calendar.ID: ptr.Bool(true), - team1Policy2.ID: ptr.Bool(false), + team1Policy1Calendar.ID: new(true), + team1Policy2.ID: new(false), globalPolicy.ID: nil, }, ), http.StatusOK, &distributedResp) @@ -11624,9 +11623,9 @@ func (s *integrationEnterpriseTestSuite) TestCalendarEvents() { s.DoJSON("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( host3Team2, map[uint]*bool{ - team2Policy1Calendar.ID: ptr.Bool(true), + team2Policy1Calendar.ID: new(true), team2Policy2.ID: nil, - globalPolicy.ID: ptr.Bool(false), + globalPolicy.ID: new(false), }, ), http.StatusOK, &distributedResp) @@ -11636,8 +11635,8 @@ func (s *integrationEnterpriseTestSuite) TestCalendarEvents() { host4Team2, map[uint]*bool{ team2Policy1Calendar.ID: nil, - team2Policy2.ID: ptr.Bool(false), - globalPolicy.ID: ptr.Bool(true), + team2Policy2.ID: new(false), + globalPolicy.ID: new(true), }, ), http.StatusOK, &distributedResp) @@ -11677,8 +11676,8 @@ func (s *integrationEnterpriseTestSuite) TestCalendarEvents() { host4Team2, map[uint]*bool{ team2Policy1Calendar.ID: nil, - team2Policy2.ID: ptr.Bool(false), - globalPolicy.ID: ptr.Bool(true), + team2Policy2.ID: new(false), + globalPolicy.ID: new(true), }, ), http.StatusOK, &distributedResp) @@ -11742,8 +11741,8 @@ func (s *integrationEnterpriseTestSuite) TestCalendarEvents() { s.DoJSON("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( host1Team1, map[uint]*bool{ - team1Policy1Calendar.ID: ptr.Bool(false), - team1Policy2.ID: ptr.Bool(true), + team1Policy1Calendar.ID: new(false), + team1Policy2.ID: new(true), globalPolicy.ID: nil, }, ), http.StatusOK, &distributedResp) @@ -11752,8 +11751,8 @@ func (s *integrationEnterpriseTestSuite) TestCalendarEvents() { s.DoJSON("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( host2Team1, map[uint]*bool{ - team1Policy1Calendar.ID: ptr.Bool(true), - team1Policy2.ID: ptr.Bool(false), + team1Policy1Calendar.ID: new(true), + team1Policy2.ID: new(false), globalPolicy.ID: nil, }, ), http.StatusOK, &distributedResp) @@ -11763,9 +11762,9 @@ func (s *integrationEnterpriseTestSuite) TestCalendarEvents() { s.DoJSON("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( host3Team2, map[uint]*bool{ - team2Policy1Calendar.ID: ptr.Bool(true), + team2Policy1Calendar.ID: new(true), team2Policy2.ID: nil, - globalPolicy.ID: ptr.Bool(false), + globalPolicy.ID: new(false), }, ), http.StatusOK, &distributedResp) @@ -11775,8 +11774,8 @@ func (s *integrationEnterpriseTestSuite) TestCalendarEvents() { host4Team2, map[uint]*bool{ team2Policy1Calendar.ID: nil, - team2Policy2.ID: ptr.Bool(false), - globalPolicy.ID: ptr.Bool(true), + team2Policy2.ID: new(false), + globalPolicy.ID: new(true), }, ), http.StatusOK, &distributedResp) @@ -11866,8 +11865,8 @@ func (s *integrationEnterpriseTestSuite) TestCalendarEvents() { s.DoJSON("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( host1Team1, map[uint]*bool{ - team1Policy1Calendar.ID: ptr.Bool(false), - team1Policy2.ID: ptr.Bool(true), + team1Policy1Calendar.ID: new(false), + team1Policy2.ID: new(true), globalPolicy.ID: nil, }, ), http.StatusOK, &distributedResp) @@ -11876,8 +11875,8 @@ func (s *integrationEnterpriseTestSuite) TestCalendarEvents() { s.DoJSON("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( host2Team1, map[uint]*bool{ - team1Policy1Calendar.ID: ptr.Bool(true), - team1Policy2.ID: ptr.Bool(false), + team1Policy1Calendar.ID: new(true), + team1Policy2.ID: new(false), globalPolicy.ID: nil, }, ), http.StatusOK, &distributedResp) @@ -11902,8 +11901,8 @@ func (s *integrationEnterpriseTestSuite) TestCalendarEvents() { s.DoJSON("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( host1Team1, map[uint]*bool{ - team1Policy1Calendar.ID: ptr.Bool(true), - team1Policy2.ID: ptr.Bool(true), + team1Policy1Calendar.ID: new(true), + team1Policy2.ID: new(true), globalPolicy.ID: nil, }, ), http.StatusOK, &distributedResp) @@ -11922,8 +11921,8 @@ func (s *integrationEnterpriseTestSuite) TestCalendarEvents() { } func (s *integrationEnterpriseTestSuite) TestCalendarEventsTransferringHosts() { - ctx := context.Background() t := s.T() + ctx := context.Background() t.Cleanup(func() { calendar.ClearMockEvents() calendar.ClearMockChannels() @@ -11978,8 +11977,8 @@ func (s *integrationEnterpriseTestSuite) TestCalendarEventsTransferringHosts() { LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now().Add(-1 * time.Minute), - OsqueryHostID: ptr.String(t.Name() + name), - NodeKey: ptr.String(t.Name() + name), + OsqueryHostID: new(t.Name() + name), + NodeKey: new(t.Name() + name), UUID: uuid.New().String(), Hostname: fmt.Sprintf("%s.%s.local", name, t.Name()), Platform: "darwin", @@ -12020,7 +12019,7 @@ func (s *integrationEnterpriseTestSuite) TestCalendarEventsTransferringHosts() { s.DoJSON("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( host1, map[uint]*bool{ - team1Policy1.ID: ptr.Bool(false), + team1Policy1.ID: new(false), }, ), http.StatusOK, &distributedResp) @@ -12042,7 +12041,7 @@ func (s *integrationEnterpriseTestSuite) TestCalendarEventsTransferringHosts() { s.DoJSON("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( host1, map[uint]*bool{ - team2Policy1.ID: ptr.Bool(false), + team2Policy1.ID: new(false), }, ), http.StatusOK, &distributedResp) @@ -12097,28 +12096,28 @@ func (s *integrationEnterpriseTestSuite) TestLabelsHostsCounts() { // create new users for tm1, tm2 and one with both tm1 and tm2 users := []fleet.UserPayload{ { - Name: ptr.String("team1 user"), - Email: ptr.String("tm1user@example.com"), - Password: ptr.String(test.GoodPassword), - AdminForcedPasswordReset: ptr.Bool(false), + Name: new("team1 user"), + Email: new("tm1user@example.com"), + Password: new(test.GoodPassword), + AdminForcedPasswordReset: new(false), Teams: &[]fleet.UserTeam{ {Team: fleet.Team{ID: tm1.ID}, Role: fleet.RoleMaintainer}, }, }, { - Name: ptr.String("team2 user"), - Email: ptr.String("tm2user@example.com"), - Password: ptr.String(test.GoodPassword), - AdminForcedPasswordReset: ptr.Bool(false), + Name: new("team2 user"), + Email: new("tm2user@example.com"), + Password: new(test.GoodPassword), + AdminForcedPasswordReset: new(false), Teams: &[]fleet.UserTeam{ {Team: fleet.Team{ID: tm2.ID}, Role: fleet.RoleAdmin}, }, }, { - Name: ptr.String("team1and2 user"), - Email: ptr.String("tm1and2user@example.com"), - Password: ptr.String(test.GoodPassword), - AdminForcedPasswordReset: ptr.Bool(false), + Name: new("team1and2 user"), + Email: new("tm1and2user@example.com"), + Password: new(test.GoodPassword), + AdminForcedPasswordReset: new(false), Teams: &[]fleet.UserTeam{ {Team: fleet.Team{ID: tm1.ID}, Role: fleet.RoleObserver}, {Team: fleet.Team{ID: tm2.ID}, Role: fleet.RoleObserverPlus}, @@ -12155,13 +12154,13 @@ func (s *integrationEnterpriseTestSuite) TestLabelsHostsCounts() { require.NotZero(t, lblD1) // record membership for hosts across no team, team1 and team2 - err = s.ds.RecordLabelQueryExecutions(ctx, hosts[4], map[uint]*bool{lblD1: ptr.Bool(true)}, time.Now(), false) + err = s.ds.RecordLabelQueryExecutions(ctx, hosts[4], map[uint]*bool{lblD1: new(true)}, time.Now(), false) require.NoError(t, err) - err = s.ds.RecordLabelQueryExecutions(ctx, hosts[2], map[uint]*bool{lblD1: ptr.Bool(true)}, time.Now(), false) + err = s.ds.RecordLabelQueryExecutions(ctx, hosts[2], map[uint]*bool{lblD1: new(true)}, time.Now(), false) require.NoError(t, err) - err = s.ds.RecordLabelQueryExecutions(ctx, hosts[1], map[uint]*bool{lblD1: ptr.Bool(true)}, time.Now(), false) + err = s.ds.RecordLabelQueryExecutions(ctx, hosts[1], map[uint]*bool{lblD1: new(true)}, time.Now(), false) require.NoError(t, err) - err = s.ds.RecordLabelQueryExecutions(ctx, hosts[0], map[uint]*bool{lblD1: ptr.Bool(true)}, time.Now(), false) + err = s.ds.RecordLabelQueryExecutions(ctx, hosts[0], map[uint]*bool{lblD1: new(true)}, time.Now(), false) require.NoError(t, err) // create another dynamic label which will stay empty @@ -12177,9 +12176,9 @@ func (s *integrationEnterpriseTestSuite) TestLabelsHostsCounts() { // test access with each team user adminUserPayload := fleet.UserPayload{ - Name: ptr.String("admin1"), - Email: ptr.String(testUsers["admin1"].Email), - Password: ptr.String(testUsers["admin1"].PlaintextPassword), + Name: new("admin1"), + Email: new(testUsers["admin1"].Email), + Password: new(testUsers["admin1"].PlaintextPassword), } cases := []struct { desc string @@ -12231,7 +12230,7 @@ func (s *integrationEnterpriseTestSuite) TestLabelsHostsCounts() { s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/labels/%d", c.lblID), fleet.ModifyLabelRequest{ ModifyLabelPayload: fleet.ModifyLabelPayload{ - Name: ptr.String("will fail"), + Name: new("will fail"), }, }, http.StatusForbidden, &fleet.ModifyLabelResponse{}) } @@ -12240,8 +12239,8 @@ func (s *integrationEnterpriseTestSuite) TestLabelsHostsCounts() { } func (s *integrationEnterpriseTestSuite) TestListHostSoftware() { - ctx := context.Background() t := s.T() + ctx := context.Background() token := "good_token" host := createOrbitEnrolledHost(t, "ubuntu", "host1", s.ds) @@ -12820,10 +12819,10 @@ func (s *integrationEnterpriseTestSuite) TestSoftwareInstallerUploadDownloadAndD // update should succeed s.updateSoftwareInstaller(t, &fleet.UpdateSoftwareInstallerPayload{ - SelfService: ptr.Bool(true), - InstallScript: ptr.String("some install script"), - PreInstallQuery: ptr.String("some pre install query"), - PostInstallScript: ptr.String("some post install script"), + SelfService: new(true), + InstallScript: new("some install script"), + PreInstallQuery: new("some pre install query"), + PostInstallScript: new("some post install script"), Filename: "ruby.deb", TitleID: titleID, TeamID: nil, @@ -12835,7 +12834,7 @@ func (s *integrationEnterpriseTestSuite) TestSoftwareInstallerUploadDownloadAndD // update with unsupported shebang in install script fails validation s.updateSoftwareInstaller(t, &fleet.UpdateSoftwareInstallerPayload{ - InstallScript: ptr.String("#!/usr/bin/perl\nprint 'hello'"), + InstallScript: new("#!/usr/bin/perl\nprint 'hello'"), TitleID: titleID, TeamID: nil, }, http.StatusBadRequest, "Interpreter not supported") @@ -13089,8 +13088,8 @@ func (s *integrationEnterpriseTestSuite) TestSoftwareInstallerUploadDownloadAndD HostSoftwareInstallResultPayload: &fleet.HostSoftwareInstallResultPayload{ HostID: hostInTeam.ID, InstallUUID: installUUID, - InstallScriptExitCode: ptr.Int(0), - InstallScriptOutput: ptr.String("done"), + InstallScriptExitCode: new(int(0)), + InstallScriptOutput: new("done"), }, }, http.StatusNoContent) @@ -13111,7 +13110,7 @@ func (s *integrationEnterpriseTestSuite) TestSoftwareInstallerUploadDownloadAndD t.Run("create team 0 software installer", func(t *testing.T) { payload := &fleet.UploadSoftwareInstallerPayload{ - TeamID: ptr.Uint(0), + TeamID: new(uint(0)), InstallScript: "another install script", PreInstallQuery: "another pre install query", PostInstallScript: "another post install script", @@ -13178,8 +13177,8 @@ func (s *integrationEnterpriseTestSuite) TestSoftwareInstallerUploadDownloadAndD HostSoftwareInstallResultPayload: &fleet.HostSoftwareInstallResultPayload{ HostID: hostInTeam.ID, InstallUUID: installUUID, - InstallScriptExitCode: ptr.Int(0), - InstallScriptOutput: ptr.String("done"), + InstallScriptExitCode: new(int(0)), + InstallScriptOutput: new("done"), }, }, http.StatusNoContent) @@ -14117,7 +14116,7 @@ func (s *integrationEnterpriseTestSuite) TestBatchSetSoftwareInstallers() { newTitlesResp = listSoftwareTitlesResponse{} s.DoJSON("GET", "/api/v1/fleet/software/titles", nil, http.StatusOK, &newTitlesResp, "available_for_install", "true", "team_id", fmt.Sprint(tm.ID)) - titlesResp.SoftwareTitles[0].SoftwarePackage.SelfService = ptr.Bool(true) + titlesResp.SoftwareTitles[0].SoftwarePackage.SelfService = new(true) require.Equal(t, titlesResp, newTitlesResp) // empty payload cleans the software items @@ -14171,7 +14170,7 @@ func (s *integrationEnterpriseTestSuite) TestBatchSetSoftwareInstallers() { require.Nil(t, packages[0].TeamID) newTitlesResp = listSoftwareTitlesResponse{} s.DoJSON("GET", "/api/v1/fleet/software/titles", nil, http.StatusOK, &newTitlesResp, "available_for_install", "true", "team_id", strconv.Itoa(int(0))) - titlesResp.SoftwareTitles[0].SoftwarePackage.SelfService = ptr.Bool(true) + titlesResp.SoftwareTitles[0].SoftwarePackage.SelfService = new(true) require.Equal(t, titlesResp, newTitlesResp) // create some labels A, B and C @@ -14573,8 +14572,8 @@ func (s *integrationEnterpriseTestSuite) TestBatchSetSoftwareInstallersSideEffec LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now().Add(-1 * time.Minute), - OsqueryHostID: ptr.String(t.Name() + uuid.New().String()), - NodeKey: ptr.String(t.Name() + uuid.New().String()), + OsqueryHostID: new(t.Name() + uuid.New().String()), + NodeKey: new(t.Name() + uuid.New().String()), Hostname: fmt.Sprintf("%sfoo.local", t.Name()), Platform: "ubuntu", }) @@ -14593,8 +14592,8 @@ func (s *integrationEnterpriseTestSuite) TestBatchSetSoftwareInstallersSideEffec LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now().Add(-1 * time.Minute), - OsqueryHostID: ptr.String(t.Name() + uuid.New().String()), - NodeKey: ptr.String(t.Name() + uuid.New().String()), + OsqueryHostID: new(t.Name() + uuid.New().String()), + NodeKey: new(t.Name() + uuid.New().String()), Hostname: fmt.Sprintf("%sbar.local", t.Name()), Platform: "ubuntu", }) @@ -14971,8 +14970,8 @@ func (s *integrationEnterpriseTestSuite) TestBatchSetSoftwareInstallersCondition } func (s *integrationEnterpriseTestSuite) TestBatchSetSoftwareInstallersWithPoliciesAssociated() { - ctx := context.Background() t := s.T() + ctx := context.Background() team1, err := s.ds.NewTeam(ctx, &fleet.Team{Name: "team1"}) require.NoError(t, err) @@ -15131,8 +15130,8 @@ func (s *integrationEnterpriseTestSuite) TestSoftwareInstallerNewInstallRequestP LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now().Add(-1 * time.Minute), - OsqueryHostID: ptr.String(t.Name() + uuid.New().String()), - NodeKey: ptr.String(t.Name() + uuid.New().String()), + OsqueryHostID: new(t.Name() + uuid.New().String()), + NodeKey: new(t.Name() + uuid.New().String()), Hostname: fmt.Sprintf("%sfoo.local", t.Name()), Platform: platform, }) @@ -15261,8 +15260,8 @@ func (s *integrationEnterpriseTestSuite) TestSoftwareInstallerHostRequests() { LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now().Add(-1 * time.Minute), - OsqueryHostID: ptr.String(t.Name() + uuid.New().String()), - NodeKey: ptr.String(t.Name() + uuid.New().String()), + OsqueryHostID: new(t.Name() + uuid.New().String()), + NodeKey: new(t.Name() + uuid.New().String()), Hostname: fmt.Sprintf("%sfoo.local", t.Name()), Platform: "ubuntu", }) @@ -15824,7 +15823,7 @@ func (s *integrationEnterpriseTestSuite) TestSelfServiceSoftwareInstallUninstall }}, http.StatusOK, &labelResp) require.NotZero(t, labelResp.Label.ID) - err := s.ds.RecordLabelQueryExecutions(context.Background(), host1, map[uint]*bool{labelResp.Label.ID: ptr.Bool(true)}, time.Now(), false) + err := s.ds.RecordLabelQueryExecutions(context.Background(), host1, map[uint]*bool{labelResp.Label.ID: new(true)}, time.Now(), false) require.NoError(t, err) payloadNoSS := &fleet.UploadSoftwareInstallerPayload{ @@ -15986,8 +15985,8 @@ func (s *integrationEnterpriseTestSuite) TestSelfServiceSoftwareInstallUninstall } func (s *integrationEnterpriseTestSuite) TestHostSoftwareInstallResult() { - ctx := context.Background() t := s.T() + ctx := context.Background() host := createOrbitEnrolledHost(t, "linux", "", s.ds) @@ -16074,8 +16073,8 @@ func (s *integrationEnterpriseTestSuite) TestHostSoftwareInstallResult() { HostID: host.ID, InstallUUID: installUUIDs[0], Status: fleet.SoftwareInstallFailed, - PreInstallQueryOutput: ptr.String(fleet.SoftwareInstallerQuerySuccessCopy), - Output: ptr.String(fmt.Sprintf(fleet.SoftwareInstallerInstallFailCopy, "failed")), + PreInstallQueryOutput: new(fleet.SoftwareInstallerQuerySuccessCopy), + Output: new(fmt.Sprintf(fleet.SoftwareInstallerInstallFailCopy, "failed")), }) wantAct := fleet.ActivityTypeInstalledSoftware{ HostID: host.ID, @@ -16084,7 +16083,7 @@ func (s *integrationEnterpriseTestSuite) TestHostSoftwareInstallResult() { SoftwarePackage: payload.Filename, InstallUUID: installUUIDs[0], Status: string(fleet.SoftwareInstallFailed), - Source: ptr.String("deb_packages"), + Source: new("deb_packages"), } s.lastActivityMatches(wantAct.ActivityName(), string(jsonMustMarshal(t, wantAct)), 0) @@ -16100,7 +16099,7 @@ func (s *integrationEnterpriseTestSuite) TestHostSoftwareInstallResult() { HostID: host.ID, InstallUUID: installUUIDs[1], Status: fleet.SoftwareInstallFailed, - PreInstallQueryOutput: ptr.String(fleet.SoftwareInstallerQueryFailCopy), + PreInstallQueryOutput: new(fleet.SoftwareInstallerQueryFailCopy), }) wantAct = fleet.ActivityTypeInstalledSoftware{ HostID: host.ID, @@ -16109,7 +16108,7 @@ func (s *integrationEnterpriseTestSuite) TestHostSoftwareInstallResult() { SoftwarePackage: payload2.Filename, InstallUUID: installUUIDs[1], Status: string(fleet.SoftwareInstallFailed), - Source: ptr.String("deb_packages"), + Source: new("deb_packages"), } s.lastActivityOfTypeMatches(wantAct.ActivityName(), string(jsonMustMarshal(t, wantAct)), 0) @@ -16129,9 +16128,9 @@ func (s *integrationEnterpriseTestSuite) TestHostSoftwareInstallResult() { HostID: host.ID, InstallUUID: installUUIDs[2], Status: fleet.SoftwareInstalled, - PreInstallQueryOutput: ptr.String(fleet.SoftwareInstallerQuerySuccessCopy), - Output: ptr.String(fmt.Sprintf(fleet.SoftwareInstallerInstallSuccessCopy, "success")), - PostInstallScriptOutput: ptr.String(fmt.Sprintf(fleet.SoftwareInstallerPostInstallSuccessCopy, "ok")), + PreInstallQueryOutput: new(fleet.SoftwareInstallerQuerySuccessCopy), + Output: new(fmt.Sprintf(fleet.SoftwareInstallerInstallSuccessCopy, "success")), + PostInstallScriptOutput: new(fmt.Sprintf(fleet.SoftwareInstallerPostInstallSuccessCopy, "ok")), }) wantAct = fleet.ActivityTypeInstalledSoftware{ HostID: host.ID, @@ -16140,7 +16139,7 @@ func (s *integrationEnterpriseTestSuite) TestHostSoftwareInstallResult() { SoftwarePackage: payload3.Filename, InstallUUID: installUUIDs[2], Status: string(fleet.SoftwareInstalled), - Source: ptr.String("deb_packages"), + Source: new("deb_packages"), } lastActID := s.lastActivityOfTypeMatches(wantAct.ActivityName(), string(jsonMustMarshal(t, wantAct)), 0) @@ -16168,7 +16167,7 @@ func (s *integrationEnterpriseTestSuite) TestHostSoftwareInstallResult() { HostID: host.ID, InstallUUID: installUUIDs[2], Status: fleet.SoftwareInstallFailed, - Output: ptr.String(fleet.SoftwareInstallerDownloadFailedCopy), + Output: new(fleet.SoftwareInstallerDownloadFailedCopy), }) wantAct = fleet.ActivityTypeInstalledSoftware{ HostID: host.ID, @@ -16177,7 +16176,7 @@ func (s *integrationEnterpriseTestSuite) TestHostSoftwareInstallResult() { SoftwarePackage: payload3.Filename, InstallUUID: installUUIDs[2], Status: string(fleet.SoftwareInstallFailed), - Source: ptr.String("deb_packages"), + Source: new("deb_packages"), } s.lastActivityOfTypeMatches(wantAct.ActivityName(), string(jsonMustMarshal(t, wantAct)), 0) @@ -16505,8 +16504,8 @@ func (s *integrationEnterpriseTestSuite) TestPKGNewSoftwareTitleFlow() { LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now().Add(-1 * time.Minute), - OsqueryHostID: ptr.String(t.Name()), - NodeKey: ptr.String(t.Name()), + OsqueryHostID: new(t.Name()), + NodeKey: new(t.Name()), UUID: uuid.New().String(), Hostname: fmt.Sprintf("%sfoo.local", t.Name()), Platform: "darwin", @@ -16697,21 +16696,21 @@ func (s *integrationEnterpriseTestSuite) TestEXEPackageUploads() { require.NotZero(t, titleID) s.updateSoftwareInstaller(t, &fleet.UpdateSoftwareInstallerPayload{ - InstallScript: ptr.String(""), + InstallScript: new(""), TitleID: titleID, TeamID: &team.ID, }, http.StatusBadRequest, "Couldn't edit. Install script is required for .exe packages.") s.updateSoftwareInstaller(t, &fleet.UpdateSoftwareInstallerPayload{ Filename: "hello-world-installer.exe", - UninstallScript: ptr.String(""), + UninstallScript: new(""), TitleID: titleID, TeamID: &team.ID, }, http.StatusBadRequest, "Couldn't edit. Uninstall script is required for .exe packages.") s.updateSoftwareInstaller(t, &fleet.UpdateSoftwareInstallerPayload{ Filename: "hello-world-installer.exe", - PostInstallScript: ptr.String("foo bar baz"), + PostInstallScript: new("foo bar baz"), TitleID: titleID, TeamID: &team.ID, }, http.StatusOK, "") @@ -16803,9 +16802,9 @@ func (s *integrationEnterpriseTestSuite) TestScriptPackageUploads() { // Test editing script package with unsupported params (should be ignored) s.updateSoftwareInstaller(t, &fleet.UpdateSoftwareInstallerPayload{ Filename: "install-app.sh", - UninstallScript: ptr.String("should be cleared"), - PostInstallScript: ptr.String("should be cleared"), - PreInstallQuery: ptr.String("should be cleared"), + UninstallScript: new("should be cleared"), + PostInstallScript: new("should be cleared"), + PreInstallQuery: new("should be cleared"), TitleID: titleID, TeamID: &team.ID, }, http.StatusOK, "") @@ -16842,8 +16841,8 @@ func (s *integrationEnterpriseTestSuite) TestPKGSoftwareAlreadyReported() { LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now().Add(-1 * time.Minute), - OsqueryHostID: ptr.String(t.Name()), - NodeKey: ptr.String(t.Name()), + OsqueryHostID: new(t.Name()), + NodeKey: new(t.Name()), UUID: uuid.New().String(), Hostname: fmt.Sprintf("%sfoo.local", t.Name()), Platform: "darwin", @@ -16930,8 +16929,8 @@ func (s *integrationEnterpriseTestSuite) TestPKGSoftwareReconciliation() { LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now().Add(-1 * time.Minute), - OsqueryHostID: ptr.String(t.Name()), - NodeKey: ptr.String(t.Name()), + OsqueryHostID: new(t.Name()), + NodeKey: new(t.Name()), UUID: uuid.New().String(), Hostname: fmt.Sprintf("%sfoo.local", t.Name()), Platform: "darwin", @@ -16999,8 +16998,8 @@ func (s *integrationEnterpriseTestSuite) TestPKGSoftwareReconciliation() { } func (s *integrationEnterpriseTestSuite) TestCalendarCallback() { - ctx := context.Background() t := s.T() + ctx := context.Background() t.Cleanup(func() { calendar.ClearMockEvents() calendar.ClearMockChannels() @@ -17029,8 +17028,8 @@ func (s *integrationEnterpriseTestSuite) TestCalendarCallback() { LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now().Add(-1 * time.Minute), - OsqueryHostID: ptr.String(t.Name() + name), - NodeKey: ptr.String(t.Name() + name), + OsqueryHostID: new(t.Name() + name), + NodeKey: new(t.Name() + name), UUID: uuid.New().String(), Hostname: fmt.Sprintf("%s.%s.local", name, t.Name()), Platform: "darwin", @@ -17104,8 +17103,8 @@ func (s *integrationEnterpriseTestSuite) TestCalendarCallback() { s.DoJSON("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( host1Team1, map[uint]*bool{ - team1Policy1Calendar.ID: ptr.Bool(false), - team1Policy2Calendar.ID: ptr.Bool(true), + team1Policy1Calendar.ID: new(false), + team1Policy2Calendar.ID: new(true), globalPolicy.ID: nil, }, ), http.StatusOK, &distributedResp) @@ -17114,8 +17113,8 @@ func (s *integrationEnterpriseTestSuite) TestCalendarCallback() { s.DoJSON("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( host2Team1, map[uint]*bool{ - team1Policy1Calendar.ID: ptr.Bool(true), - team1Policy2Calendar.ID: ptr.Bool(false), + team1Policy1Calendar.ID: new(true), + team1Policy2Calendar.ID: new(false), globalPolicy.ID: nil, }, ), http.StatusOK, &distributedResp) @@ -17442,8 +17441,8 @@ func (s *integrationEnterpriseTestSuite) TestCalendarCallback() { s.DoJSON("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( host1Team1, map[uint]*bool{ - team1Policy1Calendar.ID: ptr.Bool(true), - team1Policy2Calendar.ID: ptr.Bool(true), + team1Policy1Calendar.ID: new(true), + team1Policy2Calendar.ID: new(true), globalPolicy.ID: nil, }, ), http.StatusOK, &distributedResp) @@ -17494,8 +17493,8 @@ func (s *integrationEnterpriseTestSuite) TestCalendarCallback() { } func (s *integrationEnterpriseTestSuite) TestCalendarEventBodyUpdate() { - ctx := context.Background() t := s.T() + ctx := context.Background() t.Cleanup(func() { calendar.ClearMockEvents() calendar.ClearMockChannels() @@ -17523,8 +17522,8 @@ func (s *integrationEnterpriseTestSuite) TestCalendarEventBodyUpdate() { LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now().Add(-1 * time.Minute), - OsqueryHostID: ptr.String(t.Name() + name), - NodeKey: ptr.String(t.Name() + name), + OsqueryHostID: new(t.Name() + name), + NodeKey: new(t.Name() + name), UUID: uuid.New().String(), Hostname: fmt.Sprintf("%s.%s.local", name, t.Name()), Platform: "darwin", @@ -17604,8 +17603,8 @@ func (s *integrationEnterpriseTestSuite) TestCalendarEventBodyUpdate() { s.DoJSON("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( host1Team1, map[uint]*bool{ - team1Policy1Calendar.ID: ptr.Bool(false), - team1Policy2Calendar.ID: ptr.Bool(true), + team1Policy1Calendar.ID: new(false), + team1Policy2Calendar.ID: new(true), globalPolicy.ID: nil, }, ), http.StatusOK, &distributedResp) @@ -17614,8 +17613,8 @@ func (s *integrationEnterpriseTestSuite) TestCalendarEventBodyUpdate() { s.DoJSON("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( host2Team1, map[uint]*bool{ - team1Policy1Calendar.ID: ptr.Bool(true), - team1Policy2Calendar.ID: ptr.Bool(false), + team1Policy1Calendar.ID: new(true), + team1Policy2Calendar.ID: new(false), globalPolicy.ID: nil, }, ), http.StatusOK, &distributedResp) @@ -17695,7 +17694,7 @@ func (s *integrationEnterpriseTestSuite) TestCalendarEventBodyUpdate() { assert.Contains(t, calEvents[0].Description, fleet.CalendarDefaultResolution) // Put resolution back - team1Policy1Calendar.Resolution = ptr.String("putResolutionBack") + team1Policy1Calendar.Resolution = new("putResolutionBack") require.NoError(t, s.ds.SavePolicy(ctx, team1Policy1Calendar, false, false)) triggerAndWait(ctx, t, s.ds, s.calendarSchedule, 5*time.Second) @@ -17705,7 +17704,7 @@ func (s *integrationEnterpriseTestSuite) TestCalendarEventBodyUpdate() { assert.Contains(t, calEvents[0].Description, *team1Policy1Calendar.Resolution) // Change resolution - team1Policy1Calendar.Resolution = ptr.String("changeResolution") + team1Policy1Calendar.Resolution = new("changeResolution") require.NoError(t, s.ds.SavePolicy(ctx, team1Policy1Calendar, false, false)) triggerAndWait(ctx, t, s.ds, s.calendarSchedule, 5*time.Second) @@ -17718,8 +17717,8 @@ func (s *integrationEnterpriseTestSuite) TestCalendarEventBodyUpdate() { s.DoJSON("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( host1Team1, map[uint]*bool{ - team1Policy1Calendar.ID: ptr.Bool(false), - team1Policy2Calendar.ID: ptr.Bool(false), + team1Policy1Calendar.ID: new(false), + team1Policy2Calendar.ID: new(false), globalPolicy.ID: nil, }, ), http.StatusOK, &distributedResp) @@ -17734,8 +17733,8 @@ func (s *integrationEnterpriseTestSuite) TestCalendarEventBodyUpdate() { s.DoJSON("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( host1Team1, map[uint]*bool{ - team1Policy1Calendar.ID: ptr.Bool(false), - team1Policy2Calendar.ID: ptr.Bool(true), + team1Policy1Calendar.ID: new(false), + team1Policy2Calendar.ID: new(true), globalPolicy.ID: nil, }, ), http.StatusOK, &distributedResp) @@ -17807,7 +17806,7 @@ func (s *integrationEnterpriseTestSuite) TestVPPAppsWithoutMDM() { // Create team and add host to team var newTeamResp teamResponse - s.DoJSON("POST", "/api/latest/fleet/teams", &createTeamRequest{TeamPayload: fleet.TeamPayload{Name: ptr.String("Team 1")}}, http.StatusOK, &newTeamResp) + s.DoJSON("POST", "/api/latest/fleet/teams", &createTeamRequest{TeamPayload: fleet.TeamPayload{Name: new("Team 1")}}, http.StatusOK, &newTeamResp) team := newTeamResp.Team s.Do("POST", "/api/latest/fleet/hosts/transfer", &addHostsToTeamRequest{HostIDs: []uint{orbitHost.ID}, TeamID: &team.ID}, http.StatusOK) @@ -17860,8 +17859,8 @@ func (s *integrationEnterpriseTestSuite) TestPolicyAutomationsSoftwareInstallers LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now().Add(-1 * time.Minute), - OsqueryHostID: ptr.String(t.Name() + name), - NodeKey: ptr.String(t.Name() + name), + OsqueryHostID: new(t.Name() + name), + NodeKey: new(t.Name() + name), UUID: uuid.New().String(), Hostname: fmt.Sprintf("%s.%s.local", name, t.Name()), Platform: platform, @@ -18179,7 +18178,7 @@ func (s *integrationEnterpriseTestSuite) TestPolicyAutomationsSoftwareInstallers s.DoJSONWithoutAuth("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( host1Team1, map[uint]*bool{ - policy1Team1.ID: ptr.Bool(false), + policy1Team1.ID: new(false), }, ), http.StatusOK, &distributedResp) err = s.ds.UpdateHostPolicyCounts(ctx) @@ -18227,7 +18226,7 @@ func (s *integrationEnterpriseTestSuite) TestPolicyAutomationsSoftwareInstallers s.DoJSONWithoutAuth("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( host1Team1, map[uint]*bool{ - policy1Team1.ID: ptr.Bool(false), + policy1Team1.ID: new(false), }, ), http.StatusOK, &distributedResp) err = s.ds.UpdateHostPolicyCounts(ctx) @@ -18300,9 +18299,9 @@ func (s *integrationEnterpriseTestSuite) TestPolicyAutomationsSoftwareInstallers s.DoJSONWithoutAuth("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( host1Team1, map[uint]*bool{ - policy1Team1.ID: ptr.Bool(false), - policy2Team1.ID: ptr.Bool(false), - policy3Team1.ID: ptr.Bool(false), + policy1Team1.ID: new(false), + policy2Team1.ID: new(false), + policy3Team1.ID: new(false), }, ), http.StatusOK, &distributedResp) @@ -18324,9 +18323,9 @@ func (s *integrationEnterpriseTestSuite) TestPolicyAutomationsSoftwareInstallers s.DoJSONWithoutAuth("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( host1Team1, map[uint]*bool{ - policy1Team1.ID: ptr.Bool(false), - policy2Team1.ID: ptr.Bool(false), - policy3Team1.ID: ptr.Bool(false), + policy1Team1.ID: new(false), + policy2Team1.ID: new(false), + policy3Team1.ID: new(false), }, ), http.StatusOK, &distributedResp) @@ -18343,18 +18342,18 @@ func (s *integrationEnterpriseTestSuite) TestPolicyAutomationsSoftwareInstallers s.DoJSONWithoutAuth("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( host1Team1, map[uint]*bool{ - policy1Team1.ID: ptr.Bool(true), - policy2Team1.ID: ptr.Bool(false), - policy3Team1.ID: ptr.Bool(false), + policy1Team1.ID: new(true), + policy2Team1.ID: new(false), + policy3Team1.ID: new(false), }, ), http.StatusOK, &distributedResp) distributedResp = submitDistributedQueryResultsResponse{} s.DoJSONWithoutAuth("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( host1Team1, map[uint]*bool{ - policy1Team1.ID: ptr.Bool(false), - policy2Team1.ID: ptr.Bool(false), - policy3Team1.ID: ptr.Bool(false), + policy1Team1.ID: new(false), + policy2Team1.ID: new(false), + policy3Team1.ID: new(false), }, ), http.StatusOK, &distributedResp) @@ -18371,8 +18370,8 @@ func (s *integrationEnterpriseTestSuite) TestPolicyAutomationsSoftwareInstallers s.DoJSONWithoutAuth("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( host2Team1, map[uint]*bool{ - policy2Team1.ID: ptr.Bool(false), - policy3Team1.ID: ptr.Bool(false), + policy2Team1.ID: new(false), + policy3Team1.ID: new(false), }, ), http.StatusOK, &distributedResp) @@ -18396,7 +18395,7 @@ func (s *integrationEnterpriseTestSuite) TestPolicyAutomationsSoftwareInstallers s.DoJSONWithoutAuth("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( host3Team2, map[uint]*bool{ - policy4Team2.ID: ptr.Bool(false), + policy4Team2.ID: new(false), }, ), http.StatusOK, &distributedResp) @@ -18421,7 +18420,7 @@ func (s *integrationEnterpriseTestSuite) TestPolicyAutomationsSoftwareInstallers s.DoJSONWithoutAuth("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( host3Team2, map[uint]*bool{ - policy0AllTeams.ID: ptr.Bool(true), + policy0AllTeams.ID: new(true), }, ), http.StatusOK, &distributedResp) @@ -18430,7 +18429,7 @@ func (s *integrationEnterpriseTestSuite) TestPolicyAutomationsSoftwareInstallers s.DoJSONWithoutAuth("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( host0NoTeam, map[uint]*bool{ - policy0AllTeams.ID: ptr.Bool(false), + policy0AllTeams.ID: new(false), }, ), http.StatusOK, &distributedResp) @@ -18439,7 +18438,7 @@ func (s *integrationEnterpriseTestSuite) TestPolicyAutomationsSoftwareInstallers s.DoJSONWithoutAuth("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( host3Team2, map[uint]*bool{ - policy0AllTeams.ID: ptr.Bool(false), + policy0AllTeams.ID: new(false), }, ), http.StatusOK, &distributedResp) @@ -18456,7 +18455,7 @@ func (s *integrationEnterpriseTestSuite) TestPolicyAutomationsSoftwareInstallers s.DoJSONWithoutAuth("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( host3Team2, map[uint]*bool{ - policy4Team2.ID: ptr.Bool(false), + policy4Team2.ID: new(false), }, ), http.StatusOK, &distributedResp) @@ -18536,7 +18535,7 @@ func (s *integrationEnterpriseTestSuite) TestPolicyAutomationsSoftwareInstallers s.DoJSONWithoutAuth("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( hostVanillaOsquery5Team1, map[uint]*bool{ - policy1Team1.ID: ptr.Bool(false), + policy1Team1.ID: new(false), }, ), http.StatusOK, &distributedResp) hostVanillaOsquery5Team1LastInstall, err := s.ds.GetHostLastInstallData(ctx, hostVanillaOsquery5Team1.ID, dummyInstallerPkgInstallerID) @@ -18558,8 +18557,8 @@ func (s *integrationEnterpriseTestSuite) TestPolicyAutomationSoftwareInstallRetr LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now().Add(-1 * time.Minute), - OsqueryHostID: ptr.String(t.Name()), - NodeKey: ptr.String(t.Name()), + OsqueryHostID: new(t.Name()), + NodeKey: new(t.Name()), UUID: uuid.New().String(), Hostname: fmt.Sprintf("%s.local", t.Name()), Platform: "darwin", @@ -18619,7 +18618,7 @@ func (s *integrationEnterpriseTestSuite) TestPolicyAutomationSoftwareInstallRetr s.DoJSONWithoutAuth("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( host, map[uint]*bool{ - policyID: ptr.Bool(passes), + policyID: new(passes), }, ), http.StatusOK, &distributedResp) } @@ -18884,8 +18883,8 @@ func (s *integrationEnterpriseTestSuite) TestNonPolicySoftwareInstallRetries() { LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now().Add(-1 * time.Minute), - OsqueryHostID: ptr.String(t.Name()), - NodeKey: ptr.String(t.Name()), + OsqueryHostID: new(t.Name()), + NodeKey: new(t.Name()), UUID: uuid.New().String(), Hostname: fmt.Sprintf("%s.local", t.Name()), Platform: "darwin", @@ -19121,8 +19120,8 @@ func (s *integrationEnterpriseTestSuite) TestPolicyAutomationsSoftwareInstallers LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now().Add(-1 * time.Minute), - OsqueryHostID: ptr.String(t.Name()), - NodeKey: ptr.String(t.Name()), + OsqueryHostID: new(t.Name()), + NodeKey: new(t.Name()), UUID: uuid.New().String(), Hostname: fmt.Sprintf("%sfoo.local", t.Name()), Platform: "linux", @@ -19154,7 +19153,7 @@ func (s *integrationEnterpriseTestSuite) TestPolicyAutomationsSoftwareInstallers lbl3 := newLabelResp.Label // Add label1 and label2 to the host - err = s.ds.RecordLabelQueryExecutions(context.Background(), host, map[uint]*bool{lbl1.ID: ptr.Bool(true), lbl2.ID: ptr.Bool(true)}, time.Now(), false) + err = s.ds.RecordLabelQueryExecutions(context.Background(), host, map[uint]*bool{lbl1.ID: new(true), lbl2.ID: new(true)}, time.Now(), false) require.NoError(t, err) // upload software. Add label1 and label3 as "exclude any" labels. @@ -19209,7 +19208,7 @@ func (s *integrationEnterpriseTestSuite) TestPolicyAutomationsSoftwareInstallers s.DoJSONWithoutAuth("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( host, map[uint]*bool{ - policy1.ID: ptr.Bool(false), + policy1.ID: new(false), }, ), http.StatusOK, &distributedResp) err = s.ds.UpdateHostPolicyCounts(ctx) @@ -19274,7 +19273,7 @@ func (s *integrationEnterpriseTestSuite) TestPolicyAutomationsSoftwareInstallers s.DoJSONWithoutAuth("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( host, map[uint]*bool{ - policy2.ID: ptr.Bool(false), + policy2.ID: new(false), }, ), http.StatusOK, &distributedResp) err = s.ds.UpdateHostPolicyCounts(ctx) @@ -19472,8 +19471,8 @@ func (s *integrationEnterpriseTestSuite) TestPolicyAutomationLabelScopingRetrigg LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now().Add(-1 * time.Minute), - OsqueryHostID: ptr.String(t.Name()), - NodeKey: ptr.String(t.Name()), + OsqueryHostID: new(t.Name()), + NodeKey: new(t.Name()), UUID: uuid.New().String(), Hostname: fmt.Sprintf("%sfoo.local", t.Name()), Platform: "linux", @@ -19505,7 +19504,7 @@ func (s *integrationEnterpriseTestSuite) TestPolicyAutomationLabelScopingRetrigg lbl3 := newLabelResp.Label // Add label1 and label2 to the host - err = s.ds.RecordLabelQueryExecutions(context.Background(), host, map[uint]*bool{lbl1.ID: ptr.Bool(true), lbl2.ID: ptr.Bool(true)}, time.Now(), false) + err = s.ds.RecordLabelQueryExecutions(context.Background(), host, map[uint]*bool{lbl1.ID: new(true), lbl2.ID: new(true)}, time.Now(), false) require.NoError(t, err) // upload software. Add label1 and label3 as "exclude any" labels. @@ -19561,7 +19560,7 @@ func (s *integrationEnterpriseTestSuite) TestPolicyAutomationLabelScopingRetrigg s.DoJSONWithoutAuth("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( host, map[uint]*bool{ - policy1.ID: ptr.Bool(false), + policy1.ID: new(false), }, ), http.StatusOK, &distributedResp) err = s.ds.UpdateHostPolicyCounts(ctx) @@ -19580,9 +19579,9 @@ func (s *integrationEnterpriseTestSuite) TestPolicyAutomationLabelScopingRetrigg // Update the installer's labels to "exclude any". This de-scopes the software. s.updateSoftwareInstaller(t, &fleet.UpdateSoftwareInstallerPayload{ - InstallScript: ptr.String("some install script"), - PreInstallQuery: ptr.String("some pre install query"), - PostInstallScript: ptr.String("some post install script"), + InstallScript: new("some install script"), + PreInstallQuery: new("some pre install query"), + PostInstallScript: new("some post install script"), Filename: "ruby.deb", TitleID: rubyDebTitleID, TeamID: nil, @@ -19596,9 +19595,9 @@ func (s *integrationEnterpriseTestSuite) TestPolicyAutomationLabelScopingRetrigg // Update the installer's labels to be "include any" again. The software is now back in scope. s.updateSoftwareInstaller(t, &fleet.UpdateSoftwareInstallerPayload{ - InstallScript: ptr.String("some install script"), - PreInstallQuery: ptr.String("some pre install query"), - PostInstallScript: ptr.String("some post install script"), + InstallScript: new("some install script"), + PreInstallQuery: new("some pre install query"), + PostInstallScript: new("some post install script"), Filename: "ruby.deb", TitleID: rubyDebTitleID, TeamID: nil, @@ -19609,7 +19608,7 @@ func (s *integrationEnterpriseTestSuite) TestPolicyAutomationLabelScopingRetrigg s.DoJSONWithoutAuth("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( host, map[uint]*bool{ - policy1.ID: ptr.Bool(false), + policy1.ID: new(false), }, ), http.StatusOK, &distributedResp) err = s.ds.UpdateHostPolicyCounts(ctx) @@ -19628,9 +19627,9 @@ func (s *integrationEnterpriseTestSuite) TestPolicyAutomationLabelScopingRetrigg // Update the include any labels. The host doesn't have label2, so this means that the software // moved out of scope. s.updateSoftwareInstaller(t, &fleet.UpdateSoftwareInstallerPayload{ - InstallScript: ptr.String("some install script"), - PreInstallQuery: ptr.String("some pre install query"), - PostInstallScript: ptr.String("some post install script"), + InstallScript: new("some install script"), + PreInstallQuery: new("some pre install query"), + PostInstallScript: new("some post install script"), Filename: "ruby.deb", TitleID: rubyDebTitleID, TeamID: nil, @@ -19644,9 +19643,9 @@ func (s *integrationEnterpriseTestSuite) TestPolicyAutomationLabelScopingRetrigg // Update to exclude any with label 2. This moves the software back into scope. The policy // automation should re-trigger. s.updateSoftwareInstaller(t, &fleet.UpdateSoftwareInstallerPayload{ - InstallScript: ptr.String("some install script"), - PreInstallQuery: ptr.String("some pre install query"), - PostInstallScript: ptr.String("some post install script"), + InstallScript: new("some install script"), + PreInstallQuery: new("some pre install query"), + PostInstallScript: new("some post install script"), Filename: "ruby.deb", TitleID: rubyDebTitleID, TeamID: nil, @@ -19656,7 +19655,7 @@ func (s *integrationEnterpriseTestSuite) TestPolicyAutomationLabelScopingRetrigg s.DoJSONWithoutAuth("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( host, map[uint]*bool{ - policy1.ID: ptr.Bool(false), + policy1.ID: new(false), }, ), http.StatusOK, &distributedResp) err = s.ds.UpdateHostPolicyCounts(ctx) @@ -19688,8 +19687,8 @@ func (s *integrationEnterpriseTestSuite) TestPolicyAutomationsScripts() { LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now().Add(-1 * time.Minute), - OsqueryHostID: ptr.String(t.Name() + name), - NodeKey: ptr.String(t.Name() + name), + OsqueryHostID: new(t.Name() + name), + NodeKey: new(t.Name() + name), UUID: uuid.New().String(), Hostname: fmt.Sprintf("%s.%s.local", name, t.Name()), Platform: platform, @@ -19832,7 +19831,7 @@ func (s *integrationEnterpriseTestSuite) TestPolicyAutomationsScripts() { s.DoJSONWithoutAuth("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( host1Team1, map[uint]*bool{ - policy1Team1.ID: ptr.Bool(false), + policy1Team1.ID: new(false), }, ), http.StatusOK, &distributedResp) err = s.ds.UpdateHostPolicyCounts(ctx) @@ -19880,7 +19879,7 @@ func (s *integrationEnterpriseTestSuite) TestPolicyAutomationsScripts() { s.DoJSONWithoutAuth("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( host1Team1, map[uint]*bool{ - policy1Team1.ID: ptr.Bool(false), + policy1Team1.ID: new(false), }, ), http.StatusOK, &distributedResp) err = s.ds.UpdateHostPolicyCounts(ctx) @@ -19952,9 +19951,9 @@ func (s *integrationEnterpriseTestSuite) TestPolicyAutomationsScripts() { s.DoJSONWithoutAuth("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( host1Team1, map[uint]*bool{ - policy1Team1.ID: ptr.Bool(false), - policy2Team1.ID: ptr.Bool(false), - policy3Team1.ID: ptr.Bool(false), + policy1Team1.ID: new(false), + policy2Team1.ID: new(false), + policy3Team1.ID: new(false), }, ), http.StatusOK, &distributedResp) @@ -19971,9 +19970,9 @@ func (s *integrationEnterpriseTestSuite) TestPolicyAutomationsScripts() { s.DoJSONWithoutAuth("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( host1Team1, map[uint]*bool{ - policy1Team1.ID: ptr.Bool(false), - policy2Team1.ID: ptr.Bool(false), - policy3Team1.ID: ptr.Bool(false), + policy1Team1.ID: new(false), + policy2Team1.ID: new(false), + policy3Team1.ID: new(false), }, ), http.StatusOK, &distributedResp) @@ -19987,18 +19986,18 @@ func (s *integrationEnterpriseTestSuite) TestPolicyAutomationsScripts() { s.DoJSONWithoutAuth("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( host1Team1, map[uint]*bool{ - policy1Team1.ID: ptr.Bool(true), - policy2Team1.ID: ptr.Bool(false), - policy3Team1.ID: ptr.Bool(false), + policy1Team1.ID: new(true), + policy2Team1.ID: new(false), + policy3Team1.ID: new(false), }, ), http.StatusOK, &distributedResp) distributedResp = submitDistributedQueryResultsResponse{} s.DoJSONWithoutAuth("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( host1Team1, map[uint]*bool{ - policy1Team1.ID: ptr.Bool(false), - policy2Team1.ID: ptr.Bool(false), - policy3Team1.ID: ptr.Bool(false), + policy1Team1.ID: new(false), + policy2Team1.ID: new(false), + policy3Team1.ID: new(false), }, ), http.StatusOK, &distributedResp) @@ -20011,8 +20010,8 @@ func (s *integrationEnterpriseTestSuite) TestPolicyAutomationsScripts() { s.DoJSONWithoutAuth("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( host2Team1, map[uint]*bool{ - policy2Team1.ID: ptr.Bool(false), - policy3Team1.ID: ptr.Bool(false), + policy2Team1.ID: new(false), + policy3Team1.ID: new(false), }, ), http.StatusOK, &distributedResp) @@ -20033,7 +20032,7 @@ func (s *integrationEnterpriseTestSuite) TestPolicyAutomationsScripts() { s.DoJSONWithoutAuth("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( host3Team2, map[uint]*bool{ - policy4Team2.ID: ptr.Bool(false), + policy4Team2.ID: new(false), }, ), http.StatusOK, &distributedResp) @@ -20055,7 +20054,7 @@ func (s *integrationEnterpriseTestSuite) TestPolicyAutomationsScripts() { s.DoJSONWithoutAuth("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( host3Team2, map[uint]*bool{ - policy4Team2.ID: ptr.Bool(false), + policy4Team2.ID: new(false), }, ), http.StatusOK, &distributedResp) @@ -20065,7 +20064,7 @@ func (s *integrationEnterpriseTestSuite) TestPolicyAutomationsScripts() { s.DoJSONWithoutAuth("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( hostVanillaOsquery5Team1, map[uint]*bool{ - policy1Team1.ID: ptr.Bool(false), + policy1Team1.ID: new(false), }, ), http.StatusOK, &distributedResp) hostPendingScripts, err := s.ds.ListPendingHostScriptExecutions(ctx, hostVanillaOsquery5Team1.ID, false) @@ -20119,8 +20118,8 @@ func (s *integrationEnterpriseTestSuite) TestPolicyAutomationScriptRetries() { LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now().Add(-1 * time.Minute), - OsqueryHostID: ptr.String(t.Name()), - NodeKey: ptr.String(t.Name()), + OsqueryHostID: new(t.Name()), + NodeKey: new(t.Name()), UUID: uuid.New().String(), Hostname: fmt.Sprintf("%s.local", t.Name()), Platform: "darwin", @@ -20164,7 +20163,7 @@ func (s *integrationEnterpriseTestSuite) TestPolicyAutomationScriptRetries() { s.DoJSONWithoutAuth("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( host, map[uint]*bool{ - policyID: ptr.Bool(passes), + policyID: new(passes), }, ), http.StatusOK, &distributedResp) } @@ -20414,8 +20413,8 @@ func (s *integrationEnterpriseTestSuite) TestSoftwareInstallersWithoutBundleIden LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now().Add(-1 * time.Minute), - OsqueryHostID: ptr.String(t.Name()), - NodeKey: ptr.String(t.Name()), + OsqueryHostID: new(t.Name()), + NodeKey: new(t.Name()), UUID: uuid.New().String(), Hostname: fmt.Sprintf("%sfoo.local", t.Name()), Platform: "darwin", @@ -20499,7 +20498,7 @@ func (s *integrationEnterpriseTestSuite) TestSoftwareUploadRPM() { SoftwarePackage: payload.Filename, InstallUUID: installUUID, Status: string(fleet.SoftwareInstallFailed), - Source: ptr.String("rpm_packages"), + Source: new("rpm_packages"), } s.lastActivityMatches(wantAct.ActivityName(), string(jsonMustMarshal(t, wantAct)), 0) } @@ -20593,7 +20592,7 @@ func (s *integrationEnterpriseTestSuite) TestMaintainedApps() { // Create a team var newTeamResp teamResponse - s.DoJSON("POST", "/api/latest/fleet/teams", &createTeamRequest{TeamPayload: fleet.TeamPayload{Name: ptr.String("Team 1")}}, http.StatusOK, &newTeamResp) + s.DoJSON("POST", "/api/latest/fleet/teams", &createTeamRequest{TeamPayload: fleet.TeamPayload{Name: new("Team 1")}}, http.StatusOK, &newTeamResp) team := newTeamResp.Team // Check apps returned @@ -20765,7 +20764,7 @@ func (s *integrationEnterpriseTestSuite) TestMaintainedApps() { i, err := s.ds.GetSoftwareInstallerMetadataByID(context.Background(), getSoftwareInstallerIDByMAppID(1)) require.NoError(t, err) require.Equal(t, mapp.TitleID, i.TitleID) - require.Equal(t, ptr.Uint(1), i.FleetMaintainedAppID) + require.Equal(t, new(uint(1)), i.FleetMaintainedAppID) require.Equal(t, mapp.SHA256, i.StorageID) require.Equal(t, "darwin", i.Platform) require.NotEmpty(t, i.InstallScriptContentID) @@ -20794,10 +20793,10 @@ func (s *integrationEnterpriseTestSuite) TestMaintainedApps() { require.Equal(t, 1, resp.Count) title := resp.SoftwareTitles[0] require.NotNil(t, title.BundleIdentifier) - require.Equal(t, ptr.String(mapp.UniqueIdentifier), title.BundleIdentifier) + require.Equal(t, new(mapp.UniqueIdentifier), title.BundleIdentifier) require.Equal(t, mapp.Version, title.SoftwarePackage.Version) require.Equal(t, "installer.zip", title.SoftwarePackage.Name) - require.Equal(t, ptr.Bool(req.SelfService), title.SoftwarePackage.SelfService) + require.Equal(t, new(req.SelfService), title.SoftwarePackage.SelfService) // Check activity s.lastActivityOfTypeMatches( @@ -20849,7 +20848,7 @@ func (s *integrationEnterpriseTestSuite) TestMaintainedApps() { "team_id", "0", ) - mapp, err = s.ds.GetMaintainedAppByID(ctx, 4, ptr.Uint(0)) + mapp, err = s.ds.GetMaintainedAppByID(ctx, 4, new(uint(0))) require.NoError(t, err) _, err = maintained_apps.Hydrate(ctx, mapp, "", nil, nil) require.NoError(t, err) @@ -20865,7 +20864,7 @@ func (s *integrationEnterpriseTestSuite) TestMaintainedApps() { i, err = s.ds.GetSoftwareInstallerMetadataByID(context.Background(), getSoftwareInstallerIDByMAppID(4)) require.NoError(t, err) - require.Equal(t, ptr.Uint(4), i.FleetMaintainedAppID) + require.Equal(t, new(uint(4)), i.FleetMaintainedAppID) require.Equal(t, mapp.SHA256, i.StorageID) require.NotEmpty(t, i.InstallScriptContentID) require.Equal(t, req.PreInstallQuery, i.PreInstallQuery) @@ -20887,9 +20886,9 @@ func (s *integrationEnterpriseTestSuite) TestMaintainedApps() { updatePayload := &fleet.UpdateSoftwareInstallerPayload{ TitleID: title.ID, InstallerID: i.InstallerID, - InstallScript: ptr.String(mapp.InstallScript), + InstallScript: new(mapp.InstallScript), Version: title.SoftwarePackage.Version, - SelfService: ptr.Bool(true), + SelfService: new(true), Categories: []string{cat1.Name, cat2.Name}, } s.updateSoftwareInstaller(t, updatePayload, http.StatusOK, "") @@ -20912,7 +20911,7 @@ func (s *integrationEnterpriseTestSuite) TestMaintainedApps() { PreInstallQuery: "SELECT 1", InstallScript: "echo foo", PostInstallScript: "echo done", - TeamID: ptr.Uint(0), + TeamID: new(uint(0)), } addMAResp = addFleetMaintainedAppResponse{} @@ -21034,7 +21033,7 @@ func (s *integrationEnterpriseTestSuite) TestMaintainedApps() { PreInstallQuery: "SELECT 1", InstallScript: "echo foo", PostInstallScript: "echo done", - TeamID: ptr.Uint(0), + TeamID: new(uint(0)), LabelsIncludeAny: []string{lbl1.Name, lbl2.Name}, } @@ -21072,7 +21071,7 @@ func (s *integrationEnterpriseTestSuite) TestMaintainedApps() { PreInstallQuery: "SELECT 1", InstallScript: "echo foo", PostInstallScript: "echo done", - TeamID: ptr.Uint(0), + TeamID: new(uint(0)), LabelsIncludeAny: []string{"no-such-label"}, } addMAResp = addFleetMaintainedAppResponse{} @@ -21170,7 +21169,7 @@ func (s *integrationEnterpriseTestSuite) TestUpgradeCodesFromMaintainedApps() { // Create a team var newTeamResp teamResponse - s.DoJSON("POST", "/api/latest/fleet/teams", &createTeamRequest{TeamPayload: fleet.TeamPayload{Name: ptr.String("Team 1")}}, http.StatusOK, &newTeamResp) + s.DoJSON("POST", "/api/latest/fleet/teams", &createTeamRequest{TeamPayload: fleet.TeamPayload{Name: new("Team 1")}}, http.StatusOK, &newTeamResp) team := newTeamResp.Team // Add WARP for Windows @@ -21221,8 +21220,8 @@ func (s *integrationEnterpriseTestSuite) TestUpgradeCodesFromMaintainedApps() { LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now().Add(-1 * time.Minute), - OsqueryHostID: ptr.String(t.Name()), - NodeKey: ptr.String(t.Name()), + OsqueryHostID: new(t.Name()), + NodeKey: new(t.Name()), UUID: uuid.New().String(), Hostname: fmt.Sprintf("%sfoo.local", t.Name()), Platform: "windows", @@ -21285,7 +21284,7 @@ func (s *integrationEnterpriseTestSuite) TestUpgradeCodesFromMaintainedApps() { // Use the batch endpoint (GitOps) to add the Windows FMA softwareToInstall := []*fleet.SoftwareInstallerPayload{ - {Slug: ptr.String("cloudflare-warp/windows"), SelfService: true}, + {Slug: new("cloudflare-warp/windows"), SelfService: true}, } var batchResponse batchSetSoftwareInstallersResponse s.DoJSON("POST", "/api/latest/fleet/software/batch", batchSetSoftwareInstallersRequest{Software: softwareToInstall}, http.StatusAccepted, &batchResponse) @@ -21368,8 +21367,8 @@ func (s *integrationEnterpriseTestSuite) TestDeleteLabels() { } func (s *integrationEnterpriseTestSuite) TestListHostSoftwareWithLabelScoping() { - ctx := context.Background() t := s.T() + ctx := context.Background() host := createOrbitEnrolledHost(t, "linux", "", s.ds) @@ -21440,7 +21439,7 @@ func (s *integrationEnterpriseTestSuite) TestListHostSoftwareWithLabelScoping() }}, http.StatusOK, &labelResp) require.NotZero(t, labelResp.Label.ID) lbl2 := labelResp.Label - err := s.ds.RecordLabelQueryExecutions(context.Background(), host, map[uint]*bool{lbl2.ID: ptr.Bool(true)}, time.Now(), false) + err := s.ds.RecordLabelQueryExecutions(context.Background(), host, map[uint]*bool{lbl2.ID: new(true)}, time.Now(), false) require.NoError(t, err) updateInstallerLabel(installerID, lbl1.ID, true) @@ -21666,8 +21665,8 @@ func (s *integrationEnterpriseTestSuite) TestSoftwareInstallerOrbitDownloadFailu OrbitNodeKey: *host.OrbitNodeKey, HostSoftwareInstallResultPayload: &fleet.HostSoftwareInstallResultPayload{ InstallUUID: swInstallExecID, - InstallScriptExitCode: ptr.Int(0), - InstallScriptOutput: ptr.String("hello"), + InstallScriptExitCode: new(int(0)), + InstallScriptOutput: new("hello"), }, }, http.StatusNoContent) @@ -21691,7 +21690,7 @@ func (s *integrationEnterpriseTestSuite) TestSoftwareInstallerOrbitDownloadFailu SoftwarePackage: payload.Filename, InstallUUID: swInstallExecID, Status: string(fleet.SoftwareInstalled), - Source: ptr.String("deb_packages"), + Source: new("deb_packages"), } s.lastActivityMatches(wantAct.ActivityName(), string(jsonMustMarshal(t, wantAct)), 0) } @@ -22431,7 +22430,7 @@ func (s *integrationEnterpriseTestSuite) TestConditionalAccessBasicSetup() { u := &fleet.User{ Name: "test maintainer", Email: "maintainer@example.com", - GlobalRole: ptr.String(fleet.RoleMaintainer), + GlobalRole: new(fleet.RoleMaintainer), } password := test.GoodPassword require.NoError(t, u.SetPassword(password, 10, 10)) @@ -22626,8 +22625,8 @@ func (s *integrationEnterpriseTestSuite) TestConditionalAccessPolicies() { LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now().Add(-1 * time.Minute), - OsqueryHostID: ptr.String(t.Name() + name), - NodeKey: ptr.String(t.Name() + name), + OsqueryHostID: new(t.Name() + name), + NodeKey: new(t.Name() + name), UUID: uuid.New().String(), Hostname: fmt.Sprintf("%s.%s.local", name, t.Name()), Platform: platform, @@ -22729,9 +22728,9 @@ func (s *integrationEnterpriseTestSuite) TestConditionalAccessPolicies() { s.DoJSON("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( h1, map[uint]*bool{ - cp1.ID: ptr.Bool(true), - cp2.ID: ptr.Bool(true), - p3.ID: ptr.Bool(false), + cp1.ID: new(true), + cp2.ID: new(true), + p3.ID: new(false), }, ), http.StatusOK, &distributedResp) @@ -22760,9 +22759,9 @@ func (s *integrationEnterpriseTestSuite) TestConditionalAccessPolicies() { s.DoJSON("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( windowsHost1, map[uint]*bool{ - cp1.ID: ptr.Bool(true), - cp2.ID: ptr.Bool(true), - p3.ID: ptr.Bool(false), + cp1.ID: new(true), + cp2.ID: new(true), + p3.ID: new(false), }, ), http.StatusOK, &distributedResp) @@ -22795,9 +22794,9 @@ func (s *integrationEnterpriseTestSuite) TestConditionalAccessPolicies() { s.DoJSON("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( h1, map[uint]*bool{ - cp1.ID: ptr.Bool(true), - cp2.ID: ptr.Bool(true), - p3.ID: ptr.Bool(false), + cp1.ID: new(true), + cp2.ID: new(true), + p3.ID: new(false), }, ), http.StatusOK, &distributedResp) @@ -22828,9 +22827,9 @@ func (s *integrationEnterpriseTestSuite) TestConditionalAccessPolicies() { s.DoJSON("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( windowsHost1, map[uint]*bool{ - cp1.ID: ptr.Bool(true), - cp2.ID: ptr.Bool(true), - p3.ID: ptr.Bool(false), + cp1.ID: new(true), + cp2.ID: new(true), + p3.ID: new(false), }, ), http.StatusOK, &distributedResp) @@ -22851,9 +22850,9 @@ func (s *integrationEnterpriseTestSuite) TestConditionalAccessPolicies() { s.DoJSON("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( h1, map[uint]*bool{ - cp1.ID: ptr.Bool(true), - cp2.ID: ptr.Bool(false), - p3.ID: ptr.Bool(false), + cp1.ID: new(true), + cp2.ID: new(false), + p3.ID: new(false), }, ), http.StatusOK, &distributedResp) @@ -22877,9 +22876,9 @@ func (s *integrationEnterpriseTestSuite) TestConditionalAccessPolicies() { s.DoJSON("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( windowsHost1, map[uint]*bool{ - cp1.ID: ptr.Bool(true), - cp2.ID: ptr.Bool(false), - p3.ID: ptr.Bool(false), + cp1.ID: new(true), + cp2.ID: new(false), + p3.ID: new(false), }, ), http.StatusOK, &distributedResp) @@ -22898,9 +22897,9 @@ func (s *integrationEnterpriseTestSuite) TestConditionalAccessPolicies() { s.DoJSON("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( h1, map[uint]*bool{ - cp1.ID: ptr.Bool(true), - cp2.ID: ptr.Bool(false), - p3.ID: ptr.Bool(false), + cp1.ID: new(true), + cp2.ID: new(false), + p3.ID: new(false), }, ), http.StatusOK, &distributedResp) @@ -22919,9 +22918,9 @@ func (s *integrationEnterpriseTestSuite) TestConditionalAccessPolicies() { s.DoJSON("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( windowsHost1, map[uint]*bool{ - cp1.ID: ptr.Bool(true), - cp2.ID: ptr.Bool(false), - p3.ID: ptr.Bool(false), + cp1.ID: new(true), + cp2.ID: new(false), + p3.ID: new(false), }, ), http.StatusOK, &distributedResp) @@ -23000,8 +22999,8 @@ func (s *integrationEnterpriseTestSuite) TestConditionalAccessPolicies() { s.DoJSON("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( h2, map[uint]*bool{ - cp1.ID: ptr.Bool(false), - p2.ID: ptr.Bool(false), + cp1.ID: new(false), + p2.ID: new(false), }, ), http.StatusOK, &distributedResp) @@ -23031,7 +23030,7 @@ func (s *integrationEnterpriseTestSuite) TestConditionalAccessPolicies() { s.DoJSON("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( h2, map[uint]*bool{ - p2.ID: ptr.Bool(false), + p2.ID: new(false), }, ), http.StatusOK, &distributedResp) @@ -23118,8 +23117,8 @@ func (s *integrationEnterpriseTestSuite) TestConditionalAccessPoliciesEntraResul LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now().Add(-1 * time.Minute), - OsqueryHostID: ptr.String(t.Name() + name), - NodeKey: ptr.String(t.Name() + name), + OsqueryHostID: new(t.Name() + name), + NodeKey: new(t.Name() + name), UUID: uuid.New().String(), Hostname: fmt.Sprintf("%s.%s.local", name, t.Name()), Platform: "darwin", @@ -23336,8 +23335,8 @@ func (s *integrationEnterpriseTestSuite) TestSetupExperienceLinuxWithSoftware() LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now().Add(-time.Minute), - OsqueryHostID: ptr.String(name), - NodeKey: ptr.String(name), + OsqueryHostID: new(name), + NodeKey: new(name), UUID: uuid.New().String(), Hostname: fmt.Sprintf("%s.local", name), HardwareSerial: uuid.New().String(), @@ -23811,9 +23810,9 @@ func (s *integrationEnterpriseTestSuite) TestSetupExperienceLinuxWithSoftware() // update should succeed s.updateSoftwareInstaller(t, &fleet.UpdateSoftwareInstallerPayload{ SelfService: new(true), - InstallScript: ptr.String("some updated install script"), - PreInstallQuery: ptr.String("some new pre install query"), - PostInstallScript: ptr.String("some new post install script"), + InstallScript: new("some updated install script"), + PreInstallQuery: new("some new pre install query"), + PostInstallScript: new("some new post install script"), Filename: "vim.deb", TitleID: debVimTitleID, TeamID: &team.ID, @@ -24033,8 +24032,8 @@ func (s *integrationEnterpriseTestSuite) TestSetupExperienceLinuxWithSoftwareWit LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now().Add(-time.Minute), - OsqueryHostID: ptr.String(name), - NodeKey: ptr.String(name), + OsqueryHostID: new(name), + NodeKey: new(name), UUID: uuid.New().String(), Hostname: fmt.Sprintf("%s.local", name), HardwareSerial: uuid.New().String(), @@ -24268,8 +24267,8 @@ func (s *integrationEnterpriseTestSuite) TestSetupExperienceWindowsWithSoftware( LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now().Add(-time.Minute), - OsqueryHostID: ptr.String(name), - NodeKey: ptr.String(name), + OsqueryHostID: new(name), + NodeKey: new(name), UUID: uuid.New().String(), Hostname: fmt.Sprintf("%s.local", name), HardwareSerial: uuid.New().String(), @@ -24740,8 +24739,8 @@ func (s *integrationEnterpriseTestSuite) TestSetupExperienceWindowsWithSoftwareW LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now().Add(-time.Minute), - OsqueryHostID: ptr.String(name), - NodeKey: ptr.String(name), + OsqueryHostID: new(name), + NodeKey: new(name), UUID: uuid.New().String(), Hostname: fmt.Sprintf("%s.local", name), HardwareSerial: uuid.New().String(), @@ -24918,8 +24917,8 @@ func (s *integrationEnterpriseTestSuite) TestSetupExperiencePayloadFreePackageWi LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now().Add(-time.Minute), - OsqueryHostID: ptr.String(name), - NodeKey: ptr.String(name), + OsqueryHostID: new(name), + NodeKey: new(name), UUID: uuid.New().String(), Hostname: fmt.Sprintf("%s.local", name), HardwareSerial: uuid.New().String(), @@ -25050,7 +25049,7 @@ func (s *integrationEnterpriseTestSuite) TestHostDeviceMappingIDP() { Emails: []fleet.ScimUserEmail{ { Email: "scim.user@example.com", - Primary: ptr.Bool(true), + Primary: new(true), }, }, } @@ -25585,8 +25584,8 @@ func (s *integrationEnterpriseTestSuite) TestConditionalAccessBypass() { LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now().Add(-1 * time.Minute), - OsqueryHostID: ptr.String(token), - NodeKey: ptr.String(token), + OsqueryHostID: new(token), + NodeKey: new(token), UUID: uuid.New().String(), Hostname: fmt.Sprintf("%s-scim.local", token), HardwareSerial: uuid.New().String(), @@ -25758,8 +25757,8 @@ func (s *integrationEnterpriseTestSuite) TestConditionalAccessBypass() { LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now().Add(-1 * time.Minute), - OsqueryHostID: ptr.String(token2), - NodeKey: ptr.String(token2), + OsqueryHostID: new(token2), + NodeKey: new(token2), UUID: uuid.New().String(), Hostname: fmt.Sprintf("%s.local", token2), HardwareSerial: uuid.New().String(), @@ -25935,8 +25934,8 @@ func (s *integrationEnterpriseTestSuite) TestConditionalAccessBypass() { require.NoError(t, err) err = s.ds.RecordPolicyQueryExecutions(ctx, host, map[uint]*bool{ - caPolicy.ID: ptr.Bool(true), // passing - nonCAPolicy.ID: ptr.Bool(false), // failing + caPolicy.ID: new(true), // passing + nonCAPolicy.ID: new(false), // failing }, time.Now(), false, nil) require.NoError(t, err) @@ -25999,8 +25998,8 @@ func (s *integrationEnterpriseTestSuite) TestDeviceAuthenticationMethods() { LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now(), - OsqueryHostID: ptr.String("ios-test-host"), - NodeKey: ptr.String("ios-test-node-key"), + OsqueryHostID: new("ios-test-host"), + NodeKey: new("ios-test-node-key"), UUID: "ios-test-uuid-12345", Hostname: "ios-test-device", Platform: "ios", @@ -26013,8 +26012,8 @@ func (s *integrationEnterpriseTestSuite) TestDeviceAuthenticationMethods() { LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now(), - OsqueryHostID: ptr.String("mac-test-host"), - NodeKey: ptr.String("mac-test-node-key"), + OsqueryHostID: new("mac-test-host"), + NodeKey: new("mac-test-node-key"), UUID: "mac-test-uuid-67890", Hostname: "mac-test-device", Platform: "darwin", @@ -26141,8 +26140,8 @@ func (s *integrationEnterpriseTestSuite) TestDeviceAuthenticationMethods() { LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now(), - OsqueryHostID: ptr.String("ipad-test-host"), - NodeKey: ptr.String("ipad-test-node-key"), + OsqueryHostID: new("ipad-test-host"), + NodeKey: new("ipad-test-node-key"), UUID: "ipad-test-uuid-11111", Hostname: "ipad-test-device", Platform: "ipados", @@ -26493,8 +26492,8 @@ func (s *integrationEnterpriseTestSuite) TestTeamLabelsDistributedReadWrite() { newHost := func(name string, platform string, teamID *uint) *fleet.Host { h, err := s.ds.NewHost(t.Context(), &fleet.Host{ - OsqueryHostID: ptr.String(t.Name() + name), - NodeKey: ptr.String(t.Name() + name), + OsqueryHostID: new(t.Name() + name), + NodeKey: new(t.Name() + name), UUID: uuid.New().String(), Hostname: fmt.Sprintf("%s.%s.local", name, t.Name()), Platform: platform, @@ -26564,7 +26563,7 @@ func (s *integrationEnterpriseTestSuite) TestTeamLabelsDistributedReadWrite() { user := &fleet.User{ Name: "global admin", Email: "global_admin@example.com", - GlobalRole: ptr.String(fleet.RoleAdmin), + GlobalRole: new(fleet.RoleAdmin), } err = user.SetPassword(test.GoodPassword, 10, 10) require.NoError(t, err) @@ -26634,11 +26633,11 @@ func (s *integrationEnterpriseTestSuite) TestTeamLabelsDistributedReadWrite() { // macOST1 returns results for the label queries back. distributedResp := submitDistributedQueryResultsResponse{} s.DoJSON("POST", "/api/osquery/distributed/write", genDistributedReqWithLabelResults(macOST1, map[uint]*bool{ - l1t1.ID: ptr.Bool(true), - globalLabel.ID: ptr.Bool(true), + l1t1.ID: new(true), + globalLabel.ID: new(true), // Send fake result for t2 (*) to verify it gets filtered. // This could happen if the host was transferred to another team in between distributed/read and distributed/write. - l2t2.ID: ptr.Bool(true), + l2t2.ID: new(true), }), http.StatusOK, &distributedResp) getHostResp := getHostResponse{} @@ -26653,9 +26652,9 @@ func (s *integrationEnterpriseTestSuite) TestTeamLabelsDistributedReadWrite() { // macOST2 returns results for the label queries back. distributedResp = submitDistributedQueryResultsResponse{} s.DoJSON("POST", "/api/osquery/distributed/write", genDistributedReqWithLabelResults(macOST2, map[uint]*bool{ - l2t2.ID: ptr.Bool(true), - l3t2.ID: ptr.Bool(false), // runs but doesn't belong - globalLabel.ID: ptr.Bool(true), + l2t2.ID: new(true), + l3t2.ID: new(false), // runs but doesn't belong + globalLabel.ID: new(true), }), http.StatusOK, &distributedResp) // Add manual label on macOST2. @@ -26718,9 +26717,9 @@ func (s *integrationEnterpriseTestSuite) TestDeleteTeamCertificateTemplates() { // Create a test certificate authority ca, err := s.ds.NewCertificateAuthority(ctx, &fleet.CertificateAuthority{ Type: string(fleet.CATypeCustomSCEPProxy), - Name: ptr.String("TestDeleteTeamCertificateTemplates SCEP CA"), - URL: ptr.String("http://localhost:8080/scep"), - Challenge: ptr.String("test-challenge"), + Name: new("TestDeleteTeamCertificateTemplates SCEP CA"), + URL: new("http://localhost:8080/scep"), + Challenge: new("test-challenge"), }) require.NoError(t, err) caID := ca.ID @@ -26935,9 +26934,9 @@ func (s *integrationEnterpriseTestSuite) TestUpdateSoftwareAutoUpdateConfig() { // Update the auto-update config s.DoJSON("PATCH", fmt.Sprintf("/api/v1/fleet/software/titles/%d/app_store_app", vppApp.TitleID), updateAppStoreAppRequest{ TeamID: &teamID, - AutoUpdateEnabled: ptr.Bool(true), - AutoUpdateStartTime: ptr.String("02:00"), - AutoUpdateEndTime: ptr.String("04:00"), + AutoUpdateEnabled: new(true), + AutoUpdateStartTime: new("02:00"), + AutoUpdateEndTime: new("04:00"), }, http.StatusOK, &titlesResp) s.lastActivityMatches(fleet.ActivityEditedAppStoreApp{}.ActivityName(), fmt.Sprintf(`{"app_store_id":"adam_vpp_app_1", "auto_update_enabled":true, "auto_update_window_end":"04:00", "auto_update_window_start":"02:00", "platform":"ipados", "self_service":false, "software_display_name":"", "software_icon_url":null, "software_title":"vpp1", "software_title_id":%d, "team_id":%d, "team_name":"%s", "fleet_id":%d, "fleet_name":"%s"}`, vppApp.TitleID, team.ID, team.Name, team.ID, team.Name), 0) @@ -26954,7 +26953,7 @@ func (s *integrationEnterpriseTestSuite) TestUpdateSoftwareAutoUpdateConfig() { // Do an update without auto-update fields to check that it still includes the auto-update values. s.DoJSON("PATCH", fmt.Sprintf("/api/v1/fleet/software/titles/%d/app_store_app", vppApp.TitleID), updateAppStoreAppRequest{ TeamID: &teamID, - DisplayName: ptr.String("New Display Name"), + DisplayName: new("New Display Name"), }, http.StatusOK, &titlesResp) s.lastActivityMatches(fleet.ActivityEditedAppStoreApp{}.ActivityName(), fmt.Sprintf(`{"app_store_id":"adam_vpp_app_1", "auto_update_enabled":true, "auto_update_window_end":"04:00", "auto_update_window_start":"02:00", "platform":"ipados", "self_service":false, "software_display_name":"New Display Name", "software_icon_url":null, "software_title":"vpp1", "software_title_id":%d, "team_id":%d, "team_name":"%s", "fleet_id":%d, "fleet_name":"%s"}`, vppApp.TitleID, team.ID, team.Name, team.ID, team.Name), 0) @@ -26962,7 +26961,7 @@ func (s *integrationEnterpriseTestSuite) TestUpdateSoftwareAutoUpdateConfig() { // Disable the auto-update config s.DoJSON("PATCH", fmt.Sprintf("/api/v1/fleet/software/titles/%d/app_store_app", vppApp.TitleID), updateAppStoreAppRequest{ TeamID: &teamID, - AutoUpdateEnabled: ptr.Bool(false), + AutoUpdateEnabled: new(false), }, http.StatusOK, &titlesResp) s.lastActivityMatches(fleet.ActivityEditedAppStoreApp{}.ActivityName(), fmt.Sprintf(`{"app_store_id":"adam_vpp_app_1", "auto_update_enabled":false, "platform":"ipados", "self_service":false, "software_display_name":"", "software_icon_url":null, "software_title":"vpp1", "software_title_id":%d, "team_id":%d, "team_name":"%s", "fleet_id":%d, "fleet_name":"%s"}`, vppApp.TitleID, team.ID, team.Name, team.ID, team.Name), 0) @@ -26970,7 +26969,7 @@ func (s *integrationEnterpriseTestSuite) TestUpdateSoftwareAutoUpdateConfig() { // Do an update without auto-update fields to check that it still includes the auto-update values. s.DoJSON("PATCH", fmt.Sprintf("/api/v1/fleet/software/titles/%d/app_store_app", vppApp.TitleID), updateAppStoreAppRequest{ TeamID: &teamID, - DisplayName: ptr.String("Updated Display Name"), + DisplayName: new("Updated Display Name"), }, http.StatusOK, &titlesResp) s.lastActivityMatches(fleet.ActivityEditedAppStoreApp{}.ActivityName(), fmt.Sprintf(`{"app_store_id":"adam_vpp_app_1", "auto_update_enabled":false, "platform":"ipados", "self_service":false, "software_display_name":"Updated Display Name", "software_icon_url":null, "software_title":"vpp1", "software_title_id":%d, "team_id":%d, "team_name":"%s", "fleet_id":%d, "fleet_name":"%s"}`, vppApp.TitleID, team.ID, team.Name, team.ID, team.Name), 0) @@ -27093,7 +27092,7 @@ func (s *integrationEnterpriseTestSuite) TestFMAVersionRollback() { newTeam := func(name string) fleet.Team { var resp teamResponse s.DoJSON("POST", "/api/latest/fleet/teams", &createTeamRequest{ - TeamPayload: fleet.TeamPayload{Name: ptr.String(name)}, + TeamPayload: fleet.TeamPayload{Name: new(name)}, }, http.StatusOK, &resp) return *resp.Team } @@ -27142,7 +27141,7 @@ func (s *integrationEnterpriseTestSuite) TestFMAVersionRollback() { // Add an ingested app to the team softwareToInstall := []*fleet.SoftwareInstallerPayload{ - {Slug: ptr.String("cloudflare-warp/windows"), SelfService: true}, + {Slug: new("cloudflare-warp/windows"), SelfService: true}, } packages := batchSet(team, softwareToInstall) @@ -27200,7 +27199,7 @@ func (s *integrationEnterpriseTestSuite) TestFMAVersionRollback() { // Pin to version "2.0" in the batch request (simulating GitOps yaml with version specified). // The active installer should switch to the cached v2.0 installer. packages = batchSet(team, []*fleet.SoftwareInstallerPayload{ - {Slug: ptr.String("cloudflare-warp/windows"), SelfService: true, RollbackVersion: "2.0"}, + {Slug: new("cloudflare-warp/windows"), SelfService: true, RollbackVersion: "2.0"}, }) require.Len(t, packages, 2) @@ -27244,7 +27243,7 @@ func (s *integrationEnterpriseTestSuite) TestFMAVersionRollback() { // ---- Test switching active version back to 3.0 ---- // Pin to version "3.0" — the active installer should switch to the cached v3.0 installer. packages = batchSet(team, []*fleet.SoftwareInstallerPayload{ - {Slug: ptr.String("cloudflare-warp/windows"), SelfService: true, RollbackVersion: "3.0"}, + {Slug: new("cloudflare-warp/windows"), SelfService: true, RollbackVersion: "3.0"}, }) require.Len(t, packages, 2) @@ -27296,7 +27295,7 @@ func (s *integrationEnterpriseTestSuite) TestFMAVersionRollback() { rawResp := s.Do("POST", "/api/latest/fleet/software/batch", batchSetSoftwareInstallersRequest{ Software: []*fleet.SoftwareInstallerPayload{ - {Slug: ptr.String("cloudflare-warp/windows"), SelfService: true, RollbackVersion: "1.0"}, + {Slug: new("cloudflare-warp/windows"), SelfService: true, RollbackVersion: "1.0"}, }, TeamName: team.Name, }, @@ -27391,7 +27390,7 @@ func (s *integrationEnterpriseTestSuite) TestFMAVersionRollback() { resetFMAState(warpState, "2.0", []byte("def")) pkgs := batchSet(uiTeam, []*fleet.SoftwareInstallerPayload{ - {Slug: ptr.String("cloudflare-warp/windows"), SelfService: true}, + {Slug: new("cloudflare-warp/windows"), SelfService: true}, }) require.Len(t, pkgs, 2, "both v1.0 (UI-added) and v2.0 should be cached") @@ -27405,7 +27404,7 @@ func (s *integrationEnterpriseTestSuite) TestFMAVersionRollback() { // Roll back to the original UI-added v1.0 via batch-set. pkgs = batchSet(uiTeam, []*fleet.SoftwareInstallerPayload{ - {Slug: ptr.String("cloudflare-warp/windows"), SelfService: true, RollbackVersion: "1.0"}, + {Slug: new("cloudflare-warp/windows"), SelfService: true, RollbackVersion: "1.0"}, }) require.Len(t, pkgs, 2, "both versions should still be cached after rollback") @@ -27493,8 +27492,8 @@ func (s *integrationEnterpriseTestSuite) TestFMAVersionRollback() { multiTeam := newTeam("team_multi_" + t.Name()) bothFMAs := []*fleet.SoftwareInstallerPayload{ - {Slug: ptr.String("cloudflare-warp/windows"), SelfService: true}, - {Slug: ptr.String("zoom/windows"), SelfService: true}, + {Slug: new("cloudflare-warp/windows"), SelfService: true}, + {Slug: new("zoom/windows"), SelfService: true}, } // ---- v1.0 for both FMAs ---- @@ -27530,8 +27529,8 @@ func (s *integrationEnterpriseTestSuite) TestFMAVersionRollback() { // ---- Roll back cloudflare-warp to v2.0, leave zoom at v3.0 ---- pkgs = batchSet(multiTeam, []*fleet.SoftwareInstallerPayload{ - {Slug: ptr.String("cloudflare-warp/windows"), SelfService: true, RollbackVersion: "2.0"}, - {Slug: ptr.String("zoom/windows"), SelfService: true}, // no rollback — stays at latest + {Slug: new("cloudflare-warp/windows"), SelfService: true, RollbackVersion: "2.0"}, + {Slug: new("zoom/windows"), SelfService: true}, // no rollback — stays at latest }) require.Len(t, pkgs, 4) @@ -27557,8 +27556,8 @@ func (s *integrationEnterpriseTestSuite) TestFMAVersionRollback() { // Zoom rollback to v2.0 should also succeed independently. pkgs = batchSet(multiTeam, []*fleet.SoftwareInstallerPayload{ - {Slug: ptr.String("cloudflare-warp/windows"), SelfService: true, RollbackVersion: "2.0"}, - {Slug: ptr.String("zoom/windows"), SelfService: true, RollbackVersion: "2.0"}, + {Slug: new("cloudflare-warp/windows"), SelfService: true, RollbackVersion: "2.0"}, + {Slug: new("zoom/windows"), SelfService: true, RollbackVersion: "2.0"}, }) require.Len(t, pkgs, 4) @@ -27596,7 +27595,7 @@ func (s *integrationEnterpriseTestSuite) TestFMAVersionRollback() { teamB := newTeam("team_iso_b_" + t.Name()) warpPayload := []*fleet.SoftwareInstallerPayload{ - {Slug: ptr.String("cloudflare-warp/windows"), SelfService: true}, + {Slug: new("cloudflare-warp/windows"), SelfService: true}, } // ---- Add v1.0 to both teams ---- @@ -27657,7 +27656,7 @@ func (s *integrationEnterpriseTestSuite) TestFMAVersionRollback() { // ---- Roll back Team A to v2.0 — Team B must not be affected ---- batchSet(teamA, []*fleet.SoftwareInstallerPayload{ - {Slug: ptr.String("cloudflare-warp/windows"), SelfService: true, RollbackVersion: "2.0"}, + {Slug: new("cloudflare-warp/windows"), SelfService: true, RollbackVersion: "2.0"}, }) titleA = getActiveTitleForTeam(teamA.ID) @@ -27672,7 +27671,7 @@ func (s *integrationEnterpriseTestSuite) TestFMAVersionRollback() { // Verify Team B can still roll back to v1.0 (its eviction pool is independent). batchSet(teamB, []*fleet.SoftwareInstallerPayload{ - {Slug: ptr.String("cloudflare-warp/windows"), SelfService: true, RollbackVersion: "1.0"}, + {Slug: new("cloudflare-warp/windows"), SelfService: true, RollbackVersion: "1.0"}, }) titleB = getActiveTitleForTeam(teamB.ID) @@ -27695,7 +27694,7 @@ func (s *integrationEnterpriseTestSuite) TestFMAVersionRollback() { delTeam := newTeam("team_del_" + t.Name()) warpPayload := []*fleet.SoftwareInstallerPayload{ - {Slug: ptr.String("cloudflare-warp/windows"), SelfService: true}, + {Slug: new("cloudflare-warp/windows"), SelfService: true}, } batchSet(delTeam, warpPayload) @@ -27760,7 +27759,7 @@ func (s *integrationEnterpriseTestSuite) TestFMAVersionRollback() { statusTeam := newTeam("team_status_" + t.Name()) warpPayload := []*fleet.SoftwareInstallerPayload{ - {Slug: ptr.String("cloudflare-warp/windows"), SelfService: true}, + {Slug: new("cloudflare-warp/windows"), SelfService: true}, } // ---- Step 1a: Add v1.0 ---- @@ -27803,7 +27802,7 @@ func (s *integrationEnterpriseTestSuite) TestFMAVersionRollback() { // ---- Step 3: Roll back to v1.0 ---- batchSet(statusTeam, []*fleet.SoftwareInstallerPayload{ - {Slug: ptr.String("cloudflare-warp/windows"), SelfService: true, RollbackVersion: "1.0"}, + {Slug: new("cloudflare-warp/windows"), SelfService: true, RollbackVersion: "1.0"}, }) statusTitle = getActiveTitleForTeam(statusTeam.ID) @@ -27843,7 +27842,7 @@ func (s *integrationEnterpriseTestSuite) TestFMAVersionRollback() { editTeam := newTeam("team_edit_" + t.Name()) warpPayload := []*fleet.SoftwareInstallerPayload{ - {Slug: ptr.String("cloudflare-warp/windows"), SelfService: false}, + {Slug: new("cloudflare-warp/windows"), SelfService: false}, } // ---- Add v1.0 ---- @@ -27877,7 +27876,7 @@ func (s *integrationEnterpriseTestSuite) TestFMAVersionRollback() { s.updateSoftwareInstaller(t, &fleet.UpdateSoftwareInstallerPayload{ TitleID: editTitle.ID, TeamID: &editTeam.ID, - SelfService: ptr.Bool(true), + SelfService: new(true), }, http.StatusOK, "") // Confirm the edit actually took effect. @@ -27947,7 +27946,7 @@ func (s *integrationEnterpriseTestSuite) TestPatchPolicies() { s.DoJSONWithoutAuth("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( host, map[uint]*bool{ - policy.ID: ptr.Bool(false), + policy.ID: new(false), }, ), http.StatusOK, &distributedResp) err = s.ds.UpdateHostPolicyCounts(ctx) @@ -28018,7 +28017,7 @@ func (s *integrationEnterpriseTestSuite) TestPatchPolicies() { Name: "", Query: "", Description: "", - Type: ptr.String("patch"), + Type: new("patch"), PatchSoftwareTitleID: &titleID, }, http.StatusOK, &policyResp) require.Equal(t, "macOS - DummyApp up to date", policyResp.Policy.Name) @@ -28128,7 +28127,7 @@ func (s *integrationEnterpriseTestSuite) TestPatchPolicies() { resp := teamResponse{} s.DoJSON("POST", "/api/latest/fleet/fleets", &createTeamRequest{ - TeamPayload: fleet.TeamPayload{Name: ptr.String("team_1")}, + TeamPayload: fleet.TeamPayload{Name: new("team_1")}, }, http.StatusOK, &resp) teamID := resp.Team.ID @@ -28148,7 +28147,7 @@ func (s *integrationEnterpriseTestSuite) TestPatchPolicies() { // add a patch policy policyResp := fleet.TeamPolicyResponse{} s.DoJSON("POST", fmt.Sprintf("/api/latest/fleet/fleets/%d/policies", teamID), fleet.TeamPolicyRequest{ - Type: ptr.String("patch"), + Type: new("patch"), PatchSoftwareTitleID: &titleID, }, http.StatusOK, &policyResp) @@ -28214,7 +28213,7 @@ func (s *integrationEnterpriseTestSuite) TestPatchPolicies() { var resp batchSetSoftwareInstallersResponse s.DoJSON("POST", "/api/latest/fleet/software/batch", - batchSetSoftwareInstallersRequest{Software: []*fleet.SoftwareInstallerPayload{{Slug: ptr.String("zoom/windows")}}, TeamName: team.Name}, + batchSetSoftwareInstallersRequest{Software: []*fleet.SoftwareInstallerPayload{{Slug: new("zoom/windows")}}, TeamName: team.Name}, http.StatusAccepted, &resp, "team_name", team.Name, "team_id", fmt.Sprint(team.ID), ) @@ -28248,7 +28247,7 @@ func (s *integrationEnterpriseTestSuite) TestPatchPolicies() { Team: team.Name, Type: fleet.PolicyTypePatch, FleetMaintainedAppSlug: "zoom/windows", - SoftwareTitleID: ptr.Uint(title.ID), + SoftwareTitleID: new(title.ID), } applyResp = fleet.ApplyPolicySpecsResponse{} @@ -28300,7 +28299,7 @@ func (s *integrationEnterpriseTestSuite) TestPatchPolicies() { resetFMAState(states["/zoom/windows.json"], "1.2", []byte("abc"), "") s.DoJSON("POST", "/api/latest/fleet/software/batch", - batchSetSoftwareInstallersRequest{Software: []*fleet.SoftwareInstallerPayload{{Slug: ptr.String("zoom/windows")}}, TeamName: team.Name}, + batchSetSoftwareInstallersRequest{Software: []*fleet.SoftwareInstallerPayload{{Slug: new("zoom/windows")}}, TeamName: team.Name}, http.StatusAccepted, &resp, "team_name", team.Name, "team_id", fmt.Sprint(team.ID), ) @@ -28326,7 +28325,7 @@ func (s *integrationEnterpriseTestSuite) TestPatchPolicies() { // Test 3: FMA Version is pinned back after update to a newer version (query should use old version) s.DoJSON("POST", "/api/latest/fleet/software/batch", batchSetSoftwareInstallersRequest{Software: []*fleet.SoftwareInstallerPayload{ - {Slug: ptr.String("zoom/windows"), SelfService: true, RollbackVersion: "1.0"}, + {Slug: new("zoom/windows"), SelfService: true, RollbackVersion: "1.0"}, }, TeamName: team.Name}, http.StatusAccepted, &resp, "team_name", team.Name, "team_id", fmt.Sprint(team.ID), @@ -28358,7 +28357,7 @@ func (s *integrationEnterpriseTestSuite) TestPatchPolicies() { resetFMAState(states["/zoom/windows.json"], "1.3", []byte("ghi"), "") s.DoJSON("POST", "/api/latest/fleet/software/batch", - batchSetSoftwareInstallersRequest{Software: []*fleet.SoftwareInstallerPayload{{Slug: ptr.String("zoom/windows")}}, TeamName: team.Name}, + batchSetSoftwareInstallersRequest{Software: []*fleet.SoftwareInstallerPayload{{Slug: new("zoom/windows")}}, TeamName: team.Name}, http.StatusAccepted, &resp, "team_name", team.Name, "team_id", fmt.Sprint(team.ID), ) @@ -28397,7 +28396,7 @@ func (s *integrationEnterpriseTestSuite) TestPatchPolicies() { // Add installers at version 1.0 var resp batchSetSoftwareInstallersResponse s.DoJSON("POST", "/api/latest/fleet/software/batch", - batchSetSoftwareInstallersRequest{Software: []*fleet.SoftwareInstallerPayload{{Slug: ptr.String("zoom/windows")}, {Slug: ptr.String("1password/darwin")}}, TeamName: team2.Name}, + batchSetSoftwareInstallersRequest{Software: []*fleet.SoftwareInstallerPayload{{Slug: new("zoom/windows")}, {Slug: new("1password/darwin")}}, TeamName: team2.Name}, http.StatusAccepted, &resp, "team_name", team2.Name, "team_id", fmt.Sprint(team2.ID), ) @@ -28441,7 +28440,7 @@ func (s *integrationEnterpriseTestSuite) TestPatchPolicies() { resetFMAState(states["/1password/darwin.json"], "1.2", []byte("abc"), "SELECT 1; --custom query 1.2") s.DoJSON("POST", "/api/latest/fleet/software/batch", - batchSetSoftwareInstallersRequest{Software: []*fleet.SoftwareInstallerPayload{{Slug: ptr.String("zoom/windows")}, {Slug: ptr.String("1password/darwin")}}, TeamName: team2.Name}, + batchSetSoftwareInstallersRequest{Software: []*fleet.SoftwareInstallerPayload{{Slug: new("zoom/windows")}, {Slug: new("1password/darwin")}}, TeamName: team2.Name}, http.StatusAccepted, &resp, "team_name", team2.Name, "team_id", fmt.Sprint(team2.ID), ) @@ -28460,8 +28459,8 @@ func (s *integrationEnterpriseTestSuite) TestPatchPolicies() { // Rollback FMA versions to 1.0, queries should use older versions s.DoJSON("POST", "/api/latest/fleet/software/batch", batchSetSoftwareInstallersRequest{Software: []*fleet.SoftwareInstallerPayload{ - {Slug: ptr.String("zoom/windows"), SelfService: true, RollbackVersion: "1.0"}, - {Slug: ptr.String("1password/darwin"), SelfService: true, RollbackVersion: "1.0"}, + {Slug: new("zoom/windows"), SelfService: true, RollbackVersion: "1.0"}, + {Slug: new("1password/darwin"), SelfService: true, RollbackVersion: "1.0"}, }, TeamName: team2.Name}, http.StatusAccepted, &resp, "team_name", team2.Name, "team_id", fmt.Sprint(team2.ID), @@ -28793,7 +28792,7 @@ func (s *integrationEnterpriseTestSuite) TestPinMajorVersion() { var resp batchSetSoftwareInstallersResponse s.DoJSON("POST", "/api/latest/fleet/software/batch", - batchSetSoftwareInstallersRequest{Software: []*fleet.SoftwareInstallerPayload{{Slug: ptr.String("zoom/windows")}}, TeamName: teamName}, + batchSetSoftwareInstallersRequest{Software: []*fleet.SoftwareInstallerPayload{{Slug: new("zoom/windows")}}, TeamName: teamName}, http.StatusAccepted, &resp, "team_name", teamName, "team_id", "0", ) @@ -28808,7 +28807,7 @@ func (s *integrationEnterpriseTestSuite) TestPinMajorVersion() { // pin version to ^1, call batch, should get 1.0 s.DoJSON("POST", "/api/latest/fleet/software/batch", - batchSetSoftwareInstallersRequest{Software: []*fleet.SoftwareInstallerPayload{{Slug: ptr.String("zoom/windows"), RollbackVersion: "^1"}}, TeamName: teamName}, + batchSetSoftwareInstallersRequest{Software: []*fleet.SoftwareInstallerPayload{{Slug: new("zoom/windows"), RollbackVersion: "^1"}}, TeamName: teamName}, http.StatusAccepted, &resp, "team_name", teamName, "team_id", "0", ) @@ -28824,7 +28823,7 @@ func (s *integrationEnterpriseTestSuite) TestPinMajorVersion() { resetFMAState(states["/zoom/windows.json"], "1.1", []byte("abc"), "") s.DoJSON("POST", "/api/latest/fleet/software/batch", - batchSetSoftwareInstallersRequest{Software: []*fleet.SoftwareInstallerPayload{{Slug: ptr.String("zoom/windows"), RollbackVersion: "^1"}}, TeamName: teamName}, + batchSetSoftwareInstallersRequest{Software: []*fleet.SoftwareInstallerPayload{{Slug: new("zoom/windows"), RollbackVersion: "^1"}}, TeamName: teamName}, http.StatusAccepted, &resp, "team_name", teamName, "team_id", "0", ) @@ -28841,7 +28840,7 @@ func (s *integrationEnterpriseTestSuite) TestPinMajorVersion() { // maybe unnecessary test, can remove to speed it up s.DoJSON("POST", "/api/latest/fleet/software/batch", - batchSetSoftwareInstallersRequest{Software: []*fleet.SoftwareInstallerPayload{{Slug: ptr.String("zoom/windows"), RollbackVersion: "1.0"}}, TeamName: teamName}, + batchSetSoftwareInstallersRequest{Software: []*fleet.SoftwareInstallerPayload{{Slug: new("zoom/windows"), RollbackVersion: "1.0"}}, TeamName: teamName}, http.StatusAccepted, &resp, "team_name", teamName, "team_id", "0", ) @@ -28852,7 +28851,7 @@ func (s *integrationEnterpriseTestSuite) TestPinMajorVersion() { require.Equal(t, "1.0", titleResp.SoftwareTitle.SoftwarePackage.Version) s.DoJSON("POST", "/api/latest/fleet/software/batch", - batchSetSoftwareInstallersRequest{Software: []*fleet.SoftwareInstallerPayload{{Slug: ptr.String("zoom/windows"), RollbackVersion: "^1"}}, TeamName: teamName}, + batchSetSoftwareInstallersRequest{Software: []*fleet.SoftwareInstallerPayload{{Slug: new("zoom/windows"), RollbackVersion: "^1"}}, TeamName: teamName}, http.StatusAccepted, &resp, "team_name", teamName, "team_id", "0", ) @@ -28866,7 +28865,7 @@ func (s *integrationEnterpriseTestSuite) TestPinMajorVersion() { resetFMAState(states["/zoom/windows.json"], "2.0", []byte("abc"), "") s.DoJSON("POST", "/api/latest/fleet/software/batch", - batchSetSoftwareInstallersRequest{Software: []*fleet.SoftwareInstallerPayload{{Slug: ptr.String("zoom/windows"), RollbackVersion: "^1"}}, TeamName: teamName}, + batchSetSoftwareInstallersRequest{Software: []*fleet.SoftwareInstallerPayload{{Slug: new("zoom/windows"), RollbackVersion: "^1"}}, TeamName: teamName}, http.StatusAccepted, &resp, "team_name", teamName, "team_id", "0", ) @@ -28894,7 +28893,7 @@ func (s *integrationEnterpriseTestSuite) TestPinMajorVersion() { var resp batchSetSoftwareInstallersResponse s.DoJSON("POST", "/api/latest/fleet/software/batch", - batchSetSoftwareInstallersRequest{Software: []*fleet.SoftwareInstallerPayload{{Slug: ptr.String("1password/darwin"), RollbackVersion: "^1"}}, TeamName: teamName}, + batchSetSoftwareInstallersRequest{Software: []*fleet.SoftwareInstallerPayload{{Slug: new("1password/darwin"), RollbackVersion: "^1"}}, TeamName: teamName}, http.StatusNotFound, &resp, "team_name", teamName, "team_id", "0", ) @@ -28924,7 +28923,7 @@ func (s *integrationEnterpriseTestSuite) TestBatchSetSoftwareInstallersUnsetsObs // Setup: batch set only zoom/windows. var resp batchSetSoftwareInstallersResponse s.DoJSON("POST", "/api/latest/fleet/software/batch", - batchSetSoftwareInstallersRequest{Software: []*fleet.SoftwareInstallerPayload{{Slug: ptr.String("zoom/windows")}}, TeamName: team.Name}, + batchSetSoftwareInstallersRequest{Software: []*fleet.SoftwareInstallerPayload{{Slug: new("zoom/windows")}}, TeamName: team.Name}, http.StatusAccepted, &resp, "team_name", team.Name, "team_id", fmt.Sprint(team.ID), ) @@ -28933,8 +28932,8 @@ func (s *integrationEnterpriseTestSuite) TestBatchSetSoftwareInstallersUnsetsObs // Batch set both zoom/windows and 1password/darwin. s.DoJSON("POST", "/api/latest/fleet/software/batch", batchSetSoftwareInstallersRequest{Software: []*fleet.SoftwareInstallerPayload{ - {Slug: ptr.String("zoom/windows")}, - {Slug: ptr.String("1password/darwin")}, + {Slug: new("zoom/windows")}, + {Slug: new("1password/darwin")}, }, TeamName: team.Name}, http.StatusAccepted, &resp, "team_name", team.Name, "team_id", fmt.Sprint(team.ID), @@ -28964,7 +28963,7 @@ func (s *integrationEnterpriseTestSuite) TestBatchSetSoftwareInstallersUnsetsObs // patch_software_title_id without deleting the policy. Gitops then deletes it via the policy // delete API so the deletion produces a deleted_policy activity. s.DoJSON("POST", "/api/latest/fleet/software/batch", - batchSetSoftwareInstallersRequest{Software: []*fleet.SoftwareInstallerPayload{{Slug: ptr.String("zoom/windows")}}, TeamName: team.Name}, + batchSetSoftwareInstallersRequest{Software: []*fleet.SoftwareInstallerPayload{{Slug: new("zoom/windows")}}, TeamName: team.Name}, http.StatusAccepted, &resp, "team_name", team.Name, "team_id", fmt.Sprint(team.ID), ) @@ -28990,7 +28989,7 @@ func (s *integrationEnterpriseTestSuite) TestListAPIEndpoints() { u := &fleet.User{ Name: "test " + role, Email: role + "-api-endpoints@example.com", - GlobalRole: ptr.String(role), + GlobalRole: new(role), } require.NoError(t, u.SetPassword(test.GoodPassword, 10, 10)) _, err := s.ds.NewUser(context.Background(), u) @@ -29218,7 +29217,7 @@ func (s *integrationEnterpriseTestSuite) TestModifyAPIOnlyUserPremium() { nonAPIUser := &fleet.User{ Name: "Non API User", Email: "non-api-patch@example.com", - GlobalRole: ptr.String(fleet.RoleObserver), + GlobalRole: new(fleet.RoleObserver), } require.NoError(t, nonAPIUser.SetPassword(test.GoodPassword, 10, 10)) nonAPIUser, err = s.ds.NewUser(context.Background(), nonAPIUser) @@ -29464,10 +29463,10 @@ func (s *integrationEnterpriseTestSuite) TestGetUserReturnsAPIEndpoints() { // Create a fresh regular user rather than relying on seed data. var regularUserResp getUserResp s.DoJSON("POST", "/api/latest/fleet/users/admin", fleet.UserPayload{ - Name: ptr.String("Regular User"), - Email: ptr.String("regular-user-get-test@example.com"), - Password: ptr.String(test.GoodPassword), - GlobalRole: ptr.String(fleet.RoleObserver), + Name: new("Regular User"), + Email: new("regular-user-get-test@example.com"), + Password: new(test.GoodPassword), + GlobalRole: new(fleet.RoleObserver), }, http.StatusOK, ®ularUserResp) require.NotZero(t, regularUserResp.User.ID) @@ -29753,8 +29752,8 @@ func (s *integrationEnterpriseTestSuite) TestPolicyLabelsIncludeAll() { LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now(), - OsqueryHostID: ptr.String(t.Name() + suffix), - NodeKey: ptr.String(t.Name() + suffix), + OsqueryHostID: new(t.Name() + suffix), + NodeKey: new(t.Name() + suffix), UUID: uuid.New().String(), Hostname: fmt.Sprintf("%s-%s.local", t.Name(), suffix), Platform: "linux", @@ -29866,10 +29865,10 @@ func (s *integrationEnterpriseTestSuite) TestQueryLabelsIncludeAll() { autoOn := true var createResp fleet.CreateQueryResponse s.DoJSON("POST", "/api/latest/fleet/queries", fleet.QueryPayload{ - Name: ptr.String("q-include-all-" + t.Name()), - Query: ptr.String("SELECT 1"), - Logging: ptr.String(fleet.LoggingSnapshot), - Interval: ptr.Uint(60), + Name: new("q-include-all-" + t.Name()), + Query: new("SELECT 1"), + Logging: new(fleet.LoggingSnapshot), + Interval: new(uint(60)), AutomationsEnabled: &autoOn, LabelsIncludeAll: []string{lblA.Name, lblB.Name}, }, http.StatusOK, &createResp) @@ -29880,9 +29879,9 @@ func (s *integrationEnterpriseTestSuite) TestQueryLabelsIncludeAll() { // Mutex rejection on create. Assert on the specific validation error so a // generic 400 (e.g., name required) cannot silently satisfy the test. rejCreateResp := s.Do("POST", "/api/latest/fleet/queries", fleet.QueryPayload{ - Name: ptr.String("q-rej-" + t.Name()), - Query: ptr.String("SELECT 1"), - Logging: ptr.String(fleet.LoggingSnapshot), + Name: new("q-rej-" + t.Name()), + Query: new("SELECT 1"), + Logging: new(fleet.LoggingSnapshot), LabelsIncludeAll: []string{lblA.Name}, LabelsIncludeAny: []string{lblB.Name}, }, http.StatusBadRequest) @@ -29916,7 +29915,7 @@ func (s *integrationEnterpriseTestSuite) TestQueryLabelsIncludeAll() { mkHost := func(suffix string) *fleet.Host { h, err := s.ds.NewHost(ctx, &fleet.Host{ DetailUpdatedAt: time.Now(), LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now(), - OsqueryHostID: ptr.String("q" + suffix + t.Name()), NodeKey: ptr.String("q" + suffix + t.Name()), + OsqueryHostID: new("q" + suffix + t.Name()), NodeKey: new("q" + suffix + t.Name()), UUID: uuid.New().String(), Hostname: t.Name() + "-" + suffix + ".local", Platform: "linux", }) require.NoError(t, err) @@ -29970,9 +29969,9 @@ func (s *integrationEnterpriseTestSuite) TestCertificatesSpecs() { // Create a test certificate authority ca, err := s.ds.NewCertificateAuthority(ctx, &fleet.CertificateAuthority{ Type: string(fleet.CATypeCustomSCEPProxy), - Name: ptr.String("Test SCEP CA"), - URL: ptr.String("http://localhost:8080/scep"), - Challenge: ptr.String("test-challenge"), + Name: new("Test SCEP CA"), + URL: new("http://localhost:8080/scep"), + Challenge: new("test-challenge"), }) require.NoError(t, err) @@ -30065,7 +30064,7 @@ func (s *integrationEnterpriseTestSuite) TestCertificatesSpecs() { LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now(), - NodeKey: ptr.String("test-cert-node-key"), + NodeKey: new("test-cert-node-key"), UUID: "test-uuid-12345", Hostname: "test-cert-host.local", HardwareSerial: "TEST-SERIAL-67890", @@ -30202,7 +30201,7 @@ func (s *integrationEnterpriseTestSuite) TestCertificatesSpecs() { LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now(), - NodeKey: ptr.String("test-cert-no-team-node-key"), + NodeKey: new("test-cert-no-team-node-key"), UUID: "test-no-team-uuid-12345", Hostname: "test-cert-no-team-host.local", HardwareSerial: "TEST-NO-TEAM-SERIAL", @@ -30279,7 +30278,7 @@ func (s *integrationEnterpriseTestSuite) TestCertificatesSpecs() { observerUser := &fleet.User{ Name: "Observer User", Email: observerEmail, - GlobalRole: ptr.String(fleet.RoleObserver), + GlobalRole: new(fleet.RoleObserver), } require.NoError(t, observerUser.SetPassword(observerPwd, 10, 10)) _, err = s.ds.NewUser(ctx, observerUser) @@ -30382,7 +30381,7 @@ func (s *integrationEnterpriseTestSuite) TestOrgLogoUploadGitOpsAuth() { gitopsUser := &fleet.User{ Name: "GitOps Logo", Email: gitopsEmail, - GlobalRole: ptr.String(fleet.RoleGitOps), + GlobalRole: new(fleet.RoleGitOps), } require.NoError(t, gitopsUser.SetPassword(test.GoodPassword, 10, 10)) _, err := s.ds.NewUser(t.Context(), gitopsUser) @@ -30443,8 +30442,8 @@ func (s *integrationEnterpriseTestSuite) TestListHostReportsIncludeAllPremium() LabelUpdatedAt: time.Now(), PolicyUpdatedAt: time.Now(), SeenTime: time.Now(), - OsqueryHostID: ptr.String(t.Name() + suffix), - NodeKey: ptr.String(t.Name() + suffix), + OsqueryHostID: new(t.Name() + suffix), + NodeKey: new(t.Name() + suffix), UUID: uuid.New().String(), Hostname: t.Name() + "-" + suffix + ".local", Platform: "linux", @@ -30674,6 +30673,745 @@ func (s *integrationEnterpriseTestSuite) TestOrbitOsqueryReEnrollDoesNotChangeTe }) } +// TestTeamPolicyContinuousAutomationsCRUD exercises the create, modify, get, and +// GitOps spec-apply paths for the `continuous_automations_enabled` field on team +// policies, ensuring the value round-trips through every entry point. +func (s *integrationEnterpriseTestSuite) TestTeamPolicyContinuousAutomationsCRUD() { + t := s.T() + ctx := context.Background() + + team, err := s.ds.NewTeam(ctx, &fleet.Team{Name: t.Name()}) + require.NoError(t, err) + + // POST: default value is false. + createDefault := &fleet.TeamPolicyResponse{} + s.DoJSON("POST", fmt.Sprintf("/api/latest/fleet/teams/%d/policies", team.ID), &fleet.TeamPolicyRequest{ + Name: "default", + Query: "SELECT 1;", + Platform: "darwin", + }, http.StatusOK, &createDefault) + require.NotNil(t, createDefault.Policy) + require.False(t, createDefault.Policy.ContinuousAutomationsEnabled) + + // POST: explicitly set to true at creation. + createOn := &fleet.TeamPolicyResponse{} + s.DoJSON("POST", fmt.Sprintf("/api/latest/fleet/teams/%d/policies", team.ID), &fleet.TeamPolicyRequest{ + Name: "on", + Query: "SELECT 2;", + Platform: "darwin", + ContinuousAutomationsEnabled: true, + }, http.StatusOK, &createOn) + require.NotNil(t, createOn.Policy) + require.True(t, createOn.Policy.ContinuousAutomationsEnabled) + + // GET (single + list) returns the field as persisted. + getResp := &fleet.GetTeamPolicyByIDResponse{} + s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/teams/%d/policies/%d", team.ID, createOn.Policy.ID), nil, http.StatusOK, getResp) + require.NotNil(t, getResp.Policy) + require.True(t, getResp.Policy.ContinuousAutomationsEnabled) + + listResp := &fleet.ListTeamPoliciesResponse{} + s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/teams/%d/policies", team.ID), nil, http.StatusOK, listResp) + require.Len(t, listResp.Policies, 2) + for _, p := range listResp.Policies { + switch p.Name { + case "default": + assert.False(t, p.ContinuousAutomationsEnabled) + case "on": + assert.True(t, p.ContinuousAutomationsEnabled) + default: + t.Fatalf("unexpected policy %q", p.Name) + } + } + + // PATCH: flip the default policy on, flip the explicit one off. + patchOn := &fleet.ModifyTeamPolicyResponse{} + s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/teams/%d/policies/%d", team.ID, createDefault.Policy.ID), + &fleet.ModifyTeamPolicyRequest{ + ModifyPolicyPayload: fleet.ModifyPolicyPayload{ContinuousAutomationsEnabled: new(true)}, + }, http.StatusOK, patchOn) + require.NotNil(t, patchOn.Policy) + require.True(t, patchOn.Policy.ContinuousAutomationsEnabled) + + patchOff := &fleet.ModifyTeamPolicyResponse{} + s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/teams/%d/policies/%d", team.ID, createOn.Policy.ID), + &fleet.ModifyTeamPolicyRequest{ + ModifyPolicyPayload: fleet.ModifyPolicyPayload{ContinuousAutomationsEnabled: new(false)}, + }, http.StatusOK, patchOff) + require.NotNil(t, patchOff.Policy) + require.False(t, patchOff.Policy.ContinuousAutomationsEnabled) + + // PATCH without sending the field leaves it untouched (no implicit reset). + patchUnrelated := &fleet.ModifyTeamPolicyResponse{} + s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/teams/%d/policies/%d", team.ID, createDefault.Policy.ID), + json.RawMessage(`{"description": "unrelated edit"}`), http.StatusOK, patchUnrelated) + require.NotNil(t, patchUnrelated.Policy) + require.True(t, patchUnrelated.Policy.ContinuousAutomationsEnabled) + + // GitOps spec apply: create a new policy via /spec/policies and verify the + // field is stored, then flip it on a subsequent apply. + s.Do("POST", "/api/latest/fleet/spec/policies", fleet.ApplyPolicySpecsRequest{ + Specs: []*fleet.PolicySpec{ + { + Name: "gitops-policy", + Query: "SELECT 3;", + Platform: "darwin", + Team: team.Name, + ContinuousAutomationsEnabled: true, + }, + }, + }, http.StatusOK) + + listResp = &fleet.ListTeamPoliciesResponse{} + s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/teams/%d/policies", team.ID), nil, http.StatusOK, listResp) + var gitopsPolicy *fleet.Policy + for _, p := range listResp.Policies { + if p.Name == "gitops-policy" { + gitopsPolicy = p + break + } + } + require.NotNil(t, gitopsPolicy, "gitops-policy not found") + require.True(t, gitopsPolicy.ContinuousAutomationsEnabled) + + s.Do("POST", "/api/latest/fleet/spec/policies", fleet.ApplyPolicySpecsRequest{ + Specs: []*fleet.PolicySpec{ + { + Name: "gitops-policy", + Query: "SELECT 3;", + Platform: "darwin", + Team: team.Name, + ContinuousAutomationsEnabled: false, + }, + }, + }, http.StatusOK) + + updated, err := s.ds.Policy(ctx, gitopsPolicy.ID) + require.NoError(t, err) + require.False(t, updated.ContinuousAutomationsEnabled) +} + +// TestPolicyAutomationsContinuousScripts verifies that when a policy has +// continuous_automations_enabled=true, the attached script automation runs on +// every failing policy result — not just on the first failure or a pass→fail +// transition (the default behavior). +func (s *integrationEnterpriseTestSuite) TestPolicyAutomationsContinuousScripts() { + t := s.T() + ctx := context.Background() + + team, err := s.ds.NewTeam(ctx, &fleet.Team{Name: t.Name()}) + require.NoError(t, err) + + host, err := s.ds.NewHost(ctx, &fleet.Host{ + DetailUpdatedAt: time.Now(), + LabelUpdatedAt: time.Now(), + PolicyUpdatedAt: time.Now(), + SeenTime: time.Now().Add(-1 * time.Minute), + OsqueryHostID: new(t.Name()), + NodeKey: new(t.Name()), + UUID: uuid.New().String(), + Hostname: fmt.Sprintf("%s.local", t.Name()), + Platform: "darwin", + TeamID: &team.ID, + }) + require.NoError(t, err) + orbitKey := setOrbitEnrollment(t, host, s.ds) + host.OrbitNodeKey = &orbitKey + + // Use a dedicated script per policy. + continuousScript, err := s.ds.NewScript(ctx, &fleet.Script{ + Name: "continuous.sh", + ScriptContents: "echo continuous", + TeamID: &team.ID, + }) + require.NoError(t, err) + transitionScript, err := s.ds.NewScript(ctx, &fleet.Script{ + Name: "transition.sh", + ScriptContents: "echo transition", + TeamID: &team.ID, + }) + require.NoError(t, err) + + // Two policies on the same team: one with continuous automations, one + // without. Each has its own script attached. + continuousPolicy, err := s.ds.NewTeamPolicy(ctx, team.ID, nil, fleet.PolicyPayload{ + Name: "continuous", + Query: "SELECT 1 FROM osquery_info WHERE start_time < 0;", + Platform: "darwin", + ContinuousAutomationsEnabled: true, + }) + require.NoError(t, err) + transitionPolicy, err := s.ds.NewTeamPolicy(ctx, team.ID, nil, fleet.PolicyPayload{ + Name: "transition-only", + Query: "SELECT 1 FROM osquery_info WHERE start_time < 0;", + Platform: "darwin", + }) + require.NoError(t, err) + + // Attach the scripts via the API so the modify path is exercised. + attach := func(policyID, scriptID uint) { + var resp fleet.ModifyTeamPolicyResponse + s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/teams/%d/policies/%d", team.ID, policyID), fleet.ModifyTeamPolicyRequest{ + ModifyPolicyPayload: fleet.ModifyPolicyPayload{ + ScriptID: optjson.Any[uint]{Set: true, Valid: true, Value: scriptID}, + }, + }, http.StatusOK, &resp) + } + attach(continuousPolicy.ID, continuousScript.ID) + attach(transitionPolicy.ID, transitionScript.ID) + + submitPolicyResult := func(policyID uint, passes bool) { + var distributedResp submitDistributedQueryResultsResponse + s.DoJSONWithoutAuth("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( + host, + map[uint]*bool{policyID: new(passes)}, + ), http.StatusOK, &distributedResp) + } + completePendingScripts := func() { + pending, err := s.ds.ListPendingHostScriptExecutions(ctx, host.ID, false) + require.NoError(t, err) + for _, hs := range pending { + var orbitPostScriptResp fleet.OrbitPostScriptResultResponse + s.DoJSON("POST", "/api/fleet/orbit/scripts/result", + json.RawMessage(fmt.Sprintf( + `{"orbit_node_key": %q, "execution_id": %q, "exit_code": 0, "output": "ok"}`, + *host.OrbitNodeKey, hs.ExecutionID, + )), http.StatusOK, &orbitPostScriptResp) + } + } + // countExecutionsFor returns the number of script executions queued for a + // given (policy, script) pair on this host. Scripts are activated as soon + // as they are queued (NewHostScriptExecutionRequest calls + // activateNextUpcomingActivity), so they appear in host_script_results + // immediately — no need to also look at upcoming_activities. + countExecutionsFor := func(policyID, scriptID uint) int { + var count int + mysqltest.ExecAdhocSQL(t, s.ds, func(q sqlx.ExtContext) error { + return sqlx.GetContext(ctx, q, &count, ` + SELECT COUNT(*) FROM host_script_results + WHERE host_id = ? AND script_id = ? AND policy_id = ? + `, host.ID, scriptID, policyID) + }) + return count + } + continuousCount := func() int { return countExecutionsFor(continuousPolicy.ID, continuousScript.ID) } + transitionCount := func() int { return countExecutionsFor(transitionPolicy.ID, transitionScript.ID) } + + // assertCountStable polls the count for a window to catch delayed enqueues + // that a single point-in-time check would miss. + assertCountStable := func(expected int, countFn func() int, msgAndArgs ...any) { + t.Helper() + require.Never(t, func() bool { + return countFn() != expected + }, 2*time.Second, 100*time.Millisecond, msgAndArgs...) + } + + // Only one script can be activated at a time per host, so each step + // submits one policy result, waits for the script to record, then completes + // it before moving on (mirrors TestPolicyAutomationsContinuousSoftwareInstaller). + step := func(policyID uint, wantCount int, countFn func() int, msg string) { + t.Helper() + submitPolicyResult(policyID, false) + require.EventuallyWithT(t, func(t *assert.CollectT) { + assert.Equal(t, wantCount, countFn(), msg) + }, 5*time.Second, 100*time.Millisecond) + completePendingScripts() + } + + // First failing result: pass→fail transition queues the script on both. + step(continuousPolicy.ID, 1, continuousCount, "first script run for continuous policy") + step(transitionPolicy.ID, 1, transitionCount, "first script run for transition policy") + + // Second failing result (fail→fail): only the continuous policy re-queues. + step(continuousPolicy.ID, 2, continuousCount, "continuous policy fires on every failing result") + submitPolicyResult(transitionPolicy.ID, false) + assertCountStable(1, transitionCount, "default policy must not re-trigger on fail→fail") + + // Third failing result: continuous still re-triggers, default still does not. + step(continuousPolicy.ID, 3, continuousCount, "continuous policy fires on every failing result") + submitPolicyResult(transitionPolicy.ID, false) + assertCountStable(1, transitionCount) + + // Final: both policies pass. Neither should queue a script — passing + // results never trigger automations, regardless of continuous mode. + continuousBefore := continuousCount() + transitionBefore := transitionCount() + submitPolicyResult(continuousPolicy.ID, true) + submitPolicyResult(transitionPolicy.ID, true) + assertCountStable(continuousBefore, continuousCount, "continuous policy must not trigger script on passing result") + assertCountStable(transitionBefore, transitionCount, "transition policy must not trigger script on passing result") +} + +// TestPolicyAutomationsContinuousScriptRetryReset verifies that when a +// continuous-automation policy is still failing after its retry sequence has +// been exhausted (MaxPolicyAutomationRetries attempts), the next continuous +// re-fire resets the attempt counter so a fresh sequence of retries is +// available. Without the reset, attempt_number would just keep climbing past +// the cap and no retries would ever fire again. +func (s *integrationEnterpriseTestSuite) TestPolicyAutomationsContinuousScriptRetryReset() { + t := s.T() + ctx := context.Background() + + team, err := s.ds.NewTeam(ctx, &fleet.Team{Name: t.Name()}) + require.NoError(t, err) + + host, err := s.ds.NewHost(ctx, &fleet.Host{ + DetailUpdatedAt: time.Now(), + LabelUpdatedAt: time.Now(), + PolicyUpdatedAt: time.Now(), + SeenTime: time.Now().Add(-1 * time.Minute), + OsqueryHostID: new(t.Name()), + NodeKey: new(t.Name()), + UUID: uuid.New().String(), + Hostname: fmt.Sprintf("%s.local", t.Name()), + Platform: "darwin", + TeamID: &team.ID, + }) + require.NoError(t, err) + orbitKey := setOrbitEnrollment(t, host, s.ds) + host.OrbitNodeKey = &orbitKey + + script, err := s.ds.NewScript(ctx, &fleet.Script{ + Name: "fail.sh", + ScriptContents: "exit 1", + TeamID: &team.ID, + }) + require.NoError(t, err) + + policy, err := s.ds.NewTeamPolicy(ctx, team.ID, nil, fleet.PolicyPayload{ + Name: "continuous-retry-reset", + Query: "SELECT 1 FROM osquery_info WHERE start_time < 0;", + Platform: "darwin", + ContinuousAutomationsEnabled: true, + }) + require.NoError(t, err) + + var mtplr fleet.ModifyTeamPolicyResponse + s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/teams/%d/policies/%d", team.ID, policy.ID), fleet.ModifyTeamPolicyRequest{ + ModifyPolicyPayload: fleet.ModifyPolicyPayload{ + ScriptID: optjson.Any[uint]{Set: true, Valid: true, Value: script.ID}, + }, + }, http.StatusOK, &mtplr) + + submitPolicyResult := func(passes bool) { + var distributedResp submitDistributedQueryResultsResponse + s.DoJSONWithoutAuth("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( + host, + map[uint]*bool{policy.ID: new(passes)}, + ), http.StatusOK, &distributedResp) + } + + getPendingScript := func() *fleet.HostScriptResult { + t.Helper() + var pending *fleet.HostScriptResult + require.EventuallyWithT(t, func(t *assert.CollectT) { + scripts, err := s.ds.ListPendingHostScriptExecutions(ctx, host.ID, false) + assert.NoError(t, err) + assert.NotEmpty(t, scripts) + if len(scripts) > 0 { + pending = scripts[0] + } + }, 5*time.Second, 100*time.Millisecond) + return pending + } + + submitScriptFailure := func(executionID string) { + s.DoJSON("POST", "/api/fleet/orbit/scripts/result", + json.RawMessage(fmt.Sprintf( + `{"orbit_node_key": %q, "execution_id": %q, "exit_code": 1, "output": "fail"}`, + *host.OrbitNodeKey, executionID, + )), http.StatusOK, &fleet.OrbitPostScriptResultResponse{}) + } + + type row struct { + ExecutionID string `db:"execution_id"` + ExitCode *int64 `db:"exit_code"` + AttemptNumber *int `db:"attempt_number"` + } + listAttempts := func() []row { + var rows []row + mysqltest.ExecAdhocSQL(t, s.ds, func(q sqlx.ExtContext) error { + return sqlx.SelectContext(ctx, q, &rows, ` + SELECT execution_id, exit_code, attempt_number + FROM host_script_results + WHERE host_id = ? AND script_id = ? AND policy_id = ? + ORDER BY id ASC + `, host.ID, script.ID, policy.ID) + }) + return rows + } + + // Phase 1: pass→fail starts a sequence. Drive it to the cap by failing + // every attempt. fleet.MaxPolicyAutomationRetries is 3, so the host + // should see exactly 3 attempts: the initial run plus 2 auto-retries. + submitPolicyResult(false) + for i := 1; i <= fleet.MaxPolicyAutomationRetries; i++ { + pending := getPendingScript() + require.NotNil(t, pending) + submitScriptFailure(pending.ExecutionID) + } + require.EventuallyWithT(t, func(t *assert.CollectT) { + rows := listAttempts() + if !assert.Len(t, rows, fleet.MaxPolicyAutomationRetries) { + return + } + // All rows should be completed (exit_code recorded) and form a + // 1..MaxPolicyAutomationRetries attempt sequence. + for i, r := range rows { + if assert.NotNil(t, r.AttemptNumber) { + assert.Equal(t, i+1, *r.AttemptNumber, "row %d attempt_number", i) + } + assert.NotNil(t, r.ExitCode, "row %d should have a recorded exit_code", i) + } + }, 5*time.Second, 100*time.Millisecond) + + // No further retry is queued once the cap is hit — without continuous + // re-fire, the host_script_results count stays at MaxPolicyAutomationRetries. + require.Never(t, func() bool { + return len(listAttempts()) != fleet.MaxPolicyAutomationRetries + }, 1*time.Second, 100*time.Millisecond, "no extra attempts queued after retry cap is hit") + + // Phase 2: the policy is still failing. A continuous re-fire must reset + // the attempt counter — the new attempt should start at 1 and remain + // retry-eligible, NOT inherit the previous sequence's cap. + submitPolicyResult(false) + pending := getPendingScript() + require.NotNil(t, pending) + submitScriptFailure(pending.ExecutionID) + + require.EventuallyWithT(t, func(t *assert.CollectT) { + rows := listAttempts() + // 3 old (reset to 0) + 1 new completed (attempt 1) + 1 new queued retry (NULL) + if !assert.Len(t, rows, fleet.MaxPolicyAutomationRetries+2) { + return + } + // Old sequence is marked attempt_number=0. + for i := range fleet.MaxPolicyAutomationRetries { + if assert.NotNil(t, rows[i].AttemptNumber) { + assert.Equal(t, 0, *rows[i].AttemptNumber, "old row %d should be reset", i) + } + } + // New sequence starts at 1, and a retry has been queued (attempt_number NULL until completed). + if assert.NotNil(t, rows[fleet.MaxPolicyAutomationRetries].AttemptNumber) { + assert.Equal(t, 1, *rows[fleet.MaxPolicyAutomationRetries].AttemptNumber, "new sequence first attempt") + } + assert.Nil(t, rows[fleet.MaxPolicyAutomationRetries+1].AttemptNumber, "retry should be queued (NULL) after fresh sequence") + }, 5*time.Second, 100*time.Millisecond) +} + +// TestPolicyAutomationsContinuousSoftwareInstaller verifies that +// continuous_automations_enabled=true causes a software install automation to +// fire on every failing policy result, not just on pass→fail transitions. +func (s *integrationEnterpriseTestSuite) TestPolicyAutomationsContinuousSoftwareInstaller() { + t := s.T() + ctx := context.Background() + + team, err := s.ds.NewTeam(ctx, &fleet.Team{Name: t.Name()}) + require.NoError(t, err) + + host, err := s.ds.NewHost(ctx, &fleet.Host{ + DetailUpdatedAt: time.Now(), + LabelUpdatedAt: time.Now(), + PolicyUpdatedAt: time.Now(), + SeenTime: time.Now().Add(-1 * time.Minute), + OsqueryHostID: new(t.Name()), + NodeKey: new(t.Name()), + UUID: uuid.New().String(), + Hostname: fmt.Sprintf("%s.local", t.Name()), + Platform: "darwin", + TeamID: &team.ID, + }) + require.NoError(t, err) + orbitKey := setOrbitEnrollment(t, host, s.ds) + host.OrbitNodeKey = &orbitKey + + // Upload a macOS installer to the team. + s.uploadSoftwareInstaller(t, &fleet.UploadSoftwareInstallerPayload{ + InstallScript: "echo install", + Filename: "dummy_installer.pkg", + TeamID: &team.ID, + }, http.StatusOK, "") + + titlesResp := listSoftwareTitlesResponse{} + s.DoJSON("GET", "/api/latest/fleet/software/titles", listSoftwareTitlesRequest{}, http.StatusOK, &titlesResp, + "query", "DummyApp", "team_id", fmt.Sprintf("%d", team.ID), + ) + require.Len(t, titlesResp.SoftwareTitles, 1) + titleID := titlesResp.SoftwareTitles[0].ID + + var installerID uint + mysqltest.ExecAdhocSQL(t, s.ds, func(q sqlx.ExtContext) error { + return sqlx.GetContext(ctx, q, &installerID, + `SELECT id FROM software_installers WHERE global_or_team_id = ? AND filename = ?`, + team.ID, "dummy_installer.pkg", + ) + }) + require.NotZero(t, installerID) + + continuousPolicy, err := s.ds.NewTeamPolicy(ctx, team.ID, nil, fleet.PolicyPayload{ + Name: "continuous", + Query: "SELECT 1 FROM osquery_info WHERE start_time < 0;", + Platform: "darwin", + ContinuousAutomationsEnabled: true, + }) + require.NoError(t, err) + transitionPolicy, err := s.ds.NewTeamPolicy(ctx, team.ID, nil, fleet.PolicyPayload{ + Name: "transition-only", + Query: "SELECT 1 FROM osquery_info WHERE start_time < 0;", + Platform: "darwin", + }) + require.NoError(t, err) + + for _, p := range []*fleet.Policy{continuousPolicy, transitionPolicy} { + var resp fleet.ModifyTeamPolicyResponse + s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/teams/%d/policies/%d", team.ID, p.ID), fleet.ModifyTeamPolicyRequest{ + ModifyPolicyPayload: fleet.ModifyPolicyPayload{ + SoftwareTitleID: optjson.Any[uint]{Set: true, Valid: true, Value: titleID}, + }, + }, http.StatusOK, &resp) + } + + submitPolicyResult := func(policyID uint, passes bool) { + var distributedResp submitDistributedQueryResultsResponse + s.DoJSONWithoutAuth("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( + host, + map[uint]*bool{policyID: new(passes)}, + ), http.StatusOK, &distributedResp) + } + completePendingInstall := func() { + last, err := s.ds.GetHostLastInstallData(ctx, host.ID, installerID) + require.NoError(t, err) + if last == nil || last.Status == nil || *last.Status != fleet.SoftwareInstallPending { + return + } + s.Do("POST", "/api/fleet/orbit/software_install/result", + json.RawMessage(fmt.Sprintf(`{ + "orbit_node_key": %q, + "install_uuid": %q, + "install_script_exit_code": 0, + "install_script_output": "ok" + }`, *host.OrbitNodeKey, last.ExecutionID)), + http.StatusNoContent) + } + countInstallsFor := func(policyID uint) int { + var count int + mysqltest.ExecAdhocSQL(t, s.ds, func(q sqlx.ExtContext) error { + return sqlx.GetContext(ctx, q, &count, ` + SELECT COUNT(*) FROM host_software_installs + WHERE host_id = ? AND software_installer_id = ? AND policy_id = ? + `, host.ID, installerID, policyID) + }) + return count + } + + // First fail: both policies queue an install (pass→fail transition). + submitPolicyResult(continuousPolicy.ID, false) + require.EventuallyWithT(t, func(t *assert.CollectT) { + assert.Equal(t, 1, countInstallsFor(continuousPolicy.ID)) + }, 5*time.Second, 100*time.Millisecond) + completePendingInstall() + submitPolicyResult(transitionPolicy.ID, false) + require.EventuallyWithT(t, func(t *assert.CollectT) { + assert.Equal(t, 1, countInstallsFor(transitionPolicy.ID)) + }, 5*time.Second, 100*time.Millisecond) + completePendingInstall() + + // Second fail (fail→fail): continuous policy re-queues, default does not. + submitPolicyResult(continuousPolicy.ID, false) + require.EventuallyWithT(t, func(t *assert.CollectT) { + assert.Equal(t, 2, countInstallsFor(continuousPolicy.ID), "continuous policy must fire on every failing result") + }, 5*time.Second, 100*time.Millisecond) + completePendingInstall() + submitPolicyResult(transitionPolicy.ID, false) + // Poll for a window so a delayed enqueue doesn't slip past a one-shot check. + require.Never(t, func() bool { + return countInstallsFor(transitionPolicy.ID) != 1 + }, 2*time.Second, 100*time.Millisecond, "default policy must not re-trigger on fail→fail") + + // Final: both policies pass. Neither should queue an install — passing + // results never trigger automations, regardless of continuous mode. + continuousBefore := countInstallsFor(continuousPolicy.ID) + transitionBefore := countInstallsFor(transitionPolicy.ID) + submitPolicyResult(continuousPolicy.ID, true) + submitPolicyResult(transitionPolicy.ID, true) + require.Never(t, func() bool { + return countInstallsFor(continuousPolicy.ID) != continuousBefore + }, 2*time.Second, 100*time.Millisecond, "continuous policy must not trigger install on passing result") + require.Never(t, func() bool { + return countInstallsFor(transitionPolicy.ID) != transitionBefore + }, 2*time.Second, 100*time.Millisecond, "transition policy must not trigger install on passing result") +} + +// TestPolicyAutomationsContinuousSoftwareInstallerRetryReset is the software +// install analog of TestPolicyAutomationsContinuousScriptRetryReset: it +// verifies that when a continuous-automation policy is still failing after its +// software-install retry sequence has been exhausted, the next continuous +// re-fire resets the attempt counter so a fresh retry sequence is available. +func (s *integrationEnterpriseTestSuite) TestPolicyAutomationsContinuousSoftwareInstallerRetryReset() { + t := s.T() + ctx := context.Background() + + team, err := s.ds.NewTeam(ctx, &fleet.Team{Name: t.Name()}) + require.NoError(t, err) + + host, err := s.ds.NewHost(ctx, &fleet.Host{ + DetailUpdatedAt: time.Now(), + LabelUpdatedAt: time.Now(), + PolicyUpdatedAt: time.Now(), + SeenTime: time.Now().Add(-1 * time.Minute), + OsqueryHostID: new(t.Name()), + NodeKey: new(t.Name()), + UUID: uuid.New().String(), + Hostname: fmt.Sprintf("%s.local", t.Name()), + Platform: "darwin", + TeamID: &team.ID, + }) + require.NoError(t, err) + orbitKey := setOrbitEnrollment(t, host, s.ds) + host.OrbitNodeKey = &orbitKey + + // Upload a macOS installer to the team. + s.uploadSoftwareInstaller(t, &fleet.UploadSoftwareInstallerPayload{ + InstallScript: "exit 1", + Filename: "dummy_installer.pkg", + TeamID: &team.ID, + }, http.StatusOK, "") + + titlesResp := listSoftwareTitlesResponse{} + s.DoJSON("GET", "/api/latest/fleet/software/titles", listSoftwareTitlesRequest{}, http.StatusOK, &titlesResp, + "query", "DummyApp", "team_id", fmt.Sprintf("%d", team.ID), + ) + require.Len(t, titlesResp.SoftwareTitles, 1) + titleID := titlesResp.SoftwareTitles[0].ID + + var installerID uint + mysqltest.ExecAdhocSQL(t, s.ds, func(q sqlx.ExtContext) error { + return sqlx.GetContext(ctx, q, &installerID, + `SELECT id FROM software_installers WHERE global_or_team_id = ? AND filename = ?`, + team.ID, "dummy_installer.pkg", + ) + }) + require.NotZero(t, installerID) + + policy, err := s.ds.NewTeamPolicy(ctx, team.ID, nil, fleet.PolicyPayload{ + Name: "continuous-retry-reset-installer", + Query: "SELECT 1 FROM osquery_info WHERE start_time < 0;", + Platform: "darwin", + ContinuousAutomationsEnabled: true, + }) + require.NoError(t, err) + + var mtplr fleet.ModifyTeamPolicyResponse + s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/teams/%d/policies/%d", team.ID, policy.ID), fleet.ModifyTeamPolicyRequest{ + ModifyPolicyPayload: fleet.ModifyPolicyPayload{ + SoftwareTitleID: optjson.Any[uint]{Set: true, Valid: true, Value: titleID}, + }, + }, http.StatusOK, &mtplr) + + submitPolicyResult := func(passes bool) { + var distributedResp submitDistributedQueryResultsResponse + s.DoJSONWithoutAuth("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( + host, + map[uint]*bool{policy.ID: new(passes)}, + ), http.StatusOK, &distributedResp) + } + + getPendingInstall := func() *fleet.HostLastInstallData { + t.Helper() + var pending *fleet.HostLastInstallData + require.EventuallyWithT(t, func(t *assert.CollectT) { + last, err := s.ds.GetHostLastInstallData(ctx, host.ID, installerID) + assert.NoError(t, err) + if !assert.NotNil(t, last) || !assert.NotNil(t, last.Status) { + return + } + assert.Equal(t, fleet.SoftwareInstallPending, *last.Status) + pending = last + }, 5*time.Second, 100*time.Millisecond) + return pending + } + + submitInstallFailure := func(installUUID string) { + s.Do("POST", "/api/fleet/orbit/software_install/result", + json.RawMessage(fmt.Sprintf(`{ + "orbit_node_key": %q, + "install_uuid": %q, + "install_script_exit_code": 1, + "install_script_output": "fail" + }`, *host.OrbitNodeKey, installUUID)), + http.StatusNoContent) + } + + type row struct { + ExecutionID string `db:"execution_id"` + ExitCode *int64 `db:"install_script_exit_code"` + AttemptNumber *int `db:"attempt_number"` + } + listAttempts := func() []row { + var rows []row + mysqltest.ExecAdhocSQL(t, s.ds, func(q sqlx.ExtContext) error { + return sqlx.SelectContext(ctx, q, &rows, ` + SELECT execution_id, install_script_exit_code, attempt_number + FROM host_software_installs + WHERE host_id = ? AND software_installer_id = ? AND policy_id = ? + ORDER BY id ASC + `, host.ID, installerID, policy.ID) + }) + return rows + } + + // Phase 1: pass→fail starts a sequence. Drive it to the cap by failing + // every attempt. fleet.MaxPolicyAutomationRetries is 3, so the host + // should see exactly 3 attempts: the initial run plus 2 auto-retries. + submitPolicyResult(false) + for i := 1; i <= fleet.MaxPolicyAutomationRetries; i++ { + pending := getPendingInstall() + require.NotNil(t, pending) + submitInstallFailure(pending.ExecutionID) + } + require.EventuallyWithT(t, func(t *assert.CollectT) { + rows := listAttempts() + if !assert.Len(t, rows, fleet.MaxPolicyAutomationRetries) { + return + } + for i, r := range rows { + if assert.NotNil(t, r.AttemptNumber) { + assert.Equal(t, i+1, *r.AttemptNumber, "row %d attempt_number", i) + } + assert.NotNil(t, r.ExitCode, "row %d should have a recorded exit_code", i) + } + }, 5*time.Second, 100*time.Millisecond) + + // No further retry is queued once the cap is hit. + require.Never(t, func() bool { + return len(listAttempts()) != fleet.MaxPolicyAutomationRetries + }, 1*time.Second, 100*time.Millisecond, "no extra install attempts after retry cap is hit") + + // Phase 2: continuous re-fire after the cap is reached must reset the + // attempt counter so the new attempt starts at 1 and remains retry-eligible. + submitPolicyResult(false) + pending := getPendingInstall() + require.NotNil(t, pending) + submitInstallFailure(pending.ExecutionID) + + require.EventuallyWithT(t, func(t *assert.CollectT) { + rows := listAttempts() + // 3 old (reset to 0) + 1 new completed (attempt 1) + 1 new queued retry (NULL) + if !assert.Len(t, rows, fleet.MaxPolicyAutomationRetries+2) { + return + } + for i := range fleet.MaxPolicyAutomationRetries { + if assert.NotNil(t, rows[i].AttemptNumber) { + assert.Equal(t, 0, *rows[i].AttemptNumber, "old row %d should be reset", i) + } + } + if assert.NotNil(t, rows[fleet.MaxPolicyAutomationRetries].AttemptNumber) { + assert.Equal(t, 1, *rows[fleet.MaxPolicyAutomationRetries].AttemptNumber, "new sequence first attempt") + } + assert.Nil(t, rows[fleet.MaxPolicyAutomationRetries+1].AttemptNumber, "retry should be queued (NULL) after fresh sequence") + }, 5*time.Second, 100*time.Millisecond) +} + // TestOrbitEnrollWithIdPPopulatesDeviceMapping covers issue #45066: orbit // enrolling a Linux or Windows host through the End User Authentication flow // must populate host_emails so the hosts list endpoint returns diff --git a/server/service/integration_mdm_test.go b/server/service/integration_mdm_test.go index eafa7eec6b..b44a185145 100644 --- a/server/service/integration_mdm_test.go +++ b/server/service/integration_mdm_test.go @@ -19109,6 +19109,409 @@ func (s *integrationMDMTestSuite) TestVPPPolicyAutomationLabelScopingRetrigger() require.Equal(t, uint(1), policy1.FailingHostCount) } +// TestPolicyAutomationsContinuousVPPApp mirrors +// TestPolicyAutomationsContinuousSoftwareInstaller but for a VPP app +// automation: continuous_automations_enabled=true must re-trigger an +// install on every failing policy result (not only on pass→fail), and +// passing results must never trigger an install. +func (s *integrationMDMTestSuite) TestPolicyAutomationsContinuousVPPApp() { + t := s.T() + ctx := context.Background() + + // VPP token setup. + orgName := "Fleet Device Management Inc." + token := "mycooltoken" + expTime := time.Now().Add(200 * time.Hour).UTC().Round(time.Second) + expDate := expTime.Format(fleet.VPPTimeFormat) + tokenJSON := fmt.Sprintf(`{"expDate":"%s","token":"%s","orgName":"%s"}`, expDate, token, orgName) + dev_mode.SetOverride("FLEET_DEV_VPP_URL", s.appleVPPConfigSrv.URL, t) + var validToken uploadVPPTokenResponse + s.uploadDataViaForm("/api/latest/fleet/vpp_tokens", "token", "token.vpptoken", + []byte(base64.StdEncoding.EncodeToString([]byte(tokenJSON))), + http.StatusAccepted, "", &validToken) + + var resp getVPPTokensResponse + s.DoJSON("GET", "/api/latest/fleet/vpp_tokens", &getVPPTokensRequest{}, http.StatusOK, &resp) + require.NoError(t, resp.Err) + + // Team and MDM-enrolled host. + var newTeamResp teamResponse + s.DoJSON("POST", "/api/latest/fleet/teams", &createTeamRequest{TeamPayload: fleet.TeamPayload{Name: new(t.Name())}}, http.StatusOK, &newTeamResp) + team := newTeamResp.Team + + mdmHost, mdmDevice := createHostThenEnrollMDM(s.ds, s.server.URL, t) + setOrbitEnrollment(t, mdmHost, s.ds) + s.awaitRunAppleMDMWorkerSchedule() + s.runWorker() + checkInstallFleetdCommandSent(t, mdmDevice, true) + s.appleVPPConfigSrvConfig.SerialNumbers = append(s.appleVPPConfigSrvConfig.SerialNumbers, mdmHost.HardwareSerial) + s.Do("POST", "/api/latest/fleet/hosts/transfer", + &addHostsToTeamRequest{HostIDs: []uint{mdmHost.ID}, TeamID: &team.ID}, http.StatusOK) + + var resPatchVPP patchVPPTokensTeamsResponse + s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/vpp_tokens/%d/teams", resp.Tokens[0].ID), + patchVPPTokensTeamsRequest{TeamIDs: []uint{team.ID}}, http.StatusOK, &resPatchVPP) + + // Pick two macOS VPP apps and add them to the team. Each policy gets its + // own VPP app: a queued VPP install blocks further queueing for the same + // adam_id (MapAdamIDsPendingInstall gate), so sharing one app between the + // two policies would hide the behavior being tested. + var appResp getAppStoreAppsResponse + s.DoJSON("GET", "/api/latest/fleet/software/app_store_apps", &getAppStoreAppsRequest{}, http.StatusOK, &appResp, "team_id", fmt.Sprint(team.ID)) + require.NoError(t, appResp.Err) + var macOSApps []*fleet.VPPApp + for _, app := range appResp.AppStoreApps { + if app.Platform == fleet.MacOSPlatform { + macOSApps = append(macOSApps, app) + } + } + require.GreaterOrEqual(t, len(macOSApps), 2, "expected at least two macOS VPP apps in the mock catalog") + continuousApp, transitionApp := macOSApps[0], macOSApps[1] + + addTitleID := func(app *fleet.VPPApp) uint { + var addAppResp addAppStoreAppResponse + s.DoJSON("POST", "/api/latest/fleet/software/app_store_apps", &addAppStoreAppRequest{ + TeamID: &team.ID, + Platform: app.Platform, + AppStoreID: app.AdamID, + }, http.StatusOK, &addAppResp) + var listSw listSoftwareTitlesResponse + s.DoJSON("GET", "/api/latest/fleet/software/titles", nil, http.StatusOK, &listSw, + "team_id", fmt.Sprint(team.ID), + "available_for_install", "true", + "query", app.Name, + ) + require.NotEmpty(t, listSw.SoftwareTitles) + require.NotNil(t, listSw.SoftwareTitles[0].AppStoreApp) + return listSw.SoftwareTitles[0].ID + } + continuousTitleID := addTitleID(continuousApp) + transitionTitleID := addTitleID(transitionApp) + + // Two policies attached to the same VPP app: one continuous, one default. + continuousPolicy, err := s.ds.NewTeamPolicy(ctx, team.ID, nil, fleet.PolicyPayload{ + Name: "continuous", + Query: "SELECT 1 FROM osquery_info WHERE start_time < 0;", + Platform: "darwin", + ContinuousAutomationsEnabled: true, + }) + require.NoError(t, err) + transitionPolicy, err := s.ds.NewTeamPolicy(ctx, team.ID, nil, fleet.PolicyPayload{ + Name: "transition-only", + Query: "SELECT 1 FROM osquery_info WHERE start_time < 0;", + Platform: "darwin", + }) + require.NoError(t, err) + + attach := func(policyID, titleID uint) { + var mtplr fleet.ModifyTeamPolicyResponse + s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/teams/%d/policies/%d", team.ID, policyID), fleet.ModifyTeamPolicyRequest{ + ModifyPolicyPayload: fleet.ModifyPolicyPayload{ + SoftwareTitleID: optjson.Any[uint]{Set: true, Valid: true, Value: titleID}, + }, + }, http.StatusOK, &mtplr) + } + attach(continuousPolicy.ID, continuousTitleID) + attach(transitionPolicy.ID, transitionTitleID) + + submitPolicyResult := func(policyID uint, passes bool) { + var distributedResp submitDistributedQueryResultsResponse + s.DoJSONWithoutAuth("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( + mdmHost, + map[uint]*bool{policyID: new(passes)}, + ), http.StatusOK, &distributedResp) + } + + // host_vpp_software_installs grows by one row per queued install; a queued + // install also blocks further queueing for the same adam_id until the MDM + // install command is acknowledged. + countInstallsFor := func(policyID uint) int { + var count int + mysqltest.ExecAdhocSQL(t, s.ds, func(q sqlx.ExtContext) error { + return sqlx.GetContext(ctx, q, &count, ` + SELECT COUNT(*) FROM host_vpp_software_installs + WHERE host_id = ? AND policy_id = ? + `, mdmHost.ID, policyID) + }) + return count + } + + completeVPPInstall := func() { + s.awaitRunAppleMDMWorkerSchedule() + s.runWorker() + // First drain: acknowledge the InstallApplication command. + cmd, err := mdmDevice.Idle() + require.NoError(t, err) + for cmd != nil { + switch cmd.Command.RequestType { + case "InstallApplication": + cmd, err = mdmDevice.Acknowledge(cmd.CommandUUID) + require.NoError(t, err) + case "InstalledApplicationList": + cmd, err = mdmDevice.AcknowledgeInstalledApplicationList(mdmDevice.UUID, cmd.CommandUUID, []fleet.Software{ + {Name: continuousApp.Name, BundleIdentifier: continuousApp.BundleIdentifier, Version: continuousApp.LatestVersion, Installed: true}, + {Name: transitionApp.Name, BundleIdentifier: transitionApp.BundleIdentifier, Version: transitionApp.LatestVersion, Installed: true}, + }) + require.NoError(t, err) + default: + require.Fail(t, "unexpected command type", cmd.Command.RequestType) + } + } + // Second drain: the post-install InstalledApplicationList verification + // command is queued by a worker after the Acknowledge above, so we have + // to runWorker again and re-Idle to pick it up. + s.runWorker() + cmd, err = mdmDevice.Idle() + require.NoError(t, err) + for cmd != nil { + switch cmd.Command.RequestType { + case "InstalledApplicationList": + cmd, err = mdmDevice.AcknowledgeInstalledApplicationList(mdmDevice.UUID, cmd.CommandUUID, []fleet.Software{ + {Name: continuousApp.Name, BundleIdentifier: continuousApp.BundleIdentifier, Version: continuousApp.LatestVersion, Installed: true}, + {Name: transitionApp.Name, BundleIdentifier: transitionApp.BundleIdentifier, Version: transitionApp.LatestVersion, Installed: true}, + }) + require.NoError(t, err) + default: + require.Fail(t, "unexpected command type", cmd.Command.RequestType) + } + } + s.runWorker() + } + + step := func(policyID uint, wantCount int, countFn func() int, msg string) { + t.Helper() + submitPolicyResult(policyID, false) + require.EventuallyWithT(t, func(t *assert.CollectT) { + assert.Equal(t, wantCount, countFn(), msg) + }, 5*time.Second, 100*time.Millisecond) + completeVPPInstall() + } + + continuousCount := func() int { return countInstallsFor(continuousPolicy.ID) } + transitionCount := func() int { return countInstallsFor(transitionPolicy.ID) } + + // First failing result: pass→fail transition queues an install on both. + step(continuousPolicy.ID, 1, continuousCount, "first install for continuous policy") + step(transitionPolicy.ID, 1, transitionCount, "first install for transition policy") + + // Second failing result (fail→fail): only the continuous policy re-queues. + step(continuousPolicy.ID, 2, continuousCount, "continuous policy must fire on every failing result") + submitPolicyResult(transitionPolicy.ID, false) + require.Never(t, func() bool { + return transitionCount() != 1 + }, 2*time.Second, 100*time.Millisecond, "default policy must not re-trigger on fail→fail") + + // Third failing result: continuous still re-triggers, default still does not. + step(continuousPolicy.ID, 3, continuousCount, "continuous policy must fire on every failing result") + submitPolicyResult(transitionPolicy.ID, false) + require.Never(t, func() bool { + return transitionCount() != 1 + }, 2*time.Second, 100*time.Millisecond) + + // Final: passing results never trigger an install, regardless of mode. + continuousBefore := continuousCount() + transitionBefore := transitionCount() + submitPolicyResult(continuousPolicy.ID, true) + submitPolicyResult(transitionPolicy.ID, true) + require.Never(t, func() bool { + return continuousCount() != continuousBefore + }, 2*time.Second, 100*time.Millisecond, "continuous policy must not trigger install on passing result") + require.Never(t, func() bool { + return transitionCount() != transitionBefore + }, 2*time.Second, 100*time.Millisecond, "transition policy must not trigger install on passing result") +} + +// TestPolicyAutomationsContinuousVPPAppRetryReset is the VPP analog of the +// script and software-installer retry-reset tests, but the assertion is +// different. VPP retry tracking is per-row (host_vpp_software_installs.retry_count +// is bumped in-place by RetryVPPInstall, gated against MaxSoftwareInstallAttempts +// on that single row), so a continuous re-fire produces a *brand new* row whose +// retry_count starts at 0 — no reset of the old row is needed for the new one to +// have a fresh retry budget. This test pins that behavior so future refactors +// don't quietly break it. +func (s *integrationMDMTestSuite) TestPolicyAutomationsContinuousVPPAppRetryReset() { + t := s.T() + ctx := context.Background() + + // VPP token setup. + orgName := "Fleet Device Management Inc." + token := "mycooltoken" + expTime := time.Now().Add(200 * time.Hour).UTC().Round(time.Second) + expDate := expTime.Format(fleet.VPPTimeFormat) + tokenJSON := fmt.Sprintf(`{"expDate":"%s","token":"%s","orgName":"%s"}`, expDate, token, orgName) + dev_mode.SetOverride("FLEET_DEV_VPP_URL", s.appleVPPConfigSrv.URL, t) + var validToken uploadVPPTokenResponse + s.uploadDataViaForm("/api/latest/fleet/vpp_tokens", "token", "token.vpptoken", + []byte(base64.StdEncoding.EncodeToString([]byte(tokenJSON))), + http.StatusAccepted, "", &validToken) + + var resp getVPPTokensResponse + s.DoJSON("GET", "/api/latest/fleet/vpp_tokens", &getVPPTokensRequest{}, http.StatusOK, &resp) + require.NoError(t, resp.Err) + + var newTeamResp teamResponse + s.DoJSON("POST", "/api/latest/fleet/teams", &createTeamRequest{TeamPayload: fleet.TeamPayload{Name: new(t.Name())}}, http.StatusOK, &newTeamResp) + team := newTeamResp.Team + + mdmHost, mdmDevice := createHostThenEnrollMDM(s.ds, s.server.URL, t) + setOrbitEnrollment(t, mdmHost, s.ds) + s.awaitRunAppleMDMWorkerSchedule() + s.runWorker() + checkInstallFleetdCommandSent(t, mdmDevice, true) + s.appleVPPConfigSrvConfig.SerialNumbers = append(s.appleVPPConfigSrvConfig.SerialNumbers, mdmHost.HardwareSerial) + s.Do("POST", "/api/latest/fleet/hosts/transfer", + &addHostsToTeamRequest{HostIDs: []uint{mdmHost.ID}, TeamID: &team.ID}, http.StatusOK) + + var resPatchVPP patchVPPTokensTeamsResponse + s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/vpp_tokens/%d/teams", resp.Tokens[0].ID), + patchVPPTokensTeamsRequest{TeamIDs: []uint{team.ID}}, http.StatusOK, &resPatchVPP) + + // Pick a macOS VPP app and add it to the team. + var appResp getAppStoreAppsResponse + s.DoJSON("GET", "/api/latest/fleet/software/app_store_apps", &getAppStoreAppsRequest{}, http.StatusOK, &appResp, "team_id", fmt.Sprint(team.ID)) + require.NoError(t, appResp.Err) + var addedApp *fleet.VPPApp + for _, app := range appResp.AppStoreApps { + if app.Platform == fleet.MacOSPlatform { + addedApp = app + break + } + } + require.NotNil(t, addedApp) + + var addAppResp addAppStoreAppResponse + s.DoJSON("POST", "/api/latest/fleet/software/app_store_apps", &addAppStoreAppRequest{ + TeamID: &team.ID, + Platform: addedApp.Platform, + AppStoreID: addedApp.AdamID, + }, http.StatusOK, &addAppResp) + + var listSw listSoftwareTitlesResponse + s.DoJSON("GET", "/api/latest/fleet/software/titles", nil, http.StatusOK, &listSw, + "team_id", fmt.Sprint(team.ID), + "available_for_install", "true", + "query", addedApp.Name, + ) + require.Len(t, listSw.SoftwareTitles, 1) + require.NotNil(t, listSw.SoftwareTitles[0].AppStoreApp) + vppTitleID := listSw.SoftwareTitles[0].ID + + policy, err := s.ds.NewTeamPolicy(ctx, team.ID, nil, fleet.PolicyPayload{ + Name: "continuous-vpp-retry-reset", + Query: "SELECT 1 FROM osquery_info WHERE start_time < 0;", + Platform: "darwin", + ContinuousAutomationsEnabled: true, + }) + require.NoError(t, err) + + var mtplr fleet.ModifyTeamPolicyResponse + s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/teams/%d/policies/%d", team.ID, policy.ID), fleet.ModifyTeamPolicyRequest{ + ModifyPolicyPayload: fleet.ModifyPolicyPayload{ + SoftwareTitleID: optjson.Any[uint]{Set: true, Valid: true, Value: vppTitleID}, + }, + }, http.StatusOK, &mtplr) + + submitPolicyResult := func(passes bool) { + var distributedResp submitDistributedQueryResultsResponse + s.DoJSONWithoutAuth("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults( + mdmHost, + map[uint]*bool{policy.ID: new(passes)}, + ), http.StatusOK, &distributedResp) + } + + // errorOnInstallApplicationCommand drains the MDM queue for an + // InstallApplication command and responds with an MDM error. apple_mdm.go's + // command-result handler reacts to that by calling RetryVPPInstall (in place + // on the same host_vpp_software_installs row, incrementing retry_count) up + // to MaxSoftwareInstallAttempts. + errorOnInstallApplicationCommand := func() { + s.awaitRunAppleMDMWorkerSchedule() + s.runWorker() + cmd, err := mdmDevice.Idle() + require.NoError(t, err) + require.NotNil(t, cmd, "expected an InstallApplication command on the MDM queue") + for cmd != nil { + switch cmd.Command.RequestType { + case "InstallApplication": + cmd, err = mdmDevice.Err(cmd.CommandUUID, []mdm.ErrorChain{{ErrorCode: 1234}}) + require.NoError(t, err) + default: + cmd, err = mdmDevice.Acknowledge(cmd.CommandUUID) + require.NoError(t, err) + } + } + s.runWorker() + } + + type vppRow struct { + ID uint `db:"id"` + CommandUUID string `db:"command_uuid"` + RetryCount int `db:"retry_count"` + } + listVPPRows := func() []vppRow { + var rows []vppRow + mysqltest.ExecAdhocSQL(t, s.ds, func(q sqlx.ExtContext) error { + return sqlx.SelectContext(ctx, q, &rows, ` + SELECT id, command_uuid, retry_count + FROM host_vpp_software_installs + WHERE host_id = ? AND policy_id = ? + ORDER BY id ASC + `, mdmHost.ID, policy.ID) + }) + return rows + } + + // Phase 1: pass→fail queues a single row. Fail it through every retry until + // the per-row cap is reached. Each RetryVPPInstall reuses the same row and + // gives it a new command_uuid, so we still have exactly one row at the end. + // The gate is retry_count < MaxSoftwareInstallAttempts, so retries fire at + // retry_count 0,1,2 (→ ends at MaxSoftwareInstallAttempts); the final + // failure at the cap produces no further retry. That's + // MaxSoftwareInstallAttempts+1 failures total. + submitPolicyResult(false) + for i := 0; i <= fleet.MaxSoftwareInstallAttempts; i++ { + errorOnInstallApplicationCommand() + } + rows := listVPPRows() + require.Len(t, rows, 1, "single row tracks retry_count in place") + require.Equal(t, fleet.MaxSoftwareInstallAttempts, rows[0].RetryCount, + "retry_count incremented on each RetryVPPInstall until it reaches MaxSoftwareInstallAttempts") + firstRowID := rows[0].ID + + // No more retries should fire once the cap is reached, even though the + // install never succeeded. + require.Never(t, func() bool { + r := listVPPRows() + return len(r) != 1 || r[0].ID != firstRowID || r[0].RetryCount != fleet.MaxSoftwareInstallAttempts + }, 2*time.Second, 100*time.Millisecond, "no further VPP retries after cap is hit") + + // Phase 2: continuous re-fire. processVPPForNewlyFailingPolicies should + // queue a brand-new install, producing a *second* row in + // host_vpp_software_installs with retry_count = 0 (fresh budget). + submitPolicyResult(false) + require.EventuallyWithT(t, func(t *assert.CollectT) { + r := listVPPRows() + if !assert.Len(t, r, 2, "continuous re-fire should insert a new row") { + return + } + assert.Equal(t, firstRowID, r[0].ID) + assert.Equal(t, fleet.MaxSoftwareInstallAttempts, r[0].RetryCount, "old row's retry_count is left untouched") + assert.NotEqual(t, firstRowID, r[1].ID, "second row is a brand new install") + assert.Equal(t, 0, r[1].RetryCount, "new row starts with retry_count = 0 (fresh budget)") + }, 5*time.Second, 100*time.Millisecond) + + // And the new row's retry budget is genuinely fresh — failing its first + // InstallApplication should trigger RetryVPPInstall, taking retry_count to 1. + errorOnInstallApplicationCommand() + require.EventuallyWithT(t, func(t *assert.CollectT) { + r := listVPPRows() + if !assert.Len(t, r, 2) { + return + } + assert.Equal(t, 1, r[1].RetryCount, "new row's retries are eligible (now at 1)") + }, 5*time.Second, 100*time.Millisecond) +} + // registerResetVPPProxyData resets the VPP proxy data after tests in `t` complete. func (s *integrationMDMTestSuite) registerResetVPPProxyData(t *testing.T) { oldApps := s.appleVPPProxySrvData diff --git a/server/service/osquery.go b/server/service/osquery.go index ff04380623..34ccd9d17e 100644 --- a/server/service/osquery.go +++ b/server/service/osquery.go @@ -2021,10 +2021,12 @@ func (svc *Service) processSoftwareForNewlyFailingPolicies( return nil } - // Filter to policies with installers that are newly failing, using the pre-computed set. + // Filter to policies with installers that are newly failing, or that have + // continuous_automations_enabled set (in which case every failing result + // triggers an install, not just pass→fail transitions). var failingPoliciesWithInstaller []fleet.PolicySoftwareInstallerData for _, policyWithInstaller := range policiesWithInstaller { - if _, ok := newFailingSet[policyWithInstaller.ID]; ok { + if _, ok := newFailingSet[policyWithInstaller.ID]; ok || policyWithInstaller.ContinuousAutomationsEnabled { failingPoliciesWithInstaller = append(failingPoliciesWithInstaller, policyWithInstaller) } } @@ -2075,6 +2077,18 @@ func (svc *Service) processSoftwareForNewlyFailingPolicies( ) continue } + + // On a continuous re-fire (policy still failing), reset prior + // attempt_number values for this host/policy to 0 so the new attempt + // restarts the retry sequence at 1 instead of inheriting the cap from + // the previous sequence. A no-op on pass→fail transitions (those rows + // are already at 0 from the prior fail→pass reset). + if failingPolicyWithInstaller.ContinuousAutomationsEnabled { + if err := svc.ds.ResetPolicyAutomationRetryAttemptsForHost(ctx, hostID, []uint{policyID}); err != nil { + return ctxerr.Wrap(ctx, err, "reset policy automation retry attempts for host") + } + } + // NOTE(lucas): The user_id set in this software install will be NULL // so this means that when generating the activity for this action // (in SaveHostSoftwareInstallResult) the author will be set to Fleet. @@ -2135,10 +2149,12 @@ func (svc *Service) processVPPForNewlyFailingPolicies( return nil } - // Filter to policies with VPP apps that are newly failing, using the pre-computed set. + // Filter to policies with VPP apps that are newly failing, or that have + // continuous_automations_enabled set (in which case every failing result + // triggers an install, not just pass→fail transitions). var failingPoliciesWithVPP []fleet.PolicyVPPData for _, policyWithVPP := range policiesWithVPP { - if _, ok := newFailingSet[policyWithVPP.ID]; ok { + if _, ok := newFailingSet[policyWithVPP.ID]; ok || policyWithVPP.ContinuousAutomationsEnabled { failingPoliciesWithVPP = append(failingPoliciesWithVPP, policyWithVPP) } } @@ -2270,10 +2286,12 @@ func (svc *Service) processScriptsForNewlyFailingPolicies( return nil } - // Filter to policies with scripts that are newly failing, using the pre-computed set. + // Filter to policies with scripts that are newly failing, or that have + // continuous_automations_enabled set (in which case every failing result + // triggers a script run, not just pass→fail transitions). var failingPoliciesWithScript []fleet.PolicyScriptData for _, policyWithScript := range policiesWithScript { - if _, ok := newFailingSet[policyWithScript.ID]; ok { + if _, ok := newFailingSet[policyWithScript.ID]; ok || policyWithScript.ContinuousAutomationsEnabled { failingPoliciesWithScript = append(failingPoliciesWithScript, policyWithScript) } } @@ -2332,6 +2350,17 @@ func (svc *Service) processScriptsForNewlyFailingPolicies( continue } + // On a continuous re-fire (policy still failing), reset prior + // attempt_number values for this host/policy to 0 so the new attempt + // restarts the retry sequence at 1 instead of inheriting the cap from + // the previous sequence. A no-op on pass→fail transitions (those rows + // are already at 0 from the prior fail→pass reset). + if failingPolicyWithScript.ContinuousAutomationsEnabled { + if err := svc.ds.ResetPolicyAutomationRetryAttemptsForHost(ctx, hostID, []uint{policyID}); err != nil { + return ctxerr.Wrap(ctx, err, "reset policy automation retry attempts for host") + } + } + contents, err := svc.ds.GetScriptContents(ctx, scriptMetadata.ID) if err != nil { return ctxerr.Wrap(ctx, err, "get script contents") diff --git a/server/service/team_policies.go b/server/service/team_policies.go index 26c570c636..82cedfbc31 100644 --- a/server/service/team_policies.go +++ b/server/service/team_policies.go @@ -24,22 +24,23 @@ import ( func teamPolicyEndpoint(ctx context.Context, request interface{}, svc fleet.Service) (fleet.Errorer, error) { req := request.(*fleet.TeamPolicyRequest) resp, err := svc.NewTeamPolicy(ctx, req.TeamID, fleet.NewTeamPolicyPayload{ - QueryID: req.QueryID, - Name: req.Name, - Query: req.Query, - Description: req.Description, - Resolution: req.Resolution, - Platform: req.Platform, - Critical: req.Critical, - CalendarEventsEnabled: req.CalendarEventsEnabled, - SoftwareTitleID: req.SoftwareTitleID, - ScriptID: req.ScriptID, - LabelsIncludeAny: req.LabelsIncludeAny, - LabelsIncludeAll: req.LabelsIncludeAll, - LabelsExcludeAny: req.LabelsExcludeAny, - ConditionalAccessEnabled: req.ConditionalAccessEnabled, - Type: req.Type, - PatchSoftwareTitleID: req.PatchSoftwareTitleID, + QueryID: req.QueryID, + Name: req.Name, + Query: req.Query, + Description: req.Description, + Resolution: req.Resolution, + Platform: req.Platform, + Critical: req.Critical, + CalendarEventsEnabled: req.CalendarEventsEnabled, + SoftwareTitleID: req.SoftwareTitleID, + ScriptID: req.ScriptID, + LabelsIncludeAny: req.LabelsIncludeAny, + LabelsIncludeAll: req.LabelsIncludeAll, + LabelsExcludeAny: req.LabelsExcludeAny, + ConditionalAccessEnabled: req.ConditionalAccessEnabled, + ContinuousAutomationsEnabled: req.ContinuousAutomationsEnabled, + Type: req.Type, + PatchSoftwareTitleID: req.PatchSoftwareTitleID, }) if err != nil { return fleet.TeamPolicyResponse{Err: err}, nil @@ -215,23 +216,24 @@ func (svc *Service) newTeamPolicyPayloadToPolicyPayload(ctx context.Context, tea return fleet.PolicyPayload{}, err } return fleet.PolicyPayload{ - QueryID: p.QueryID, - Name: p.Name, - Query: p.Query, - Critical: p.Critical, - Description: p.Description, - Resolution: p.Resolution, - Platform: p.Platform, - CalendarEventsEnabled: p.CalendarEventsEnabled, - SoftwareInstallerID: softwareInstallerID, - VPPAppsTeamsID: vppAppsTeamsID, - ScriptID: p.ScriptID, - LabelsIncludeAny: p.LabelsIncludeAny, - LabelsIncludeAll: p.LabelsIncludeAll, - LabelsExcludeAny: p.LabelsExcludeAny, - ConditionalAccessEnabled: p.ConditionalAccessEnabled, - Type: policyType, - PatchSoftwareTitleID: p.PatchSoftwareTitleID, + QueryID: p.QueryID, + Name: p.Name, + Query: p.Query, + Critical: p.Critical, + Description: p.Description, + Resolution: p.Resolution, + Platform: p.Platform, + CalendarEventsEnabled: p.CalendarEventsEnabled, + SoftwareInstallerID: softwareInstallerID, + VPPAppsTeamsID: vppAppsTeamsID, + ScriptID: p.ScriptID, + LabelsIncludeAny: p.LabelsIncludeAny, + LabelsIncludeAll: p.LabelsIncludeAll, + LabelsExcludeAny: p.LabelsExcludeAny, + ConditionalAccessEnabled: p.ConditionalAccessEnabled, + ContinuousAutomationsEnabled: p.ContinuousAutomationsEnabled, + Type: policyType, + PatchSoftwareTitleID: p.PatchSoftwareTitleID, }, nil } @@ -528,6 +530,12 @@ func (svc *Service) modifyPolicy(ctx context.Context, teamID *uint, id uint, p f }) } + if p.ContinuousAutomationsEnabled != nil && *p.ContinuousAutomationsEnabled && teamID == nil { + return nil, ctxerr.Wrap(ctx, &fleet.BadRequestError{ + Message: fmt.Sprintf(`policy payload verification: %s`, errPolicyAllFleetsForContinuousAutomations), + }) + } + p.Type = policy.Type if err := p.Verify(); err != nil { return nil, ctxerr.Wrap(ctx, &fleet.BadRequestError{ @@ -576,6 +584,9 @@ func (svc *Service) modifyPolicy(ctx context.Context, teamID *uint, id uint, p f if p.ConditionalAccessEnabled != nil { policy.ConditionalAccessEnabled = *p.ConditionalAccessEnabled } + if p.ContinuousAutomationsEnabled != nil { + policy.ContinuousAutomationsEnabled = *p.ContinuousAutomationsEnabled + } if removeStats { policy.FailingHostCount = 0 policy.PassingHostCount = 0 diff --git a/server/webhooks/failing_policies_test.go b/server/webhooks/failing_policies_test.go index 07383108eb..2212504d12 100644 --- a/server/webhooks/failing_policies_test.go +++ b/server/webhooks/failing_policies_test.go @@ -129,6 +129,7 @@ func TestTriggerFailingPoliciesWebhookBasic(t *testing.T) { "critical": true, "calendar_events_enabled": false, "conditional_access_enabled": false, + "continuous_automations_enabled": false, "type": "dynamic" }, "hosts": [ @@ -322,6 +323,7 @@ func TestTriggerFailingPoliciesWebhookTeam(t *testing.T) { "critical": false, "calendar_events_enabled": true, "conditional_access_enabled": false, + "continuous_automations_enabled": false, "type": "dynamic" }, "hosts": [