diff --git a/changes/24958-gitops-webhooks-disable b/changes/24958-gitops-webhooks-disable new file mode 100644 index 000000000000..64d22ac4fe60 --- /dev/null +++ b/changes/24958-gitops-webhooks-disable @@ -0,0 +1 @@ +- Disable webhooks if not present in gitops diff --git a/cmd/fleetctl/gitops_test.go b/cmd/fleetctl/gitops_test.go index affa9a555041..74738aacce0c 100644 --- a/cmd/fleetctl/gitops_test.go +++ b/cmd/fleetctl/gitops_test.go @@ -3431,6 +3431,26 @@ func TestGitOpsWindowsMigration(t *testing.T) { } } +func TestGitOpsWebhooksDisable(t *testing.T) { + _, appConfig, _ := setupFullGitOpsPremiumServer(t) + + webhook := &(*appConfig).WebhookSettings + webhook.ActivitiesWebhook.Enable = true + webhook.FailingPoliciesWebhook.Enable = true + webhook.HostStatusWebhook.Enable = true + webhook.VulnerabilitiesWebhook.Enable = true + + // Run config with no webooks settings + _, err := runAppNoChecks([]string{"gitops", "-f", "testdata/gitops/global_config_windows_migration_true_true.yml"}) + require.NoError(t, err) + + webhook = &(*appConfig).WebhookSettings + require.False(t, webhook.ActivitiesWebhook.Enable) + require.False(t, webhook.FailingPoliciesWebhook.Enable) + require.False(t, webhook.HostStatusWebhook.Enable) + require.False(t, webhook.VulnerabilitiesWebhook.Enable) +} + type memKeyValueStore struct { m sync.Map } diff --git a/docs/Configuration/yaml-files.md b/docs/Configuration/yaml-files.md index 16fe872dec23..f280b2021d30 100644 --- a/docs/Configuration/yaml-files.md +++ b/docs/Configuration/yaml-files.md @@ -565,6 +565,21 @@ For secrets, you can add [GitHub environment variables](https://docs.github.com/ The `webhook_settings` section lets you define webhook settings for failing policy, vulnerability, and host status automations. Learn more about automations in Fleet [here](https://fleetdm.com/docs/using-fleet/automations). +#### activities_webhook + +- `enable_activities_webhook` (default: `false`) +- `destination_url` is the URL to `POST` to when an activity is generated (default: `""`) + +### Example + +```yaml +org_settings: + webhook_settings: + activities_webhook: + enable_activities_webhook: true + destination_url: https://example.org/webhook_handler +``` + #### failing_policies_webhook - `enable_failing_policies_webhook` (default: `false`) diff --git a/server/service/client.go b/server/service/client.go index d5eac68bf975..c58b98d73c2c 100644 --- a/server/service/client.go +++ b/server/service/client.go @@ -1505,6 +1505,50 @@ func (c *Client) DoGitOps( } } + // Ensure webhooks settings exists + webhookSettings, ok := group.AppConfig.(map[string]any)["webhook_settings"] + if !ok || webhookSettings == nil { + webhookSettings = map[string]any{} + group.AppConfig.(map[string]any)["webhook_settings"] = webhookSettings + } + + activitiesWebhook, ok := webhookSettings.(map[string]any)["activities_webhook"] + if !ok || activitiesWebhook == nil { + activitiesWebhook = map[string]any{} + webhookSettings.(map[string]any)["activities_webhook"] = activitiesWebhook + } + // make sure the "enable" key either exists, or set to false + if _, ok := activitiesWebhook.(map[string]any)["enable_activities_webhook"]; !ok { + activitiesWebhook.(map[string]any)["enable_activities_webhook"] = false + } + + hostStatusWebhook, ok := webhookSettings.(map[string]any)["host_status_webhook"] + if !ok || hostStatusWebhook == nil { + hostStatusWebhook = map[string]any{} + webhookSettings.(map[string]any)["host_status_webhook"] = hostStatusWebhook + } + if _, ok := hostStatusWebhook.(map[string]any)["enable_host_status_webhook"]; !ok { + hostStatusWebhook.(map[string]any)["enable_host_status_webhook"] = false + } + + failingPoliciesWebhook, ok := webhookSettings.(map[string]any)["failing_policies_webhook"] + if !ok || failingPoliciesWebhook == nil { + failingPoliciesWebhook = map[string]any{} + webhookSettings.(map[string]any)["failing_policies_webhook"] = failingPoliciesWebhook + } + if _, ok := failingPoliciesWebhook.(map[string]any)["enable_failing_policies_webhook"]; !ok { + failingPoliciesWebhook.(map[string]any)["enable_failing_policies_webhook"] = false + } + + vulnerabilitiesWebhook, ok := webhookSettings.(map[string]any)["vulnerabilities_webhook"] + if !ok || vulnerabilitiesWebhook == nil { + vulnerabilitiesWebhook = map[string]any{} + webhookSettings.(map[string]any)["vulnerabilities_webhook"] = vulnerabilitiesWebhook + } + if _, ok := vulnerabilitiesWebhook.(map[string]any)["enable_vulnerabilities_webhook"]; !ok { + vulnerabilitiesWebhook.(map[string]any)["enable_vulnerabilities_webhook"] = false + } + // Ensure mdm config exists mdmConfig, ok := group.AppConfig.(map[string]interface{})["mdm"] if !ok || mdmConfig == nil { diff --git a/server/service/integration_core_test.go b/server/service/integration_core_test.go index c84a0de3d835..655c393b4235 100644 --- a/server/service/integration_core_test.go +++ b/server/service/integration_core_test.go @@ -4679,7 +4679,7 @@ func (s *integrationTestSuite) TestUsers() { var modResp modifyUserResponse s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/users/%d", 1), json.RawMessage(`{ "settings": { - "hidden_host_columns": ["osquery_version"]} + "hidden_host_columns": ["osquery_version"]} }`), http.StatusOK, &modResp) // get session user with ui settings, should now be present, two endpoints @@ -4701,7 +4701,7 @@ func (s *integrationTestSuite) TestUsers() { // modify user ui settings, check they are returned modified s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/users/%d", 1), json.RawMessage(`{ "settings": { - "hidden_host_columns": ["hostname", "osquery_version"]} + "hidden_host_columns": ["hostname", "osquery_version"]} }`), http.StatusOK, &modResp) // get session user with ui settings, should now be modified, two endpoints @@ -4723,7 +4723,7 @@ func (s *integrationTestSuite) TestUsers() { // modify user ui settings, empty array, check they are returned correctly s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/users/%d", 1), json.RawMessage(`{ "settings": { - "hidden_host_columns": []} + "hidden_host_columns": []} }`), http.StatusOK, &modResp) // get session user with ui settings, should now be modified, two endpoints @@ -6089,6 +6089,34 @@ func (s *integrationTestSuite) TestExternalIntegrationsConfig() { config = s.getConfig() require.Len(t, config.Integrations.Jira, 0) require.Len(t, config.Integrations.Zendesk, 0) + + // enable webhooks + s.DoRaw("PATCH", "/api/v1/fleet/config", []byte(`{ + "webhook_settings": { + "activities_webhook": { + "enable_activities_webhook": true, + "destination_url": "http://some/url" + }, + "failing_policies_webhook": { + "enable_failing_policies_webhook": true, + "destination_url": "http://some/url", + "host_batch_size": 1000 + }, + "host_status_webhook": { + "enable_host_status_webhook": true, + "destination_url": "http://some/url", + "host_percentage": 2, + "days_count": 1 + } + } + }`), http.StatusOK) + config = s.getConfig() + require.True(t, config.WebhookSettings.ActivitiesWebhook.Enable) + require.Equal(t, "http://some/url", config.WebhookSettings.ActivitiesWebhook.DestinationURL) + require.True(t, config.WebhookSettings.FailingPoliciesWebhook.Enable) + require.Equal(t, "http://some/url", config.WebhookSettings.FailingPoliciesWebhook.DestinationURL) + require.True(t, config.WebhookSettings.HostStatusWebhook.Enable) + require.Equal(t, "http://some/url", config.WebhookSettings.HostStatusWebhook.DestinationURL) } func (s *integrationTestSuite) TestGoogleCalendarIntegrations() {