diff --git a/.github/scripts/update_osquery_versions.py b/.github/scripts/update_osquery_versions.py index c65deceb2ee4..28a932e6acb1 100755 --- a/.github/scripts/update_osquery_versions.py +++ b/.github/scripts/update_osquery_versions.py @@ -14,9 +14,8 @@ def fetch_osquery_versions(): resp = conn.getresponse() content = resp.read() conn.close() - releases = json.loads(content.decode('utf-8')) - return [release['tag_name'] for release in releases if not release['prerelease']] + return [release['tag_name'] for release in json.loads(content.decode('utf-8'))] def update_min_osquery_version_options(new_versions): with open(FILE_PATH, 'r') as file: diff --git a/CHANGELOG.md b/CHANGELOG.md index 0fc2d7d3f10b..bc0999a01ebe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,84 @@ +## Fleet 4.62.1 (Jan 13, 2025) + +### Bug fixes + +* Fixed issue when identical MDM commands were sent twice to the same device when replica DB was being used. + +## Fleet 4.62.0 (Jan 09, 2025) + +## Endpoint operations +- Updated macos 13, 14 per latest CIS documents. Added macos 15 support. +- Updated queries API to support above targeted platform filtering. +- Updated UI queries page to filter, sort, paginate, etc. via query params in call to server. +- Added searchable query targets and cleaner UI for uses with many teams or labels. + +## Device management (MDM) +- Added ability to use secrets (`$FLEET_SECRET_YOURNAME`) in scripts and profiles. +- Added ability to scope Fleet-maintained apps and custom packages via labels in UI, API, and CLI. +- Added capability to automatically generate "trigger policies" for custom software packages. +- Added UI for scoping software via labels. +- Added validation to prevent label deletion if it is used to scope the hosts targeted by a software installer. +- Added ability to filter host software based on label scoping. +- Added support for Fleet secret validation in software installer scripts. +- Updated `fleetctl gitops` to support scope software installers by labels, with the `labels_include_any` or `labels_exclude_any` conditions. +- Updated `fleetctl gitops` to identify secrets in scripts and profiles and saves them on the Fleet server. +- Updated `fleetctl gitops` so that when it updates profiles, if the secret value has changed, the profile is updated on the host. +- Added `/fleet/spec/secret_variables` API endpoint. +- Added functionality for skipping automatic installs if the software is not scoped to the host via labels. +- Added the ability to click a software row on the my device page and see the details of that software's installation on the host. +- Allowed software uninstalls and script-based host lock/unlock/wipe to run while global scripts are disabled. + +## Vulnerability management +- Added missing vulncheck data from NVD feeds. +- Fixed MSI parsing for packages including long interned strings (e.g. licenses for the OpenVPN Connect installer). +- Fixed a panic (and resulting failure to load CVE details) on new installs when OS versions have not been populated yet. +- Fixed CVE-2024-10004 false positive on Fleet-supported platforms (vuln is iOS-only and iOS vuln checking is not supported). + +## Bug fixes and improvements +- Added license key validation on `fleetctl preview` if a license key is provided; fixes cases where an invalid license key would cause `fleetctl preview` to hang. +- Increased maximum length for installer URLs specified in GitOps to 4000 characters. +- Stopped older scheduled queries from filling logs with errors. +- Changed script upload endpoint (`POST /api/v1/fleet/scripts`) to automatically switch CRLF line endings to LF. +- Fleshed out server response from `queries` endpoint to include `count` and `meta` pagination information. +- Updated platform filtering on queries page to refer to targeted platforms instead of compatible platforms. +- Included osquery pre-releases in daily UI constant update GitHub Actions job. +- Updated to send alert via SNS when a scheduled "cron" job returns errors. +- SNS topic for job error alerts can be configured separately from the existing monitor alert by adding "cron_job_failure_monitoring" to sns_topic_arns_map, otherwise defaults to the using the same topic. +- Improved validation workflow on SMTP settings page. +- Allowed team policy endpoint (`PATCH /api/latest/fleet/teams/{team_id}/policies/{policy_id}`) to receive explicit `null` as a value for `script_id` or `software_title_id` to unset a script or software installer respectively. +- Aliased EAP versions of JetBrains IDEs to "last release version plus all fixes" (e.g. 2024.3 EAP -> 2024.2.99) to avoid vulnerability false positives. +- Removed server error if no private IP was found by detail_query_network_interface. +- Updated `fleetctl` dependencies that cause warnings. +- Added service annotation field to Helm Chart. +- Updated so that on policy deletion any associated pending software installer or scripts are deleted. +- Added fallback to FileVersion on EXE installers when FileVersion is set but ProductVersion isn't to allow more custom packages to be uploaded. +- Added Mastodon icon and URL to server email templates. +- Improved table text wrapper in UI. +- Added helpful tooltip for the install software setup experience page. +- Added offset to the tooltips on hover of the profile aggregate status indicators. +- Added the `software_title_id` field to the `added_software` activity details. +- Allow maintainers to manage install software or run scripts on policy automations. +- Removed duplicate software records from homebrew casks already reported in the osquery `apps` table to address false positive vulnerabilities due to lack of bundle_identifier. +- Added the `labels_include_any` and `labels_exclude_any` fields to the software installer activities. +- Updated the get host endpoint to include disk encryption stats for a linux host only if the setting is enabled. +- Updated Helm chart to support customization options such as the Google cloud_sql_proxy in the fleet-migration job. +- Updated example windows policies. +- Added a descriptive error when a GitOps file contains script references that are missing paths. +- Removed `invalid UUID` log message when validating Apple MDM UDID. +- Added validation Fleet secrets embedded into scripts and profiles on ingestion. +- Display the correct percentage of hosts online when there are no hosts online. +- Fixed bug when creating a label to preserve the selected team. +- Fixed export to CSV trimming leading zeros by treating those values as strings. +- Fixed reporting of software uninstall results after a host has been locked/unlocked. +- Fixed issue where minio software was not scanned for vulnerabilities correctly because of unexpected trailing characters in the version string. +- Fixed bug on the "Controls" page where incorrect timestamp information was displayed while the "Current versions" table was loading. +- Fixed policy truncation UI bug. +- Fixed cases where showing results of an inherited query viewed inside a team would include results from hosts not on thta team by adding an optional team_id parameter to queris report endpoint (`GET /api/latest/fleet/queries/{query_id}/report`). +- Fixed issue where deleted Apple config profiles were installing on devices because devices were offline when the profile was added. +- Fixed UI bug involving pagination of subsections within the "Controls" page. +- Fixed "Verifying" disk encryption status count and filter for macOS hosts to not include hosts where end-user action is required. +- Fixed a bug in determining sort type of query result columns by deducing that type from the data present in those columns. + ## Fleet 4.61.0 (Dec 17, 2024) ## Endpoint operations diff --git a/changes/19930-alert-on-cron-errors b/changes/19930-alert-on-cron-errors deleted file mode 100644 index 0374bf8b0530..000000000000 --- a/changes/19930-alert-on-cron-errors +++ /dev/null @@ -1,2 +0,0 @@ -- Send alert via SNS when a scheduled "cron" job returns errors -- SNS topic for job error alerts can be configured separately from the existing monitor alert by adding "cron_job_failure_monitoring" to sns_topic_arns_map, otherwise defaults to the using the same topic diff --git a/changes/21855-paginate-queries b/changes/21855-paginate-queries deleted file mode 100644 index a54dfb43c8c7..000000000000 --- a/changes/21855-paginate-queries +++ /dev/null @@ -1,5 +0,0 @@ -- Fleshed out server response from `queries` endpoint to include `count` and `meta` pagination information. -- Updated UI queries page to filter, sort, paginate, etc. via query params in call to server. -- Updated platform filtering on queries page to refer to targeted platforms instead of compatible - platforms -- Updated queries API to support above targeted platform filtering diff --git a/changes/22444-gitops-script-missing-path b/changes/22444-gitops-script-missing-path deleted file mode 100644 index e9a5bb299731..000000000000 --- a/changes/22444-gitops-script-missing-path +++ /dev/null @@ -1 +0,0 @@ -* Added a descriptive error when a GitOps file contains script references that are missing paths diff --git a/changes/22448-searchable-query-targets b/changes/22448-searchable-query-targets deleted file mode 100644 index 5cbb33f42d34..000000000000 --- a/changes/22448-searchable-query-targets +++ /dev/null @@ -1 +0,0 @@ -- Fleet UI: Add searchable query targets and cleaner UI I for uses with many teams or labels diff --git a/changes/22523-cve-500 b/changes/22523-cve-500 deleted file mode 100644 index d2170348a354..000000000000 --- a/changes/22523-cve-500 +++ /dev/null @@ -1 +0,0 @@ -* Fixed a panic (and resulting failure to load CVE details) on new installs when OS versions have not been populated yet. diff --git a/changes/22723-jetbrains-eap-versions b/changes/22723-jetbrains-eap-versions deleted file mode 100644 index 6efe38c67461..000000000000 --- a/changes/22723-jetbrains-eap-versions +++ /dev/null @@ -1 +0,0 @@ -* Aliased EAP versions of JetBrains IDEs to "last release version plus all fixes" (e.g. 2024.3 EAP -> 2024.2.99) to avoid vulnerability false positives \ No newline at end of file diff --git a/changes/22813-software-scope-labels b/changes/22813-software-scope-labels deleted file mode 100644 index 4a4681a2c618..000000000000 --- a/changes/22813-software-scope-labels +++ /dev/null @@ -1 +0,0 @@ -- Added features to scope Fleet-maintained apps and custom packages via labels in UI, API, and CLI. diff --git a/changes/22875-uninstall-with-scripts-disabled b/changes/22875-uninstall-with-scripts-disabled deleted file mode 100644 index 5f399869b5e5..000000000000 --- a/changes/22875-uninstall-with-scripts-disabled +++ /dev/null @@ -1 +0,0 @@ -* Allowed software uninstalls and script-based host lock/unlock/wipe to run while global scripts are disabled. diff --git a/changes/22884-license-error-fleetctl b/changes/22884-license-error-fleetctl deleted file mode 100644 index f3bb25527ebe..000000000000 --- a/changes/22884-license-error-fleetctl +++ /dev/null @@ -1 +0,0 @@ -* Added license key validation on `fleetctl preview` if a license key is provided; fixes cases where an invalid license key would cause `fleetctl preview` to hang. diff --git a/changes/22944-homebrew-casks b/changes/22944-homebrew-casks deleted file mode 100644 index abaf22ffa250..000000000000 --- a/changes/22944-homebrew-casks +++ /dev/null @@ -1 +0,0 @@ -* removed duplicate software records from homebrew casks already reported in the osquery `apps` table to address false positive vulnerabilities due to lack of bundle_identifier \ No newline at end of file diff --git a/changes/23011-dynamic-column-sort-type b/changes/23011-dynamic-column-sort-type deleted file mode 100644 index 9ac874713f1d..000000000000 --- a/changes/23011-dynamic-column-sort-type +++ /dev/null @@ -1,2 +0,0 @@ -- Fixed a bug in determining sort type of query result columns by deducing that type from the data - present in those columns. diff --git a/changes/23238-use-secrets-in-scripts-profiles b/changes/23238-use-secrets-in-scripts-profiles deleted file mode 100644 index 4df69e0d13cc..000000000000 --- a/changes/23238-use-secrets-in-scripts-profiles +++ /dev/null @@ -1,5 +0,0 @@ -Added ability to use secrets ($FLEET_SECRET_YOURNAME) in scripts and profiles. -- Added `/fleet/spec/secret_variables` API endpoint. -- fleetctl gitops identifies secrets in scripts and profiles and saves them on the Fleet server. -- secret values are populated when scripts and profiles are sent to devices. -- When fleetctl gitops updates profiles, if the secret value has changed, the profile is updated on the host. diff --git a/changes/23309-mastodon-in-email-templates b/changes/23309-mastodon-in-email-templates deleted file mode 100644 index 6eac06da3e60..000000000000 --- a/changes/23309-mastodon-in-email-templates +++ /dev/null @@ -1 +0,0 @@ -* Added Mastodon icon and URL to server email templates. diff --git a/changes/23315-show-sw-install-details-on-my-device b/changes/23315-show-sw-install-details-on-my-device deleted file mode 100644 index fc5c476c8c9c..000000000000 --- a/changes/23315-show-sw-install-details-on-my-device +++ /dev/null @@ -1,2 +0,0 @@ -* Add the ability to click a software row on the my device page and see the details of that -software's installation on the host. diff --git a/changes/23448-maintainer-policy-automations b/changes/23448-maintainer-policy-automations deleted file mode 100644 index a5a0f38532c9..000000000000 --- a/changes/23448-maintainer-policy-automations +++ /dev/null @@ -1 +0,0 @@ -- Fleet UI bug fix: Allow maintainers to manage install software or run scripts on policy automations diff --git a/changes/23490-null-script-software-on-policies b/changes/23490-null-script-software-on-policies deleted file mode 100644 index cf2db860dce3..000000000000 --- a/changes/23490-null-script-software-on-policies +++ /dev/null @@ -1 +0,0 @@ -* Allowed team policy endpoint (`PATCH /api/latest/fleet/teams/{team_id}/policies/{policy_id}`) to receive explicit `null` as a value for `script_id` or `software_title_id` to unset a script or software installer respectively. \ No newline at end of file diff --git a/changes/23541-fileversion-fallback b/changes/23541-fileversion-fallback deleted file mode 100644 index b9ec9f22adbe..000000000000 --- a/changes/23541-fileversion-fallback +++ /dev/null @@ -1 +0,0 @@ -* Added fallback to FileVersion on EXE installers when FileVersion is set but ProductVersion isn't to allow more custom packages to be uploaded diff --git a/changes/23557-minio b/changes/23557-minio deleted file mode 100644 index 2fa00913f424..000000000000 --- a/changes/23557-minio +++ /dev/null @@ -1 +0,0 @@ -* fixed issue where minio software was not scanned for vulnerabilities correctly because of unexpected trailing characters in the version string \ No newline at end of file diff --git a/changes/23579-cve-2024-10004-false-positive b/changes/23579-cve-2024-10004-false-positive deleted file mode 100644 index de3ed40f7b56..000000000000 --- a/changes/23579-cve-2024-10004-false-positive +++ /dev/null @@ -1 +0,0 @@ -* Fixed CVE-2024-10004 false positive on Fleet-supported platforms (vuln is iOS-only and iOS vuln checking is not supported) diff --git a/changes/23611-Update-CIS b/changes/23611-Update-CIS deleted file mode 100644 index 8b72853be652..000000000000 --- a/changes/23611-Update-CIS +++ /dev/null @@ -1 +0,0 @@ - * Updated macos 13, 14 per latest CIS documents. Added macos 15 support. diff --git a/changes/23783-controls-subnav-pagination b/changes/23783-controls-subnav-pagination deleted file mode 100644 index 46094c2e5f89..000000000000 --- a/changes/23783-controls-subnav-pagination +++ /dev/null @@ -1 +0,0 @@ -- Fixed UI bug involving pagination of subsections within the "Controls" page. diff --git a/changes/23800-host-online-pctage b/changes/23800-host-online-pctage deleted file mode 100644 index 4e6d92d75e68..000000000000 --- a/changes/23800-host-online-pctage +++ /dev/null @@ -1 +0,0 @@ -* Display the correct percentage of hosts online, 0, when there are no hosts online. diff --git a/changes/23803-leading-zeros-bug b/changes/23803-leading-zeros-bug deleted file mode 100644 index a3ea4104bfad..000000000000 --- a/changes/23803-leading-zeros-bug +++ /dev/null @@ -1 +0,0 @@ -- Fleet UI: Fix export to CSV from trimming leading zeros by treating those values as strings diff --git a/changes/23886-remove-associations-on-policy-delete b/changes/23886-remove-associations-on-policy-delete deleted file mode 100644 index 318ca34bec79..000000000000 --- a/changes/23886-remove-associations-on-policy-delete +++ /dev/null @@ -1 +0,0 @@ -* On policy deletion any associated pending software installer or scripts are deleted. \ No newline at end of file diff --git a/changes/24006-host-query-report-team-id b/changes/24006-host-query-report-team-id deleted file mode 100644 index 588ab1eac91e..000000000000 --- a/changes/24006-host-query-report-team-id +++ /dev/null @@ -1 +0,0 @@ -* Fixed cases where showing results of an inherited query viewed inside a team would include results from hosts not on thta team by adding an optional team_id parameter to queries report endpoint (`GET /api/latest/fleet/queries/{query_id}/report`) \ No newline at end of file diff --git a/changes/24025-add-label-team-bug b/changes/24025-add-label-team-bug deleted file mode 100644 index cb4396199129..000000000000 --- a/changes/24025-add-label-team-bug +++ /dev/null @@ -1 +0,0 @@ -- Fix bug when creating a label to preserve the selected team diff --git a/changes/24033-helm-customization-options b/changes/24033-helm-customization-options deleted file mode 100644 index 1aafbedcde5f..000000000000 --- a/changes/24033-helm-customization-options +++ /dev/null @@ -1 +0,0 @@ -Helm chart: Supported customization options such as the Google cloud_sql_proxy in the fleet-migration job. diff --git a/changes/24120-sw-title-id b/changes/24120-sw-title-id deleted file mode 100644 index 5a1b8ebe72e3..000000000000 --- a/changes/24120-sw-title-id +++ /dev/null @@ -1 +0,0 @@ -- Adds the `software_title_id` field to the `added_software` activity details. \ No newline at end of file diff --git a/changes/24166-script-line-endings b/changes/24166-script-line-endings deleted file mode 100644 index 3beeb8d9dd4a..000000000000 --- a/changes/24166-script-line-endings +++ /dev/null @@ -1 +0,0 @@ -* Changed script upload endpoint (`POST /api/v1/fleet/scripts`) to automatically switch CRLF line endings to LF diff --git a/changes/24244-macos-encryption-verifying-query b/changes/24244-macos-encryption-verifying-query deleted file mode 100644 index f88dbd6e88d9..000000000000 --- a/changes/24244-macos-encryption-verifying-query +++ /dev/null @@ -1 +0,0 @@ -* Fixed "Verifying" disk encryption status count and filter for macOS hosts to not include hosts where end-user action is required diff --git a/changes/24268-update-fleetctl-deps b/changes/24268-update-fleetctl-deps deleted file mode 100644 index 0b22a53d6585..000000000000 --- a/changes/24268-update-fleetctl-deps +++ /dev/null @@ -1 +0,0 @@ -* Update fleetctl dependencies that cause warnings \ No newline at end of file diff --git a/changes/24286-vulncheck b/changes/24286-vulncheck deleted file mode 100644 index 2104095dd5b5..000000000000 --- a/changes/24286-vulncheck +++ /dev/null @@ -1 +0,0 @@ -* added missing vulncheck data from nvd feeds \ No newline at end of file diff --git a/changes/24315-update-windows-policy-constants b/changes/24315-update-windows-policy-constants deleted file mode 100644 index 36032790089d..000000000000 --- a/changes/24315-update-windows-policy-constants +++ /dev/null @@ -1 +0,0 @@ -- Update example windows policies diff --git a/changes/24334-policy-truncation b/changes/24334-policy-truncation deleted file mode 100644 index a8137dcb3d05..000000000000 --- a/changes/24334-policy-truncation +++ /dev/null @@ -1 +0,0 @@ -- Fix policy truncation UI bug diff --git a/changes/24385-automatic-install-custom-packages b/changes/24385-automatic-install-custom-packages deleted file mode 100644 index b36526d1687f..000000000000 --- a/changes/24385-automatic-install-custom-packages +++ /dev/null @@ -1 +0,0 @@ -* Added capability to automatically generate "trigger policies" for custom software packages. diff --git a/changes/24386-fleet-legacy-query-pack b/changes/24386-fleet-legacy-query-pack deleted file mode 100644 index 66878d24a716..000000000000 --- a/changes/24386-fleet-legacy-query-pack +++ /dev/null @@ -1 +0,0 @@ -- Stop older scheduled queries from filling logs with errors diff --git a/changes/24456-include-linux-encryption-data-only-when-enabled b/changes/24456-include-linux-encryption-data-only-when-enabled deleted file mode 100644 index cefe63053829..000000000000 --- a/changes/24456-include-linux-encryption-data-only-when-enabled +++ /dev/null @@ -1 +0,0 @@ -- Updated the get host endpoint to include disk encryption stats for a linux host only if the setting is enabled diff --git a/changes/24459-chart-serrvice-annotation b/changes/24459-chart-serrvice-annotation deleted file mode 100644 index 62a199ec582d..000000000000 --- a/changes/24459-chart-serrvice-annotation +++ /dev/null @@ -1 +0,0 @@ -* Added service annotation field to Helm Chart diff --git a/changes/24533-skip-policy b/changes/24533-skip-policy deleted file mode 100644 index 4de7d634a3b3..000000000000 --- a/changes/24533-skip-policy +++ /dev/null @@ -1 +0,0 @@ -- Adds functionality for skipping automatic installs if the software is not scoped to the host via labels. \ No newline at end of file diff --git a/changes/24534-hide-software-2 b/changes/24534-hide-software-2 deleted file mode 100644 index 9b73513ddd20..000000000000 --- a/changes/24534-hide-software-2 +++ /dev/null @@ -1 +0,0 @@ -- Add functionality to filter host software based on label scoping. \ No newline at end of file diff --git a/changes/24536-prevent-label-deletion-if-referenced-by-software b/changes/24536-prevent-label-deletion-if-referenced-by-software deleted file mode 100644 index ef3e4753f351..000000000000 --- a/changes/24536-prevent-label-deletion-if-referenced-by-software +++ /dev/null @@ -1 +0,0 @@ -* Added a validation to prevent label deletion if it is used to scope the hosts targeted by a software installer. diff --git a/changes/24538-24542-UI-for-scope-software-via-labels b/changes/24538-24542-UI-for-scope-software-via-labels deleted file mode 100644 index d8d65558df8e..000000000000 --- a/changes/24538-24542-UI-for-scope-software-via-labels +++ /dev/null @@ -1 +0,0 @@ -- add UI for scoping software via labels diff --git a/changes/24549-validate-script-profle-secrets b/changes/24549-validate-script-profle-secrets deleted file mode 100644 index fdf7ea4a416e..000000000000 --- a/changes/24549-validate-script-profle-secrets +++ /dev/null @@ -1 +0,0 @@ -- Validate fleet secrets embedded into scripts and profiles on ingestion diff --git a/changes/24663-software-scoped-via-labels-gitops b/changes/24663-software-scoped-via-labels-gitops deleted file mode 100644 index 4bb1c15cf230..000000000000 --- a/changes/24663-software-scoped-via-labels-gitops +++ /dev/null @@ -1 +0,0 @@ -* Added `fleetctl gitops` support to scope software installers by labels, with the `labels_include_any` or `labels_exclude_any` conditions. diff --git a/changes/24725-no-private-ip-found b/changes/24725-no-private-ip-found deleted file mode 100644 index 83b72288a521..000000000000 --- a/changes/24725-no-private-ip-found +++ /dev/null @@ -1 +0,0 @@ -Removed server error if no private IP was found by detail_query_network_interface. diff --git a/changes/24792-update-software-installer-activities b/changes/24792-update-software-installer-activities deleted file mode 100644 index 206fa80dac8b..000000000000 --- a/changes/24792-update-software-installer-activities +++ /dev/null @@ -1 +0,0 @@ -* Added the `labels_include_any` and `labels_exclude_any` fields to the software installer activities. diff --git a/changes/24795-add-helpful-tooltip-setup-experience b/changes/24795-add-helpful-tooltip-setup-experience deleted file mode 100644 index 4c108c223152..000000000000 --- a/changes/24795-add-helpful-tooltip-setup-experience +++ /dev/null @@ -1 +0,0 @@ -- add helpful tooltip for the install software setup experience page diff --git a/changes/24899-software-installer-scripts-secrets b/changes/24899-software-installer-scripts-secrets deleted file mode 100644 index f5f11a77c74c..000000000000 --- a/changes/24899-software-installer-scripts-secrets +++ /dev/null @@ -1 +0,0 @@ -- Add support for fleet secret validation in software installer scripts diff --git a/changes/24917-installer-url-length b/changes/24917-installer-url-length deleted file mode 100644 index af3287c8076f..000000000000 --- a/changes/24917-installer-url-length +++ /dev/null @@ -1 +0,0 @@ -* Increased maximum length for installer URLs specified in GitOps to 4000 characters diff --git a/changes/24961-invalid-uuid b/changes/24961-invalid-uuid deleted file mode 100644 index fae9c81341ee..000000000000 --- a/changes/24961-invalid-uuid +++ /dev/null @@ -1 +0,0 @@ -Removed `invalid UUID` log message when validating Apple MDM UDID. diff --git a/changes/25038-fix-profile-status-aggregate-tooltips-spacing b/changes/25038-fix-profile-status-aggregate-tooltips-spacing deleted file mode 100644 index 79504e60eca0..000000000000 --- a/changes/25038-fix-profile-status-aggregate-tooltips-spacing +++ /dev/null @@ -1 +0,0 @@ -* Add offset to the tooltips on hover of the profile aggregate status indicators. diff --git a/changes/8903c-table-text-wrapping b/changes/8903c-table-text-wrapping deleted file mode 100644 index 08ce77f6b0dd..000000000000 --- a/changes/8903c-table-text-wrapping +++ /dev/null @@ -1 +0,0 @@ -- Fleet UI: Clean up some table text wrapping diff --git a/charts/fleet/Chart.yaml b/charts/fleet/Chart.yaml index b258d1c234fb..fb788c8bedbf 100644 --- a/charts/fleet/Chart.yaml +++ b/charts/fleet/Chart.yaml @@ -4,11 +4,11 @@ name: fleet keywords: - fleet - osquery -version: v6.3.0 +version: v6.3.1 home: https://github.com/fleetdm/fleet sources: - https://github.com/fleetdm/fleet.git -appVersion: v4.61.0 +appVersion: v4.62.1 dependencies: - name: mysql condition: mysql.enabled diff --git a/charts/fleet/values.yaml b/charts/fleet/values.yaml index 4d7aa0885577..0228b3346ce5 100644 --- a/charts/fleet/values.yaml +++ b/charts/fleet/values.yaml @@ -3,7 +3,7 @@ hostName: fleet.localhost replicas: 3 # The number of Fleet instances to deploy imageRepository: fleetdm/fleet -imageTag: v4.61.0 # Version of Fleet to deploy +imageTag: v4.62.1 # Version of Fleet to deploy podAnnotations: {} # Additional annotations to add to the Fleet pod serviceAnnotations: {} # Additional annotations to add to the Fleet service serviceAccountAnnotations: {} # Additional annotations to add to the Fleet service account diff --git a/docs/Contributing/Audit-logs.md b/docs/Contributing/Audit-logs.md index feadc6e0cda6..19dea07e2f81 100644 --- a/docs/Contributing/Audit-logs.md +++ b/docs/Contributing/Audit-logs.md @@ -1376,6 +1376,7 @@ Generated when an App Store app is added to Fleet. This activity contains the following fields: - "software_title": Name of the App Store app. +- "software_title_id": ID of the added software title. - "app_store_id": ID of the app on the Apple App Store. - "platform": Platform of the app (`darwin`, `ios`, or `ipados`). - "self_service": App installation can be initiated by device owner. @@ -1387,6 +1388,7 @@ This activity contains the following fields: ```json { "software_title": "Logic Pro", + "software_title_id": 123, "app_store_id": "1234567", "platform": "darwin", "self_service": false, diff --git a/ee/server/service/software_installers.go b/ee/server/service/software_installers.go index 81b539c5b1f4..4bdba884a577 100644 --- a/ee/server/service/software_installers.go +++ b/ee/server/service/software_installers.go @@ -438,10 +438,41 @@ func (svc *Service) UpdateSoftwareInstaller(ctx context.Context, payload *fleet. payload.SelfService = &existingInstaller.SelfService } + // Get the hosts that are NOT in label scope currently (before the update happens) + var hostsNotInScope map[uint]struct{} + if dirty["Labels"] { + hostsNotInScope, err = svc.ds.GetExcludedHostIDMapForSoftwareInstaller(ctx, payload.InstallerID) + if err != nil { + return nil, ctxerr.Wrap(ctx, err, "getting hosts not in scope for installer") + } + } + if err := svc.ds.SaveInstallerUpdates(ctx, payload); err != nil { return nil, ctxerr.Wrap(ctx, err, "saving installer updates") } + if dirty["Labels"] { + // Get the hosts that are now IN label scope (after the update) + hostsInScope, err := svc.ds.GetIncludedHostIDMapForSoftwareInstaller(ctx, payload.InstallerID) + if err != nil { + return nil, ctxerr.Wrap(ctx, err, "getting hosts in scope for installer") + } + + var hostsToClear []uint + for id := range hostsInScope { + if _, ok := hostsNotInScope[id]; ok { + // it was not in scope but now it is, so we should clear policy status + hostsToClear = append(hostsToClear, id) + } + } + + // We clear the policy status here because otherwise the policy automation machinery + // won't pick this up and the software won't install. + if err := svc.ds.ClearAutoInstallPolicyStatusForHosts(ctx, payload.InstallerID, hostsToClear); err != nil { + return nil, ctxerr.Wrap(ctx, err, "failed to clear auto install policy status for host") + } + } + // if we're updating anything other than self-service, we cancel pending installs/uninstalls, // and if we're updating the package we reset counts. This is run in its own transaction internally // for consistency, but independent of the installer update query as the main update should stick @@ -484,7 +515,8 @@ func (svc *Service) UpdateSoftwareInstaller(ctx context.Context, payload *fleet. } func (svc *Service) validateEmbeddedSecretsOnScript(ctx context.Context, scriptName string, script *string, - argErr *fleet.InvalidArgumentError) *fleet.InvalidArgumentError { + argErr *fleet.InvalidArgumentError, +) *fleet.InvalidArgumentError { if script != nil { if errScript := svc.ds.ValidateEmbeddedSecrets(ctx, []string{*script}); errScript != nil { if argErr != nil { diff --git a/ee/server/service/vpp.go b/ee/server/service/vpp.go index d8f453a950e3..04eaef1ea9fa 100644 --- a/ee/server/service/vpp.go +++ b/ee/server/service/vpp.go @@ -363,17 +363,20 @@ func (svc *Service) AddAppStoreApp(ctx context.Context, teamID *uint, appID flee Name: assetMD.TrackName, LatestVersion: assetMD.Version, } - if _, err := svc.ds.InsertVPPAppWithTeam(ctx, app, teamID); err != nil { + + addedApp, err := svc.ds.InsertVPPAppWithTeam(ctx, app, teamID) + if err != nil { return ctxerr.Wrap(ctx, err, "writing VPP app to db") } act := fleet.ActivityAddedAppStoreApp{ - AppStoreID: app.AdamID, - Platform: app.Platform, - TeamName: &teamName, - SoftwareTitle: app.Name, - TeamID: teamID, - SelfService: app.SelfService, + AppStoreID: app.AdamID, + Platform: app.Platform, + TeamName: &teamName, + SoftwareTitle: app.Name, + SoftwareTitleId: addedApp.TitleID, + TeamID: teamID, + SelfService: app.SelfService, } if err := svc.NewActivity(ctx, authz.UserFromContext(ctx), act); err != nil { return ctxerr.Wrap(ctx, err, "create activity for add app store app") diff --git a/frontend/components/PlatformSelector/PlatformSelector.tsx b/frontend/components/PlatformSelector/PlatformSelector.tsx index 3eb907f9b2ea..c46f85c956b6 100644 --- a/frontend/components/PlatformSelector/PlatformSelector.tsx +++ b/frontend/components/PlatformSelector/PlatformSelector.tsx @@ -1,6 +1,12 @@ import React from "react"; import classNames from "classnames"; + +import { IPolicySoftwareToInstall } from "interfaces/policy"; import Checkbox from "components/forms/fields/Checkbox"; +import CustomLink from "components/CustomLink"; +import TooltipWrapper from "components/TooltipWrapper"; +import { buildQueryStringFromParams } from "utilities/url"; +import paths from "router/paths"; interface IPlatformSelectorProps { baseClass?: string; @@ -13,6 +19,8 @@ interface IPlatformSelectorProps { setCheckLinux: (val: boolean) => void; setCheckChrome: (val: boolean) => void; disabled?: boolean; + installSoftware?: IPolicySoftwareToInstall; + currentTeamId?: number; } export const PlatformSelector = ({ @@ -26,6 +34,8 @@ export const PlatformSelector = ({ setCheckLinux, setCheckChrome, disabled = false, + installSoftware, + currentTeamId, }: IPlatformSelectorProps): JSX.Element => { const baseClass = "platform-selector"; @@ -33,9 +43,39 @@ export const PlatformSelector = ({ [`form-field__label--disabled`]: disabled, }); + const renderInstallSoftwareHelpText = () => { + if (!installSoftware) { + return null; + } + const softwareName = installSoftware.name; + const softwareId = installSoftware.software_title_id.toString(); + const softwareLink = `${paths.SOFTWARE_TITLE_DETAILS( + softwareId + )}?${buildQueryStringFromParams({ team_id: currentTeamId })}`; + + return ( + + will only install + on{" "} + + To see targets, select{" "} + {softwareName} > Actions > Edit. Currently, hosts + that aren't targeted show an empty (---) policy status. + + } + > + targeted hosts + + . + + ); + }; + return (
- Targets: + Target:
- To apply the profile to new hosts, you'll have to delete it and - upload a new profile. + Policy runs on all hosts with these platform(s). + {renderInstallSoftwareHelpText()}
); diff --git a/frontend/components/PlatformSelector/_styles.scss b/frontend/components/PlatformSelector/_styles.scss index edd515568764..387171815c4a 100644 --- a/frontend/components/PlatformSelector/_styles.scss +++ b/frontend/components/PlatformSelector/_styles.scss @@ -2,7 +2,7 @@ // override global form-field width: 100% width: auto; - span { + &__checkboxes { display: flex; align-items: center; gap: 12px; @@ -15,4 +15,10 @@ &__platform-checkbox-wrapper { width: auto; } + + .form-field__help-text { + display: flex; + flex-direction: column; + gap: $pad-medium; + } } diff --git a/frontend/hooks/usePlatformSelector.tsx b/frontend/hooks/usePlatformSelector.tsx index 4d7ad70f3a73..6f5e615182c9 100644 --- a/frontend/hooks/usePlatformSelector.tsx +++ b/frontend/hooks/usePlatformSelector.tsx @@ -6,6 +6,7 @@ import { QUERYABLE_PLATFORMS, QueryablePlatform, } from "interfaces/platform"; +import { IPolicySoftwareToInstall } from "interfaces/policy"; import PlatformSelector from "components/PlatformSelector"; @@ -15,12 +16,16 @@ export interface IPlatformSelector { isAnyPlatformSelected: boolean; render: () => JSX.Element; disabled?: boolean; + installSoftware?: IPolicySoftwareToInstall; + currentTeamId?: number; } const usePlatformSelector = ( platformContext: SelectedPlatformString | null | undefined, baseClass = "", - disabled = false + disabled = false, + installSoftware: IPolicySoftwareToInstall | undefined, + currentTeamId: number | undefined ): IPlatformSelector => { const [checkDarwin, setCheckDarwin] = useState(false); const [checkWindows, setCheckWindows] = useState(false); @@ -73,6 +78,8 @@ const usePlatformSelector = ( setCheckLinux={setCheckLinux} setCheckChrome={setCheckChrome} disabled={disabled} + installSoftware={installSoftware} + currentTeamId={currentTeamId} /> ); }, [checkDarwin, checkWindows, checkLinux, checkChrome, disabled]); diff --git a/frontend/interfaces/software.ts b/frontend/interfaces/software.ts index 5f8797f27fb3..99470e4585df 100644 --- a/frontend/interfaces/software.ts +++ b/frontend/interfaces/software.ts @@ -82,7 +82,7 @@ export interface ISoftwarePackage { pending_uninstall: number; failed_uninstall: number; }; - automatic_install_policies?: ISoftwarePackagePolicy[]; + automatic_install_policies?: ISoftwarePackagePolicy[] | null; install_during_setup?: boolean; labels_include_any: ILabelSoftwareTitle[] | null; labels_exclude_any: ILabelSoftwareTitle[] | null; diff --git a/frontend/pages/DashboardPage/cards/ActivityFeed/components/SoftwareDetailsModal/_styles.scss b/frontend/pages/DashboardPage/cards/ActivityFeed/components/SoftwareDetailsModal/_styles.scss index 023d021a9869..6c4db7f6d6e3 100644 --- a/frontend/pages/DashboardPage/cards/ActivityFeed/components/SoftwareDetailsModal/_styles.scss +++ b/frontend/pages/DashboardPage/cards/ActivityFeed/components/SoftwareDetailsModal/_styles.scss @@ -1,7 +1,9 @@ .software-details-modal { &__modal-content { display: flex; - gap: $pad-xxlarge; + column-gap: $pad-xxlarge; + row-gap: $pad-xlarge; + flex-wrap: wrap; } .react-tooltip { diff --git a/frontend/pages/ManageControlsPage/OSSettings/cards/CustomSettings/components/ProfileUploader/helpers.tsx b/frontend/pages/ManageControlsPage/OSSettings/cards/CustomSettings/components/ProfileUploader/helpers.tsx index f33d5fc08f10..4a3defbf1cf7 100644 --- a/frontend/pages/ManageControlsPage/OSSettings/cards/CustomSettings/components/ProfileUploader/helpers.tsx +++ b/frontend/pages/ManageControlsPage/OSSettings/cards/CustomSettings/components/ProfileUploader/helpers.tsx @@ -1,6 +1,7 @@ import React from "react"; import { AxiosResponse } from "axios"; import { IApiError } from "interfaces/errors"; +import { generateSecretErrMsg } from "pages/SoftwarePage/helpers"; export const parseFile = async (file: File): Promise<[string, string]> => { // get the file name and extension @@ -60,7 +61,7 @@ export const getErrorMessage = (err: AxiosResponse) => { } if (apiReason.includes("Secret variable")) { - return apiReason.replace("missing from database", "doesn't exist"); + return generateSecretErrMsg(err); } return apiReason || DEFAULT_ERROR_MESSAGE; diff --git a/frontend/pages/ManageControlsPage/OSUpdates/components/CurrentVersionSection/CurrentVersionSection.tsx b/frontend/pages/ManageControlsPage/OSUpdates/components/CurrentVersionSection/CurrentVersionSection.tsx index 7e1cc7f085d5..e7a4f251518e 100644 --- a/frontend/pages/ManageControlsPage/OSUpdates/components/CurrentVersionSection/CurrentVersionSection.tsx +++ b/frontend/pages/ManageControlsPage/OSUpdates/components/CurrentVersionSection/CurrentVersionSection.tsx @@ -135,7 +135,7 @@ const CurrentVersionSection = ({
{renderTable()} diff --git a/frontend/pages/ManageControlsPage/Scripts/components/ScriptUploader/helpers.ts b/frontend/pages/ManageControlsPage/Scripts/components/ScriptUploader/helpers.ts index f341ec38b953..016efb8b6e08 100644 --- a/frontend/pages/ManageControlsPage/Scripts/components/ScriptUploader/helpers.ts +++ b/frontend/pages/ManageControlsPage/Scripts/components/ScriptUploader/helpers.ts @@ -1,4 +1,5 @@ import { getErrorReason } from "interfaces/errors"; +import { generateSecretErrMsg } from "pages/SoftwarePage/helpers"; const DEFAULT_ERROR_MESSAGE = "Couldn't upload. Please try again."; @@ -13,7 +14,7 @@ export const getErrorMessage = (err: unknown) => { ) { return "Couldn't upload. The file should be .sh or .ps1 file."; } else if (apiErrMessage.includes("Secret variable")) { - return apiErrMessage.replace("missing from database", "doesn't exist"); + return generateSecretErrMsg(err); } return apiErrMessage || DEFAULT_ERROR_MESSAGE; diff --git a/frontend/pages/SoftwarePage/SoftwareAddPage/SoftwareCustomPackage/helpers.tsx b/frontend/pages/SoftwarePage/SoftwareAddPage/SoftwareCustomPackage/helpers.tsx index 99a09e229bcc..06e3c2e23fdc 100644 --- a/frontend/pages/SoftwarePage/SoftwareAddPage/SoftwareCustomPackage/helpers.tsx +++ b/frontend/pages/SoftwarePage/SoftwareAddPage/SoftwareCustomPackage/helpers.tsx @@ -6,6 +6,8 @@ import { LEARN_MORE_ABOUT_BASE_LINK } from "utilities/constants"; import CustomLink from "components/CustomLink"; +import { generateSecretErrMsg } from "pages/SoftwarePage/helpers"; + const DEFAULT_ERROR_MESSAGE = "Couldn't add. Please try again."; // eslint-disable-next-line import/prefer-default-export @@ -30,7 +32,7 @@ export const getErrorMessage = (err: unknown) => { ); } else if (reason.includes("Secret variable")) { - return reason.replace("missing from database", "doesn't exist"); + return generateSecretErrMsg(err); } else if (reason.includes("Unable to extract necessary metadata")) { return ( <> diff --git a/frontend/pages/SoftwarePage/SoftwareAddPage/SoftwareFleetMaintained/FleetMaintainedAppDetailsPage/FleetAppDetailsForm/FleetAppDetailsForm.tsx b/frontend/pages/SoftwarePage/SoftwareAddPage/SoftwareFleetMaintained/FleetMaintainedAppDetailsPage/FleetAppDetailsForm/FleetAppDetailsForm.tsx index d70e229e3646..74d5943b305d 100644 --- a/frontend/pages/SoftwarePage/SoftwareAddPage/SoftwareFleetMaintained/FleetMaintainedAppDetailsPage/FleetAppDetailsForm/FleetAppDetailsForm.tsx +++ b/frontend/pages/SoftwarePage/SoftwareAddPage/SoftwareFleetMaintained/FleetMaintainedAppDetailsPage/FleetAppDetailsForm/FleetAppDetailsForm.tsx @@ -124,7 +124,7 @@ export const InstallTypeSection = ({ color="yellow" cta={ diff --git a/frontend/pages/SoftwarePage/SoftwareAddPage/SoftwareFleetMaintained/FleetMaintainedAppDetailsPage/FleetMaintainedAppDetailsPage.tsx b/frontend/pages/SoftwarePage/SoftwareAddPage/SoftwareFleetMaintained/FleetMaintainedAppDetailsPage/FleetMaintainedAppDetailsPage.tsx index d47ccd9ef045..8516ff248378 100644 --- a/frontend/pages/SoftwarePage/SoftwareAddPage/SoftwareFleetMaintained/FleetMaintainedAppDetailsPage/FleetMaintainedAppDetailsPage.tsx +++ b/frontend/pages/SoftwarePage/SoftwareAddPage/SoftwareFleetMaintained/FleetMaintainedAppDetailsPage/FleetMaintainedAppDetailsPage.tsx @@ -12,7 +12,6 @@ import labelsAPI, { getCustomLabels } from "services/entities/labels"; import { QueryContext } from "context/query"; import { AppContext } from "context/app"; import { NotificationContext } from "context/notification"; -import { getErrorReason } from "interfaces/errors"; import { Platform, PLATFORM_DISPLAY_NAMES } from "interfaces/platform"; import { ILabelSummary } from "interfaces/label"; import useToggleSidePanel from "hooks/useToggleSidePanel"; @@ -33,6 +32,7 @@ import { IFleetMaintainedAppFormData } from "./FleetAppDetailsForm/FleetAppDetai import AddFleetAppSoftwareModal from "./AddFleetAppSoftwareModal"; import { + getErrorMessage, getFleetAppPolicyDescription, getFleetAppPolicyName, getFleetAppPolicyQuery, @@ -192,7 +192,7 @@ const FleetMaintainedAppDetailsPage = ({ } catch (error) { // quick exit if there was an error adding the software. Skip the policy // creation. - renderFlash("error", getErrorReason(error)); + renderFlash("error", getErrorMessage(error)); setShowAddFleetAppSoftwareModal(false); return; } diff --git a/frontend/pages/SoftwarePage/SoftwareAddPage/SoftwareFleetMaintained/FleetMaintainedAppDetailsPage/helpers.tsx b/frontend/pages/SoftwarePage/SoftwareAddPage/SoftwareFleetMaintained/FleetMaintainedAppDetailsPage/helpers.tsx index 3ccdf8df4c3c..3a1f93411e6d 100644 --- a/frontend/pages/SoftwarePage/SoftwareAddPage/SoftwareFleetMaintained/FleetMaintainedAppDetailsPage/helpers.tsx +++ b/frontend/pages/SoftwarePage/SoftwareAddPage/SoftwareFleetMaintained/FleetMaintainedAppDetailsPage/helpers.tsx @@ -1,3 +1,7 @@ +import { getErrorReason } from "interfaces/errors"; + +import { generateSecretErrMsg } from "pages/SoftwarePage/helpers"; + import fleetAppData from "../../../../../../server/mdm/maintainedapps/apps.json"; const NameToIdentifierMap: Record = { @@ -40,3 +44,13 @@ export const getFleetAppPolicyDescription = (appName: string) => { export const getFleetAppPolicyQuery = (name: string) => { return getFleetAppData(name)?.automatic_policy_query; }; + +export const getErrorMessage = (err: unknown) => { + const reason = getErrorReason(err); + + if (reason.includes("Secret variable")) { + return generateSecretErrMsg(err); + } + + return reason; +}; diff --git a/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/ConfirmSaveChangesModal/ConfirmSaveChangesModal.tsx b/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/ConfirmSaveChangesModal/ConfirmSaveChangesModal.tsx index d164f8dd8b89..ecc4bc8f8832 100644 --- a/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/ConfirmSaveChangesModal/ConfirmSaveChangesModal.tsx +++ b/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/ConfirmSaveChangesModal/ConfirmSaveChangesModal.tsx @@ -3,8 +3,6 @@ import React from "react"; import Button from "components/buttons/Button"; import Modal from "components/Modal"; -import { IPackageFormData } from "pages/SoftwarePage/components/PackageForm/PackageForm"; - const baseClass = "save-changes-modal"; export interface IConfirmSaveChangesModalProps { @@ -38,7 +36,7 @@ const ConfirmSaveChangesModal = ({

