b1ecaefedc1a103b5aa2c419d1428eefe279970a
4942
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
b1ecaefedc |
Fix cond access bypass activity on unrelated app config saves
Fixes #43609 and #43566 Fixed bug were toggling GitOps mode was creating a spurious update_conditional_access_bypass activity whenever Okta conditional access was already configured with bypass_disabled=true. |
||
|
|
93e2025e5f |
Fixed flaky test TestQueries/DeleteMany (#39618)
Fixes #39618 Fixed flaky test TestQueries/DeleteMany |
||
|
|
038d4458cc |
Fix homebrew package matching incorrect CPE (#45186)
**Related issue:** Resolves #35195 |
||
|
|
683a66b4d1 |
Recovery Key can be viewed after team transfer if still present (#45280)
**Related issue:** Resolves #44459 ## Summary Fixed an issue where the recovery lock password for a macOS host could become unretrievable via the UI and API after the host was transferred to a team with recovery lock disabled, even though the password was still stored in the database. ## Root causes Three bugs combined to produce the symptom: - **Frontend visibility**: `canShowRecoveryLockPassword` gated the "Show Recovery Lock password" action on the current team's `enable_recovery_lock_password` setting and ignored the `recoveryLockPasswordAvailable` signal, so the UI option vanished whenever the host's new team had the feature off. - **API 404 on view**: `MarkRecoveryLockPasswordViewed` returned a `notFound` error when its UPDATE matched zero rows. This happened as soon as the `ClaimHostsForRecoveryLockClear` cron flipped the password row's `operation_type` from `install` to `remove` — causing `GET /hosts/:id/recovery_lock_password` to 404 even though the password had already been successfully retrieved and decrypted moments earlier in the same request. - **Stale rotation deadline**: `ClaimHostsForRecoveryLockClear` left the row's `auto_rotate_at` untouched when flipping to `remove`, so subsequent reads still surfaced the pre-transfer view-deadline and the UI rendered a rotation banner promising an auto-rotation that the cron (filtered on `operation_type='install'`) would never honor. ## Fix - **Frontend**: updated `canShowRecoveryLockPassword` to also show the action when a password is available, regardless of the team setting. - **API**: changed `MarkRecoveryLockPasswordViewed` to return a zero `time.Time` with no error when no install-state row exists. The service skips the `AutoRotateAt` assignment in that case and explicitly nulls any stale value loaded from the DB, so the response's `auto_rotate_at` is omitted. - **Data hygiene**: updated `ClaimHostsForRecoveryLockClear` to also set `auto_rotate_at = NULL` when flipping a row to `remove`, since the rotation deadline is meaningful only for install-state rows. - [x] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. See [Changes files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files) for more information. - [x] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements), JS inline code is prevented especially for url redirects, and untrusted data interpolated into shell scripts/commands is validated against shell metacharacters. |
||
|
|
0c45575b82 |
Custom org logo fixes: delete for external URLs + gitops switch from path to URL (#45236)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #45230, Resolves #45213 # Checklist for submitter - [ ] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. See [Changes files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files) for more information. ## Testing - [x] Added/updated automated tests - [x] QA'd all new/changed functionality manually #### For 45213 Did a gitops run to apply external URLs as logos: <img width="395" height="122" alt="Screenshot 2026-05-12 at 10 52 25 AM" src="https://github.com/user-attachments/assets/a1fea9ce-7a3d-419b-8c56-68568dcc704e" /> Command: `./build/fleetctl gitops -f /Users/nico/dev/gitops-output-test/default.yml` (**gitops-output-test** is where I usually have my gitops outputs). Then I deleted both from the UI: https://github.com/user-attachments/assets/03899795-7cda-485d-b87e-25f829b928b7 #### For 45230 - Uploaded logos using **org_logo_path_dark_mode** and **org_logo_path_light_mode** in the first GitOps run. - In the second GitOps run, set **org_logo_url_dark_mode: "https://placehold.co/100"** and **org_logo_url_light_mode: "https://placehold.co/100"**. https://github.com/user-attachments/assets/4dfd0440-9a17-44e1-aa7d-395afd9c7d7a For unreleased bug fixes in a release candidate, one of: - [x] Confirmed that the fix is not expected to adversely impact load test results <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Organization logo deletion is idempotent and no longer errors on repeated deletes. * Orphaned hosted logo blobs are cleaned up after config changes; deletion or activity-emission failures are logged and do not abort requests. * Conflicting/contradictory URL updates now produce validation errors. * **Improvements** * GitOps/logo sync strips gitops-only path keys and only performs uploads in non-dry-run flows. * Logo URL handling simplified: deprecated alias fields are mirrored and path keys are stripped to avoid unintended deletions. * **Tests** * Added lifecycle tests for upload/delete, activity emissions, and in-memory PNG generation. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45236) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
4390d57f74 |
Fix POST /queries returning 500 on JSON null name/query (#43031)
Fixes #43031 Make sure we reject nil Name or Query in NewQuery with a BadRequestError before Verify(). |
||
|
|
8228f50511 |
Reject null name on POST /packs (#43032)
Fixes #43032 Added a nil-check in NewPack so a missing/null name returns the same BadRequestError as an empty-string name. |
||
|
|
24e5baf21f |
Only collect data about tracked CVEs (#45247)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #45163 # Details Limits CVE data collection to only those CVEs which we report on in the chart. This is a performance optimization necessitated by the large amount of data that bigger fleets may generate. The plan is to implement a data compression strategy so that we can go back to collecting full CVE data soon. # Checklist for submitter If some of the following don't apply, delete the relevant line. - [ ] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. See [Changes files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files) for more information. n/a, unreleased - [X] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements), JS inline code is prevented especially for url redirects, and untrusted data interpolated into shell scripts/commands is validated against shell metacharacters. ## Testing - [X] Added/updated automated tests - [X] QA'd all new/changed functionality manually - [X] Ran some collection jobs and verified that only tracked CVEs were represented in "open" rows. - [ ] Ran load test w/ new code For unreleased bug fixes in a release candidate, one of: - [ ] Confirmed that the fix is not expected to adversely impact load test results should improve results! - [X] Alerted the release DRI if additional load testing is needed <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Enhancements** * CVE vulnerability tracking is now scoped to a curated set of critical vulnerabilities, improving the relevance of security impact data displayed across your systems. [](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45247) <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
7e3dea60b2 |
Fix for ONC profiles losing their details when adding another profile (#45299)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #42405 Unreleased bug fix. # Checklist for submitter ## Testing - [x] Added/updated automated tests - [x] QA'd all new/changed functionality manually <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Android MDM profile detail messages (e.g., certificate status) are preserved when adding additional profiles or marking profiles pending, preventing loss of important status information. * **Tests** * Added an integration test verifying ONC/certificate detail is retained when additional Android MDM profiles are uploaded for the same team. [](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45299) <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
049f29ee3f |
Apply labels before consumers in GitOps (#45194)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #44046 # Details Updates GitOps to ensure that team labels are created before any consumers (e.g. profiles, policies, software) that might use the labels are applied. It does this by adding a new `afterTeamApply` callback option to `ApplyGroup` that is called after team config is applied -- this is when team labels are now created, instead of after `ApplyGroup` runs. # Checklist for submitter If some of the following don't apply, delete the relevant line. - [X] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. See [Changes files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files) for more information. ## Testing - [X] Added/updated automated tests - [ ] QA'd all new/changed functionality manually <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Fixed GitOps deployments failing when a label and a profile that references it are created in the same run. * Ensures the correct apply ordering so dry-run/log output shows label application before profile application. * **Tests** * Added a regression test validating label → profile apply ordering to prevent future regressions. [](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45194) <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
ca648e9c04 |
EUA (no Apple MDM) UI fix (#45212)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #44801 Fixed remaining issue setting end user authentication in the UI. The root cause was that the frontend was always sending `enable_managed_local_account : false` even when macOS MDM was disabled. Fix: <img width="756" height="363" alt="image" src="https://github.com/user-attachments/assets/5f88797d-c5c3-4c03-9048-c8ee2981c374" /> # Checklist for submitter ## Testing - [x] Added/updated automated tests - [x] QA'd all new/changed functionality manually For unreleased bug fixes in a release candidate, one of: - [x] Confirmed that the fix is not expected to adversely impact load test results <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Automatic syncing of "Lock end user info" when toggling End User Authentication now only runs when Apple MDM is enabled and configured (with an exception when EUA is being disabled to preserve behavior). * Save payloads omit Apple-only fields unless Apple MDM is configured. * **UI** * "Lock end user info" checkbox shows an Apple MDM–gated tooltip and is disabled when Apple MDM is not configured. * **Tests** * Added coverage for Apple MDM–gated behaviors and saved-payload variations. [](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45212) <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
393007ede1 |
First move of server/service to server/service/svctest to prevent testing code in Fleet's production binary (#45221)
**Related issue:** Resolves #45220 (one of many small PRs) ## Testing - [x] QA'd all new/changed functionality manually. (Ran basic smoke testing.) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Tests** * Added a consolidated test utilities package to boot full test servers, seed users, retrieve auth tokens, and provide common mocks for integration/service tests. * Updated integration and service tests to use the new helpers for more consistent, reliable test setup and wiring. * **Chores** * Centralized and reorganized test configuration types and options, and standardized test wiring for clearer, maintainable test setup. [](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45221) <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
0b31e13595 |
iOS/iPadOS managed config: send-paths audit (#43968) (#44936)
Part of #38790. Stacked on top of #44935. Closes #43968. The two activate functions are the only `InstallApplication` command builders, so fetching configuration and substituting `$FLEET_VAR_*` inside them covers every enqueue path (manual, self-service, policy auto-install, scheduled auto-update, setup experience, retry, admin reinstall) by construction. Documents this invariant on each function. Adds integration tests asserting an iOS install enqueues `<key>Configuration>` with the host UUID substituted in, and macOS installs omit the field. --------- Co-authored-by: jkatz01 <yehonatankatz@gmail.com> |
||
|
|
88e4a88f95 |
iOS/iPadOS managed config: Fleet variable expansion (#43967) (#44935)
Part of #38790. Stacked on top of #44934. Closes #43967. Adds `SubstituteFleetVarsInAppConfig` in `server/mdm/apple`, called from `nanoEnqueueVPPInstall` and `activateNextInHouseAppInstallActivity` right before the `InstallApplication` plist is built. Reuses `profiles.ReplaceFleetVariableInXML` (XML-escapes substituted values) and `profiles.ReplaceHostEndUserIDPVariables` for IDP fields. Supports the full `FleetVarsSupportedInAppleAppConfig` allow-list: `HOST_UUID`, `HOST_HARDWARE_SERIAL`, `HOST_PLATFORM`, `HOST_END_USER_EMAIL_IDP`, `HOST_END_USER_IDP_USERNAME` / `_LOCAL_PART` / `_GROUPS` / `_DEPARTMENT` / `_FULLNAME`. Returns `ErrUnresolvableAppConfigVar` when the host can't supply a referenced variable (e.g. end-user IDP not enrolled) so the caller can fail the install rather than send an empty value to the device. Pulls `hardware_serial` onto the host SELECT so `HOST_HARDWARE_SERIAL` is available without a second round-trip. --------- Co-authored-by: jkatz01 <yehonatankatz@gmail.com> |
||
|
|
f4157899d1 |
iOS/iPadOS managed config: Configuration dict injection (#43966) (#44934)
Part of #38790. Stacked on top of #44933. Closes #43966. The `InstallApplication` MDM command for VPP and in-house (`.ipa`) apps was assembled inline in SQL via `CONCAT`, which can't carry per-(adam_id, team_id, platform) configuration. Move the assembly into Go: new `BuildInstallApplicationCommand` helper in `server/mdm/apple`, plus refactored `nanoEnqueueVPPInstall` and `activateNextInHouseAppInstallActivity` to SELECT pending tuples, bulk-fetch configurations, build per-host plist bytes, and batch-INSERT into `nano_commands`. For iOS / iPadOS, the `Configuration` dict is inlined when stored configuration is present. macOS VPP installs always drop the field regardless of input. Empty / absent configuration omits the `<key>Configuration>` entry — Apple treats this as "clear any managed config for this app on next apply." `$FLEET_VAR_*` tokens in the configuration are passed through unsubstituted in this PR; per-host substitution comes in #43967. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Enhanced Apple app installation handling with improved command generation and configuration management for VPP and in-house app deployments. * **Tests** * Added comprehensive test coverage for app installation command generation. [](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/44934) <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: jkatz01 <yehonatankatz@gmail.com> |
||
|
|
55636b3ef6 |
iOS/iPadOS managed config: GitOps (#43969) (#44933)
Part of #38790. Stacked on top of #44932. Closes #43969. `fleetctl gitops` reads `configuration.path` for iOS / iPadOS VPP apps and in-house `.ipa` apps, validates the file via `fleet.ValidateAppleAppConfiguration`, and stores the bytes through the service layer. `fleetctl generate-gitops` emits `configuration.path` for apps that have a stored configuration, writing the XML to `lib/<team>/software/<app-slug>-config.xml`. Apps without configuration omit the block entirely. Round-trip integration tests (`cmd/fleetctl/integrationtest/gitops/software_test.go`) cover apply + generate for both VPP and in-house, plus a negative case for invalid configuration content. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes * **New Features** * Added managed app configuration support for enterprise software deployments through GitOps * Configurations now support platform-specific formats: XML for iOS/iPadOS, JSON for Android * Configuration validation ensures compatibility and prevents invalid variable references * **Tests** * Added integration tests for configuration handling in software deployment workflows [](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/44933) <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: jkatz01 <yehonatankatz@gmail.com> |
||
|
|
1fb91ab2d5 |
Fixed flaky test (#45222)
Fixes #39552 Fixed flaky test |
||
|
|
fc907c4634 |
Rename Apple Business 'Location' to 'Organization Unit' in UI and docs (#44833)
## Summary - Renames Apple Business "Location" / "Locations" to "Organization Unit" / "Organization Units" across user-facing UI strings, documentation, and code comments - Updates the VPP table column header, modal text, error messages, audit log descriptions, YAML configuration docs, and article guides - Underlying API field names (`location` in JSON) and YAML config keys remain unchanged for backward compatibility --- Built for [Mel Pike](https://fleetdm.slack.com/archives/D0AKX7DJFCN/p1778077861693279?thread_ts=1777299502.461149&cid=D0AKX7DJFCN) by [Kilo for Slack](https://kilo.ai/slack) --------- Co-authored-by: kiloconnect[bot] <240665456+kiloconnect[bot]@users.noreply.github.com> Co-authored-by: melpike <melpike.dev@gmail.com> Co-authored-by: Copilot <copilot@github.com> Co-authored-by: melpike <79950145+melpike@users.noreply.github.com> |
||
|
|
47cc3256c1 |
iOS/iPadOS managed config: service wiring (#43965) (#44932)
Part of #38790. Stacked on top of #44931. Closes #43965. Wires managed configuration through the existing REST endpoints (`POST /api/.../app_store_apps`, `PATCH /api/.../software/titles/:id/app_store_app`, in-house `.ipa` upload / update). Validation runs at the service layer for iOS / iPadOS; macOS VPP installs silently drop the field. Wire format: a JSON-encoded string of the XML plist on POST/PATCH and on GET single-title responses (not base64). Includes `server/service/integration_apple_vpp_config_test.go` with end-to-end coverage: add / update with valid plist, allowed `$FLEET_VAR_HOST_UUID`, omit-field-no-change, **`configuration: null` → row deleted** (regression test for the clear-on-null fix in #43964), malformed XML → 422, disallowed Fleet variable → 422, and macOS silent-drop pre- / post-validation. Also drops a stray `fmt.Println("auth")` in `SoftwareTitleByID`'s authorization-failure branch. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added support for managed app configuration on iOS/iPadOS devices through VPP and in-house installers. * Configuration now validates plist format and detects disallowed Fleet variables. * **Bug Fixes** * macOS apps now correctly ignore configuration settings as expected. * **Tests** * Added comprehensive integration tests for Apple VPP and in-house installer configuration workflows. [](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/44932) <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: jkatz01 <yehonatankatz@gmail.com> Co-authored-by: Jonathan Katz <44128041+jkatz01@users.noreply.github.com> |
||
|
|
7e875eac78 | Fleet UI: return app name on success of adding android app (#44068) | ||
|
|
36de1a6792 |
iOS/iPadOS managed config: datastore (#43964) (#44931)
Part of #38790. Stacked on top of #44930. Closes #43964. Adds VPP and in-house datastore methods (`GetVPPAppConfiguration`, `BulkGetVPPAppConfigurations`, `DeleteVPPAppConfiguration`, `HasVPPAppConfigurationChanged`, plus in-house equivalents) keyed on the merged `vpp_app_configurations` and `in_house_app_configurations` tables. Wires them into `InsertVPPAppWithTeam`, `SaveInHouseAppUpdates`, and the team / app removal paths. Two follow-up bug fixes folded into this branch: 1. iPadOS in-house apps received no configuration: a single `.ipa` upload creates two `in_house_apps` rows but config was only stored against the iOS row's id, so iPadOS lookups returned NotFound. Now writes to both sibling rows on insert and propagates updates / clears via `installerIDsForInHouseAppSibling`. 2. Single-app PATCH with `"configuration": null` was inserting empty bytes instead of deleting; aligned the iOS/iPadOS branch in `InsertVPPAppWithTeam` with the batch path's `len > 0` upsert / `len == 0` delete semantics. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added support for managing in-house app configurations including storage, updates, and deletion. * Expanded VPP app configuration support for iOS/iPadOS platforms with configuration storage and change detection. * **Refactor** * Updated Android app configuration handling to improve internal data consistency and streamline configuration management workflows across all app types. [](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/44931) <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: jkatz01 <yehonatankatz@gmail.com> |
||
|
|
63f69986a7 |
Final Windows setup experience (ESP) fixes (#44740)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #43776 ESP (Enrollment Status Page) related fixes after manual QA. Note that we have an email thread with Microsoft regarding improving the UX of the ESP page/flow. # Checklist for submitter ## Testing - [x] Added/updated automated tests - [x] QA'd all new/changed functionality manually <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved Windows MDM Enrollment Status Page (ESP) handling so user-scoped provisioning nodes are created reliably during the enrollment hold phase, reducing transient provisioning failures. * On timeout paths, emit a canceled setup-experience activity for the first pending/running setup item to ensure clearer provisioning state. * **Tests** * Strengthened tests to assert precise ESP command outputs and require completion signals at both device and user scopes. [](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/44740) <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Konstantin Sykulev <konst@sykulev.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> |
||
|
|
3517ff661e |
iOS/iPadOS managed config: validator (#43963) (#44930)
Part of #38790 (iOS / iPadOS managed app configuration). Closes #43963. Adds `ValidateAppleAppConfiguration` and the `FleetVarsSupportedInAppleAppConfig` allow-list in `server/fleet/vpp.go`. Walks the decoded plist (keys + string values) so XML-entity-encoded `$FLEET_VAR_*` tokens can't slip past the disallow check, and rejects non-XML plist formats (binary, OpenStep, GNUStep) since Apple's `InstallApplication` only accepts XML. Stacked PRs (review bottom up): - #43963 validator (this PR) - 43964 datastore - 43965 service wiring - 43969 gitops - 43966 InstallApplication Configuration dict injection - 43967 Fleet variable expansion - 43968 send-paths audit <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added validation for Apple managed app configurations to allow only supported Fleet variable placeholders, reject malformed plist formats, and accept empty payloads. * **Bug Fixes** * Improved handling of app configuration payloads to ensure consistent validation and error responses across Android and iOS flows. * **Tests** * Added comprehensive tests covering plist validation, allowed/disallowed variables, and edge cases to increase reliability. [](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/44930) <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: jkatz01 <yehonatankatz@gmail.com> |
||
|
|
9a5fae6f02 |
Scope windows mdm profile removal query (#45203)
**Related issue:** Resolves #44798 # Checklist for submitter If some of the following don't apply, delete the relevant line. - [x] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. See [Changes files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files) for more information. - [x] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements), JS inline code is prevented especially for url redirects, and untrusted data interpolated into shell scripts/commands is validated against shell metacharacters. ## Testing - [x] Added/updated automated tests - [x] Where appropriate, [automated tests simulate multiple hosts and test for host isolation](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/reference/patterns-backend.md#unit-testing) (updates to one hosts's records do not affect another) - [x] QA'd all new/changed functionality manually <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Performance Improvements** * Optimized Windows MDM profile removal operations for improved performance when managing device profiles. * **Bug Fixes** * Enhanced Windows profile handling during host team transfers to ensure correct profiles are properly installed and removed based on team configuration. [](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45203) <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
46784bbb52 |
Add host activity entries for retried software installs and script runs from policy automations (#45233)
Resolves #42930 - [X] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. Ready for review, pending [this](https://fleetdm.slack.com/archives/C084F4MKYSJ/p1778593457182719) UX question. ## Testing - [X] Added/updated automated tests - [X] QA'd all new/changed functionality manually <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Host activity details are now recorded and displayed for every attempt — including queued and pending retries — of script executions and software installations triggered by policy automations. * **Tests** * Integration tests updated to assert activity creation for each failed attempt and retry flows. [](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45233) <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
0276662545 |
Fix MDM SSO callback 'missing profile' error for Android enrollment (#45046)
Closes #45024 ## Summary - Fixed the MDM SSO callback handler returning a `"missing profile: missing profile"` error when an Android device enrolls via SSO (OTA enrollment) on a Fleet instance that does **not** have Apple MDM configured. - Refactored all MDM SSO initiator magic strings (`"ota_enroll"`, `"setup_experience"`, `"account_driven_enroll"`) into named constants (`fleet.SSOInitiatorOTAEnroll`, etc.) to prevent typos and missed cases — which is the class of bug that caused this issue. ## Code walkthrough ### The bug The bug is in `ee/server/service/mdm.go` in `mdmSSOHandleCallbackAuth()`. **The flow:** 1. Android enrollment hits `/enroll?enroll_secret=xxx` → frontend calls `InitiateMDMSSO` with initiator `"ota_enroll"` (`server/service/frontend.go:248`) 2. User authenticates at the SAML IdP 3. The SSO callback arrives at `MDMSSOCallback` → calls `mdmSSOHandleCallbackAuth` 4. After successful SAML auth, the function checks early-exit conditions: - Line 1133: account-driven enrollment (`originalURL == appleMDMAccountDrivenEnrollmentUrl`) → **no match** for OTA - Line 1139: `Initiator != "setup_experience"` → **true** for `"ota_enroll"` → enters the block 5. Line 1140: calls `getAutomaticEnrollmentProfile()` → returns `nil` because **no Apple MDM is configured** 6. Line 1144–1146: `depProf == nil` → **returns `"missing profile"` error** Note that `MDMSSOCallback` (the caller) already has a guard at line 931 that correctly skips the Apple MDM verification for `/enroll?` paths: ```go if !strings.HasPrefix(originalURL, "/enroll?") && ssoRequestData.Initiator != "setup_experience" { if err := svc.VerifyMDMAppleConfigured(ctx); err != nil { ... } } ``` But `mdmSSOHandleCallbackAuth` was missing the equivalent guard — it unconditionally tried to fetch the Apple DEP profile for any non-`setup_experience` initiator. ### The fix Adds an early return for OTA enrollments (where `originalURL` starts with `/enroll?`), matching the existing pattern for account-driven enrollments right above it. OTA enrollments don't use the Apple DEP profile token. ### The refactor Replaced all raw initiator string literals across the backend with named constants defined in `server/fleet/app.go`: | Constant | Value | Used by | |---|---|---| | `fleet.SSOInitiatorOTAEnroll` | `"ota_enroll"` | `/enroll` page (Android, BYOD iPhone/iPad) | | `fleet.SSOInitiatorSetupExperience` | `"setup_experience"` | Orbit agent (macOS Setup Assistant) | | `fleet.SSOInitiatorAccountDrivenEnroll` | `"account_driven_enroll"` | Apple account-driven MDM enrollment | Constants are in `server/fleet/` (not `server/sso/`) so orbit can import them without pulling in Redis dependencies. **Files changed:** - `ee/server/service/mdm.go` — 6 string replacements (switch cases + comparisons) - `server/service/frontend.go` — 1 replacement - `orbit/cmd/orbit/orbit.go` — 1 replacement - `server/service/testing_client.go` — 1 replacement - `server/service/integration_mdm_test.go` — 1 replacement ## Local reproduction ### Setup 1. Started dev server: `build/fleet serve --dev --dev_license` 2. Infrastructure: MySQL, Redis, SimpleSAML IdP via `docker compose up` 3. Created admin user and enroll secret 4. Configured MDM SSO (`entity_id: mdm.test.com`, SimpleSAML IdP at `localhost:9080`) 5. Set `enable_end_user_authentication: true` directly in DB (API blocks this without Apple MDM — matches customer state) 6. **Did NOT configure Apple MDM** — only SSO + EUA, simulating Android-only instance ### Steps 1. `GET https://localhost:8080/enroll?enroll_secret=test_enroll_secret` → 303 redirect to SimpleSAML IdP 2. Completed SAML login programmatically (user: `sso_user`, pass: `user123#`) 3. `POST https://localhost:8080/api/v1/fleet/mdm/sso/callback` with the SAMLResponse ### Before fix ``` === CALLBACK RESULT === Status: HTTP/2 303 Location: /mdm/sso/callback?error=true === SERVER LOGS === ts=2026-05-08T16:53:49Z level=error component=http method=POST uri=/api/v1/fleet/mdm/sso/callback took=12.148708ms err="missing profile: missing profile" ``` ### After fix ``` === CALLBACK RESULT === Status: HTTP/2 303 Location: /enroll?enroll_secret=test_enroll_secret&enrollment_reference=7c67326c-...&initiator=ota_enroll&profile_token= === SERVER LOGS === ts=2026-05-08T17:27:54Z level=info component=http method=POST uri=/api/v1/fleet/mdm/sso/callback took=15.973ms ``` No errors. Successful redirect back to the enrollment page with the enrollment reference. ## Integration test Added `TestOTAEnrollSSOWithoutAppleDEPProfile` which: 1. Configures SSO and creates a team with IdP enabled 2. **Deletes all Apple DEP enrollment profiles** to simulate an Android-only instance 3. Runs the full OTA enrollment SSO flow (GET `/enroll` → SAML IdP login → callback) 4. Verifies the callback redirects to `/enroll?...` with `enrollment_reference` and `initiator=ota_enroll` (not `?error=true`) Confirmed the test **fails without the fix** (`err="missing profile: missing profile"`) and **passes with the fix**. Also added a `LoginOTAEnrollSSOUser` test helper that drives the complete OTA SSO flow starting from `GET /enroll` through SAML IdP login to the callback, using a single cookie jar. ## Test plan - [ ] Verify Android SSO enrollment works on an instance with **only** Android MDM configured (no Apple MDM) - [ ] Verify Apple DEP enrollment with SSO still works (the DEP profile path is unchanged) - [ ] Verify Apple OTA enrollment with SSO still works (also uses `/enroll?` path) - [ ] Verify account-driven enrollment with SSO still works (has its own early return) - [ ] Verify setup experience SSO still works (uses `Initiator == "setup_experience"`) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Resolved a regression where OTA enrollment via SSO could return a "missing profile" error on Android when Apple MDM is not configured; OTA SSO now redirects correctly to the enrollment flow. [](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45046) <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Magnus Jensen <magnus@fleetdm.com> |
||
|
|
2935856f37 |
validate apple payload scope conflict, and unknown variable use in dry-run (#45139)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #44456 # Checklist for submitter If some of the following don't apply, delete the relevant line. - [x] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. See [Changes files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files) for more information. - [x] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements), JS inline code is prevented especially for url redirects, and untrusted data interpolated into shell scripts/commands is validated against shell metacharacters. - [x] Timeouts are implemented and retries are limited to avoid infinite loops - [x] If paths of existing endpoints are modified without backwards compatibility, checked the frontend/CLI for any necessary changes ## Testing - [x] Added/updated automated tests - [x] QA'd all new/changed functionality manually <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Dry-run now performs Apple config profile payload scope conflict validation and reports unknown Fleet variables for all profile types before completing. * **Tests** * Added tests covering Apple config profile scope-conflict validation and dry-run/batch profile workflows to ensure conflicts are detected in both dry-run and live flows. [](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45139) <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
b0dc97006c |
Dedupe network errors so usage_statistics cron stops failing (#45142)
**Related issue:** Resolves #42613 Dedupes errors that report HTTP 408 (request timeouts). As of now, I believe this only fires for timeouts on the **/api/v1/osquery/distributed/write** endpoint. This is so that we have a unique error hash with an incrementing count, instead of thousands of entries each with count: 1, which produces a huge JSON payload when passed to https://fleetdm.com/api/v1/webhooks/receive-usage-analytics for processing. Trade-off: - Before: every occurrence got its own Redis entry so thousands of near-identical examples coexisted. - After: they collapse into one entry whose :json value still contains a representative example, but we'd only keep the last IP+Port instead of all of them. # Checklist for submitter - [x] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. See [Changes files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files) for more information. ## Testing - [x] Added/updated automated tests - [x] QA'd all new/changed functionality manually Build a ~5 MB JSON body in a temporary file: ```bash { printf '{"node_key":"'; head -c 5000000 /dev/zero | tr '\0' 'x'; printf '"}'; } > /tmp/distwrite-body.json ``` Clear out redis: ```bash docker exec fleet-redis-1 redis-cli FLUSHDB ``` Send a dummy request and throttle the upload at 100 KB/s → ~50s to send, read timeout fires at 25s. I sent this 3 times and got the "request body read error" error back after each request. ```bash curl -sk --limit-rate 100K -X POST -H 'Content-Type: application/json' --data-binary @/tmp/distwrite-body.json https://127.0.0.1:8080/api/v1/osquery/distributed/write { "error": "request body read error: i/o timeout", "uuid": "95937f50-1008-4625-9423-bc19c7be6818" } ``` Count the error keys containing "request body read error" as the value. ```bash docker exec fleet-redis-1 sh -c 'for k in $(redis-cli --scan --pattern "error:*:json"); do v=$(redis-cli GET "$k"); echo "$v" | grep -q "request body read error" && echo "$k count=$(redis-cli GET "${k%:json}:count")"; done'\ error:{Cco_JmAdBVVVJI9k0XjNNUCmG0z1IKguMQD4VDaejfc=}:json count=3 ``` Notice the single entry and count=3 (since I ran the dummy request 3 times). Running this on main outputs three entries each with count=1. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Network error deduplication for request-timeout errors now normalizes socket addresses, preventing the usage statistics cron from failing when many similar network errors accumulate. [](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45142) <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
1213e5da12 |
Fixed validation that rejected enabling end user authentication on Fleet deployments without Apple MDM configured (#45162)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #44801 Note there is a related bug: https://github.com/fleetdm/fleet/issues/45170 # Checklist for submitter If some of the following don't apply, delete the relevant line. - [x] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. ## Testing - [x] QA'd all new/changed functionality manually <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * End user authentication can now be enabled for Windows-only and Linux-only fleets without requiring macOS MDM configuration. [](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45162) <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
f5c59ae3b4 |
Fix google calendar key validation (#44556)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #42886 # Checklist for submitter If some of the following don't apply, delete the relevant line. - [X] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. See [Changes files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files) for more information. ## Testing - [X] Added/updated automated tests - [X] QA'd all new/changed functionality manually - [X] gitops run with extra keys (besides `client_email` and `private_key` in `api_key_json` fails on main, passes on this branch - [X] gitops run with missing `client_email` or `private_key` in `api_key_json` still fails gitops (including dry run) - [X] gitops run with extra keys sibling to api_key_json still fails as expected <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Corrected GitOps validation so Google Calendar API key JSON no longer rejects valid nested keys; required-field validation for the integration still enforced. * **Tests** * Added test coverage to ensure nested unknown keys are accepted while sibling-level unknown fields are reported as validation errors. [](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/44556) <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: Tim Lee <timlee@fleetdm.com> |
||
|
|
714ae967fe |
Fix: SCIM user creation 500s when host already has a SCIM mapping (#44275)
**Related issue:** Resolves #43656 ## Summary When a new SCIM user is associated to a host that was previously associated to another SCIM user (different username/email), we the host_scim_user record is upserted with the new SCIM user's ID (instead of 500ing). # Checklist for submitter - [x] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. See [Changes files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files) for more information. - [x] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements), JS inline code is prevented especially for url redirects, and untrusted data interpolated into shell scripts/commands is validated against shell metacharacters. ## Testing - [x] Added/updated automated tests - [x] QA'd all new/changed functionality manually Setup: - Host associated with a SCIM user. I first enrolled a Linux host with end user authentication enabled, and logged in with **nico+testeua@fleetdm.com**. This creates a record in the **mdm_idp_accounts** table. - Provisioned the **nico+testeua@fleetdm.com** user from Okta to Fleet by following this guide: https://fleetdm.com/guides/foreign-vitals-map-idp-users-to-hosts#step-1-create-application-in-okta. This creates records in **scim_users** and **host_scim_user** tables. <img width="705" height="269" alt="Screenshot 2026-05-11 at 10 22 33 AM" src="https://github.com/user-attachments/assets/1f1a03ee-494c-4b09-a020-fe38b73a6b0b" /> <img width="502" height="136" alt="Screenshot 2026-05-11 at 10 26 59 AM" src="https://github.com/user-attachments/assets/42cd84d7-0a43-4937-90ed-0dbb0066ff32" /> #### Before (main branch) - Changed **username** to **nico+test500main** and **email** to **nico+test500main@fleetdm.com** on the **mdm_idp_accounts** record from the setup. - Replayed the **POST /api/v1/fleet/scim/Users** request from the Setup, but modified **username** and **email** to **nico+test500main@fleetdm.com**. This reproduced the 500. <img width="1201" height="599" alt="Screenshot 2026-05-11 at 10 30 26 AM" src="https://github.com/user-attachments/assets/abd4541a-b900-4171-9cee-03c7780045a0" /> #### After Performed the same steps as above, now with **nico+test500**: Request: <img width="1235" height="708" alt="Screenshot 2026-05-11 at 10 26 42 AM" src="https://github.com/user-attachments/assets/ef0fde5e-7b2f-48af-ac4b-ed2897a4e54b" /> UI: <img width="697" height="294" alt="Screenshot 2026-05-11 at 10 27 46 AM" src="https://github.com/user-attachments/assets/2c033f1c-483c-43c5-b901-d949a24a8a5a" /> DB: **scim_users** table contains both records and **host_scim_user** mapping was updated to the new scim_user ID. <img width="795" height="159" alt="Screenshot 2026-05-11 at 10 26 53 AM" src="https://github.com/user-attachments/assets/73ecfcd7-d6be-4e47-90ea-760d5f6d6cc3" /> <img width="501" height="134" alt="Screenshot 2026-05-11 at 10 27 05 AM" src="https://github.com/user-attachments/assets/a24140f9-070f-4236-b80d-910a21504efd" /> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Fixed HTTP 500 errors on the SCIM Users endpoint when associating a user with a host that already had an existing SCIM user mapping; host mappings are now reassigned to the newly created SCIM user as needed. * **Tests** * Added a test ensuring creating a second SCIM user for the same host succeeds and does not create duplicate host–user mappings. [](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/44275) <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
4daed869ad |
Add API param linter (#44045)
Adds a linter to ensure we don't add new instances of `team` or `query`
in API params. This will be used incrementally, but this PR also adds
`nolint` directives to places that still have these terms, both to avoid
false-positives later and to help with full migration away from these
terms in in Fleet 5.
Example:
```
server/fleet/campaigns.go:51:16: json tag "team_id": uses deprecated "team"/"teams" — use "fleet"/"fleets" instead (apiparamcheck)
Team *uint `json:"team_id,omitempty"`
```
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Added a new static analyzer (apiparamcheck) to flag deprecated API
parameter names ("team/teams") and improper usages of "query/queries".
* **Chores**
* Integrated the new check into CI tooling and configuration.
* Added analyzer tests and plugin registration.
* Applied targeted lint-suppression annotations across code and tests
where legacy parameter names must remain.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
|
||
|
|
04d773f10f |
Fix get policy by id endpoint and unify access in UI (#45048)
**Related issue:** Resolves https://github.com/fleetdm/fleet/issues/44949. - [X] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. See [Changes files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files) for more information. ## Testing - [X] Added/updated automated tests - [X] QA'd all new/changed functionality manually For unreleased bug fixes in a release candidate, one of: - [X] Confirmed that the fix is not expected to adversely impact load test results. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Policy retrieval now correctly enforces team authorization, preventing unauthorized cross-team access and ensuring team policies are returned properly. * **New Features** * UI uses a unified policy access path for viewing/editing policies, improving consistency for inherited/team-scoped policies, back-navigation, and fleet-name display (All fleets / No team). * **Tests** * Added unit and integration tests covering cross-team access rules and that policy automation fields are populated when policies are returned. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
d439cb1690 |
Fix missing deleted_policy activity for auto-cleaned patch policies (#45045)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #44286 Unset `patch_software_title_id` rather than deleting the policy in `BatchSetSoftwareInstallers`, so the orphaned policy gets picked up by the `policiesToDelete` loop in `server/service/client.go:3121`. As a result, the `deleted_policy` activity is now created properly, and gitops dry/real runs also report the deletion: ``` dry run: [-] would've deleted policy macOS - 010 Editor up to date [-] would've deleted 1 policy real run: [-] deleting policy macOS - 010 Editor up to date [-] deleting 1 policy [-] deleted 1 policy ``` # Checklist for submitter If some of the following don't apply, delete the relevant line. - [x] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. See [Changes files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files) for more information. - [ ] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements), JS inline code is prevented especially for url redirects, and untrusted data interpolated into shell scripts/commands is validated against shell metacharacters. - [ ] Timeouts are implemented and retries are limited to avoid infinite loops - [ ] If paths of existing endpoints are modified without backwards compatibility, checked the frontend/CLI for any necessary changes ## Testing - [x] Added/updated automated tests - [ ] Where appropriate, [automated tests simulate multiple hosts and test for host isolation](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/reference/patterns-backend.md#unit-testing) (updates to one hosts's records do not affect another) - [x] QA'd all new/changed functionality manually <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Fixed missing deletion activity logs when patch policies are removed via GitOps so policy deletion events are now recorded. * **Behavior Changes** * Batch-updating installers now retains obsolete patch policies but clears their patch installer reference instead of deleting the policy. * **Tests** * Added integration coverage to verify deletion activities are emitted and installer batch behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
f60ce942f8 |
Make activity list end-date filter consistent (#38437)
Resolves #38437 The list activities endpoint applied an implicit `created_at <= now` cap only when `start_created_at` was set, leaving the upper bound unbounded in every other case, this was changed so that we now apply that cap unconditionally and override only when the caller passes an explicit `end_created_at` (as peer the REST docs). |
||
|
|
fadd803793 |
Don't wipe out dataset collection config when not provided in GitOps (#45049)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #45042 # Details On Dogfood, we have v4.85.0 server running but we run our GitOps with the currently published fleetctl (4.84). This mismatch caused us to disable (and therefore wipe out data for) both of our historical chart datasets. This PR patches the "update app config" code so that when in "overwrite mode" (i.e. GitOps), it checks for empty `historical_data` keys in the incoming JSON and replaces them with the default values (currently `true`, i.e. "collect the data"). Tested manually (see testing below). # Checklist for submitter If some of the following don't apply, delete the relevant line. - [ ] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. See [Changes files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files) for more information. n/a, unreleased ## Testing - [X] Added/updated automated tests - [X] Where appropriate, [automated tests simulate multiple hosts and test for host isolation](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/reference/patterns-backend.md#unit-testing) (updates to one hosts's records do not affect another) - [X] QA'd all new/changed functionality manually - [X] reproduced issue on both current fleet v4.85 and main branch servers, using fleetctl v4.84 - [X] on this branch, ran fleetctl v4.84 w/out `historical_data` in gitops and verified that charts were enabled. - [X] on branch applied to 4.85, ran fleetctl v4.84 w/out `historical_data` in gitops and verified that charts were enabled. - [X] disabled one chart in the UI, and verified that updating unrelated app config in the UI did not affect that config (PATCH still works) For unreleased bug fixes in a release candidate, one of: - [X] Confirmed that the fix is not expected to adversely impact load test results <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes * **Bug Fixes** * Fixed GitOps configuration handling for historical data settings to properly apply default values when fields are omitted by clients. This ensures that previous configuration settings are preserved correctly in overwrite mode, preventing incorrect defaults from being inadvertently persisted when managing configurations with older clients. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
0ef22939f4 |
Improve auth around osquery endpoints (#44209)
Added an optional HTTP-level pre-auth middleware (enabled using the FLEET_OSQUERY_ALLOW_BODY_AUTH_FALLBACK server config) that validates incoming osquery requests based on `Authorization: NodeKey <node_key>` header. |
||
|
|
360fa7d1cd |
Fixes flaky test (#37026)
Resolves #37026 Fixes flaky calendar cron test. |
||
|
|
ea3513a1e7 |
always assign profile to missing devices due to replica lag (#45008)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #44980 # Checklist for submitter If some of the following don't apply, delete the relevant line. - [x] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. See [Changes files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files) for more information. - [x] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements), JS inline code is prevented especially for url redirects, and untrusted data interpolated into shell scripts/commands is validated against shell metacharacters. - [x] Timeouts are implemented and retries are limited to avoid infinite loops - [x] If paths of existing endpoints are modified without backwards compatibility, checked the frontend/CLI for any necessary changes ## Testing - [x] Added/updated automated tests - [ ] QA'd all new/changed functionality manually (Not, outside of tests due to exercising replica lag is difficult) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes * **Bug Fixes** * Improved reliability of device profile assignment by ensuring all devices receive profiles consistently, even when replica lag affects device synchronization from Device Enrollment Program services. * **Tests** * Added test coverage validating device profile assignment behavior under replica lag scenarios. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
034691966f |
check push cert staleness after 5 minutes of in-memory cache time (#44919)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #44376 I opted for an in-memory cache here, as it's not a critical cache piece, we are fine with the cache being different times on different containers (just means some might rotate to the correct cert faster than 5 minutes). It's also a small piece of work, rather than pulling in redis etc. Verified that it now logs, if the cert is stale after a 5 minute in-memory cache. ``` ts=2026-05-07T11:30:08Z level=info msg="push certificate is stale after re-checking" topic=com.apple.mgmt.External.34c4a9b0-6501-4ce6-afc6-32eac6420ee7 staleToken="\x90C\xe4K\xc6a\x97\xb5?\x1b\x9a\x04'\xe7b\x8d" newHash=".fP\xc7O7\xab\xab\x9d\x92\xd5#\xe4u\xe0\xf6" ts=2026-05-07T11:30:08Z level=info component=apple-mdm-push msg="retrieved push cert" topic=com.apple.mgmt.External.34c4a9b0-6501-4ce6-afc6-32eac6420ee7 ``` # Checklist for submitter If some of the following don't apply, delete the relevant line. - [x] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. See [Changes files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files) for more information. - [x] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements), JS inline code is prevented especially for url redirects, and untrusted data interpolated into shell scripts/commands is validated against shell metacharacters. - [x] Timeouts are implemented and retries are limited to avoid infinite loops - [x] If paths of existing endpoints are modified without backwards compatibility, checked the frontend/CLI for any necessary changes ## Testing - [x] Added/updated automated tests - [x] QA'd all new/changed functionality manually <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * APNs push certificates now refresh in-memory when rotated; staleness is detected using certificate checksums with a short grace window. * **Tests** * Added tests for certificate retrieval, staleness detection/refresh behavior, and push-cert storage error handling. * **Documentation** * Updated docs to describe the APNs push-certificate refresh and staleness behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
f3f830bd9d |
Fix GitOps failure when moving labels from global to fleet scope (#44983)
Closes #44950 ## Local reproduction Reproduced locally using a MySQL integration test against the local test database. The test simulates the exact GitOps scenario from the issue: 1. Create a label and associate it with an MDM profile 2. Delete the label (FK `ON DELETE SET NULL` sets `label_id = NULL`) 3. Create a new label with the **same name** (simulates moving from global to fleet scope) 4. Call `batchSetProfileLabelAssociationsDB` with the profile referencing the new label **Before fix** (code from `main`, unfixed): ``` $ MYSQL_TEST=1 go test -run "TestMDMShared/TestBatchSetProfileLabelAssociations/same_label_name_recreated" -v -count=1 ./server/datastore/mysql/... === RUN TestMDMShared/TestBatchSetProfileLabelAssociations/same_label_name_recreated_after_deletion_darwin Error: selecting existing profile labels: sql: Scan error on column index 1, name "label_id": converting NULL to uint is unsupported === RUN TestMDMShared/TestBatchSetProfileLabelAssociations/same_label_name_recreated_after_deletion_windows Error: selecting existing profile labels: sql: Scan error on column index 1, name "label_id": converting NULL to uint is unsupported --- FAIL: TestMDMShared/TestBatchSetProfileLabelAssociations/same_label_name_recreated_after_deletion_darwin (0.02s) --- FAIL: TestMDMShared/TestBatchSetProfileLabelAssociations/same_label_name_recreated_after_deletion_windows (0.02s) FAIL ``` **After fix:** ``` $ MYSQL_TEST=1 go test -run "TestMDMShared/TestBatchSetProfileLabelAssociations/same_label_name_recreated" -v -count=1 ./server/datastore/mysql/... === RUN TestMDMShared/TestBatchSetProfileLabelAssociations/same_label_name_recreated_after_deletion_windows === RUN TestMDMShared/TestBatchSetProfileLabelAssociations/same_label_name_recreated_after_deletion_darwin --- PASS: TestMDMShared/TestBatchSetProfileLabelAssociations/same_label_name_recreated_after_deletion_windows (0.03s) --- PASS: TestMDMShared/TestBatchSetProfileLabelAssociations/same_label_name_recreated_after_deletion_darwin (0.03s) PASS ok github.com/fleetdm/fleet/v4/server/datastore/mysql 2.761s ``` ## Code changes When a label is deleted, MySQL's `ON DELETE SET NULL` foreign key constraint automatically sets `label_id = NULL` in the profile-label association row. The Go code then crashes trying to scan that NULL into a `uint` field. - **`server/datastore/mysql/mdm.go`** — Added `COALESCE(label_id, 0)` to the SELECT in `batchSetProfileLabelAssociationsDB`, so that NULL `label_id` values are returned as 0 instead of causing a scan error when Go tries to read NULL into a `uint`. - **`server/datastore/mysql/apple_mdm.go`** — Same `COALESCE(label_id, 0)` fix in `batchSetDeclarationLabelAssociationsDB`. Also added `OR label_id IS NULL` to the DELETE statement to clean up broken rows, matching the profile labels behavior from #42637. Other queries in the same codebase (e.g., `listProfileLabelsForProfiles`) already use `COALESCE(label_id, 0)` — these two were missed. ## Testing - `same_label_name_recreated_after_deletion_{darwin,windows}` — reproduces the exact bug: associates a profile with a label, deletes the label (NULL label_id), creates a new label with the same name, and verifies `batchSetProfileLabelAssociationsDB` succeeds, the broken row is cleaned up, and the correct label association exists - Full MDM test suite passes: `MYSQL_TEST=1 go test -run "TestMDM" ./server/datastore/mysql/...` (76s) - `make lint-go-incremental` passes |
||
|
|
e15f37d4e0 |
Optimize OSV vulnerability scanning (#44684)
**Related issue:** Resolves #44391 # Checklist for submitter If some of the following don't apply, delete the relevant line. - [x] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. See [Changes files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files) for more information. - [x] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements), JS inline code is prevented especially for url redirects, and untrusted data interpolated into shell scripts/commands is validated against shell metacharacters. ## Testing - [x] Added/updated automated tests - [x] Where appropriate, [automated tests simulate multiple hosts and test for host isolation](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/reference/patterns-backend.md#unit-testing) (updates to one hosts's records do not affect another) - [x] QA'd all new/changed functionality manually I tested this locally number of ubuntu hosts: 6,252 average software per host: 2,302 distinct software items: 61,213 host_software rows: 14.4M generates software_cve rows 305,826 OS sub-versions: 25 The time before my optimization **10m53s** down to **4m26s** the optimization. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Optimized OSV vulnerability scanning to aggregate work by OS version and batch lookups, reducing redundant queries for faster scans. * **Refactor** * Restructured scanning flow to process OS versions in batched chunks with clearer logging and early exits when no work is required. * **Tests** * Added tests for querying, batching, source filtering, deduplication, and empty-input behaviors. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> |
||
|
|
361a5a402e |
Creating product index to speed up vulnerability scanning (#44910)
**Related issue:** Resolves #44391 # Checklist for submitter If some of the following don't apply, delete the relevant line. - [x] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. See [Changes files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files) for more information. ## Testing - [x] QA'd all new/changed functionality manually <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Added release notes documenting vulnerability scanning performance improvements * **Refactor** * Optimized vulnerability scanning performance through enhanced CVE product matching efficiency <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
64a50d0c16 |
Fix relative spread + calendar dates on checkerboard (#44959)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #44958 # Details Fixes two issues on the checkerboard: 1. Ensures that the chart shows data going back 30 calendar days (not 720 hours) if it has it 2. Leaves `0` values out of the chart color band calculations in "relative" color mode # Checklist for submitter If some of the following don't apply, delete the relevant line. - [ ] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. See [Changes files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files) for more information. n/a, unreleased ## Testing - [X] Added/updated automated tests - [X] QA'd all new/changed functionality manually **Before** Colors clustered in top 3 levels, empty boxes in first column: <img width="705" height="416" alt="image" src="https://github.com/user-attachments/assets/b867a1a9-4c52-4b96-92fd-04e7848c6295" /> **After** Colors spread over all levels, no empty boxes in first column: <img width="707" height="412" alt="image" src="https://github.com/user-attachments/assets/c67e11c5-6dd8-4e66-9c32-9d9213ccb24f" /> For unreleased bug fixes in a release candidate, one of: - [X] Confirmed that the fix is not expected to adversely impact load test results <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Charts request an extra day to ensure full calendar-day coverage across timezones. * Checkerboard visualization excludes empty/no-data slots from relative color scaling so color ramps reflect non-zero data. * Calendar view trims leading partial days so the displayed window matches the selected range. * **New Features** * Chart date-range selection expanded to support any value from 1–31 days. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
dc0c7bd72f | Recover stuck SCEP managed-cert state via matcher extension (#44691) | ||
|
|
292bab32f6 |
Clarify SMTP TLS error and surface STARTTLS toggle (#34104)
Resolves #34104 When saving SMTP settings with SSL/TLS off, STARTTLS on, and SSL cert verification on, the test-email send produced an opaque Go cert error that gave users no actionable hint. The two TLS-related toggles also live on different settings cards with no cross-reference, which made the conflict hard to spot before hitting Save. |
||
|
|
119feeda02 |
42218 updated ios version number to include supplemental extra (#44727)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #42218 # Checklist for submitter If some of the following don't apply, delete the relevant line. - [x] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. See [Changes files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files) for more information. - [x] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements), JS inline code is prevented especially for url redirects, and untrusted data interpolated into shell scripts/commands is validated against shell metacharacters. ## Testing - [x] Added/updated automated tests - [x] QA'd all new/changed functionality manually Note: Sim update included and validated with and without supplemental, screen shots attached <img width="760" height="87" alt="Host List" src="https://github.com/user-attachments/assets/c55f0ace-a205-4242-95da-510e8e6ec4ad" /> <img width="1511" height="523" alt="Standard" src="https://github.com/user-attachments/assets/74a42e57-9391-4ce0-8b0a-ad3de6ab4745" /> <img width="1505" height="526" alt="Supplimental" src="https://github.com/user-attachments/assets/392fc603-c7a2-4d6f-8ae0-87767cab7e3c" /> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * iOS/iPadOS devices managed via MDM now include reported supplemental OS version text (e.g., Rapid Security Response suffixes) in the displayed OS version string. * **Bug Fixes** * Supplemental extras are validated; invalid values are ignored. Combined version strings are length-limited and safely truncated. * **Tests** * Added tests for supplemental handling, validation, fallback, and truncation. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
d8a1ffae81 |
Clear stale broken label rows on profile batch upsert (#44847)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #42637 # Checklist for submitter - [x] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. See [Changes files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files) for more information. ## Testing - [x] Added/updated automated tests - [x] QA'd all new/changed functionality manually ### Reproduction steps: - Created Label X and Label Y as manual labels in the UI. - Applied gitops referencing the labels. The specified profile referenced Label X: ```yaml macos_settings: custom_settings: - path: ../repro-42637-profile.mobileconfig labels_exclude_any: - "Repro Label X 42637" ``` - Manually ran a SQL query to update `label_id` to NULL. <img width="712" height="46" alt="Screenshot 2026-05-06 at 6 19 51 PM" src="https://github.com/user-attachments/assets/32f386c7-adf3-48e8-adee-03102831e556" /> - Re-ran gitops referencing Label Y in the profile config. ```yaml macos_settings: custom_settings: - path: ../repro-42637-profile.mobileconfig labels_include_any: - "Repro Label Y 42637" ``` - Old row was preserved AND a new one was created (association to Label Y): <img width="709" height="68" alt="Screenshot 2026-05-06 at 6 22 07 PM" src="https://github.com/user-attachments/assets/fe2c4644-eb95-45a0-a582-994ad88e45be" /> ### Testing steps - Re-built fleetctl with the fix applied and re-ran gitops, still referencing Label Y for the profile. - Confirmed the orphan row was deleted. <img width="740" height="212" alt="Screenshot 2026-05-06 at 6 24 43 PM" src="https://github.com/user-attachments/assets/da9e9461-c352-4266-80b8-625a98e055ec" /> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Bug Fixes * Fixed an issue where MDM configuration profiles would remain enforced on hosts after their associated labels were deleted during fleetctl gitops apply operations. Label associations are now properly cleared when profiles are reapplied with updated targeting. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
684becade8 |
Allow disabling chart datasets: backend (#44769)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** For #44077 # Details This PR implements enforcement of the "disable dataset" feature. When a dataset is disabled globally, we: * Stop collecting all data for that dataset (the `Collect` method for that dataset is not called in the cron job) * Remove all previously-collected data for the dataset via an asynchronous job When a dataset is disabled for one or more fleets, we: * Provide the list of disabled fleets as an argument to each dataset's `Collect` method. Each dataset is responsible for filtering out hosts in the most efficient way possible * Scrub the data for the relevant datasets using a bitmask, so that all hosts from the disabled fleets are removed from the data. This is done via an asynchronous job. # Checklist for submitter If some of the following don't apply, delete the relevant line. - [ ] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. See [Changes files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files) for more information. n/a, unreleased - [X] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements), JS inline code is prevented especially for url redirects, and untrusted data interpolated into shell scripts/commands is validated against shell metacharacters. - [X] Timeouts are implemented and retries are limited to avoid infinite loops ## Testing - [X] Added/updated automated tests - [X] Where appropriate, [automated tests simulate multiple hosts and test for host isolation](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/reference/patterns-backend.md#unit-testing) (updates to one hosts's records do not affect another) - [ ] QA'd all new/changed functionality manually ### Prerequisites / Test Setup - [ ] Fleet running with at least 3 teams (call them T1, T2, T3) and ≥3 hosts in each, plus ≥2 hosts with no team - [ ] At least one host on each team has reported recent uptime (within the bucket window) - [ ] At least one host in each team is affected by a tracked CVE (so `host_scd_data` for `dataset='cve'` will have non-empty bitmaps) - [ ] AppConfig: both `features.historical_data.uptime` and `features.historical_data.vulnerabilities` start as `true`; same for every team - [ ] Let the collection cron run at least one full tick to populate baseline rows in `host_scd_data` for both `uptime` and `cve` - [ ] Note the current row count per dataset: `SELECT dataset, COUNT(*) FROM host_scd_data GROUP BY dataset;` --- ### 1. Cron Skips Globally-Disabled Datasets #### 1.1 Global disable of `uptime` - [x] Disable globally: `PATCH /api/v1/fleet/config` with `features.historical_data.uptime = false` - [x] Verify activity feed shows `disabled_historical_dataset` for `uptime` (existing behavior) - [x] Wait for next collection tick (or trigger it via fleetctl debug if available) - [x] Confirm **no new rows** appear for `dataset='uptime'`: `SELECT MAX(valid_from) FROM host_scd_data WHERE dataset='uptime';` should not advance after the disable - [x] Confirm cron still writes `cve` rows on the same tick (per-dataset isolation) - [x] Re-enable: PATCH `historical_data.uptime = true` - [x] Verify next tick resumes writing `uptime` rows #### 1.2 Global disable of `vulnerabilities` - [x] Repeat 1.1 with `features.historical_data.vulnerabilities` - [x] Confirm `cve` writes stop, `uptime` continues #### 1.3 Both disabled globally - [x] Disable both globally - [x] Confirm cron tick produces zero new rows for either dataset - [x] Confirm cron does not error or get stuck - [x] Re-enable both --- ### 2. Per-Fleet Disable — Cron Filters at SQL #### 2.1 Single team disabled for one dataset - [x] Disable uptime for T1 only: PATCH team T1 with `features.historical_data.uptime = false` - [x] Verify scoped `disabled_historical_dataset` activity emitted for T1 - [x] Wait for next cron tick / trigger cron - [x] Pick a host known to be in T1 (call it `H_T1`); confirm its bit is NOT set in any `uptime` row written *after* the disable by filtering the chart to that host - [x] Pick a host in T2 (`H_T2`); confirm its bit IS still set in the same rows (T2 is not disabled) - [x] Pick a no-team host (`H_none`); confirm its bit IS still set (no-team hosts follow the global value) #### 2.2 Same fleet, different dataset - [x] With T1's uptime disabled, confirm T1's hosts ARE still written into `cve` rows on subsequent ticks (per-dataset isolation) #### 2.3 All teams disabled, global on, no-team hosts - [x] Disable uptime on every team (T1, T2, T3) - [x] Confirm next tick still writes a row containing only no-team hosts' bits (global is on, no-team hosts always count) - [x] Re-enable uptime on all teams --- ### 3. Global Scrub — DELETE #### 3.1 Successful global scrub - [x] Note baseline: `SELECT COUNT(*) FROM host_scd_data WHERE dataset='uptime';` (should be > 5000 to exercise the loop; if not, manually insert filler rows or run multiple cron ticks) - [x] Disable uptime globally via the API - [x] Wait for the worker to pick up the scrub / trigger the job - [x] Confirm the count drops to 0: `SELECT COUNT(*) FROM host_scd_data WHERE dataset='uptime';` - [x] Confirm rows for **other datasets** are untouched - [ ] Test again but disable via GitOps --- ### 4. Per-Fleet Scrub — ANDNOT #### 4.1 Single-fleet scrub clears bits - [x] Identify hosts in T1 and record their IDs (call this set `S`) - [x] Pre-disable, confirm at least one `host_scd_data` row for `dataset='uptime'` has bits set at positions in `S` by filtering the chart to those hosts - [x] Disable uptime on T1 only, via the API - [x] Wait for the scrub to run / trigger it - [x] Confirm: every existing row for `dataset='uptime'` now has NO bits set at any position in `S`. Spot-check by filtering the chart to those hosts - [x] Confirm rows for `dataset='cve'` (different dataset) are untouched - [x] Confirm bits for hosts in T2/T3 (not disabled) are still set - [x] Run test again but disable via GitOps #### 4.2 Multi-fleet scrub via GitOps batch - [x] Apply a GitOps spec that flips cve to false on T1 and T3 in a single apply - [x] Wait for scrub(s) to complete - [x] Confirm bits for the union of T1∪T2 hosts are cleared from every row of `dataset='cve'` - [x] Confirm T2 hosts' bits remain set --- ### 5. Activity Feed Cross-Check - [x] Each global flip emits exactly one `disabled_historical_dataset` activity (existing behavior, unchanged) - [x] Each per-team flip emits one scoped activity with the team's ID and name - [x] PATCH submitting unchanged values emits **no** activity and causes **no** scrub (no `host_scd_data` data change observed after the cron tick) - [x] No new "scrub completed" or "scrub started" activity is emitted (out of scope for v1) - [x] Re-enable flips emit `enabled_historical_dataset` activities and do NOT emit any scrub-related activity --- ### 6. Regression Spot Checks - [x] With everything enabled (default), the chart UI renders the same data as before this change (no behavior change in the "all on" case) - [x] AppConfig YAML round-trip (`fleetctl apply`) is benign: applying the unchanged config produces no scrub jobs and no activities - [x] GitOps apply with `historical_data` omitted from team specs defaults to `true` (per the gitops-api change) and does not trigger spurious scrubs - [x] After a full disable+scrub of cve, the `host_scd_data` table has no `dataset='cve'` rows; the chart UI for "vulnerable hosts over time" shows an empty/zero state without errors --- <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Chart collection now supports per-dataset scoping and honors team-level disables; new scrub jobs are registered and worker handlers added. * New dataset scrub operations: global and fleet-scoped scrubs; scrubs can be enqueued and are deduplicated to avoid duplicate pending jobs. Historical-data changes enqueue scrubs after save (errors logged, non-blocking). * **Tests** * Added unit tests for scope resolution, scrub enqueue/dedup behavior, scrub workers, scrub application, and low-level blob scrub logic. * **Documentation** * Added OpenSpec metadata for the chart scrub change. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
4910c450a4 |
43887 MLAPR backend (#44726)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #43887 Adds the password rotation state machine for macOS local admin accounts. Changes file covered in prior PR # Checklist for submitter If some of the following don't apply, delete the relevant line. - [x] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. See [Changes files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files) for more information. - [x] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements), JS inline code is prevented especially for url redirects, and untrusted data interpolated into shell scripts/commands is validated against shell metacharacters. - [x] Timeouts are implemented and retries are limited to avoid infinite loops - [x] If paths of existing endpoints are modified without backwards compatibility, checked the frontend/CLI for any necessary changes ## Testing - [x] Added/updated automated tests - [x] Where appropriate, [automated tests simulate multiple hosts and test for host isolation](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/reference/patterns-backend.md#unit-testing) (updates to one hosts's records do not affect another) - [x] QA'd all new/changed functionality manually <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Automatic macOS managed-local-account password rotation (5‑minute scheduler) with queued SetAutoAdminPassword device commands * Manual rotation API: POST /hosts/{id}/managed_local_account/rotate (returns 204) * API now reports auto-rotation timing and pending-rotation state (auto_rotate_at, pending_rotation) * Activity records for successful and failed rotations * **Behavior Changes** * Password availability is based on stored encrypted password (broader than before) * Rotate-while-in-flight is rejected to prevent duplicate rotations * **Tests** * New unit and integration tests for rotation flows, cron behavior, and failure paths <!-- end of auto-generated comment: release notes by coderabbit.ai --> |