Commit Graph
5328 Commits
Author SHA1 Message Date
Magnus Jensen 17e115a517 add mdm configured endpoints for DDM assets for testing (#49633)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #

Saw I missed these when doing the DDM assets backend

# Checklist for submitter

If some of the following don't apply, delete the relevant line.

## 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

* **Tests**
* Expanded endpoint coverage for device management asset routes,
including listing, retrieving, deleting, and batch creation.
  * Documented a remaining limitation affecting multipart asset uploads.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-21 15:14:16 +02:00
Andrew MellorandJordan Montgomery 15a0f4b201 48342 edit config profile endpoint (#49141)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #48342

# 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



<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Added support for editing existing Apple, Windows, and Android
configuration profiles through the API.
* Supports updating profile content, names where applicable, label
targeting, and Fleet variable associations without replacing the profile
identity.
  * Added support for editing Apple DDM declarations.
  * Added activity tracking for configuration profile edits.
* **Bug Fixes**
* Added validation for unsupported edits, invalid labels, duplicate
names, missing profiles, and protected Fleet-managed profiles.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Jordan Montgomery <elijah.jordan.montgomery@gmail.com>
2026-07-21 08:20:03 -04:00
Carlo fb0e817bd0 Show .py script-only packages as available for install on macOS hosts (#49457)
**Related issue:** Resolves #49455

Offer `.py` script-only packages on macOS hosts, matching `.sh`.

# Checklist for submitter

- [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


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Python (`.py`) installer packages are now treated as compatible
alongside shell (`.sh`) installers on macOS and Linux.
* Python installers can now appear in software availability,
self-service installation, and setup experience selections.
* Windows behavior remains unchanged (Unix-script installers are
excluded).

* **Bug Fixes**
* Improved cross-platform compatibility matching for Unix-like hosts
when choosing the first eligible installer package.

* **Tests**
* Added and expanded unit/integration coverage for `.py` installer
compatibility across platforms and flows.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-20 15:13:50 -04:00
Nico 900c54e822 Fix label membership being cleared when a label query errors (#49403)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #46399

When a label's query errors on a host (e.g. the extension socket is
unavailable) instead of returning zero rows, Fleet was recording that
error the same as a definitive "no match," clearing the host's existing
label membership. This could unintentionally remove configuration
profiles or other automations scoped to that label. The fix leaves
existing label membership untouched when a label query errors.

# 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

**Setup:** macOS VM enrolled as a Fleet host, with a dynamic label whose
query targets a real, always-present table but with a deliberately
invalid `WHERE` clause, so the query fails deterministically (a `no such
column` SQL error).

```sql
-- working version (label matches)
SELECT * FROM os_version;

-- broken version (query errors on every run)
SELECT * FROM os_version WHERE this_column_does_not_exist = 1;
```

### Before (bug reproduced on unpatched code)

1. Set the label's query to the working version and refetched the host —
confirmed it shows up under the host's Labels.
2. Edited the label's query to the broken version.
3. Clicked **Refetch** on the host.
4. **Result:** the label disappeared from the host's Labels list — a
query error incorrectly cleared existing membership.

### After (fix verified)

1. Reset the label's query to the working version and refetched —
confirmed membership was restored.
2. Edited the label's query to the broken version again.
3. Clicked **Refetch** on the host.
4. **Result:** the label remained on the host's Labels list — a query
error now correctly leaves existing membership untouched.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Bug Fixes**
* Preserved existing dynamic label memberships when label queries fail
or yield unknown results.
  * Avoided treating unknown/failed evaluations as label removals.
* Ensured label updates/removals are applied only when a definite match
or non-match is returned.
* **Tests**
* Expanded coverage for label query errors across datastore, async
processing, and distributed execution to confirm memberships remain
unchanged.
* Updated expectations for queued async updates to skip errored labels.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-20 10:31:09 -03:00
Carlo 7cb2399700 Redirect FMA installs to the active version after auto-update (#49525)
**Related issue:** Resolves #49495

Redirects queued Fleet-maintained app installs to the newly-active
installer (canceling already-dispatched ones) atomically when an
auto-update or pin change flips the active version, and re-resolves
install retries to the active installer, so a host no longer installs a
superseded cached version.

# Checklist for submitter

- [x] Changes file added for user-visible changes in `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


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Bug Fixes**
* Fleet-maintained app installs now consistently use the currently
active version after automatic promotions, preventing stale installer
targeting.
* Queued installs tied to an older promoted installer are redirected to
the newly active installer instead of being canceled.
* Install retry flows now re-resolve to the active installer at retry
time, avoiding stale retries after version changes.
* **Tests**
* Added datastore coverage for active-installer redirection and updated
retry tests to verify the correct installer ID is used.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-18 06:01:45 -04:00
Jonathan Katz 8a33fcd058 Fix FMA pinning not changing patch policy (#49519)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #49474

# 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
- Relied on integration test for testing changes made by the
`maintained_apps_auto_update` job


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Bug Fixes**
* Fixed patch policies for Fleet-maintained apps not updating when the
active app version changes.
* Patch policy queries now refresh to match the currently active (or
pinned) installer version, including changes driven by pinning, cron,
and GitOps.
* Improved behavior when pins are cleared or switched, ensuring the
policy continues referencing the correct version-specific query.
* **Tests**
* Expanded integration coverage to verify version-pinned patch policy
queries across scenario updates.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-17 19:00:13 -04:00
Carlo 8cd9503267 Fix false-success reporting for failed software installs (#49515)
**Related issue:** Resolves #49475

Makes a non-zero install-script exit code a terminal failure so an
install that failed but whose post-install script exited 0 is no longer
reported as installed, in both the Go status computation and the
`host_software_installs` `status`/`execution_status` generated columns.

# Checklist for submitter

- [x] Changes file added for user-visible changes in `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

## Database migrations

- [x] Checked schema for all modified table for columns that will
auto-update timestamps during migration. Redefining the
`status`/`execution_status` generated columns rebuilds the table, but
`ON UPDATE CURRENT_TIMESTAMP` is not triggered by `ALTER TABLE`, so
`updated_at` is preserved.
- [x] Confirmed that updating the timestamps is acceptable, and will not
cause unwanted side effects.
- [x] Ensured the correct collation is explicitly set for character
columns (`COLLATE utf8mb4_unicode_ci`).


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Bug Fixes**
* Installations that fail during the install script are now correctly
reported as failed, even if the post-install script succeeds.
* Install and execution status reporting is now consistent about which
script exit code takes precedence.
* Pending, successful, failed, canceled, and uninstall outcomes continue
to be reported correctly.
* **Tests**
* Added regression/unit test coverage for install-status and
execution-status precedence across mixed install/post-install exit code
scenarios.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-17 17:59:14 -04:00
Dante Catalfamo 67c06a9820 Mask team enroll secrets in team write responses (#49422) 2026-07-17 16:45:40 -04:00
Lucas Manuel Rodriguez da3f30df79 Allow Microsoft conditional access on premium self-hosted (#49414)
Resolves #47699.

- [X] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/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

* **New Features**
* Microsoft Entra Conditional Access is now supported for self-hosted
Fleet Premium instances.
* Conditional Access is available only on the Fleet Premium license
tier.
* **Changes**
* Removed the Microsoft Compliance Partner API key configuration and
updated the proxy behavior accordingly.
* Removed the managed-cloud indicator from license/config responses and
adjusted related UI rendering and gating.
* **Tests / Maintenance**
* Updated fixtures and automated tests to reflect the new licensing
gates and API/proxy behavior (including updated failure codes).
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-17 10:59:32 -03:00
Juan Fernandez d2210243fc Rejected empty and whitespace-only enroll secrets when creating or updating teams
Rejected empty and whitespace-only enroll secrets when creating or updating teams
2026-07-16 18:54:38 -04:00
Juan Fernandez 0d3a3bdc95 Added audit activities when secret variables are upserted
Added audit activities when secret variables are created or updated
through the `PUT /api/latest/fleet/spec/secret_variables` endpoint.
2026-07-16 18:54:04 -04:00
Carlo 57bab9e5ec Allow Python script-only packages (#49070)
**Related issue:** Resolves #41470

Adds support for uploading Python (`.py`) script-only software packages
— accepted as script-only (the file contents become the install script;
advanced options and automatic install follow `.sh`/`.ps1`), assigned
the new `py_packages` source, and installable on macOS and Linux hosts
across the UI, REST API, and GitOps.

Feature branch combining the backend (#48942) and frontend (#48946)
sub-PRs.

# Checklist for submitter

- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
- [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


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added support for Python (`.py`) script-only software packages across
UI uploads, API/self-service installs, and GitOps parsing.
* Python installers now derive metadata correctly and render the proper
Python icon, with install eligibility for macOS & Linux.
* **Bug Fixes**
* Improved installer-script validation and “supported file types” error
messages to include `.py` (and consistent handling of related script
fields/options).
* **Tests**
* Expanded unit, integration, and GitOps tests to cover Python package
parsing, metadata derivation, platform/host eligibility, and UI
rendering.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-16 14:20:03 -04:00
Juan Fernandez 83cef5483f Extend support for all built-in
Relates to #38806

Extend host name templates beyond the three host-identity variables to
also accept the IdP end-user variables, and re-enqueue the rename when a
referenced variable's value changes.

Re-enqueue on value change:
- An IdP data change (SCIM user/group create/update/delete) re-queues
only the affected hosts whose template uses the changed IdP variable —
IdP values are per host, so the scope is the specific hosts mapped to
that user/group.
- A custom (secret) value change re-queues every eligible host in each
team / "No team" whose template references the changed secret — secret
values are global, so the scope is the whole team/No-team.

Built-in variables intentionally NOT supported:
- Certificate/CA variables — $FLEET_VAR_NDES_SCEP_CHALLENGE,
_NDES_SCEP_PROXY_URL, _CUSTOM_SCEP_CHALLENGE_*,
_CUSTOM_SCEP_PROXY_URL_*, _SMALLSTEP_SCEP_CHALLENGE_*,
_SMALLSTEP_SCEP_PROXY_URL_*, _DIGICERT_DATA_*, _DIGICERT_PASSWORD_*,
_SCEP_WINDOWS_CERTIFICATE_ID, _CERTIFICATE_RENEWAL_ID (and legacy
_SCEP_RENEWAL_ID), _PSSO_DEVICE_REGISTRATION_TOKEN. These resolve to
one-time SCEP challenges, proxy URLs, base64 PKCS12 cert data, or
Fleet-minted tokens — meaningless as a device name, and resolving them
has side effects (issuing certificates, consuming one-time challenges)
and would leak secrets into a name that's broadcast on-device, in
osquery, and in the UI.
- Legacy $FLEET_VAR_HOST_END_USER_EMAIL_IDP — deprecated ("avoid in new
replacements") and not a documented built-in variable, so it's excluded
in favor of the supported IDP_USERNAME variables.
2026-07-16 10:43:37 -04:00
Juan FernandezandKonstantin Sykulev 621ede7584 Software > OS: Show Android versions and vulnerabilities (#49399)
Resolves #35075 

- Added vulnerability (CVE) reporting for Android OS versions.
- Folded the Android security patch level into the host's OS version.

---------

Co-authored-by: Konstantin Sykulev <konst@sykulev.com>
2026-07-16 10:37:57 -04:00
Jordan Montgomery 5f95d683ff Speculative fix for iOS/iPadOS enrollment w/ required sw update (#49280)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #49260

This fix is based on direct discussion with Apple and consultation of
the Apple docs. We are not currently sure if this is actually issue the
customer is running into but we have identified it as an issue with our
enrollment process.

As far as testing my iPad running 18.7 gets prompted to update every
time now when I enroll it with updates turned on. If I back up and don't
take the upgrade and try to enroll again I get an error but I believe
this is an Apple bug which we've been told was fixed in 26+

# 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

* **Bug Fixes**
* Fixed an issue during Android Device Enrollment where devices assigned
a mandatory software update could incorrectly show a failure status.
* Resolved cases where the required software update was not displayed
correctly.
* Improved Apple device enrollment update details by reporting the
operating system version consistently.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-15 17:52:57 -07:00
George KarrandCopilot Autofix powered by AI e0edd46448 Windows MDM: accept discovery RequestVersion >= 4.0 (#49329) (#49380)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #49329

## What & why

Fresh **Windows 11 25H2** (build 10.0.26200) devices failed Microsoft
Entra / Autopilot MDM auto-enrollment during OOBE with error
**80180006**. The device advertises an MS-MDE2 discovery
`RequestVersion` of `"9.0"`, and Fleet's `IsValidDiscoveryMsg()`
rejected it via an exact-match allow-list (`{"4.0","5.0","6.0","7.0"}`)
that could only be changed by rebuilding the server.

The discovery **response** already pins the protocol to
`EnrollmentVersionV4` (`"4.0"`) and the client negotiates down, so the
exact-match check was the only blocker. This PR implements the issue's
preferred fix: **accept any `RequestVersion >= 4.0`**, which is
forward-compatible with future Windows version bumps.

- `server/mdm/microsoft/syncml/syncml.go`: replaced the
`SupportedEnrollmentVersions` allow-list var with a
`MinSupportedEnrollmentVersion` constant.
- `server/fleet/microsoft_mdm.go`: added `enrollmentVersionAtLeast`
(numeric component-wise compare, so `"10.0" > "9.0"`) and changed
discovery validation to accept any version at or above the minimum.

# 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
- [ ] 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**
* Fixed MDM enrollment failures on fresh Windows 11 25H2 and other
recent builds.
* Discovery requests now accept supported MDE2 `RequestVersion` values
at or above the minimum supported version (instead of requiring an exact
match).
* Invalid or outdated discovery versions now return more specific
validation errors.
* **Tests**
* Added unit test coverage for minimum, equal, newer, and invalid
enrollment version comparisons.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-07-15 17:42:22 -07:00
Carlo DiCelico 4ce133cb26 merge main 2026-07-15 19:17:29 -04:00
Nico b10642be3c 44954 custom host vitals (#49334)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #44954 

# 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


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added Custom Host Vitals management (create/edit/delete, search) with
copyable variable tokens and per-host values.
* Show Custom Host Vitals on host details, including role-based editing.
* Enabled Custom Host Vitals in host-vitals labels and the activity
feed.
* Extended GitOps to manage global Custom Host Vitals declaratively
(including dry-run behavior).
* Split Controls → Variables into Global Variables and Custom Host
Vitals, including routing updates.

* **Bug Fixes**
* Improved validation and expansion of Custom Host Vital references
across scripts, profiles, installers, and deployments, with clearer
failures when values are missing or invalid.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-15 19:35:27 -03:00
Carlo DiCelico 46c9895bb5 bump migrations 2026-07-15 17:50:04 -04:00
Carlo DiCelico a65af7461e Merge remote-tracking branch 'origin/main' into feat/28108-multiple-custom-packages 2026-07-15 17:47:12 -04:00
Carlo b8ddf171c4 Fix installer edit rejecting same-software new versions (#49353)
**Related issue:** Resolves #49234

Editing a software installer to a new version failed with "The selected
package is for different software" when the title's stored
(osquery-reported) name differed from the installer's extracted name.
The edit now validates by software identity (bundle identifier / upgrade
code / name) instead of an exact name match.

# Checklist for submitter

- [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
2026-07-15 17:16:38 -04:00
Juan Fernandez 89ec4f3abb Support custom (secret) variables in host name templates
Relates to #38806

Host name templates previously accepted only built-in $FLEET_VAR_*
variables and rejected custom $FLEET_SECRET_* (secret) variables. Allow
secret variables so admins can embed an org-wide custom value in an
Apple host's name.

# Checklist for submitter

If some of the following don't apply, delete the relevant line.

- [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
2026-07-15 14:29:02 -04:00
Carlo 90857fe359 Fix multi-package host software details (#49335)
**Related issue:** Resolves #49208

Host software details now show the status and install details for the
installer scoped to the host, for titles with multiple packages.

No `changes/` file: this is an unreleased bug fix, and the
multiple-packages feature PR carries the changes entry.

# Checklist for submitter

- [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
2026-07-15 14:09:11 -04:00
Sharon Katz 18d3481604 Batch extension label-membership checks in GetOrbitConfig (#49154)
**Related issue:** Resolves #45320

# 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.

## Summary

`filterExtensionsForHost` (called on every Orbit config fetch, ~30s per
host) had an N+1 query pattern: it called `HostMemberOfAllLabels` once
per extension in a loop, issuing a separate DB query for each.

This PR replaces the N queries with a single batch query via a new
`HostMembershipForLabels` datastore method that returns which labels
(from a given list) the host belongs to. Extension filtering then
happens in-memory.

### Changes

- **New datastore method** `HostMembershipForLabels(ctx, hostID,
labelNames) -> map[string]bool` -- single `SELECT l.name FROM labels l
JOIN label_membership` query
- **Updated `filterExtensionsForHost`** in `server/service/orbit.go` --
collects all unique label names across extensions, calls the new method
once, filters in-memory
- **No API, UI, CLI, agent, or schema changes** -- purely server-side
internal optimization. Full backward compatibility: old agents work with
new servers and vice versa (no protocol change).

## Benchmark

Ran a local end-to-end benchmark against the live `POST
/api/fleet/orbit/config` endpoint to measure the real-world impact.

**Setup:**
- MacBook (Fleet server + Docker MySQL 8.0 + Redis, all localhost)
- 50 enrolled Orbit hosts (darwin), 5 label-scoped extensions, all hosts
members of all 5 labels
- 500 requests at concurrency 10, cycling through all 50 orbit_node_keys
- Built Fleet binary from `main` (before) and this PR branch (after),
same database and test data

**Results:**

| Metric | Before (main) | After (this PR) | Improvement |
|--------|:---:|:---:|:---:|
| Avg latency | 25.33 ms | 17.46 ms | **-31%, 1.45x faster** |
| P50 latency | 24.55 ms | 16.52 ms | **-33%, 1.49x faster** |
| P95 latency | 34.42 ms | 27.53 ms | **-20%, 1.25x faster** |
| Throughput | 390.6 req/s | 564.2 req/s | **+44%** |

### Extrapolation to 100,000 hosts

At 100k hosts with a 30-second check-in interval (3,333 req/s steady
state):

| Metric | Before | After |
|--------|--------|-------|
| Server host capacity (measured MacBook) | 11,718 | 16,926 (+44%) |
| Label-check DB queries/sec | **16,665** (5/req) | **3,333** (1/req) |
| **DB queries eliminated** | | **13,332/sec (80% reduction)** |

The improvement scales linearly with extension count:

| Extensions | DB queries eliminated/sec | Reduction |
|:---:|---:|:---:|
| 5 | 13,332 | 80% |
| 10 | 29,997 | 90% |
| 15 | 46,662 | 93% |
| 20 | 63,327 | 95% |

> **Note:** These are conservative localhost numbers. In production,
where each DB round-trip includes real network latency, the per-request
latency improvement would be more pronounced because each eliminated
query saves a network hop.

## 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)

### Automated

- New `testHostMembershipForLabels` MySQL integration test covering:
empty input, full membership, partial membership, nonexistent labels,
nonexistent host, host with no memberships
- Existing `testHostMemberOfAllLabels` unchanged and unaffected

### Manual QA

1. Fleet Premium instance with 2+ Orbit-enrolled hosts
2. Configure 3+ osquery extensions with different label scoping
3. Verify each host receives only the extensions whose label
requirements it meets
4. Verify extensions with no label scoping are included for all hosts

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Performance**
* Improved Orbit configuration loading by batching host label membership
checks into a single query for extension label filtering.
* **Behavior**
* Extension availability and filtering behavior remains the same, with
more efficient processing when multiple extensions use labels.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-15 09:55:54 -04:00
RachelElysia f29ecfa09b Fleet: Pin installer download token to a specific package (#49239) (#49263) 2026-07-14 11:01:33 -07:00
Carlo d131518ba7 Fix mismatched package upload creating a new title instead of erroring (#49264)
**Related issue:** Resolves #49209

Adding a package to an existing software title (`POST /software/package`
with `software_title_id`) now validates that the uploaded installer
actually belongs to that title. Previously the `software_title_id` sent
by the title page's "Add package" flow was ignored, so uploading
mismatched software (e.g. a 1Password package onto a Zoom title)
silently created a new separate title instead of erroring. It now
returns a 400 with a clear message and writes nothing. When
`software_title_id` is omitted (general "Add software" flow, GitOps),
behavior is unchanged.

# Checklist for submitter

- [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
2026-07-14 13:05:29 -04:00
RachelElysia 1098d395d4 Fleet UI: Multi-package follow-ups — target section, banner icons, display-name save, observer download (#49244) 2026-07-14 09:51:17 -07:00
Konstantin Sykulev 81e5634f74 De-duplicated resent_certificate activity (#49266)
**Related issue:** Resolves #49007

## Testing

- [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**
* Improved reliability when updating host-to-user mappings by ensuring
related mapping changes are completed as one transaction.
* Simplified certificate handling during mapping updates to provide more
consistent results.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-14 10:15:30 -05:00
Konstantin SykulevandCopilot Autofix powered by AI f981b15c1a Android enrollment debug logging (#49043)
## 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**
* Improved Android MDM device policy logging during profile
reconciliation and verification, including host and profile counts.
* Added clearer warnings when policy updates are skipped while returning
an invalid policy version, preventing missing policy metadata from going
unnoticed.
* Enhanced verification diagnostics with more detail on
pending/failed/non-compliant profiles and warnings when expected policy
request details cannot be matched.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-07-14 09:35:51 -05:00
Juan Fernandez 82db4d5389 macOS & iOS/iPadOS: Rename hosts
Resolves #38806 

Add an IT-admin naming convention for macOS/iOS/iPadOS hosts. An admin
sets a name template (e.g. "iPad $FLEET_VAR_HOST_HARDWARE_SERIAL") under
Controls > OS settings > Host names for a fleet or for "No team"; Fleet
resolves it per host, delivers it via an Apple `Settings`/`DeviceName`
MDM command, renames its own record on ACK, then verifies the name via
osquery (macOS) or a DeviceInformation refetch (iOS/iPadOS). Clearing
the template stops enforcement without renaming any host. Fleet Premium
only, mirroring disk encryption.
2026-07-14 10:28:19 -04:00
Konstantin Sykulev 1318b3c017 Android certificates resend generate resent_certificate (#49249)
This `resent_certificate` activity is generated from the edit user flow
in fleet server.

**Related issue:** Resolves #49007

## 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

* **New Features**
* Device-to-identity-provider mapping changes can now generate
certificate resend activities when applicable.
* Certificate resend activities can now be marked as automated versus
manual.

* **Improvements**
* Certificate resend details are produced when SCIM host-user mappings
are added, updated, or removed.
* If creating the associated resend activities fails, the mapping change
still proceeds; errors are handled non-blockingly.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-13 19:03:05 -05:00
Carlo 5e2b76a3ad Rename setup_experience_platforms to singular comma-separated setup_experience_platform (#49245)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** #43667

# Summary

Renames the unreleased GitOps field `setup_experience_platforms` to
singular `setup_experience_platform`, accepting a comma-separated string
of `darwin`/`linux` (rejecting the `macos` alias) to match the
query/policy/label `platform` convention.

# Checklist for submitter

- [ ] 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

- [ ] Added/updated automated tests
- [ ] QA'd all new/changed functionality manually

## New Fleet configuration settings

- [ ] Verified that the setting is exported via `fleetctl
generate-gitops`
- [ ] Verified the setting is documented in a separate PR to [the GitOps
documentation](https://github.com/fleetdm/fleet/blob/main/docs/Configuration/yaml-files.md#L485)
- [ ] Verified that the setting is cleared on the server if it is not
supplied in a YAML file (or that it is documented as being optional)


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Improvements**
* Updated software setup-experience platform configuration to use a
single comma-separated `setup_experience_platform` value.
* Platform values are normalized for casing and whitespace,
deduplicated, and validated against supported platforms.
* macOS setup selections now use the canonical `darwin` value; the
`macos` alias is rejected.
* GitOps-generated configurations now use the updated field name and
platform format.
* **Bug Fixes**
* Improved validation messages for invalid setup-experience platform
values.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-13 20:02:36 -04:00
Konstantin Sykulev 3b329e49e7 Android certificates resent_certificate (#49171)
**Related issue:** Resolves #49007

# Checklist for submitter

- [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

* **New Features**
* SCIM user create/reactivation, replace, patch, and delete flows now
automatically record certificate resend activities when applicable.
* Certificate resend activities are generated alongside SCIM
persistence, tied to the resulting “resent certificates”.
* **Bug Fixes**
* Improved reliability and synchronization of certificate resend
activity recording during SCIM and Google Workspace reconciliation.
* Failures to record individual resend activities no longer block the
underlying SCIM operation.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-13 13:22:50 -05:00
Sharon KatzandClaude Opus 4.6 74b10d8a0d Cache pack config JSON per team to reduce redundant marshaling (#48702)
**Related issue:** #21847

## Summary

`GetClientConfig` is called by every host every ~60 seconds. It rebuilds
the full pack config (all scheduled query SQL text) from DB and
JSON-marshals it on every request. For all hosts in the same team, the
result is identical, yet we run 3-5 DB queries + `json.Marshal` of ~50KB
per request.

This PR adds an in-memory cache for the marshaled pack config JSON,
keyed by `(teamID, queryReportsDisabled)` with a 1-minute TTL. The cache
is invalidated when queries or AppConfig are modified.

### What changed

- Extracted pack config building from `GetClientConfig` into a new
`getPackConfig` method
- Added `packConfigCache` field to Service struct using `go-cache`
(1-minute TTL, 5-minute cleanup)
- On cache hit (no legacy packs): returns cached `json.RawMessage`
immediately, skipping all DB queries and JSON marshaling
- On cache miss: builds pack config from DB, marshals, caches, and
returns
- Cache is flushed on any query mutation (`NewQuery`, `ModifyQuery`,
`DeleteQuery`, `DeleteQueries`, `ApplyQuerySpecs`, `DeleteQueryByID`)
and on `ModifyAppConfig`

### Expected impact at 100K hosts

| Metric | Before | After |
|--------|--------|-------|
| Pack config marshals/second | ~1,667 | ~1 per minute per team |
| DB queries for scheduled queries/second | ~5,000 | ~5 per minute per
team |
| CPU from JSON encoding | Dominant in pprof | Negligible |

### Known limitation

`ListScheduledQueriesForAgents` supports label-scoped query filtering
per host. The cache is keyed by team (not host), so when label-scoped
scheduled queries exist, all hosts in a team receive the same query set
from the cache regardless of their label memberships. This is an
acceptable trade-off because:
- Label-scoped scheduled queries are uncommon in most deployments
- The cache TTL is 1 minute, so divergence is temporary
- Running an extra query on a host is not harmful (just unnecessary
work)
- This can be refined in a follow-up to filter label-scoped queries from
the cached result

## Testing

### Unit tests (9 tests, all pass)

| Test | What it verifies |
|------|-----------------|
| `TestPackConfigCacheHit` | Second `GetClientConfig` call triggers zero
DB calls for scheduled queries |
| `TestPackConfigCacheInvalidationOnQueryCreate` | After
`InvalidatePackConfigCache()`, new query appears in config |
| `TestPackConfigCacheInvalidationOnQueryModify` | After invalidation,
updated SQL is reflected in config |
| `TestPackConfigCacheInvalidationOnQueryDelete` | After invalidation
with empty query list, packs key is absent |
| `TestPackConfigCacheInvalidationOnApplyQuerySpecs` | After
invalidation simulating GitOps apply, new specs appear |
| `TestPackConfigCacheTTLExpiration` | After 50ms TTL expires, fresh DB
read occurs and new query appears |
| `TestPackConfigCacheTeamIsolation` | Global, team-1, team-2 hosts get
correctly isolated cached configs |
| `TestPackConfigCacheLegacyPacksBypass` | Host with legacy pack
triggers DB calls on every request (no caching) |
| `TestPackConfigCachePerformance` | 1000 cached calls: 0 DB calls. 1000
uncached: 1000 DB calls. ~1.4x speedup with mock (real DB would be much
larger) |

```
=== RUN   TestPackConfigCacheHit           --- PASS (0.01s)
=== RUN   TestPackConfigCacheInvalidationOnQueryCreate  --- PASS (0.01s)
=== RUN   TestPackConfigCacheInvalidationOnQueryModify  --- PASS (0.01s)
=== RUN   TestPackConfigCacheInvalidationOnQueryDelete  --- PASS (0.01s)
=== RUN   TestPackConfigCacheInvalidationOnApplyQuerySpecs --- PASS (0.01s)
=== RUN   TestPackConfigCacheTTLExpiration  --- PASS (0.11s)
=== RUN   TestPackConfigCacheTeamIsolation  --- PASS (0.01s)
=== RUN   TestPackConfigCacheLegacyPacksBypass --- PASS (0.01s)
=== RUN   TestPackConfigCachePerformance   --- PASS (0.02s)
    Performance: cached=2.37ms, uncached=3.42ms, speedup=1.4x
```

Note: The 1.4x speedup is with mock datastore (no real DB/network). With
real MySQL over network, the speedup would be orders of magnitude larger
since cached calls skip 3-5 DB round-trips + ~50KB JSON marshal
entirely.

# 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)

## Testing

- [x] Added/updated automated tests
- [x] QA'd all new/changed functionality manually

- [x] Confirmed that the fix is not expected to adversely impact load
test results

## QA: Load test verification

To validate the real-world impact, QA should run a load test before and
after this change and compare:

1. Capture a CPU pprof profile **before** the change under load (e.g.,
10K+ simulated hosts, 50+ scheduled queries)
2. Deploy the change and capture a **second** pprof profile under the
same load
3. Compare the flamegraphs -- the `encoding/json.Marshal` and
`GetClientConfig` CPU time should drop significantly
4. Monitor Fleet container CPU utilization -- expect a measurable
reduction in steady-state CPU

See #21847 for the original pprof showing `encoding/json` dominating CPU
at scale.



<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Improved host config response performance by caching pack
configuration data.
* Query changes now automatically refresh cached host config so updates
appear promptly.

* **Bug Fixes**
* Host configs now stay accurate after creating, updating, deleting, or
applying queries.
* Cached data is isolated correctly and falls back to fresh data when
legacy packs are present.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-07-13 13:51:02 -04:00
Lucas Manuel Rodriguez 53c0ca8dda Use generated UUID for mdm_idp_account table on Linux and Windows (#49215)
Resolves #47626.

- [X] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/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**
- Fixed Fleet re-enrollment on Linux for end-user authentication SSO
when the re-enrollment email differs from the original enrollment email.
- Re-enrollment now remaps the device to the correct SSO account, with
no SSO callback/login errors, and does not reuse the prior account UUID.
- **Tests**
- Added a regression test covering re-enrollment with the same device
host UUID but a different IdP user/email, validating email updates and
account UUID change.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-13 14:43:39 -03:00
Konstantin Sykulev 9f111d2a24 Android managed config insert job with empty err vs null err (#49213)
**Related issue:** Resolves #49210

# Checklist for submitter

- [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] 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**
* Improved reliability when queuing managed configuration resend jobs by
ensuring newly created jobs start with a consistent empty error state.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-13 11:49:14 -05:00
Juan Fernandez f4ee5c6da9 Skip live-query reverse-index read when no reverse queries are active
Relates to #42441

Small-target live queries are stored in a per-host reverse index
(livequery:host:{hostID}) that QueriesForHost reads once per checkin via
SMEMBERS. That read was issued unconditionally on every host checkin —
even when no active query used the reverse model — so every checkin
probed a per-host key that did not exist and acquired an extra Redis
connection.
2026-07-13 09:53:37 -04:00
Sharon KatzandClaude Opus 4.6 a1531e6752 Fix CPE matching for python3-prefixed packages on Ubuntu/Debian (#48599)
Closes #43328

## Summary

- On Ubuntu/Debian/RHEL, `pythonPackageFilter` in osquery.go prepends
`python3-` to Python package names (e.g., `geopandas` becomes
`python3-geopandas`) to match OVAL definitions
- However, the CPE database uses the bare package name (e.g.,
`geopandas`, not `python3-geopandas`), so CPE matching fails and no
vulnerabilities are reported
- This fix adds the stripped name (without `python3-` prefix) as an
additional product variation during CPE lookup, so both
`python3-geopandas` and `geopandas` are tried
- The original prefixed name is preserved so packages genuinely named
`python3-*` on PyPI (e.g., `python3-openid`, `python3-saml`) still match
correctly on non-Ubuntu platforms

## How I reproduced

Used the `nvdvuln` tool to simulate CPE matching:

**Before fix** (on main branch):
```
$ go run --tags=fts5 tools/nvd/nvdvuln/nvdvuln.go \
    --software_name python3-geopandas \
    --software_source python_packages \
    --software_version 1.0.1
Translating software to CPE...
Unable to match a CPE for the software...
```

**After fix:**
```
$ go run --tags=fts5 tools/nvd/nvdvuln/nvdvuln.go \
    --software_name python3-geopandas \
    --software_source python_packages \
    --software_version 1.0.1
Translating software to CPE...
Matched CPE: 0: cpe:2.3:a:geopandas:geopandas:1.0.1:*:*:*:*:python:*:*
Translating CPEs to CVEs...
CVEs found for python3-geopandas (1.0.1): CVE-2025-69662
```

Also verified with `python3-django` (version 3.2.12) -- correctly finds
CVE-2024-24680 and other CVEs.

## How I tested

- Unit tests: added test cases for `productVariations` covering:
- `python3-geopandas` (source: `python_packages`) -> produces both
`python3-geopandas` and `geopandas` variations
- `python3-django` (source: `python_packages`) -> produces both
`python3-django` and `django` variations
- `requests` (source: `python_packages`, no prefix) -> no extra
variations added
- Manual: ran `nvdvuln` tool for both packages from the issue, confirmed
CPE match and CVE detection
- Lint: `make lint-go-incremental` passes clean


🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Bug Fixes**
* Improved vulnerability detection for Python packages on Ubuntu/Debian
by handling package names with or without the `python3-` prefix.
* Added additional matching variations derived from sanitized names,
ensuring both full and stripped forms are considered.
* Ensured existing non-Python package matching behavior remains
unchanged.
* **Tests**
* Expanded NVD sanitization and product variation test coverage for
`python_packages` scenarios (including cases with and without the
`python3-` prefix).
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-07-13 09:46:49 -04:00
c5575e9d9a Add PSSO end to end integration tests (#48589)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #47171

Added integration tests for the fleet-psso feature and added PSSO
functionality to our MDM test client - idea being it is so tightly
integrated into the MDM side of things on the Apple side AND we ideall
want osquery-perf to be able to exercise it(coming in the next PR)

# 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.

- [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**
* Added Apple Platform SSO (PSSO) support for device registration,
password login, key requests, and key exchange.
* Added a simulator/test device for exercising the full PSSO workflow
end-to-end.
* Made PSSO AASA development app IDs configurable and enhanced macOS
PSSO activity in performance testing (with new counters).
  * Improved local macOS Desktop packaging/signing configurability.

* **Bug Fixes**
* Strengthened PSSO token/crypto handling, including algorithm pinning,
key ID canonicalization, encrypted assertion `typ` validation, and
replay protection.

* **Tests**
* Added extensive crypto interoperability tests (including Apple
known-answer vectors) plus new end-to-end integration coverage.
<!-- 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: Magnus Jensen <magnus@fleetdm.com>
2026-07-10 18:51:33 -04:00
Jordan Montgomery 91971a3637 Add better index to nano_enrollment_queue (#48865)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #48883

# 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

For unreleased bug fixes in a release candidate, one of:

- [ ] Confirmed that the fix is not expected to adversely impact load
test results
- [ ] Alerted the release DRI if additional load testing is needed

## Database migrations

- [x] Checked schema for all modified table for columns that will
auto-update timestamps during migration.
- [x] Confirmed that updating the timestamps is acceptable, and will not
cause unwanted side effects.
- [x] Ensured the correct collation is explicitly set for character
columns (`COLLATE utf8mb4_unicode_ci`).

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Improved performance for retrieving the next Apple MDM command, making
queue lookups faster and more reliable.
* Added a new database index to better support ordering and selection of
pending commands.
* **Tests**
* Added coverage to verify the new indexing behavior is applied
correctly during database updates.
* **Chores**
* Updated database schema and migration records to include the new
index.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-10 15:51:14 -04:00
Carlo DiCelico 06863c4b37 Merge remote-tracking branch 'origin/main' into feat/28108-multiple-custom-packages
# Conflicts:
#	frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/LibraryItemAccordion/LibraryItemAccordion.tsx
#	frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/SoftwareTitleDetailsPage.tsx
#	pkg/spec/gitops.go
#	server/datastore/mysql/schema.sql
#	server/fleet/software_installer.go
2026-07-10 14:48:55 -04:00
078fbc0f40 Add Targeted platforms column and platform filter to Policies page (#44125)
- @noahtalerman: For the following quick win:
  - https://github.com/fleetdm/fleet/issues/23737

## Summary

Adds a "Targeted platforms" column and a platform filter dropdown to the
Policies page (`/policies/manage`), matching the pattern already used on
the Reports page (`/queries/manage`, `ManageQueriesPage`).

### Frontend
- New non-sortable **Targeted platforms** column rendered via
`PlatformCell`, sourced from each policy's comma-separated `platform`
field.
- New platform filter dropdown (All / macOS / Windows / Linux /
ChromeOS) wired as a `customControl` on the Policies table, alongside
the existing automation filter. Selecting a value pushes a new URL (not
a replace), resets `page` to 0, and updates the `platform` query param.
- `ManagePoliciesPage` reads `location.query.platform` and threads it
through to both `globalPoliciesAPI.loadAll` / `teamPoliciesAPI.loadAll`
and the react-query keys, plus the count endpoints. The
automation-filter and count "hide" conditions now include the platform
filter so they remain visible when only a platform filter is active.
- `frontend/services/entities/global_policies.ts` and `team_policies.ts`
accept an optional `platform` param (with `"all"` normalized to
`undefined`).
- Added tests for the new column and dropdown in
`PoliciesTable.tests.tsx`.

### Backend
- Added `Platform string ` + `` `query:"platform,optional"` `` to
`ListGlobalPoliciesRequest`, `CountGlobalPoliciesRequest`,
`ListTeamPoliciesRequest`, `CountTeamPoliciesRequest`.
- Extended datastore and service signatures (`ListGlobalPolicies`,
`ListTeamPolicies`, `ListMergedTeamPolicies`, `CountPolicies`,
`CountMergedTeamPolicies`, `ListGlobalPolicies`/`ListTeamPolicies` on
the service) to accept a `platform string` arg. Mocks and all call sites
updated.
- Platform filtering in SQL uses a new helper `platformFilterClause`:
  ```sql
  AND (p.platforms = '' OR FIND_IN_SET(?, p.platforms))
  ```
so policies targeting "all platforms" (empty `platforms` field) always
match regardless of the selected filter. `FIND_IN_SET` uses a bound
parameter (no injection risk).
- Added a new MySQL integration test `testPoliciesPlatformFilter`
covering empty-platform (match-all), per-platform filter, and
team/merged paths.

### Docs
- REST API docs for `GET /api/v1/fleet/global/policies`, `GET
/api/v1/fleet/fleets/:id/policies`, and the corresponding `/count`
endpoints now document the `platform` query param.
- Added `changes/policies-targeted-platforms-filter`.

## Behavior

- `platform=all` (or missing) returns all policies.
- Selecting a specific platform returns policies whose `platforms`
column is empty OR contains the selected token.
- The dropdown only renders when the table is searchable (results exist
OR any filter is active).
- Changing the filter pushes a new URL and resets the page.

# Checklist for submitter

- [x] Changes file added for user-visible changes in `changes/`.

- [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] 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

Local verification:
- `go build ./...` — clean
- `go vet ./server/... ./cmd/... ./ee/...` — clean
- `make lint-go-incremental` — 0 issues
- Go service-level policy tests pass. MySQL integration tests compile
but could not be run locally (no Docker); CI will exercise the new
`testPoliciesPlatformFilter` test.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added a "Targeted platforms" column with platform icons and an "All
platforms" option.
* Added a platform filter dropdown to scope policy lists; counts,
last-updated, and controls adapt when a platform filter is active.
Backend now honors an optional platform query parameter so filtering
returns matching policies.

* **Tests**
* Added and updated unit and integration tests covering the new column,
filter UI, and platform-filtered policy listings.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: nulmete <nicoulmete1@gmail.com>
2026-07-10 13:32:16 -05:00
RachelElysia 2c9fa3767e Fleet UI: Multi-package secondary UI — policy automation, setup experience, install-details hash (#49079) 2026-07-10 11:26:20 -07:00
Carlo 6cfc4a3611 Add GitOps support for macOS script-only packages in setup experience (#49089)
**Related issue:** Resolves #43667

  # Summary

Adds a `setup_experience_platforms` field to the GitOps software package
spec so `.sh` script-only installers can be selected for macOS setup
experience declaratively. Reconciles the cross-platform selection table
on every batch apply.

  # 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

  ## New Fleet configuration settings

- [x] Verified that the setting is exported via `fleetctl
generate-gitops`
- [x] Verified the setting is documented in a separate PR to [the GitOps
documentation](https://github.com/fleetdm/fleet/blob/main/docs/Configuration/yaml-files.md#L485)
- [x] Verified that the setting is cleared on the server if it is not
supplied in a YAML file (or that it is documented as being optional)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added declarative `setup_experience_platforms` to software package
definitions to control “setup experience” targets, including selecting
script-only installers for macOS (mapped appropriately).
* Batch uploads now propagate these cross-platform selections and
reconcile installer cross-entries.

* **Bug Fixes**
* Improved platform normalization (trimming, casing, alias mapping),
deduplication, and extension-specific validation.
* Enhanced update behavior: omitting the field leaves existing
selections unchanged; providing an empty list clears them, with correct
setup/installation timing.

* **Tests**
* Added unit and integration coverage for normalization and batch
re-apply/reconcile behavior (nil vs empty, idempotency, mixed updates,
and validation failures).
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-10 13:52:48 -04:00
Magnus Jensen 790f457bf0 SAAD: GitOps for DDM assets (#49046)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #48570

# 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. Added in a previous PR

- [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

* **New Features**
* Added end-to-end Apple DDM asset support in GitOps, including export
and GitOps parsing for `macOS settings` assets.
* Introduced Apple DDM asset management APIs
(list/get/download/create/delete) plus a batch set operation with
dry-run.
* **Bug Fixes**
* Improved Apple MDM/DDM reconciliation so referenced asset updates
trigger re-delivery via asset-aware tokening.
* Added safer validation around asset type changes and deletion
conflicts when assets are still referenced.
* **Tests**
* Expanded unit and integration coverage for asset parsing, upload/apply
behavior, reconciliation, and access control.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-10 12:56:26 -04:00
Magnus Jensen 2b2a5991a4 handle client error decoding errors in ACME urls (#49137)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #46282

# 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**
* Malformed ACME URLs and resource identifiers now return a clear **400
Bad Request** response instead of a **500 Internal Server Error**.
* Error details were improved to more accurately distinguish malformed
client requests.
* **Tests**
* Added an integration test covering invalid ACME endpoint path IDs
across resource types, verifying **400** responses with the expected
malformed error type.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-10 12:31:17 -04:00
Jonathan Katz 307f9b3108 Add hash_sha256 field to host installer result and install software activity (#49085)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #
- Adds hash_sha256 field to host installer result and install software
activity so they can be used in combination to cover past activities
with existing installers + all new activities even if their installer
will get deleted

# Checklist for submitter


## 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

* **New Features**
* Software installation results now include the installer’s SHA-256 hash
when available.
* Installed-software activity records now include the corresponding
`hash_sha256` value.

* **Bug Fixes**
* Hash values are retained in activity history after an installer is
deleted, while live results correctly show the value as unavailable.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-10 12:16:38 -04:00
Sharon Katz 2f0c1b338a Restrict SCIM endpoints to global admin only (#48858)
**Related issue:** N/A

# Checklist for submitter

- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
- [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

## Summary

Restricts SCIM endpoint access to global admin users only. Previously,
global maintainers also had access, which is broader than necessary.

### Changes
- **`server/authz/policy.rego`**: Removed `maintainer` from the SCIM
authorization rule, leaving only `admin`.
- **`ee/server/integrationtest/scim/scim_test.go`**: Updated auth tests
to verify maintainers now get 403, and that only admins can access SCIM
endpoints.

> **Breaking change for 4.89**: Customers using a global maintainer API
token for SCIM will need to update to a global admin token before
upgrading.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
  * Restricted SCIM endpoint access to global administrators only.

* **Bug Fixes**
* Prevented unauthorized observer and maintainer users from accessing
SCIM reads, writes, and details.
* Improved authorization error tracking for denied SCIM requests
(including recorded request status and details).

* **Tests**
* Updated SCIM authorization integration tests to reflect the tightened
admin-only access rules.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-10 11:53:48 -04:00
Magnus Jensen b4ce88645b SAAD: Support DDM assets in sync + reconciliation (#49016)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #48568 second part

# 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

## Summary by CodeRabbit

* **New Features**
* Apple declarative management now supports asset-backed declarations,
including device delivery of referenced DDM assets.
* Added a new device-facing endpoint to fetch managed DDM assets by
identifier (scoped to the device’s team).

* **Bug Fixes**
* Declaration/profile updates now refresh when referenced assets change
(not just variables).
* Device and host token/declaration matching now accounts for asset
update timing to trigger redeploys reliably.
* Improved validation to detect missing/invalid asset references before
saving.

* **Other**
* Updated which configuration declaration types are blocked during
user-provided validation.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-10 14:47:23 +02:00
Konstantin Sykulev a6a24391d1 Android filter out empty enterprises (#49097)
**Related issue:** Resolves #49004

- [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] 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**
* Improved Android managed-configuration resend processing by ignoring
invalid empty enterprise IDs.
* Prevented resend jobs from being queued when no valid enterprise ID is
available.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-09 18:51:34 -05:00