{warningText}

Installs or uninstalls currently running on a host will still - complete, but results won’t appear in Fleet. + complete, but results won't appear in Fleet.

You cannot undo this action.

diff --git a/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/EditSoftwareModal/EditSoftwareModal.tsx b/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/EditSoftwareModal/EditSoftwareModal.tsx index 98f2ee9bc69e..a7c69196906d 100644 --- a/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/EditSoftwareModal/EditSoftwareModal.tsx +++ b/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/EditSoftwareModal/EditSoftwareModal.tsx @@ -24,6 +24,7 @@ import { IPackageFormData } from "pages/SoftwarePage/components/PackageForm/Pack import { generateSelectedLabels, getCustomTarget, + getInstallType, getTargetType, } from "pages/SoftwarePage/components/PackageForm/helpers"; @@ -70,11 +71,7 @@ const EditSoftwareModal = ({ }); const [uploadProgress, setUploadProgress] = useState(0); - const { - data: labels, - isLoading: isLoadingLabels, - isError: isErrorLabels, - } = useQuery( + const { data: labels } = useQuery( ["custom_labels"], () => labelsAPI.summary().then((res) => getCustomLabels(res.labels)), { @@ -178,6 +175,7 @@ const EditSoftwareModal = ({ postInstallScript: software.post_install_script || "", uninstallScript: software.uninstall_script || "", selfService: software.self_service || false, + installType: getInstallType(software), targetType: getTargetType(software), customTarget: getCustomTarget(software), labelTargets: generateSelectedLabels(software), diff --git a/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/EditSoftwareModal/helpers.tsx b/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/EditSoftwareModal/helpers.tsx index 9b4151003cfe..df399a8c5c34 100644 --- a/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/EditSoftwareModal/helpers.tsx +++ b/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/EditSoftwareModal/helpers.tsx @@ -6,6 +6,7 @@ import { ISoftwarePackage } from "interfaces/software"; import CustomLink from "components/CustomLink"; import { LEARN_MORE_ABOUT_BASE_LINK } from "utilities/constants"; +import { generateSecretErrMsg } from "pages/SoftwarePage/helpers"; const DEFAULT_ERROR_MESSAGE = "Couldn't edit software. Please try again."; @@ -36,9 +37,7 @@ export const getErrorMessage = (err: unknown, software: ISoftwarePackage) => { ); } else if (reason.includes("Secret variable")) { - return reason - .replace("missing from database", "doesn't exist") - .replace("Couldn't add", "Couldn't edit"); + return generateSecretErrMsg(err).replace("Couldn't add", "Couldn't edit"); } return reason || DEFAULT_ERROR_MESSAGE; diff --git a/frontend/pages/SoftwarePage/components/PackageForm/PackageForm.tsx b/frontend/pages/SoftwarePage/components/PackageForm/PackageForm.tsx index 8da22a54071f..a623cc7884c6 100644 --- a/frontend/pages/SoftwarePage/components/PackageForm/PackageForm.tsx +++ b/frontend/pages/SoftwarePage/components/PackageForm/PackageForm.tsx @@ -241,12 +241,14 @@ const PackageForm = ({ formData.software ? getFileDetails(formData.software) : undefined } /> - + {!isEditingSoftware && ( + + )} { + return softwarePackage.automatic_install_policies ? "automatic" : "manual"; +}; + export const getTargetType = (softwarePackage: ISoftwarePackage) => { if (!softwarePackage) return "All hosts"; diff --git a/frontend/pages/SoftwarePage/helpers.ts b/frontend/pages/SoftwarePage/helpers.ts new file mode 100644 index 000000000000..a323982309b5 --- /dev/null +++ b/frontend/pages/SoftwarePage/helpers.ts @@ -0,0 +1,43 @@ +import { getErrorReason } from "interfaces/errors"; + +/** + * helper function to generate error message for secret variables based + * on the error reason. + */ +// eslint-disable-next-line import/prefer-default-export +export const generateSecretErrMsg = (err: unknown) => { + const reason = getErrorReason(err); + + let errorType = ""; + if (getErrorReason(err, { nameEquals: "install script" })) { + errorType = "install script"; + } else if (getErrorReason(err, { nameEquals: "post-install script" })) { + errorType = "post-install script"; + } else if (getErrorReason(err, { nameEquals: "uninstall script" })) { + errorType = "uninstall script"; + } else if (getErrorReason(err, { nameEquals: "profile" })) { + errorType = "profile"; + } + + if (errorType === "profile") { + // for profiles we can get two different error messages. One contains a colon + // and the other doesn't. We need to handle both cases. + const message = reason.split(":").pop() ?? ""; + + return message + .replace(/Secret variables?/i, "Variable") + .replace("missing from database", "doesn't exist."); + } + + // all other specific error types + if (errorType) { + return reason + .replace(/Secret variables?/i, `Variable used in ${errorType} `) + .replace("missing from database", "doesn't exist."); + } + + // no spcial error type. return generic secret error message + return reason + .replace(/Secret variables?/i, "Variable") + .replace("missing from database", "doesn't exist."); +}; diff --git a/frontend/pages/admin/OrgSettingsPage/_styles.scss b/frontend/pages/admin/OrgSettingsPage/_styles.scss index 9919e5865f96..10d7a76b4af3 100644 --- a/frontend/pages/admin/OrgSettingsPage/_styles.scss +++ b/frontend/pages/admin/OrgSettingsPage/_styles.scss @@ -58,18 +58,6 @@ em { font-style: normal; } - - &--configured { - em { - color: $ui-success; - } - } - - &--notconfigured { - em { - color: $ui-error; - } - } } } diff --git a/frontend/pages/admin/OrgSettingsPage/cards/Smtp/Smtp.tsx b/frontend/pages/admin/OrgSettingsPage/cards/Smtp/Smtp.tsx index d1f6160a5b1c..eaef7914de9d 100644 --- a/frontend/pages/admin/OrgSettingsPage/cards/Smtp/Smtp.tsx +++ b/frontend/pages/admin/OrgSettingsPage/cards/Smtp/Smtp.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect, useContext } from "react"; +import React, { useState, useContext } from "react"; import { AppContext } from "context/app"; @@ -43,6 +43,54 @@ interface ISmtpConfigFormErrors { password?: string | null; } +const validateFormData = (newData: ISmtpConfigFormData) => { + const errors: ISmtpConfigFormErrors = {}; + + const { + enableSMTP, + smtpSenderAddress, + smtpServer, + smtpPort, + smtpAuthenticationType, + smtpUsername, + smtpPassword, + } = newData; + + if (enableSMTP) { + if (!smtpSenderAddress) { + errors.sender_address = "SMTP sender address must be present"; + } else if (!validEmail(smtpSenderAddress)) { + errors.sender_address = `${smtpSenderAddress} is not a valid email`; + } + + if (!smtpServer) { + errors.server = "SMTP server must be present"; + } + if (!smtpPort) { + errors.server = "SMTP server port must be present"; + errors.server_port = "Port"; + } + if (!smtpServer && !smtpPort) { + errors.server = "SMTP server and server port must be present"; + errors.server_port = "Port"; + } + if (smtpAuthenticationType === "authtype_username_password") { + if (smtpUsername === "") { + errors.user_name = "SMTP username must be present"; + } + if (smtpPassword === "") { + errors.password = "SMTP password must be present"; + } + } + } else if (smtpSenderAddress && !validEmail(smtpSenderAddress)) { + // validations for valid submissions even when smtp not enabled, i.e., updating what will be + // used once it IS enabled + errors.sender_address = `${smtpSenderAddress} is not a valid email`; + } + + return errors; +}; + const baseClass = "app-config-form"; const Smtp = ({ @@ -82,50 +130,35 @@ const Smtp = ({ const sesConfigured = appConfig.email?.backend === "ses" || false; const onInputChange = ({ name, value }: IFormField) => { - setFormData({ ...formData, [name]: value }); - }; - - const validateForm = () => { - const errors: ISmtpConfigFormErrors = {}; - - if (enableSMTP) { - if (!smtpSenderAddress) { - errors.sender_address = "SMTP sender address must be present"; - } else if (!validEmail(smtpSenderAddress)) { - errors.sender_address = `${smtpSenderAddress} is not a valid email`; - } - - if (!smtpServer) { - errors.server = "SMTP server must be present"; - } - if (!smtpPort) { - errors.server = "SMTP server port must be present"; - errors.server_port = "Port"; + const newFormData = { ...formData, [name]: value }; + setFormData(newFormData); + const newErrs = validateFormData(newFormData); + // only set errors that are updates of existing errors + // new errors are only set onBlur or submit + const errsToSet: Record = {}; + Object.keys(formErrors).forEach((k) => { + // @ts-ignore + if (newErrs[k]) { + // @ts-ignore + errsToSet[k] = newErrs[k]; } - if (!smtpServer && !smtpPort) { - errors.server = "SMTP server and server port must be present"; - errors.server_port = "Port"; - } - if (smtpAuthenticationType === "authtype_username_password") { - if (smtpUsername === "") { - errors.user_name = "SMTP username must be present"; - } - if (smtpPassword === "") { - errors.password = "SMTP password must be present"; - } - } - } - - setFormErrors(errors); + }); + setFormErrors(errsToSet); }; - useEffect(() => { - validateForm(); - }, [smtpAuthenticationType]); + const onInputBlur = () => { + setFormErrors(validateFormData(formData)); + }; const onFormSubmit = (evt: React.MouseEvent) => { evt.preventDefault(); + const errs = validateFormData(formData); + if (Object.keys(errs).length > 0) { + setFormErrors(errs); + return; + } + // Formatting of API not UI const formDataToSubmit = { smtp_settings: { @@ -157,7 +190,7 @@ const Smtp = ({ name="smtpUsername" value={smtpUsername} parseTarget - onBlur={validateForm} + onBlur={onInputBlur} error={formErrors.user_name} blockAutoComplete /> @@ -168,7 +201,7 @@ const Smtp = ({ name="smtpPassword" value={smtpPassword} parseTarget - onBlur={validateForm} + onBlur={onInputBlur} error={formErrors.password} blockAutoComplete /> @@ -177,6 +210,7 @@ const Smtp = ({ options={authMethodOptions} placeholder="" onChange={onInputChange} + onBlur={onInputBlur} name="smtpAuthenticationMethod" value={smtpAuthenticationMethod} parseTarget @@ -205,6 +239,7 @@ const Smtp = ({
@@ -228,7 +263,7 @@ const Smtp = ({ name="smtpServer" value={smtpServer} parseTarget - onBlur={validateForm} + onBlur={onInputBlur} error={formErrors.server} tooltip="The hostname / private IP address and corresponding port of your organization's SMTP server." /> @@ -239,12 +274,13 @@ const Smtp = ({ name="smtpPort" value={smtpPort} parseTarget - onBlur={validateForm} + onBlur={onInputBlur} error={formErrors.server_port} />
- - - {appConfig.smtp_settings?.configured - ? "CONFIGURED" - : "NOT CONFIGURED"} - - - ) : ( - <> - ) - } - /> + {sesConfigured ? renderSesEnabled() : renderSmtpForm()}
diff --git a/frontend/pages/hosts/ManageHostsPage/components/DeleteLabelModal/DeleteLabelModal.tsx b/frontend/pages/hosts/ManageHostsPage/components/DeleteLabelModal/DeleteLabelModal.tsx index 8780026f1d1d..7bd4f7753186 100644 --- a/frontend/pages/hosts/ManageHostsPage/components/DeleteLabelModal/DeleteLabelModal.tsx +++ b/frontend/pages/hosts/ManageHostsPage/components/DeleteLabelModal/DeleteLabelModal.tsx @@ -26,11 +26,13 @@ const DeleteLabelModal = ({ <>

If a configuration profile uses this label as a custom target, the - profile will break: it won't be applied to new hosts. + profile will break. After deleting the label, remove broken profiles + and upload new profiles in their place.

- To apply the profile to new hosts, you'll have to delete it and - upload a new profile. + If software uses this label as a custom target, the label will not be + able to be deleted. Please remove the label from the software target + first before deleting.