From c22f57515070aea07959847cc66fdcd3de0a39d1 Mon Sep 17 00:00:00 2001
From: jacobshandling <61553566+jacobshandling@users.noreply.github.com>
Date: Thu, 20 Feb 2025 08:40:46 -0800
Subject: [PATCH] Add `gitops` app config fields, API access, activities, tests
(#26282)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## For #26230
- Add `gitops` settings to app config
- GET and PATCH endpoint functionality to retrieve and modify these
settings
- generate activities for enabling and disabling GitOps mode
- Premium only
- Update tests
## Checklist for submitter
- [x] Added/updated automated tests
- [ ] A detailed QA plan exists on the associated ticket (if it isn't
there, work with the product group's QA engineer to add it)
- [x] Manual QA for all new/changed functionality
---------
Co-authored-by: Jacob Shandling
---
.../expectedGetConfigAppConfigJson.json | 304 +++++++------
...dGetConfigAppConfigTeamMaintainerJson.json | 6 +-
...edGetConfigAppConfigTeamMaintainerYaml.yml | 3 +
.../expectedGetConfigAppConfigYaml.yml | 3 +
...ectedGetConfigIncludeServerConfigJson.json | 428 +++++++++---------
...pectedGetConfigIncludeServerConfigYaml.yml | 3 +
.../macosSetupExpectedAppConfigEmpty.yml | 3 +
.../macosSetupExpectedAppConfigSet.yml | 3 +
docs/Contributing/Audit-logs.md | 12 +
server/datastore/mysql/schema.sql | 2 +-
server/fleet/activities.go | 23 +
server/fleet/app.go | 9 +
server/service/appconfig.go | 26 ++
server/service/integration_core_test.go | 9 +
server/service/integration_enterprise_test.go | 21 +
.../generated_files/appconfig.txt | 3 +
16 files changed, 494 insertions(+), 364 deletions(-)
diff --git a/cmd/fleetctl/testdata/expectedGetConfigAppConfigJson.json b/cmd/fleetctl/testdata/expectedGetConfigAppConfigJson.json
index 37daec6859..eed96b690b 100644
--- a/cmd/fleetctl/testdata/expectedGetConfigAppConfigJson.json
+++ b/cmd/fleetctl/testdata/expectedGetConfigAppConfigJson.json
@@ -1,152 +1,156 @@
{
- "kind": "config",
- "apiVersion": "v1",
- "spec": {
- "org_info": {
- "org_name": "",
- "org_logo_url": "",
- "org_logo_url_light_background": "",
- "contact_url": "https://fleetdm.com/company/contact"
- },
- "server_settings": {
- "server_url": "",
- "live_query_disabled": false,
- "query_report_cap": 0,
- "query_reports_disabled": false,
- "enable_analytics": false,
- "deferred_save_host": false,
- "scripts_disabled": false,
- "ai_features_disabled": false
- },
- "smtp_settings": {
- "enable_smtp": false,
- "configured": false,
- "sender_address": "",
- "server": "",
- "port": 0,
- "authentication_type": "",
- "user_name": "",
- "password": "",
- "enable_ssl_tls": false,
- "authentication_method": "",
- "domain": "",
- "verify_ssl_certs": false,
- "enable_start_tls": false
- },
- "host_expiry_settings": {
- "host_expiry_enabled": false,
- "host_expiry_window": 0
- },
- "activity_expiry_settings": {
- "activity_expiry_enabled": false,
- "activity_expiry_window": 0
- },
- "features": {
- "enable_host_users": true,
- "enable_software_inventory": false
- },
- "sso_settings": {
- "entity_id": "",
- "issuer_uri": "",
- "idp_image_url": "",
- "metadata": "",
- "metadata_url": "",
- "idp_name": "",
- "enable_jit_provisioning": false,
- "enable_jit_role_sync": false,
- "enable_sso": false,
- "enable_sso_idp_login": false
- },
- "fleet_desktop": {
- "transparency_url": "https://fleetdm.com/transparency"
- },
- "vulnerability_settings": {
- "databases_path": "/some/path"
- },
- "webhook_settings": {
- "activities_webhook": {
- "enable_activities_webhook": false,
- "destination_url": ""
- },
- "host_status_webhook": {
- "enable_host_status_webhook": false,
- "destination_url": "",
- "host_percentage": 0,
- "days_count": 0
- },
- "failing_policies_webhook": {
- "enable_failing_policies_webhook": false,
- "destination_url": "",
- "policy_ids": null,
- "host_batch_size": 0
- },
- "vulnerabilities_webhook": {
- "enable_vulnerabilities_webhook": false,
- "destination_url": "",
- "host_batch_size": 0
- },
- "interval": "0s"
- },
- "integrations": {
- "jira": null,
- "zendesk": null,
- "google_calendar": null,
- "ndes_scep_proxy": null
- },
- "mdm": {
- "android_enabled_and_configured": false,
- "apple_bm_terms_expired": false,
- "apple_server_url": "",
- "apple_bm_enabled_and_configured": false,
- "enabled_and_configured": false,
- "apple_business_manager": null,
- "volume_purchasing_program": null,
- "windows_enabled_and_configured": false,
- "enable_disk_encryption": false,
- "macos_updates": {
- "minimum_version": null,
- "deadline": null
- },
- "ios_updates": {
- "minimum_version": null,
- "deadline": null
- },
- "ipados_updates": {
- "minimum_version": null,
- "deadline": null
- },
- "windows_updates": {
- "deadline_days": 7,
- "grace_period_days": 3
- },
- "windows_migration_enabled": false,
- "macos_migration": {
- "enable": false,
- "mode": "",
- "webhook_url": ""
- },
- "macos_settings": {
- "custom_settings": null
- },
- "macos_setup": {
- "bootstrap_package": null,
- "enable_end_user_authentication": false,
- "macos_setup_assistant": null,
- "enable_release_device_manually": false,
- "script": null,
- "software": null
- },
- "windows_settings": {
- "custom_settings": null
- },
- "end_user_authentication": {
- "entity_id": "",
- "issuer_uri": "",
- "metadata": "",
- "metadata_url": "",
- "idp_name": ""
- }
- },
- "scripts": null
- }
+ "kind": "config",
+ "apiVersion": "v1",
+ "spec": {
+ "org_info": {
+ "org_name": "",
+ "org_logo_url": "",
+ "org_logo_url_light_background": "",
+ "contact_url": "https://fleetdm.com/company/contact"
+ },
+ "server_settings": {
+ "server_url": "",
+ "live_query_disabled": false,
+ "query_report_cap": 0,
+ "query_reports_disabled": false,
+ "enable_analytics": false,
+ "deferred_save_host": false,
+ "scripts_disabled": false,
+ "ai_features_disabled": false
+ },
+ "smtp_settings": {
+ "enable_smtp": false,
+ "configured": false,
+ "sender_address": "",
+ "server": "",
+ "port": 0,
+ "authentication_type": "",
+ "user_name": "",
+ "password": "",
+ "enable_ssl_tls": false,
+ "authentication_method": "",
+ "domain": "",
+ "verify_ssl_certs": false,
+ "enable_start_tls": false
+ },
+ "host_expiry_settings": {
+ "host_expiry_enabled": false,
+ "host_expiry_window": 0
+ },
+ "activity_expiry_settings": {
+ "activity_expiry_enabled": false,
+ "activity_expiry_window": 0
+ },
+ "features": {
+ "enable_host_users": true,
+ "enable_software_inventory": false
+ },
+ "sso_settings": {
+ "entity_id": "",
+ "issuer_uri": "",
+ "idp_image_url": "",
+ "metadata": "",
+ "metadata_url": "",
+ "idp_name": "",
+ "enable_jit_provisioning": false,
+ "enable_jit_role_sync": false,
+ "enable_sso": false,
+ "enable_sso_idp_login": false
+ },
+ "fleet_desktop": {
+ "transparency_url": "https://fleetdm.com/transparency"
+ },
+ "vulnerability_settings": {
+ "databases_path": "/some/path"
+ },
+ "webhook_settings": {
+ "activities_webhook": {
+ "enable_activities_webhook": false,
+ "destination_url": ""
+ },
+ "host_status_webhook": {
+ "enable_host_status_webhook": false,
+ "destination_url": "",
+ "host_percentage": 0,
+ "days_count": 0
+ },
+ "failing_policies_webhook": {
+ "enable_failing_policies_webhook": false,
+ "destination_url": "",
+ "policy_ids": null,
+ "host_batch_size": 0
+ },
+ "vulnerabilities_webhook": {
+ "enable_vulnerabilities_webhook": false,
+ "destination_url": "",
+ "host_batch_size": 0
+ },
+ "interval": "0s"
+ },
+ "integrations": {
+ "jira": null,
+ "zendesk": null,
+ "google_calendar": null,
+ "ndes_scep_proxy": null
+ },
+ "mdm": {
+ "android_enabled_and_configured": false,
+ "apple_bm_terms_expired": false,
+ "apple_server_url": "",
+ "apple_bm_enabled_and_configured": false,
+ "enabled_and_configured": false,
+ "apple_business_manager": null,
+ "volume_purchasing_program": null,
+ "windows_enabled_and_configured": false,
+ "enable_disk_encryption": false,
+ "macos_updates": {
+ "minimum_version": null,
+ "deadline": null
+ },
+ "ios_updates": {
+ "minimum_version": null,
+ "deadline": null
+ },
+ "ipados_updates": {
+ "minimum_version": null,
+ "deadline": null
+ },
+ "windows_updates": {
+ "deadline_days": 7,
+ "grace_period_days": 3
+ },
+ "windows_migration_enabled": false,
+ "macos_migration": {
+ "enable": false,
+ "mode": "",
+ "webhook_url": ""
+ },
+ "macos_settings": {
+ "custom_settings": null
+ },
+ "macos_setup": {
+ "bootstrap_package": null,
+ "enable_end_user_authentication": false,
+ "macos_setup_assistant": null,
+ "enable_release_device_manually": false,
+ "script": null,
+ "software": null
+ },
+ "windows_settings": {
+ "custom_settings": null
+ },
+ "end_user_authentication": {
+ "entity_id": "",
+ "issuer_uri": "",
+ "metadata": "",
+ "metadata_url": "",
+ "idp_name": ""
+ }
+ },
+ "scripts": null,
+ "gitops": {
+ "gitops_mode_enabled": false,
+ "repository_url": ""
+ }
+ }
}
diff --git a/cmd/fleetctl/testdata/expectedGetConfigAppConfigTeamMaintainerJson.json b/cmd/fleetctl/testdata/expectedGetConfigAppConfigTeamMaintainerJson.json
index 3acb9fc088..9c4b5f8fb1 100644
--- a/cmd/fleetctl/testdata/expectedGetConfigAppConfigTeamMaintainerJson.json
+++ b/cmd/fleetctl/testdata/expectedGetConfigAppConfigTeamMaintainerJson.json
@@ -120,6 +120,10 @@
"idp_name": ""
}
},
- "scripts": null
+ "scripts": null,
+ "gitops": {
+ "gitops_mode_enabled": false,
+ "repository_url": ""
+ }
}
}
diff --git a/cmd/fleetctl/testdata/expectedGetConfigAppConfigTeamMaintainerYaml.yml b/cmd/fleetctl/testdata/expectedGetConfigAppConfigTeamMaintainerYaml.yml
index 44093ff318..1c811da323 100644
--- a/cmd/fleetctl/testdata/expectedGetConfigAppConfigTeamMaintainerYaml.yml
+++ b/cmd/fleetctl/testdata/expectedGetConfigAppConfigTeamMaintainerYaml.yml
@@ -98,3 +98,6 @@ spec:
destination_url: ""
enable_vulnerabilities_webhook: false
host_batch_size: 0
+ gitops:
+ gitops_mode_enabled: false
+ repository_url: ""
diff --git a/cmd/fleetctl/testdata/expectedGetConfigAppConfigYaml.yml b/cmd/fleetctl/testdata/expectedGetConfigAppConfigYaml.yml
index f830c2d117..54b62c8d33 100644
--- a/cmd/fleetctl/testdata/expectedGetConfigAppConfigYaml.yml
+++ b/cmd/fleetctl/testdata/expectedGetConfigAppConfigYaml.yml
@@ -123,3 +123,6 @@ spec:
destination_url: ""
enable_vulnerabilities_webhook: false
host_batch_size: 0
+ gitops:
+ gitops_mode_enabled: false
+ repository_url: ""
diff --git a/cmd/fleetctl/testdata/expectedGetConfigIncludeServerConfigJson.json b/cmd/fleetctl/testdata/expectedGetConfigIncludeServerConfigJson.json
index 109b6dfd14..c7d5f27dd8 100644
--- a/cmd/fleetctl/testdata/expectedGetConfigIncludeServerConfigJson.json
+++ b/cmd/fleetctl/testdata/expectedGetConfigIncludeServerConfigJson.json
@@ -1,214 +1,218 @@
{
- "kind": "config",
- "apiVersion": "v1",
- "spec": {
- "org_info": {
- "org_name": "",
- "org_logo_url": "",
- "org_logo_url_light_background": "",
- "contact_url": "https://fleetdm.com/company/contact"
- },
- "server_settings": {
- "server_url": "",
- "live_query_disabled": false,
- "query_report_cap": 0,
- "query_reports_disabled": false,
- "enable_analytics": false,
- "deferred_save_host": false,
- "scripts_disabled": false,
- "ai_features_disabled": false
- },
- "smtp_settings": {
- "enable_smtp": false,
- "configured": false,
- "sender_address": "",
- "server": "",
- "port": 0,
- "authentication_type": "",
- "user_name": "",
- "password": "",
- "enable_ssl_tls": false,
- "authentication_method": "",
- "domain": "",
- "verify_ssl_certs": false,
- "enable_start_tls": false
- },
- "host_expiry_settings": {
- "host_expiry_enabled": false,
- "host_expiry_window": 0
- },
- "activity_expiry_settings": {
- "activity_expiry_enabled": false,
- "activity_expiry_window": 0
- },
- "features": {
- "enable_host_users": true,
- "enable_software_inventory": false
- },
- "mdm": {
- "android_enabled_and_configured": false,
- "apple_business_manager": null,
- "apple_server_url": "",
- "volume_purchasing_program": null,
- "apple_bm_terms_expired": false,
- "apple_bm_enabled_and_configured": false,
- "enabled_and_configured": false,
- "windows_enabled_and_configured": false,
- "enable_disk_encryption": false,
- "macos_updates": {
- "minimum_version": null,
- "deadline": null
- },
- "ios_updates": {
- "minimum_version": null,
- "deadline": null
- },
- "ipados_updates": {
- "minimum_version": null,
- "deadline": null
- },
- "windows_updates": {
- "deadline_days": 7,
- "grace_period_days": 3
- },
- "windows_migration_enabled": false,
- "macos_migration": {
- "enable": false,
- "mode": "",
- "webhook_url": ""
- },
- "macos_settings": {
- "custom_settings": null
- },
- "macos_setup": {
- "bootstrap_package": null,
- "enable_end_user_authentication": false,
- "macos_setup_assistant": null,
- "enable_release_device_manually": false,
- "script": null,
- "software": null
- },
- "windows_settings": {
- "custom_settings": null
- },
- "end_user_authentication": {
- "entity_id": "",
- "issuer_uri": "",
- "metadata": "",
- "metadata_url": "",
- "idp_name": ""
- }
- },
- "scripts": null,
- "sso_settings": {
- "enable_jit_provisioning": false,
- "enable_jit_role_sync": false,
- "entity_id": "",
- "issuer_uri": "",
- "idp_image_url": "",
- "metadata": "",
- "metadata_url": "",
- "idp_name": "",
- "enable_sso": false,
- "enable_sso_idp_login": false
- },
- "fleet_desktop": {
- "transparency_url": "https://fleetdm.com/transparency"
- },
- "vulnerability_settings": {
- "databases_path": "/some/path"
- },
- "webhook_settings": {
- "activities_webhook": {
- "enable_activities_webhook": false,
- "destination_url": ""
- },
- "host_status_webhook": {
- "enable_host_status_webhook": false,
- "destination_url": "",
- "host_percentage": 0,
- "days_count": 0
- },
- "failing_policies_webhook": {
- "enable_failing_policies_webhook": false,
- "destination_url": "",
- "policy_ids": null,
- "host_batch_size": 0
- },
- "vulnerabilities_webhook": {
- "enable_vulnerabilities_webhook": false,
- "destination_url": "",
- "host_batch_size": 0
- },
- "interval": "0s"
- },
- "integrations": {
- "jira": null,
- "zendesk": null,
- "google_calendar": null,
- "ndes_scep_proxy": null
- },
- "update_interval": {
- "osquery_detail": "1h0m0s",
- "osquery_policy": "1h0m0s"
- },
- "vulnerabilities": {
- "databases_path": "",
- "periodicity": "0s",
- "cpe_database_url": "",
- "cpe_translations_url": "",
- "cve_feed_prefix_url": "",
- "current_instance_checks": "",
- "disable_data_sync": false,
- "recent_vulnerability_max_age": "0s",
- "disable_win_os_vulnerabilities": false
- },
- "license": {
- "tier": "free",
- "expiration": "0001-01-01T00:00:00Z"
- },
- "logging": {
- "debug": true,
- "json": false,
- "result": {
- "plugin": "filesystem",
- "config": {
- "enable_log_compression": false,
- "enable_log_rotation": false,
- "result_log_file": "/dev/null",
- "status_log_file": "/dev/null",
- "audit_log_file": "/dev/null",
- "max_size": 500,
- "max_age": 0,
- "max_backups": 0
- }
- },
- "status": {
- "plugin": "filesystem",
- "config": {
- "enable_log_compression": false,
- "enable_log_rotation": false,
- "result_log_file": "/dev/null",
- "status_log_file": "/dev/null",
- "audit_log_file": "/dev/null",
- "max_size": 500,
- "max_age": 0,
- "max_backups": 0
- }
- },
- "audit": {
- "plugin": "filesystem",
- "config": {
- "enable_log_compression": false,
- "enable_log_rotation": false,
- "result_log_file": "/dev/null",
- "status_log_file": "/dev/null",
- "audit_log_file": "/dev/null",
- "max_size": 500,
- "max_age": 0,
- "max_backups": 0
- }
- }
- }
- }
+ "kind": "config",
+ "apiVersion": "v1",
+ "spec": {
+ "org_info": {
+ "org_name": "",
+ "org_logo_url": "",
+ "org_logo_url_light_background": "",
+ "contact_url": "https://fleetdm.com/company/contact"
+ },
+ "server_settings": {
+ "server_url": "",
+ "live_query_disabled": false,
+ "query_report_cap": 0,
+ "query_reports_disabled": false,
+ "enable_analytics": false,
+ "deferred_save_host": false,
+ "scripts_disabled": false,
+ "ai_features_disabled": false
+ },
+ "smtp_settings": {
+ "enable_smtp": false,
+ "configured": false,
+ "sender_address": "",
+ "server": "",
+ "port": 0,
+ "authentication_type": "",
+ "user_name": "",
+ "password": "",
+ "enable_ssl_tls": false,
+ "authentication_method": "",
+ "domain": "",
+ "verify_ssl_certs": false,
+ "enable_start_tls": false
+ },
+ "host_expiry_settings": {
+ "host_expiry_enabled": false,
+ "host_expiry_window": 0
+ },
+ "activity_expiry_settings": {
+ "activity_expiry_enabled": false,
+ "activity_expiry_window": 0
+ },
+ "features": {
+ "enable_host_users": true,
+ "enable_software_inventory": false
+ },
+ "mdm": {
+ "android_enabled_and_configured": false,
+ "apple_business_manager": null,
+ "apple_server_url": "",
+ "volume_purchasing_program": null,
+ "apple_bm_terms_expired": false,
+ "apple_bm_enabled_and_configured": false,
+ "enabled_and_configured": false,
+ "windows_enabled_and_configured": false,
+ "enable_disk_encryption": false,
+ "macos_updates": {
+ "minimum_version": null,
+ "deadline": null
+ },
+ "ios_updates": {
+ "minimum_version": null,
+ "deadline": null
+ },
+ "ipados_updates": {
+ "minimum_version": null,
+ "deadline": null
+ },
+ "windows_updates": {
+ "deadline_days": 7,
+ "grace_period_days": 3
+ },
+ "windows_migration_enabled": false,
+ "macos_migration": {
+ "enable": false,
+ "mode": "",
+ "webhook_url": ""
+ },
+ "macos_settings": {
+ "custom_settings": null
+ },
+ "macos_setup": {
+ "bootstrap_package": null,
+ "enable_end_user_authentication": false,
+ "macos_setup_assistant": null,
+ "enable_release_device_manually": false,
+ "script": null,
+ "software": null
+ },
+ "windows_settings": {
+ "custom_settings": null
+ },
+ "end_user_authentication": {
+ "entity_id": "",
+ "issuer_uri": "",
+ "metadata": "",
+ "metadata_url": "",
+ "idp_name": ""
+ }
+ },
+ "scripts": null,
+ "sso_settings": {
+ "enable_jit_provisioning": false,
+ "enable_jit_role_sync": false,
+ "entity_id": "",
+ "issuer_uri": "",
+ "idp_image_url": "",
+ "metadata": "",
+ "metadata_url": "",
+ "idp_name": "",
+ "enable_sso": false,
+ "enable_sso_idp_login": false
+ },
+ "fleet_desktop": {
+ "transparency_url": "https://fleetdm.com/transparency"
+ },
+ "vulnerability_settings": {
+ "databases_path": "/some/path"
+ },
+ "webhook_settings": {
+ "activities_webhook": {
+ "enable_activities_webhook": false,
+ "destination_url": ""
+ },
+ "host_status_webhook": {
+ "enable_host_status_webhook": false,
+ "destination_url": "",
+ "host_percentage": 0,
+ "days_count": 0
+ },
+ "failing_policies_webhook": {
+ "enable_failing_policies_webhook": false,
+ "destination_url": "",
+ "policy_ids": null,
+ "host_batch_size": 0
+ },
+ "vulnerabilities_webhook": {
+ "enable_vulnerabilities_webhook": false,
+ "destination_url": "",
+ "host_batch_size": 0
+ },
+ "interval": "0s"
+ },
+ "integrations": {
+ "jira": null,
+ "zendesk": null,
+ "google_calendar": null,
+ "ndes_scep_proxy": null
+ },
+ "update_interval": {
+ "osquery_detail": "1h0m0s",
+ "osquery_policy": "1h0m0s"
+ },
+ "vulnerabilities": {
+ "databases_path": "",
+ "periodicity": "0s",
+ "cpe_database_url": "",
+ "cpe_translations_url": "",
+ "cve_feed_prefix_url": "",
+ "current_instance_checks": "",
+ "disable_data_sync": false,
+ "recent_vulnerability_max_age": "0s",
+ "disable_win_os_vulnerabilities": false
+ },
+ "license": {
+ "tier": "free",
+ "expiration": "0001-01-01T00:00:00Z"
+ },
+ "logging": {
+ "debug": true,
+ "json": false,
+ "result": {
+ "plugin": "filesystem",
+ "config": {
+ "enable_log_compression": false,
+ "enable_log_rotation": false,
+ "result_log_file": "/dev/null",
+ "status_log_file": "/dev/null",
+ "audit_log_file": "/dev/null",
+ "max_size": 500,
+ "max_age": 0,
+ "max_backups": 0
+ }
+ },
+ "status": {
+ "plugin": "filesystem",
+ "config": {
+ "enable_log_compression": false,
+ "enable_log_rotation": false,
+ "result_log_file": "/dev/null",
+ "status_log_file": "/dev/null",
+ "audit_log_file": "/dev/null",
+ "max_size": 500,
+ "max_age": 0,
+ "max_backups": 0
+ }
+ },
+ "audit": {
+ "plugin": "filesystem",
+ "config": {
+ "enable_log_compression": false,
+ "enable_log_rotation": false,
+ "result_log_file": "/dev/null",
+ "status_log_file": "/dev/null",
+ "audit_log_file": "/dev/null",
+ "max_size": 500,
+ "max_age": 0,
+ "max_backups": 0
+ }
+ }
+ },
+ "gitops": {
+ "gitops_mode_enabled": false,
+ "repository_url": ""
+ }
+ }
}
diff --git a/cmd/fleetctl/testdata/expectedGetConfigIncludeServerConfigYaml.yml b/cmd/fleetctl/testdata/expectedGetConfigIncludeServerConfigYaml.yml
index 78c755abf4..202cd0ff33 100644
--- a/cmd/fleetctl/testdata/expectedGetConfigIncludeServerConfigYaml.yml
+++ b/cmd/fleetctl/testdata/expectedGetConfigIncludeServerConfigYaml.yml
@@ -175,3 +175,6 @@ spec:
destination_url: ""
enable_vulnerabilities_webhook: false
host_batch_size: 0
+ gitops:
+ gitops_mode_enabled: false
+ repository_url: ""
diff --git a/cmd/fleetctl/testdata/macosSetupExpectedAppConfigEmpty.yml b/cmd/fleetctl/testdata/macosSetupExpectedAppConfigEmpty.yml
index cd8044be86..701ade6abe 100644
--- a/cmd/fleetctl/testdata/macosSetupExpectedAppConfigEmpty.yml
+++ b/cmd/fleetctl/testdata/macosSetupExpectedAppConfigEmpty.yml
@@ -123,3 +123,6 @@ spec:
destination_url: ""
enable_vulnerabilities_webhook: false
host_batch_size: 0
+ gitops:
+ gitops_mode_enabled: false
+ repository_url: ""
diff --git a/cmd/fleetctl/testdata/macosSetupExpectedAppConfigSet.yml b/cmd/fleetctl/testdata/macosSetupExpectedAppConfigSet.yml
index d3dff15f76..78e849b2d1 100644
--- a/cmd/fleetctl/testdata/macosSetupExpectedAppConfigSet.yml
+++ b/cmd/fleetctl/testdata/macosSetupExpectedAppConfigSet.yml
@@ -123,3 +123,6 @@ spec:
destination_url: ""
enable_vulnerabilities_webhook: false
host_batch_size: 0
+ gitops:
+ gitops_mode_enabled: false
+ repository_url: ""
diff --git a/docs/Contributing/Audit-logs.md b/docs/Contributing/Audit-logs.md
index e91981dbe8..d12eb9731b 100644
--- a/docs/Contributing/Audit-logs.md
+++ b/docs/Contributing/Audit-logs.md
@@ -810,6 +810,18 @@ This activity contains the following fields:
}
```
+## enabled_gitops_mode
+
+Generated when a user enables GitOps mode.
+
+This activity does not contain any detail fields.
+
+## disabled_gitops_mode
+
+Generated when a user disables GitOps mode.
+
+This activity does not contain any detail fields.
+
## added_bootstrap_package
Generated when a user adds a new bootstrap package to a team (or no team).
diff --git a/server/datastore/mysql/schema.sql b/server/datastore/mysql/schema.sql
index 5c3647c9ad..c806449fd1 100644
--- a/server/datastore/mysql/schema.sql
+++ b/server/datastore/mysql/schema.sql
@@ -76,7 +76,7 @@ CREATE TABLE `app_config_json` (
PRIMARY KEY (`id`)
) /*!50100 TABLESPACE `innodb_system` */ ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
-INSERT INTO `app_config_json` VALUES (1,'{\"mdm\": {\"ios_updates\": {\"deadline\": null, \"minimum_version\": null}, \"macos_setup\": {\"script\": null, \"software\": null, \"bootstrap_package\": null, \"macos_setup_assistant\": null, \"enable_end_user_authentication\": false, \"enable_release_device_manually\": false}, \"macos_updates\": {\"deadline\": null, \"minimum_version\": null}, \"ipados_updates\": {\"deadline\": null, \"minimum_version\": null}, \"macos_settings\": {\"custom_settings\": null}, \"macos_migration\": {\"mode\": \"\", \"enable\": false, \"webhook_url\": \"\"}, \"windows_updates\": {\"deadline_days\": null, \"grace_period_days\": null}, \"apple_server_url\": \"\", \"windows_settings\": {\"custom_settings\": null}, \"apple_bm_terms_expired\": false, \"apple_business_manager\": null, \"enable_disk_encryption\": false, \"enabled_and_configured\": false, \"end_user_authentication\": {\"idp_name\": \"\", \"metadata\": \"\", \"entity_id\": \"\", \"issuer_uri\": \"\", \"metadata_url\": \"\"}, \"volume_purchasing_program\": null, \"windows_migration_enabled\": false, \"android_enabled_and_configured\": false, \"windows_enabled_and_configured\": false, \"apple_bm_enabled_and_configured\": false}, \"scripts\": null, \"features\": {\"enable_host_users\": true, \"enable_software_inventory\": false}, \"org_info\": {\"org_name\": \"\", \"contact_url\": \"\", \"org_logo_url\": \"\", \"org_logo_url_light_background\": \"\"}, \"integrations\": {\"jira\": null, \"zendesk\": null, \"google_calendar\": null, \"ndes_scep_proxy\": null}, \"sso_settings\": {\"idp_name\": \"\", \"metadata\": \"\", \"entity_id\": \"\", \"enable_sso\": false, \"issuer_uri\": \"\", \"metadata_url\": \"\", \"idp_image_url\": \"\", \"enable_jit_role_sync\": false, \"enable_sso_idp_login\": false, \"enable_jit_provisioning\": false}, \"agent_options\": {\"config\": {\"options\": {\"logger_plugin\": \"tls\", \"pack_delimiter\": \"/\", \"logger_tls_period\": 10, \"distributed_plugin\": \"tls\", \"disable_distributed\": false, \"logger_tls_endpoint\": \"/api/osquery/log\", \"distributed_interval\": 10, \"distributed_tls_max_attempts\": 3}, \"decorators\": {\"load\": [\"SELECT uuid AS host_uuid FROM system_info;\", \"SELECT hostname AS hostname FROM system_info;\"]}}, \"overrides\": {}}, \"fleet_desktop\": {\"transparency_url\": \"\"}, \"smtp_settings\": {\"port\": 587, \"domain\": \"\", \"server\": \"\", \"password\": \"\", \"user_name\": \"\", \"configured\": false, \"enable_smtp\": false, \"enable_ssl_tls\": true, \"sender_address\": \"\", \"enable_start_tls\": true, \"verify_ssl_certs\": true, \"authentication_type\": \"0\", \"authentication_method\": \"0\"}, \"server_settings\": {\"server_url\": \"\", \"enable_analytics\": false, \"query_report_cap\": 0, \"scripts_disabled\": false, \"deferred_save_host\": false, \"live_query_disabled\": false, \"ai_features_disabled\": false, \"query_reports_disabled\": false}, \"webhook_settings\": {\"interval\": \"0s\", \"activities_webhook\": {\"destination_url\": \"\", \"enable_activities_webhook\": false}, \"host_status_webhook\": {\"days_count\": 0, \"destination_url\": \"\", \"host_percentage\": 0, \"enable_host_status_webhook\": false}, \"vulnerabilities_webhook\": {\"destination_url\": \"\", \"host_batch_size\": 0, \"enable_vulnerabilities_webhook\": false}, \"failing_policies_webhook\": {\"policy_ids\": null, \"destination_url\": \"\", \"host_batch_size\": 0, \"enable_failing_policies_webhook\": false}}, \"host_expiry_settings\": {\"host_expiry_window\": 0, \"host_expiry_enabled\": false}, \"vulnerability_settings\": {\"databases_path\": \"\"}, \"activity_expiry_settings\": {\"activity_expiry_window\": 0, \"activity_expiry_enabled\": false}}','2020-01-01 01:01:01','2020-01-01 01:01:01');
+INSERT INTO `app_config_json` VALUES (1,'{\"mdm\": {\"ios_updates\": {\"deadline\": null, \"minimum_version\": null}, \"macos_setup\": {\"script\": null, \"software\": null, \"bootstrap_package\": null, \"macos_setup_assistant\": null, \"enable_end_user_authentication\": false, \"enable_release_device_manually\": false}, \"macos_updates\": {\"deadline\": null, \"minimum_version\": null}, \"ipados_updates\": {\"deadline\": null, \"minimum_version\": null}, \"macos_settings\": {\"custom_settings\": null}, \"macos_migration\": {\"mode\": \"\", \"enable\": false, \"webhook_url\": \"\"}, \"windows_updates\": {\"deadline_days\": null, \"grace_period_days\": null}, \"apple_server_url\": \"\", \"windows_settings\": {\"custom_settings\": null}, \"apple_bm_terms_expired\": false, \"apple_business_manager\": null, \"enable_disk_encryption\": false, \"enabled_and_configured\": false, \"end_user_authentication\": {\"idp_name\": \"\", \"metadata\": \"\", \"entity_id\": \"\", \"issuer_uri\": \"\", \"metadata_url\": \"\"}, \"volume_purchasing_program\": null, \"windows_migration_enabled\": false, \"android_enabled_and_configured\": false, \"windows_enabled_and_configured\": false, \"apple_bm_enabled_and_configured\": false}, \"gitops\": {\"repository_url\": \"\", \"gitops_mode_enabled\": false}, \"scripts\": null, \"features\": {\"enable_host_users\": true, \"enable_software_inventory\": false}, \"org_info\": {\"org_name\": \"\", \"contact_url\": \"\", \"org_logo_url\": \"\", \"org_logo_url_light_background\": \"\"}, \"integrations\": {\"jira\": null, \"zendesk\": null, \"google_calendar\": null, \"ndes_scep_proxy\": null}, \"sso_settings\": {\"idp_name\": \"\", \"metadata\": \"\", \"entity_id\": \"\", \"enable_sso\": false, \"issuer_uri\": \"\", \"metadata_url\": \"\", \"idp_image_url\": \"\", \"enable_jit_role_sync\": false, \"enable_sso_idp_login\": false, \"enable_jit_provisioning\": false}, \"agent_options\": {\"config\": {\"options\": {\"logger_plugin\": \"tls\", \"pack_delimiter\": \"/\", \"logger_tls_period\": 10, \"distributed_plugin\": \"tls\", \"disable_distributed\": false, \"logger_tls_endpoint\": \"/api/osquery/log\", \"distributed_interval\": 10, \"distributed_tls_max_attempts\": 3}, \"decorators\": {\"load\": [\"SELECT uuid AS host_uuid FROM system_info;\", \"SELECT hostname AS hostname FROM system_info;\"]}}, \"overrides\": {}}, \"fleet_desktop\": {\"transparency_url\": \"\"}, \"smtp_settings\": {\"port\": 587, \"domain\": \"\", \"server\": \"\", \"password\": \"\", \"user_name\": \"\", \"configured\": false, \"enable_smtp\": false, \"enable_ssl_tls\": true, \"sender_address\": \"\", \"enable_start_tls\": true, \"verify_ssl_certs\": true, \"authentication_type\": \"0\", \"authentication_method\": \"0\"}, \"server_settings\": {\"server_url\": \"\", \"enable_analytics\": false, \"query_report_cap\": 0, \"scripts_disabled\": false, \"deferred_save_host\": false, \"live_query_disabled\": false, \"ai_features_disabled\": false, \"query_reports_disabled\": false}, \"webhook_settings\": {\"interval\": \"0s\", \"activities_webhook\": {\"destination_url\": \"\", \"enable_activities_webhook\": false}, \"host_status_webhook\": {\"days_count\": 0, \"destination_url\": \"\", \"host_percentage\": 0, \"enable_host_status_webhook\": false}, \"vulnerabilities_webhook\": {\"destination_url\": \"\", \"host_batch_size\": 0, \"enable_vulnerabilities_webhook\": false}, \"failing_policies_webhook\": {\"policy_ids\": null, \"destination_url\": \"\", \"host_batch_size\": 0, \"enable_failing_policies_webhook\": false}}, \"host_expiry_settings\": {\"host_expiry_window\": 0, \"host_expiry_enabled\": false}, \"vulnerability_settings\": {\"databases_path\": \"\"}, \"activity_expiry_settings\": {\"activity_expiry_window\": 0, \"activity_expiry_enabled\": false}}','2020-01-01 01:01:01','2020-01-01 01:01:01');
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `calendar_events` (
diff --git a/server/fleet/activities.go b/server/fleet/activities.go
index 6ef7743b6e..a51cb0fca5 100644
--- a/server/fleet/activities.go
+++ b/server/fleet/activities.go
@@ -107,6 +107,9 @@ var ActivityDetailsList = []ActivityDetails{
ActivityTypeEnabledMacosDiskEncryption{},
ActivityTypeDisabledMacosDiskEncryption{},
+ ActivityTypeEnabledGitOpsMode{},
+ ActivityTypeDisabledGitOpsMode{},
+
ActivityTypeAddedBootstrapPackage{},
ActivityTypeDeletedBootstrapPackage{},
@@ -1152,6 +1155,26 @@ func (a ActivityTypeDisabledMacosDiskEncryption) Documentation() (activity, deta
}`
}
+type ActivityTypeEnabledGitOpsMode struct{}
+
+func (a ActivityTypeEnabledGitOpsMode) ActivityName() string {
+ return "enabled_gitops_mode"
+}
+
+func (a ActivityTypeEnabledGitOpsMode) Documentation() (activity, details, detailsExample string) {
+ return `Generated when a user enables GitOps mode.`, `This activity does not contain any detail fields.`, ``
+}
+
+type ActivityTypeDisabledGitOpsMode struct{}
+
+func (a ActivityTypeDisabledGitOpsMode) ActivityName() string {
+ return "disabled_gitops_mode"
+}
+
+func (a ActivityTypeDisabledGitOpsMode) Documentation() (activity, details, detailsExample string) {
+ return `Generated when a user disables GitOps mode.`, `This activity does not contain any detail fields.`, ``
+}
+
type ActivityTypeAddedBootstrapPackage struct {
BootstrapPackageName string `json:"bootstrap_package_name"`
TeamID *uint `json:"team_id"`
diff --git a/server/fleet/app.go b/server/fleet/app.go
index 83158164b8..5ba7b6c480 100644
--- a/server/fleet/app.go
+++ b/server/fleet/app.go
@@ -216,6 +216,11 @@ type MDM struct {
/////////////////////////////////////////////////////////////////
}
+type UIGitOpsModeConfig struct {
+ GitopsModeEnabled bool `json:"gitops_mode_enabled"`
+ RepositoryURL string `json:"repository_url"`
+}
+
func (c *AppConfig) MDMUrl() string {
if c.MDM.AppleServerURL == "" {
return c.ServerSettings.ServerURL
@@ -555,6 +560,8 @@ type AppConfig struct {
MDM MDM `json:"mdm"`
+ UIGitOpsMode UIGitOpsModeConfig `json:"gitops"`
+
// Scripts is a slice of script file paths.
//
// NOTE: These are only present here for informational purposes.
@@ -728,6 +735,8 @@ func (c *AppConfig) Copy() *AppConfig {
clone.MDM.MacOSSetup.Software = optjson.SetSlice(sw)
}
+ // UIGitOpsMode: nothing needs cloning
+
if c.YaraRules != nil {
rules := make([]YaraRule, len(c.YaraRules))
copy(rules, c.YaraRules)
diff --git a/server/service/appconfig.go b/server/service/appconfig.go
index 6a2c4bf7dc..a3f8230170 100644
--- a/server/service/appconfig.go
+++ b/server/service/appconfig.go
@@ -193,6 +193,7 @@ func getAppConfigEndpoint(ctx context.Context, request interface{}, svc fleet.Se
Integrations: appConfig.Integrations,
MDM: appConfig.MDM,
Scripts: appConfig.Scripts,
+ UIGitOpsMode: appConfig.UIGitOpsMode,
},
appConfigResponseFields: appConfigResponseFields{
UpdateInterval: updateIntervalConfig,
@@ -627,6 +628,31 @@ func (svc *Service) ModifyAppConfig(ctx context.Context, p []byte, applyOpts fle
appConfig.Integrations.GoogleCalendar = oldAppConfig.Integrations.GoogleCalendar
}
+ gme, rurl := newAppConfig.UIGitOpsMode.GitopsModeEnabled, newAppConfig.UIGitOpsMode.RepositoryURL
+ if gme {
+ if !license.IsPremium() {
+ return nil, fleet.NewInvalidArgumentError("UI GitOpsMode: ", ErrMissingLicense.Error())
+ }
+ if rurl == "" {
+ return nil, fleet.NewInvalidArgumentError("UI GitOps Mode: ", "Repository URL is required when GitOps mode is enabled")
+ }
+ }
+ appConfig.UIGitOpsMode = newAppConfig.UIGitOpsMode
+
+ if oldAppConfig.UIGitOpsMode.GitopsModeEnabled != appConfig.UIGitOpsMode.GitopsModeEnabled {
+ // generate the activity
+ var act fleet.ActivityDetails
+ if gme {
+ act = fleet.ActivityTypeEnabledGitOpsMode{}
+ } else {
+ act = fleet.ActivityTypeDisabledGitOpsMode{}
+ }
+ if err := svc.NewActivity(ctx, authz.UserFromContext(ctx), act); err != nil {
+ return nil, ctxerr.Wrapf(ctx, err, "create activity %s", act.ActivityName())
+ }
+
+ }
+
if !license.IsPremium() {
// reset transparency url to empty for downgraded licenses
appConfig.FleetDesktop.TransparencyURL = ""
diff --git a/server/service/integration_core_test.go b/server/service/integration_core_test.go
index ff3b4c4bbf..9cea3fd4f8 100644
--- a/server/service/integration_core_test.go
+++ b/server/service/integration_core_test.go
@@ -6845,6 +6845,8 @@ func (s *integrationTestSuite) TestAppConfig() {
assert.False(t, acResp.ActivityExpirySettings.ActivityExpiryEnabled)
assert.Zero(t, acResp.ActivityExpirySettings.ActivityExpiryWindow)
assert.False(t, acResp.ServerSettings.AIFeaturesDisabled)
+ assert.False(t, acResp.UIGitOpsMode.GitopsModeEnabled)
+ assert.Zero(t, acResp.UIGitOpsMode.RepositoryURL)
// set the apple BM terms expired flag, and the enabled and configured flags,
// we'll check again at the end of this test to make sure they weren't
@@ -7146,6 +7148,13 @@ func (s *integrationTestSuite) TestAppConfig() {
defAppCfg.OrgInfo.OrgName = acResp.OrgInfo.OrgName
defAppCfg.ServerSettings.ServerURL = acResp.ServerSettings.ServerURL
s.DoRaw("PATCH", "/api/latest/fleet/config", jsonMustMarshal(t, defAppCfg), http.StatusOK)
+
+ // turn on GitOps mode, premium only
+ res = s.Do("PATCH", "/api/latest/fleet/config", json.RawMessage(`{
+ "gitops": { "gitops_mode_enabled": true, "repository_url": "" }
+ }`), http.StatusUnprocessableEntity)
+ errMsg = extractServerErrorText(res.Body)
+ assert.Contains(t, errMsg, "missing or invalid license")
}
// TODO(lucas): Add tests here.
diff --git a/server/service/integration_enterprise_test.go b/server/service/integration_enterprise_test.go
index e829deed8d..14c832acf0 100644
--- a/server/service/integration_enterprise_test.go
+++ b/server/service/integration_enterprise_test.go
@@ -2534,6 +2534,27 @@ func (s *integrationEnterpriseTestSuite) TestWindowsUpdatesTeamConfig() {
}, http.StatusUnprocessableEntity, &tmResp)
}
+func (s *integrationEnterpriseTestSuite) TestGitOpsModeConfig() {
+ t := s.T()
+
+ res := s.Do("PATCH", "/api/latest/fleet/config", json.RawMessage(`{
+ "gitops": { "gitops_mode_enabled": true, "repository_url": "" }
+ }`), http.StatusUnprocessableEntity)
+ errMsg := extractServerErrorText(res.Body)
+ assert.Contains(t, errMsg, "Repository URL is required when GitOps mode is enabled")
+
+ s.Do("PATCH", "/api/latest/fleet/config", json.RawMessage(`{
+ "gitops": { "gitops_mode_enabled": true, "repository_url": "a.b.cc" }
+ }`), http.StatusOK)
+ s.lastActivityOfTypeMatches(fleet.ActivityTypeEnabledGitOpsMode{}.ActivityName(), "", 0)
+
+ // turn off, persists repo url
+ s.Do("PATCH", "/api/latest/fleet/config", json.RawMessage(`{
+ "gitops": { "gitops_mode_enabled": false, "repository_url": "a.b.cc" }
+ }`), http.StatusOK)
+ s.lastActivityOfTypeMatches(fleet.ActivityTypeDisabledGitOpsMode{}.ActivityName(), "", 0)
+}
+
func (s *integrationEnterpriseTestSuite) assertAppleOSUpdatesDeclaration(teamID *uint, profileName string, expected *fleet.AppleOSUpdateSettings) {
t := s.T()
if teamID == nil {
diff --git a/tools/cloner-check/generated_files/appconfig.txt b/tools/cloner-check/generated_files/appconfig.txt
index 09ce197b65..2ab3173f21 100644
--- a/tools/cloner-check/generated_files/appconfig.txt
+++ b/tools/cloner-check/generated_files/appconfig.txt
@@ -175,6 +175,9 @@ github.com/fleetdm/fleet/v4/pkg/optjson/Slice[github.com/fleetdm/fleet/v4/server
github.com/fleetdm/fleet/v4/server/fleet/MDMAppleVolumePurchasingProgramInfo Location string
github.com/fleetdm/fleet/v4/server/fleet/MDMAppleVolumePurchasingProgramInfo Teams []string
github.com/fleetdm/fleet/v4/server/fleet/MDM AndroidEnabledAndConfigured bool
+github.com/fleetdm/fleet/v4/server/fleet/AppConfig UIGitOpsMode fleet.UIGitOpsModeConfig
+github.com/fleetdm/fleet/v4/server/fleet/UIGitOpsModeConfig GitopsModeEnabled bool
+github.com/fleetdm/fleet/v4/server/fleet/UIGitOpsModeConfig RepositoryURL string
github.com/fleetdm/fleet/v4/server/fleet/AppConfig Scripts optjson.Slice[string]
github.com/fleetdm/fleet/v4/pkg/optjson/Slice[string] Set bool
github.com/fleetdm/fleet/v4/pkg/optjson/Slice[string] Valid bool