Commit graph

1582 commits

Author SHA1 Message Date
Nico
b4a207fb5a
Add ability to upload custom org logos (#44390)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #44330, Resolves #44331

# 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. (I'd defer integration tests to a
separate PR since this one is pretty large already.)

- [x] QA'd all new/changed functionality manually. I've tested this on
both the setup flow and the organization settings page. I haven't had
the time to test this on other places where we render the logo (macOS
setup experience / MDM migration dialog).


https://github.com/user-attachments/assets/95d4eae5-3da6-40f4-98a1-8575b97d96b3

## New Fleet configuration settings

- [x] Setting(s) is/are explicitly excluded from GitOps.

Will handle GitOps in a separate PR.

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

* **New Features**
  * Organizations can upload custom logos for light and dark modes.
* Registration and Org Settings support logo file upload, preview,
per-mode replace/delete, and validation (size & image formats).
* Activity feed records logo changes/deletions; site nav displays
uploaded logos per theme.
* File uploader/preview adds a Fleet logo graphic option and improved
logo validation.
  * Config/GitOps outputs now include separate dark/light logo fields.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-05 14:42:52 +02:00
Sharon Katz
beca71e674
Fix gitops dry-run to catch manual_agent_install + macos_script conflict (#44432)
**Related issue:** Resolves #34464

# 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.
- [x] Timeouts are implemented and retries are limited to avoid infinite
loops

## Testing

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

---

## What

GitOps `--dry-run` was succeeding when `macos_manual_agent_install` was
set to `true` and a `macos_script` was configured under
`setup_experience`, but the actual GitOps run would fail with:

```
Couldn't add setup experience script. To add script, first disable macos_manual_agent_install.
```

## Why

The `manual_agent_install` conflict validation only existed server-side
in `ee/server/service/setup_experience.go:SetSetupExperienceScript()`.
The script upload call (`uploadMacOSSetupScript()`) was gated by
`!opts.DryRun` in `server/service/client.go`, so during dry-run the
upload was skipped entirely and the validation never fired.

## Fix

Added client-side validation in `server/service/client.go` at the point
where the YAML-parsed `MacOSSetup` struct is processed — before the
script file is validated and loaded. This check runs for **both dry-run
and real runs**, catching the conflict early. Two code paths were fixed:

1. **Team path** (~line 803): Checks `setup.ManualAgentInstall.Value`
when `setup.Script.Value` is set
2. **No-team path** (~line 2603): Checks
`macOSSetup.ManualAgentInstall.Value` when `macOSSetup.Script.Value` is
set

## How I reproduced the issue locally

### Prerequisites
- MySQL and Redis running via Docker: `docker compose up -d mysql_test
redis`

### Steps
1. Wrote an integration test
(`TestDryRunMacOSSetupScriptWithManualAgentInstallConflict`) that:
   - Creates a GitOps user and fleetctl config
   - Creates a bootstrap package server serving `testdata/signed.pkg`
   - Creates a `.sh` script file with `echo "setup script"`
   - Creates a **global config** YAML (minimal server settings)
- Creates a **team config** YAML with `macos_manual_agent_install:
true`, `macos_script: <path>`, and `macos_bootstrap_package: <url>`
   - Runs `fleetctl gitops --dry-run` and asserts it fails
   - Runs `fleetctl gitops` (no dry-run) and asserts it fails

2. Ran the test **before the fix** — confirmed the bug:
   ```
Dry-run error: <nil> ← BUG: should have failed
Real run error: ...status 422...first disable macos_manual_agent_install
← correctly fails
   ```

3. Applied the fix and re-ran — **both dry-run and real run now fail**
with the `macos_manual_agent_install` conflict error.

### Test command
```bash
MYSQL_TEST=1 REDIS_TEST=1 go test -v \
  -run TestIntegrationsEnterpriseGitops/TestDryRunMacOSSetupScriptWithManualAgentInstallConflict \
  ./cmd/fleetctl/integrationtest/gitops/... -count=1 -timeout 600s
```

Both sub-tests (team and no-team paths) pass. All related existing tests
continue to pass:
- `TestMacOSSetup`, `TestMacOSSetupScriptWithFleetSecret`,
`TestDeletingNoTeamYAML`, `TestDisallowSoftwareSetupExperience`

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

* **Bug Fixes**
* GitOps dry-run now correctly fails when a macOS setup configuration
combines manual agent installation with a provided setup script,
preventing false-positive dry-run success.

* **Tests**
* Added unit and integration regression tests to verify dry-run and
real-run rejection of conflicting macOS setup configurations for both
team-scoped and unassigned host scopes.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-04 15:32:21 -04:00
Konstantin Sykulev
5c18f726b2
Add Info logging around vulnerability scanning phases (#44653)
related to [#44391](https://github.com/fleetdm/fleet/issues/44391)

This will add 10 info level log statements during vulnerability
scanning.
Example:
`ts=2026-05-03T18:32:26Z level=info msg="phase completed"
cron=vulnerabilities phase=nvd elapsed=59.450125s`


## Testing

- [x] QA'd all new/changed functionality manually


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

* **Improvements**
* Vulnerability scanning now logs overall elapsed time and per-phase
durations so operators can see how long full scans and each scanner
phase take.

* **Chores**
* Repository ignore settings updated to exclude an additional path
(non-functional housekeeping).
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: ksykulev <230639+ksykulev@users.noreply.github.com>
2026-05-04 14:17:23 -05:00
Konstantin Sykulev
779cdd663b
Periodic background job to cleanup Windows MDM command queue (#44458)
**Related issue:** Resolves #44190

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

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

* **New Features**
* Added a periodic cleanup job that removes aged, acknowledged Windows
MDM command-queue entries to reduce write pressure during ACK
processing.

* **Bug Fixes**
* Pending-command detection now excludes already-ACKed commands from
dispatch; queue rows are retained after ACK and cleaned later.

* **Tests**
* Added and updated tests to validate cleanup behavior and revised
ACK/queue semantics.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-05-04 11:32:45 -05:00
Juan Fernandez
2ee5404ed3
Validate label platform during gitops --dry-run (#42477) (#44594)
Resolves #42477 

Move the platform check into pkg/spec parseLabels so both --dry-run and
apply hit the same validation and surface the same error.
2026-05-04 07:18:07 -04:00
Juan Fernandez
376f602088
Fixed bug with about to expire CLI banner (#34924)
Resolves #34924

Updated the message shown on about to expire license to point to
https://fleetdm.com/learn-more-about/downgrading.
2026-05-04 07:17:08 -04:00
Noah Talerman
7cd2a1a34a
fleetctl preview: Clarify that this is for trying Fleet (#44133)
- Add link to deploy Fleet for long-lived instances (shown in `fleetctl
preview` Description field)
- Add helpful message after preview setup completes: "Use the stop and
reset subcommands to manage the server and dependencies once started."
2026-05-01 15:47:59 -04:00
Carlo
ce5640c99e
Prevent silent corruption of software title icons (#44540) 2026-05-01 14:19:48 -04:00
Noah Talerman
8755a4dddc
fleetctl new: Update automatic enrollment profile (#44441)
- @noahtalerman: We're updating the default profile for new Fleet
instances as part of this story:
  - https://github.com/fleetdm/fleet/issues/40905


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

* **Configuration Updates**
* Updated the default macOS enrollment profile name to "Fleet default
enrollment profile."
* Enrollment onboarding now shows the full setup flow (no setup items
are auto-skipped).
  * Removed region-specific configuration constraints.

* **Behavioral Changes**
  * MDM profile can be removed after enrollment.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-01 11:18:58 -06:00
Victor Lyuboslavsky
de86536f42
Redis-backed cache for host-by-key lookups (#43936)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #43928 

This PR adds a Redis-backed cache in front of the two host-by-key
lookups on the agent auth paths.

Docs: https://github.com/fleetdm/fleet/pull/44504

## What changes

**Read path (osquery/orbit auth):**

- `LoadHostByNodeKey` and `LoadHostByOrbitNodeKey` now check Redis
before falling through to MySQL.
- Successful lookups are cached for 60s ± 10% jitter (configurable via
`FLEET_REDIS_HOST_CACHE_TTL`).
- `NotFound` results are cached for 5s as a negative entry, dampening
repeated probes for keys that
do not exist (deleted hosts whose agents are still polling, attacker
scans, retry storms).
- Concurrent lookups for the same key collapse into one DB query via
`singleflight`. The shared
query runs under a context detached from any one caller's deadline so
the leader giving up does
not abort the work for joiners. The shared query is itself bounded by a
30s timeout so a wedged
  DB call cannot pin the singleflight slot indefinitely.

**Write path (invalidations):**

- These methods now invalidate the cache after a successful inner call:
`UpdateHost`, `SerialUpdateHost`, `UpdateHostOsqueryIntervals`,
`UpdateHostRefetchRequested`,
`UpdateHostRefetchCriticalQueriesUntil`,
`UpdateHostIdentityCertHostIDBySerial`, `EnrollOsquery`,
`EnrollOrbit`, `NewHost`, `DeleteHost`, `DeleteHosts`,
`CleanupExpiredHosts`,
  `CleanupIncomingHosts`, `AddHostsToTeam`.
- `AddHostsToTeam`, `DeleteHosts`, `CleanupExpiredHosts`, and
`CleanupIncomingHosts` use a pipelined
batch invalidator so 10k-host operations stay in the millisecond range
instead of taking minutes
  of sequential round-trips.
- Inner-call errors are not invalidations: a failing write leaves cached
state intact.

**Configuration:**

- New flags `FLEET_REDIS_HOST_CACHE_ENABLED` (default `true`) and
`FLEET_REDIS_HOST_CACHE_TTL`
  (default `60s`).
- Server refuses to start if the cache is enabled with `TTL <= 0`.

**Observability:**

- Three new OTEL counters under the `fleet` meter:
  - `fleet.host_cache.lookups{result=hit|negative_hit|miss}`
  - `fleet.host_cache.errors{op=get|set|del}`
-
`fleet.host_cache.invalidations{reason=update|enroll|team|delete|cert}`
- A pre-built SigNoz dashboard ships in
`tools/signoz/host_cache_dashboard.json`.

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

- [x] QA'd all new/changed functionality manually


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

* **New Features**
* Optional Redis-backed host lookup cache for osquery and orbit auth,
with automatic invalidation and metrics/monitoring dashboard.

* **Bug Fixes**
* Fixed host-removal batching so cache-related removals use correct
chunks.

* **Tests**
* Added comprehensive host-cache unit tests covering hits, negative
cache, invalidation, concurrency, and JSON round-trips.

* **Chores**
* New config flags to enable the cache and set TTL (default 60s ±10%
jitter).
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-01 12:06:16 -05:00
Lucas Manuel Rodriguez
1e4a9f292f
Add activities for user actions on labels (#44522)
Resolves #36976

- [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**
* Label operations (create, edit, delete) now generate activities shown
in the activity feed with label and optional fleet context.
* Host label add/remove operations emit corresponding label edited
activities; duplicate label names are deduplicated.
* Label activity types are selectable/filterable in the activity
dashboard.

* **Tests**
* Added unit, integration, and UI tests covering label activity
emission, rendering, filtering, and GitOps label lifecycle scenarios.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-01 10:19:45 -03:00
Tim Lee
13cec63bd1
Add RHEL 8/9/10 simulated hosts to osquery-perf (#44453) 2026-04-30 11:01:04 -06:00
Tim Lee
2d586cb2ff
fleetctl vulnerability-data-stream to download OSV data (#44260) 2026-04-30 10:46:51 -06:00
Carlo
07e4e7afe6
Short-circuit for empty software config in Gitops dry run (#44405)
Fixes #42607
2026-04-29 14:54:49 -04:00
Magnus Jensen
98cad56716
redirect to correct URL, and allow both URLs for MDM SSO SAML validation if set (#44156)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #41592 

# 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**
* Fixed SSO failures when a custom Apple MDM URL is configured: callback
requests are now redirected to the configured MDM URL when needed, and
SAML validation correctly considers the configured MDM/server URLs so
authentication succeeds for custom MDM setups.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-04-29 08:43:58 -06:00
Scott Gress
4334017b38
Add Vulnerabilities exposure dataset (#44124)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** For #43769

# Details

Adds methods to collect data for the `cve` dataset. As with all sets
this is collected at hourly granularity, but unlike the `uptime` set,
the `cve` set uses the "snapshot" strategy so that we record at most one
change (the most recent) per hour.

For this first iteration, we are _recording_ data for all CVEs (i.e.,
which hosts were exposed to which CVEs at a given time), but we are only
_reporting_ a subset of CVEs for the dashboard chart. See [this
comment](https://github.com/fleetdm/fleet/pull/44124#discussion_r3155554405)
for more info.

# 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
- [X] Spot-checked the CVEs chosen by the `trackedCVESoftwareMatchers`
and didn't find any outside of the expected
- [X] With [front-end PR](https://github.com/fleetdm/fleet/pull/44261),
generated chart:
<img width="706" height="421" alt="image"
src="https://github.com/user-attachments/assets/539d9877-6573-4406-a159-1d2a711a045f"
/>



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

* **New Features**
* Host vulnerability (CVE) chart added to the dashboard; CVE chart data
collection is now active.
  * Critical CVE tracking surfaces high-severity vulnerabilities.

* **Improvements**
* CVE chart refreshes every 3 hours (was daily) for more timely
insights.
* Snapshot collection reconciles and closes prior data during empty runs
to keep charts accurate.
* CVE queries may produce zero datapoints when no tracked CVEs exist,
without affecting other metrics.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-04-29 09:30:31 -05:00
Lucas Manuel Rodriguez
3cadfa1714
Fix issue with fleet's docker image in k8s environments (#44373)
Resolves #44298

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

1. Running the docker image pushed by this PR with the user 3333 doesn't
fail anymore:
```sh
docker run --platform linux/amd64 -it --user 3333:3333 fleetdm/fleet@sha256:1a06bcae25e13e37f871378c7c156f5a2cdf67bc3c3e3bcdc95b6afc0c6decbb
[...]
ts=2026-04-29T13:25:56Z level=warn msg="could not connect to db" err="dial tcp [::1]:3306: connect: connection refused" sleep_interval=0s
[...]
```
4.84.0 fails with:
```sh
docker run --platform linux/amd64 -it --user 3333:3333 fleetdm/fleet:v4.84.0@sha256:51b56ad59a840b28e074ff9b06d6d5b232b0ca2f0d999bb164820da69c7cbe15

Failed to fetch user info for home directory: user: unknown userid 33332026/04/29 13:28:08 71 <nil>
```
2. `strings ./build/fleet | rg github.com/AbGuthrie/goquery/v2` returns
nothing in this branch and returns plenty of matches in `main`.
3. Smoke tested `fleetctl goquery` functionality.

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

## Summary by CodeRabbit

* **Bug Fixes**
* Resolved Docker image startup failures in Kubernetes environments
caused by a dependency side effect.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-04-29 11:19:13 -03:00
Martin Angers
2c609ae78e
CSAH: appconfig/gitops/DB migration to add preserve_host_activities_on_reenrollment field (#44212)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #43943 

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

See
https://github.com/fleetdm/fleet/issues/43943#issuecomment-4329658412

## Database migrations

- [x] Checked schema for all modified table for columns that will
auto-update timestamps during migration.

## 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)
(see https://github.com/fleetdm/fleet/pull/43877/changes)
- [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)
- [ ] Verified that any relevant UI is disabled when GitOps mode is
enabled (should be done by
https://github.com/fleetdm/fleet/issues/43947)



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

* **New Features**
* Added a configuration option to preserve host activities during host
re-enrollment, letting admins choose whether activity history is
retained when hosts re-enroll.

* **Chores**
* Updated defaults and database migration state so the new setting is
present in stored and generated configs and in GitOps outputs.

* **Tests**
* Added unit, integration, migration, and GitOps fixtures to validate
behavior, serialization, and upgrade semantics.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-04-28 08:47:38 -04:00
Scott Gress
9ae4373f89
Don't ignore GitOps secrets on free tier (#44148)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #44118

# Details

On free tier, ignore exceptions and always apply enroll secrets when
present.

# 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
@AndreyKizimenko QA'd 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 GitOps to correctly apply enrollment secrets and labels on free
tier licenses, even when exception flags are configured.

* **Tests**
* Added tests validating that GitOps properly applies secrets and labels
for free tier customers.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-04-27 16:31:58 -05:00
Lucas Manuel Rodriguez
bd18bac797
Adding gitOpsModeEnabled and gitOpsModeExceptions to anonymous statistics payload (#44161)
**Related issue:** Resolves #42240.

- [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**
* Statistics now include GitOps mode: whether it’s enabled and the
ordered list of configured exception categories (serializes as an empty
list when none).

* **Tests**
* Added tests for GitOps-related statistics transitions and made
statistics-timing tests deterministic for reliable behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-04-27 08:28:49 -03:00
Scott Gress
9b01710a80
Don't throw gitops-exceptions-related errors on Free tier (#44118)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #44098 

# Details

We set the "secrets" exception on for all new instances (and the label
exception for existing instances), but you can't turn them off in the
free tier. That means GitOps runs (including the one we use to
initialize new instances) would fail with the "you can't use this key
because the exception is on" error. This PR fixes the issue by not
enforcing that rule for free tier instances.

# 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] added test verifying that the free tier can run gitops using
excepted keys w/out error, and verified that it fails on main and passes
on this branch
- [X] QA'd all new/changed functionality manually
  - [X] spun up a new free-tier server successfully

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**
* GitOps exception enforcement no longer blocks free-tier users;
enforcement is applied only for premium licenses, allowing GitOps
applies on free tiers.
* **Tests**
* Added an integration test validating free-tier GitOps behavior to
prevent regressions.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-04-24 10:46:45 -05:00
Juan Fernandez
1539c6b094
Enforce consistent fleet name uniqueness across UI and GitOps (#33557)
Resolves #33557 

The tems.name column uses utf8mb4_unicode_ci, so names like "ABC" and
"abc" compare as equal at the database level. Before this change name
collisions were handled in different ways in the UI and in GitOps.

The changes introduced here, consolidates the logic used for detecting
name collisions in all code path. All conflicts return 409 with the
canonical copy "Fleet names must differ by at least one non-special
character (case-insensitive).
2026-04-23 16:44:09 -04:00
Jonathan Katz
ba0f6b3c72
Update GitOps for managed local account fields (#44058)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #42948 
- Updated `(mos *MacOSSetup) Validate()` and `(mos *MacOSSetup)
SetDefaultsIfNeeded()` to account for new fields
- Updated default creation and editing for team edit/creation paths
- Updated `generate-gitops` warning message from `macos_setup` to
`setup_experience`
- Updated fields types to optjson and updated test files

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

- [ ] 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
- Team edit and team creation through GitOps, validated config with `
curl -k -X GET 'https://localhost:8080/api/v1/fleet/fleets/:id'`
- New error message says `setup_experience` instead of `macos_setup`


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

* **New Features**
* Added macOS MDM settings to control local account behavior: enable
managed local accounts (default false) and specify end-user local
account type (default "admin") for fleet and team configs. GitOps output
now highlights unsupported setup-experience cases.

* **Tests**
* Updated fixtures and integration tests to assert and persist the new
macOS local-account settings across config, team, and GitOps scenarios.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-04-23 15:05:27 -04:00
Scott Gress
28908e6083
Dashboard charts backend (#43910)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** For #42812 

# Details

This PR implements a new bounded context, `chart`, with a single
endpoint `/charts`. The context encompasses a framework for recording
and querying and aggregating historical data for Fleet hosts, and
returning that data via the API for the purpose of charting.

This initial iteration has a full implementation of a dataset called
"uptime" which captures which hosts were online hour-by-hour (online
meaning, having been "seen" at some point during that hour). It has a
partial implementation of a "cve" dataset which will capture which hosts
were vulnerable to which CVEs during a given day.

### Data storage

Data is stored in an SCD (slowly-changing dimension) format in the
`host_scd_data` table, where the main "value" in a row is stored in the
`host_bitmap` column, which is a `mediumblob` where each bit encodes a
host ID (bit one represents host ID 1, bit 1444 represents host ID 1444,
etc.). The set of bits set on a row represents that hosts for which that
dataset is "on" during a given time period represented by the
`valid_from` (inclusive) and `valid_to` (exclusive) dates, where a
`valid_to` can have the special "sentinel" value 9999-12-31T00:00:00.000
meaning that the row is still "open" (the value represents everything
from `valid_from` to the present). Additionally an `entity_id` column
can be used for datasets with multiple dimensions, e.g. CVE exposure or
software usage which would have entity IDs representing CVEs or software
items respectively.

### Data collection

Data is collected via a cron job that runs every 10 minutes. Each
dataset has its own `Collect` method which will sample the data for the
given moment. For example the "uptime" dataset gathers the set of hosts
that are online at the moment, and the "cve" dataset will gather the set
of hosts that are vulnerable to each CVE at that moment. The sample can
then be recorded using one of two strategies:

* `accumulate`: bitwise OR the sample with any data already recorded for
the current hour, or add a new pre-closed row for that hour.
* `snapshot`: if there is no open row, create one with the sample and
`valid_to set` to the sentinel. Otherwise:
  * If the sample has the same value as the current open row, do nothing
* If the sample has a different value and the current open row's
`valid_from` is within the same hour, update the current row's value
* If the sample has a different value and the current open row's
`valid_from` is not within the same hour, close the current open row and
start a new one with `valid_from` = the start of the current hour

### Data retrieval 

1. Gets the set of host IDs to retrieve data for. This starts with the
set of host IDs in the requested fleet (or all the hosts a user has
access to if no `fleet_id` param was passed to the `/charts` endpoint),
and further whittled down by any filter options supplied with the
request (labels, platforms, etc.).
2. Finds all `host_scd_data` rows for the requested dataset and date
range (i.e. all rows whose `valid_from` is < the date range end and
`valid_to` is > the date range start).
3. Calculates the date ranges of the "buckets" to return datapoints for.
For the uptime chart we default to 3-hour buckets, so we want 8 buckets
per day.
4. Iterates over each bucket and finds the row or rows from
host_scd_data that cover that bucket range. For datasets using the
"accumulate" strategy, the values for those rows are ORed together. For
"snapshot"s, we take the one active at the bucket end time to represent
the bucket (e.g. "which hosts had a given CVE at the end of the day")

### Tools

This PR includes two dev tools that don't require deep review:

* **chart-backfill** - used to backfill data to various datasets for
testing
* **charts-collect** - used to collect data from a live server via the
API and put into a local hosts_scd_data table

# 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
  - With [front-end branch](https://github.com/fleetdm/fleet/pull/43878)
<img width="712" height="434" alt="image"
src="https://github.com/user-attachments/assets/b2ccce49-b5fd-4076-b47f-0eea6a53260c"
/>

## 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**
* Added charting bounded context: HTTP API for metrics (uptime, CVE),
dataset registry, hosted dataset collection, background
collection/cleanup with opt-out env.
* New utilities: host bitmap operations and string-list/uint-list
parsers.
  * New CLI tools to collect and backfill chart data.

* **Database**
  * Migration and schema to store host time-series SCD chart data.

* **Tests**
* Extensive unit and integration tests for service, storage, caching,
cron, and utilities.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-04-23 12:43:23 -05:00
Martin Angers
5da912a33e
Bugfix: escape characters not supported in JSON when resolving variables (#43955)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #38013 

# 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

See
https://drive.google.com/file/d/1zeFNLuf_rT5FWzDiYyL2_hbIBW2neba-/view?usp=drive_link

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

## Summary by CodeRabbit

* **Bug Fixes**
* GitOps variables in JSON configuration profiles (Apple DDM
declarations and Android profiles) are now automatically escaped for
JSON special characters, ensuring proper handling of sensitive values.

* **Tests**
* Added JSON configuration profile escaping validation to the enterprise
GitOps integration test suite.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-04-23 10:34:12 -06:00
Tim Lee
79da2f0028
Add RHEL OSV vulnerability scanning (#43377) 2026-04-22 15:34:23 -06:00
Tim Lee
9feb9c2be0
Fix Recovery Lock password desync on MDM re-enrollment (#43827) 2026-04-22 15:17:48 -06:00
Victor Lyuboslavsky
d79dc50883
Remove Win MDM "Status on a Status" from osquery perf (#43940)
Estimate ~5% load improvement.

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

## Summary by CodeRabbit

* **Bug Fixes**
* Fixed MDM command handling in the performance testing agent to
properly skip duplicate status responses.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-04-22 10:42:31 -05:00
Carlo
39e4f616ea
macOS managed local account foundations (#43381)
Implements both #42942 and #42943 

Co-authored-by: jkatz01 <yehonatankatz@gmail.com>
2026-04-22 09:05:07 -04:00
Scott Gress
91d9b25924
Allow conditional downloads across fleets (#43679)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #43417

# 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`.
done in https://github.com/fleetdm/fleet/pull/42216

## Testing

- [X] Added/updated automated tests
- [X] QA'd all new/changed functionality manually
- Using a local fileserver, added the same software to two fleets and
ran `fleetctl gitops`. Verified that the first fleet downloaded the
file, the second fleet used the cache, and both fleet showed the
software installer in the UI.

## Summary by CodeRabbit

* **Chores**
* Updated software installer lookup mechanism to support optional
team-scoped searches, enabling fallback to cross-team installer cache
when team-specific installers are unavailable.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-04-21 17:06:23 -05:00
Konstantin Sykulev
ba7720f7de
Use UTC time for osv processing (#43889)
**Related issue:** Resolves #39900

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

* **Bug Fixes**
* Improved timestamp handling for OS vulnerability data synchronization
to use UTC timezone when synchronization is enabled, ensuring consistent
timing behavior across different system configurations.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-04-21 14:42:16 -05:00
Tim Lee
e0d7e0c6b8
Add RHEL support to osv-processor (#43277) 2026-04-21 13:39:22 -06:00
Martin Angers
ade597b5e1
DDMV: improve osquery-perf simulation of DDM traffic (#43607)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #43050 

## Testing

- [x] QA'd all new/changed functionality manually

Confirmed the traffic sequence with ngrok and DDM stats are as expected
in the osquery-perf logs:

### Adding a new DDM

* `DeclarativeManagement` command and Ack
* `tokens` request
* `declaration-items` request
* `activation` for the DDM
* `configuration` for the DDM
* `tokens` request confirms changes settled
* `status` request

### Remove/re-add DDM (no global change)

* `DeclarativeManagement` command and Ack
* `tokens` request

### Adding a second DDM

* `DeclarativeManagement` command and Ack
* `tokens` request
* `declaration-items` request
* `activation` for the new DDM only
* `configuration` for the new DDM only
* `tokens` request confirms changes settled
* `status` request

### Removing a DDM

* `DeclarativeManagement` command and Ack
* `tokens` request
* `declaration-items` request
* `tokens` request
* `status` request

### Remove all DDMs

* `DeclarativeManagement` command and Ack
* `tokens` request
* `declaration-items` request
* `tokens` request
* `status` request

---

State correctly updates on the host's profiles:

<img width="1246" height="512" alt="image"
src="https://github.com/user-attachments/assets/0d289d4e-1e9b-4283-aef0-fd1ab3ecb355"
/>


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

* **New Features**
* Improved macOS Declarative Management sync: faster convergence,
fetches only changed declarations, detects removals, and sends
consolidated status updates.

* **Monitoring**
* Added metrics to track declaration token fetch success and error
rates.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-04-21 13:26:46 -04:00
Juan Fernandez
2b35eabd5d
Added middleware for api-only users auth (#43772)
Fixes #42885

Added new middleware (APIOnlyEndpointCheck) that enforces 403 for
API-only users whose request either isn't in the API endpoint catalog or
falls outside their configured per-user endpoint restrictions.
2026-04-21 07:11:33 -04:00
Tim Lee
81ea7436c3
Fix OSV sync shallow clone failing on quiet weekends (#43450)
## Summary

The nightly OSV artifact generation in `fleetdm/vulnerabilities` failed
over the weekend with:

```
fatal: error processing shallow info: 4
```

at `cmd/osv-processor/sync-and-detect-changes.sh` during:

```bash
git fetch --shallow-since="3 days ago" origin main
```

Root cause: `git fetch --shallow-since` errors out when the upstream
(`canonical/ubuntu-security-notices`) has zero commits newer than the
cutoff. Canonical didn't push anything over the weekend, so the 3-day
window returned empty and upload-pack produced an unusable shallow
response.

Fix:
- Fall back to `git fetch --depth=3` if `--shallow-since` still returns
empty, so the initial clone always succeeds.

Subsequent runs reuse the existing clone and take the other branch of
the script (plain `git fetch origin main`), which doesn't have this
failure mode.

Failing run:
https://github.com/fleetdm/vulnerabilities/actions/runs/24330589309/job/71035337352

## Test plan

- [x] Re-run the Ubuntu OSV artifact generation workflow; initial clone
succeeds regardless of upstream push frequency.
- [x] Manually exercise the cold-cache path locally: `rm -rf
ubuntu-security-notices &&
./cmd/osv-processor/sync-and-detect-changes.sh` — completes without
error.

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

* **Bug Fixes**
* Improved initial repository sync: if the primary shallow fetch returns
no commits, the process now falls back to a limited-depth fetch, warns
the user, and shows recent commit history before continuing. Downstream
change detection and existing behavior for already-cloned repos remain
unchanged.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Konstantin Sykulev <konst@sykulev.com>
2026-04-20 10:30:55 -05:00
Martin Angers
2a8803884b
DDMV: Support Fleet variables in DDM (#43222)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #43047 

# 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] 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
See
https://github.com/fleetdm/fleet/issues/42960#issuecomment-4244206563
and subsequent comments.


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

* **New Features**
* Apple DDM declarations support a vetted subset of Fleet variables with
per-host substitution; premium license required. Declaration tokens and
resend behavior now reflect variable changes; unresolved host
substitutions mark that host’s declaration as failed.

* **Bug Fixes**
* Clearer errors for unsupported or license-restricted Fleet variables
and more consistent DDM resend/update semantics when variables change.

* **Tests**
* Added extensive unit and integration tests covering Fleet variable
validation, substitution, token changes, resends, and failure states.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-04-20 09:14:52 -04:00
Victor Lyuboslavsky
bd74265aa6
Fix broken OTEL due to #43298 (#43705)
Resolves broken OTEL on main, which was introduced with dependabot
update #43298

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

## Summary by CodeRabbit

* **Chores**
* Updated OpenTelemetry semantic conventions dependency to the latest
version.

* **Tests**
  * Added test coverage for OpenTelemetry resource creation validation.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-04-17 09:05:26 -05:00
Juan Fernandez
f791f4b309
Allow the creation of API-only users (#43440)
**Related issues:** 
- Resolves #42882 
- Resolves #42880 
- Resolves #42884 

# Changes

- Added POST /users/api_only endpoint for creating API-only users.
- Added PATCH /users/api_only/{id} for updating existing API-only users.
- Updated `fleetctl user create --api-only` removing email/password
field requirements.
2026-04-16 11:11:39 -04:00
Dan Tsekhanskiy
aff440236e
Add cache option for software packages to skip re-downloading unchanged content (#42216)
**Related issue:** 
Ref #34797
Ref #42675 

## Problem

When a software installer spec has no `hash_sha256`, Fleet re-downloads
the package, re-extracts metadata, and re-upserts the DB on every GitOps
run, even if the upstream file hasn't changed. For deployments with 50+
URL-only packages across multiple teams, this wastes bandwidth and
processing time on every run.

## Solution

By default, use etags to avoid unnecessary downloads:

1. First run: Fleet downloads the package normally and stores the
server's ETag header
2. Subsequent runs: Fleet sends a conditional GET with `If-None-Match`.
If the server returns 304 Not Modified, Fleet skips the download,
metadata extraction, S3 upload, and DB upsert entirely

Opt-out with `always_download:true`, meaning packages continue to be
downloaded and re-processed on every run, same as today. No UI changes
needed.

```yaml
url: https://nvidia.gpcloudservice.com/global-protect/getmsi.esp?version=64&platform=windows
always_download: true
install_script:
  path: install.ps1
```

### Why conditional GET instead of HEAD

Fleet team [analysis of 276 maintained
apps](https://github.com/fleetdm/fleet/pull/42216#issuecomment-4105430061)
showed 7 apps where HEAD requests fail (405, 403, timeout) but GET works
for all. Conditional GET eliminates that failure class: if the server
doesn't support conditional requests, it returns 200 with the full body,
same as today.

### Why opt-in

5 of 276 apps (1.8%) have stale ETags (content changes but ETag stays
the same), caused by CDN caching artifacts (CloudFront, Cloudflare,
nginx inode-based ETags). The `cache` key lets users opt in per package
for URLs where they've verified ETag behavior is correct.

Validation rejects `always_download: true` when hash_sha256` is set

## Changes

- New YAML field: `cache` (bool, package-level)
- New migration: `http_etag` VARCHAR(512) column (explicit
`utf8mb4_unicode_ci` collation) + composite index `(global_or_team_id,
url(255))` on `software_installers`
- New datastore method: `GetInstallerByTeamAndURL`
- `downloadURLFn` accepts optional `If-None-Match` header, returns 304
as `(resp, nil, nil)` with `http.NoBody`
- ETag validated per RFC 7232 (ASCII printable only, no control chars,
max 512 bytes) at both write and read time
- Cache skipped for `.ipa` packages (multi-platform extraInstallers)
- TempFileReader and HTTP response leak prevention on download retry
- Docs updated in `yaml-files.md`

## What doesn't change

- Packages with `hash_sha256`: existing hash-based skip, untouched
- FMA packages: FMA version cache, untouched
- Packages with `always_download: true`: identical to current behavior
- Fleet UI: no changes

## Test plan

Automated testing:
- [x] 16 unit tests for `validETag`
- [x] 8 unit tests for conditional GET behavior (304, 200, 403, 500,
weak ETag, S3 multipart, no ETag)
- [x] MySQL integration test for `GetInstallerByTeamAndURL`
- [x] All 23 existing `TestSoftwareInstallers` datastore tests pass
- [x] All existing service tests pass

Manual testing:
- [x] E2E: 86 packages across 6 CDN patterns, second apply shows 51
conditional hits (304)
- [x] @sgress454 used a local fileserver tool to test w/ a new instance
and dummy packages


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

* **New Features**
* ETag-based conditional downloads to skip unchanged remote installer
files.
  * New always_download flag to force full re-downloads.

* **Tests**
* Added integration and unit tests covering conditional GETs, ETag
validation, retries, edge cases, and payload behavior.

* **Chores**
* Persist HTTP ETag and related metadata; DB migration and index to
speed installer lookups.
* Added installer lookup by team+URL to support conditional download
flow.

* **Bug Fix**
* Rejects using always_download together with an explicit SHA256 in
uploads.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Scott Gress <scott@fleetdm.com>
Co-authored-by: Scott Gress <scott@pigandcow.com>
Co-authored-by: Ian Littman <iansltx@gmail.com>
2026-04-14 13:01:33 -05:00
Ian Littman
3675f8ff90
Clean up setup experience cancellation behavior (#43437)
Fixes #34288.

# 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

* **New Features**
* Setup experience cancellations now create explicit cancellation
activities for skipped/failed software and VPP app installs, plus a new
"Canceled setup experience" activity type and a from_setup_experience
flag. Activity text and host activity views now indicate "during setup
experience" when applicable.
* **Tests**
* Added and updated tests for cancellation activity creation, VPP
license-failure handling, and WasFromAutomation/from_setup_experience
behaviors.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-04-14 09:39:26 -05:00
Tim Lee
1f45f5383a
Add Windows Program Files scan for software without registry entries (#42992) 2026-04-11 13:42:50 -06:00
Juan Fernandez
1bc32467a7
Implement GET /api/v1/fleet/rest_api (#42883)
**Related issue:** Resolves #42883 

Added a new premium GET /api/_version_/fleet/rest_api endpoint that
returns the contents of the embedded `api_endpoints.yml` artifact.
2026-04-10 11:12:38 -04:00
Ian Littman
8509b18c46
🤖 Add fallback for FMA manifest URL pulls (#43312)
**Related issue:** Resolves #42754

# 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

* **Bug Fixes**
* Improved app manifest retrieval with automatic fallback to hosted
copies when the primary source is unavailable, reducing sync failures.

* **Documentation**
* Clarified that Fleet will fall back to hosted manifest copies if the
new manifest site is inaccessible.

* **New Features**
* Streamlined maintained-app synchronization to use a simpler sync
entrypoint and unified primary/fallback fetch logic.

* **Tests**
* Added comprehensive tests for primary/fallback fetch flows, error
handling, large-response truncation, and environment-based overrides.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-04-09 17:36:18 -05:00
melpike
75982f44de
Rename Apple Business Manager in UI (#42584)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #42512

---------

Co-authored-by: Luke Heath <luke@fleetdm.com>
Co-authored-by: Noah Talerman <47070608+noahtalerman@users.noreply.github.com>
2026-04-08 11:14:19 -06:00
Scott Gress
3ae98ee01d
Clean up Gitops tests and add deprecation tests (#43039)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** For #40015

* Moves repeated empty mocks into a new `setupEmptyGitOpsMocks` method
* Adds new "deprecation" tests:
* In TestGitOpsFullGlobal, TestGitOpsFullTeam and
TestGitOpsFullGlobalAndTeam tests "kitchen sink" with both new and
deprecated keys
* Added keys and checks to verify `setup_experience`,
`apple_business_manager` and `volume_purchasing_program` configs
* Consolidated map of deprecated -> new GitOps keys in one place
2026-04-08 11:57:03 -05:00
Magnus Jensen
6a9d394e62
Implement clear passcode backend (#43072)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #42368 

# 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. For the overall story

- [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
2026-04-07 15:23:59 -05:00
Ian Littman
f60903cea9
Don't turn Prometheus on in --dev mode (#43129)
# 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

- [ ] QA'd all new/changed functionality manually
2026-04-07 12:01:26 -05:00
Juan Fernandez
3df6449426
API endpoints initial models (#42881)
**Related issue:** Resolves #42881

- Added user_api_endpoints table to track per user API endpoint
permissions.
- Added service/api_endpoints, used to handle service/api_endpoints.yml
artifact.
- Added check on server start that makes sure that
service/apin_endpoints.yml is a subset of router routes.
2026-04-07 10:40:39 -04:00
Victor Lyuboslavsky
c4479c6a84
Add require_all_software_windows config option (#43011)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #42853

This PR simply adds the `require_all_software_windows` config option. It
doesn't use it. The logic to use it will be hooked up in subsequent PRs.

The fleetctl TestIntegrationsPreview test is expected to fail since it
builds the server against main and doesn't know about our new config
option.

# 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] 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`
- Not exported. generate-gitops does not export
require_all_software_windows (or require_all_software_macos either). The
generateControls function (generate_gitops.go) outputs a "TODO: update
with your setup_experience configuration" placeholder when any setup
experience config exists, rather than exporting individual field values.
This is a pre-existing limitation that applies equally to both fields -
not something introduced by our PR.
- [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)
- Yes. PR #42046 adds require_all_software_windows to both docs/REST
API/rest-api.md and docs/Configuration/yaml-files.md.
- [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)
- Yes, it gets cleared to false - both when setup_experience: is present
without the field, and when setup_experience: is omitted entirely. This
is the same behavior as the existing require_all_software_macos field
- [x] Verified that any relevant UI is disabled when GitOps mode is
enabled
- Covered by #42854 (frontend subtask). The existing macOS checkbox in
InstallSoftwareForm.tsx:271 already checks gitOpsModeEnabled to disable
itself. The Windows checkbox to be added in #42854 will follow the same
pattern.


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

## Summary by CodeRabbit

* **New Features**
* Added a Windows setup experience software requirement setting. When
enabled, Windows devices will cancel the Autopilot setup if any required
software installation fails.

* **Tests**
* Added test coverage for the new Windows software requirement
configuration.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-04-06 17:39:59 -05:00
Scott Gress
1eabb85a5a
Activate deprecation warnings (#41449)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #40015

# Details

Activates deprecation warnings for old API params and CLI args, updates
tests that would generate warnings (except for tests explicitly designed
to generate warnings).

The expectation from here on is that Fleet UI usage should not generate
any deprecation warnings in the server logs, nor should the output from
`generate-gitops` generate any warnings when fed into `gitops`.

# 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
- [X] clicked around in an mdm-enabled instance, turned setup experience
features on and off, saw no server warnings
- [X] did `fleetctl generate-gitops` on mdm-enabled instance, saw no
server or cli warnings
- [X] did `fleetctl gitops` on mdm-enabled instance, saw no server or
cli warnings
2026-04-06 09:59:32 -05:00