Commit Graph
1615 Commits
Author SHA1 Message Date
Scott Gress 313df2c45a Fix checkout action version in fleetctl new template (#45502)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves
https://github.com/fleetdm/confidential/issues/15917

# 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

- [ ] Added/updated automated tests
- I didn't see any tests that checked the contents of the templates
directly; will update if anything fails.
- [X] QA'd all new/changed functionality manually
- Tested on my test gitops repo:
https://github.com/sgress454/fleet-gitops-test/actions/runs/25875796027/job/76042556514


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

* **Bug Fixes**
* Resolved Node-related warnings that appeared when using the Fleet
"new" project and GitOps workflow templates, improving clarity during
template execution and initial project setup.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45502)

<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-14 16:38:04 -05:00
Victor Lyuboslavsky c2de7315cd fleetctl get mdm-commands now requires the --host flag (#45476)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #44422 

# Checklist for submitter

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

- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files)
for more information.

## Testing

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

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

* **Refactor**
* The CLI command to list MDM commands now requires a --host flag;
calling it without a host will error.
* The API endpoint for listing commands now requires a host_identifier
parameter; requests without it are deprecated.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45476)

<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-14 12:58:52 -05:00
Lucas Manuel Rodriguez 057e1615b4 Move mysql/testing_utils.go to a separate mysql/mysqltest package (#45406)
Resolves #45220 (one of several PRs to achieve removing "testing"
package as dependency in production binary)

## Testing

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

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

* **Tests**
* Switched many tests to use a dedicated MySQL test helper package and
consolidated test-only utilities for datastore setup, cleanup, ad‑hoc
SQL, certificate generation, and activity/aggregation helpers.
* Added expanded test utilities for replication, DB connections and test
data seeding to improve integration-test reliability.

* **Chores**
  * No production behavior or user-facing APIs were changed.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45406)

<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-14 11:18:20 -03:00
Sharon Katz 47773c58ad Fix enable_host_users defaulting to false on fresh install (#45393)
Closes #44630

## Summary

- After a fresh Fleet install (`fleet prepare db` + `fleetctl setup`),
`enable_host_users` persisted as `false` despite the documented and
coded default being `true`.
- **Root cause**: During setup, `NewAppConfig` correctly saves
`enable_host_users: true`. However, the starter library then runs
`fleetctl gitops` with a template that has no `features` section. In
`DoGitOps`, when `features` is absent, an empty features map is created.
`enable_software_inventory` was explicitly defaulted to `true`, but
`enable_host_users` was not. The overwrite-mode PATCH then reset
`enable_host_users` to `false` (Go's bool zero value).
- Adds the same defaulting logic for `enable_host_users` as exists for
`enable_software_inventory`, in both the global and team config paths in
`DoGitOps`.

## Test plan

Reproduced locally before and after the fix with a Fleet server +
osqueryd agent (osquery 5.23.0):

**Before fix:**
1. Created a fresh database, ran `fleet prepare db`, started `fleet
serve --dev`, ran `fleetctl setup`.
2. Checked DB: `enable_host_users` was `false` (bug).
3. Enrolled a local osqueryd agent against the server.
4. Queried the host details API: `users` field was `null` (user
collection disabled).
5. Confirmed `features.enable_host_users: false` via `GET
/api/latest/fleet/config`.

**After fix:**
1. Same steps with the fixed binary.
2. Checked DB: `enable_host_users` was `true` (correct).
3. Enrolled a local osqueryd agent against the server.
4. Queried the host details API: `users` field contained 3 collected
users (root, sharonkatz, testuser) -- user collection working.
5. Confirmed `features.enable_host_users: true` via `GET
/api/latest/fleet/config`.

**Unit tests:**
- [x] `TestGitOpsFeatures` -- updated assertion to expect
`enable_host_users: true` when features are omitted from GitOps YAML
(was previously testing the broken behavior).
- [x] All `TestGitOps*` tests pass (`go test ./cmd/fleetctl/fleetctl/
-run TestGitOps`).

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

## Summary by CodeRabbit

## Bug Fixes
* Fixed default host user collection behavior on fresh Fleet installs.
Host user collection now correctly defaults to enabled, matching
documented settings and ensuring the host details page displays accurate
collection status information instead of incorrectly showing it as
disabled.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45393)

<!-- review_stack_entry_end -->

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-14 09:05:45 -04:00
Rajendra kadam 363b01df44 Inject initFatal as a package-level var (#33370) (#45343)
Second PR in the staged plan from
[#33370](https://github.com/fleetdm/fleet/issues/33370#issuecomment-4394807680).
Per [@getvictor's
confirmation](https://github.com/fleetdm/fleet/issues/33370#issuecomment-4421816049),
takes the package-level var approach so tests can swap `initFatal`
without terminating the test binary.

The new `TestGetTLSConfigInvalidProfile` covers `getTLSConfig`'s default
case (previously unreachable in tests because it calls `initFatal`)

**Related issue:** Part of #33370.

# Checklist for submitter

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

## Testing

- [x] Added/updated automated tests

## Database migrations

_N/A — no database migrations in this PR._

## New Fleet configuration settings

_N/A — no new configuration settings._

## fleetd/orbit/Fleet Desktop

_N/A — no agent code changes._


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

## Summary by CodeRabbit

* **Tests**
  * Improved test coverage for TLS configuration error handling.

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45343)

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-13 11:13:39 -05:00
Scott Gress a29ba6befc Update data collection interval and strategy (#45293) 2026-05-13 10:09:22 -05:00
Scott Gress 049f29ee3f Apply labels before consumers in GitOps (#45194)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #44046 

# Details

Updates GitOps to ensure that team labels are created before any
consumers (e.g. profiles, policies, software) that might use the labels
are applied. It does this by adding a new `afterTeamApply` callback
option to `ApplyGroup` that is called after team config is applied --
this is when team labels are now created, instead of after `ApplyGroup`
runs.

# Checklist for submitter

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

- [X] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files)
for more information.

## Testing

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




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

* **Bug Fixes**
* Fixed GitOps deployments failing when a label and a profile that
references it are created in the same run.
* Ensures the correct apply ordering so dry-run/log output shows label
application before profile application.

* **Tests**
* Added a regression test validating label → profile apply ordering to
prevent future regressions.

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45194)
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-12 17:15:33 -05:00
Jonathan Katz fd7bf3118b Fix TestGitOpsTeamVPPAppleConfiguration failing (#45305)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #

# Checklist for submitter

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


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

## Summary by CodeRabbit

* **Tests**
* Updated test fixtures for Apple VPP configuration in GitOps workflows
to better reflect real-world scenarios.

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45305)

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-12 18:11:57 -04:00
Lucas Manuel Rodriguez 393007ede1 First move of server/service to server/service/svctest to prevent testing code in Fleet's production binary (#45221)
**Related issue:** Resolves #45220 (one of many small PRs)

## Testing

- [x] QA'd all new/changed functionality manually. (Ran basic smoke
testing.)

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

* **Tests**
* Added a consolidated test utilities package to boot full test servers,
seed users, retrieve auth tokens, and provide common mocks for
integration/service tests.
* Updated integration and service tests to use the new helpers for more
consistent, reliable test setup and wiring.

* **Chores**
* Centralized and reorganized test configuration types and options, and
standardized test wiring for clearer, maintainable test setup.

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45221)
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-12 17:43:37 -03:00
Carloandjkatz01 55636b3ef6 iOS/iPadOS managed config: GitOps (#43969) (#44933)
Part of #38790. Stacked on top of #44932.

Closes #43969.

`fleetctl gitops` reads `configuration.path` for iOS / iPadOS VPP apps
and in-house `.ipa` apps, validates the file via
`fleet.ValidateAppleAppConfiguration`, and stores the bytes through the
service layer.

`fleetctl generate-gitops` emits `configuration.path` for apps that have
a stored configuration, writing the XML to
`lib/<team>/software/<app-slug>-config.xml`. Apps without configuration
omit the block entirely.

Round-trip integration tests
(`cmd/fleetctl/integrationtest/gitops/software_test.go`) cover apply +
generate for both VPP and in-house, plus a negative case for invalid
configuration content.

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

## Summary by CodeRabbit

## Release Notes

* **New Features**
* Added managed app configuration support for enterprise software
deployments through GitOps
* Configurations now support platform-specific formats: XML for
iOS/iPadOS, JSON for Android
* Configuration validation ensures compatibility and prevents invalid
variable references

* **Tests**
* Added integration tests for configuration handling in software
deployment workflows

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/44933)

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

---------

Co-authored-by: jkatz01 <yehonatankatz@gmail.com>
2026-05-12 14:15:25 -04:00
fc907c4634 Rename Apple Business 'Location' to 'Organization Unit' in UI and docs (#44833)
## Summary

- Renames Apple Business "Location" / "Locations" to "Organization Unit"
/ "Organization Units" across user-facing UI strings, documentation, and
code comments
- Updates the VPP table column header, modal text, error messages, audit
log descriptions, YAML configuration docs, and article guides
- Underlying API field names (`location` in JSON) and YAML config keys
remain unchanged for backward compatibility

---

Built for [Mel
Pike](https://fleetdm.slack.com/archives/D0AKX7DJFCN/p1778077861693279?thread_ts=1777299502.461149&cid=D0AKX7DJFCN)
by [Kilo for Slack](https://kilo.ai/slack)

---------

Co-authored-by: kiloconnect[bot] <240665456+kiloconnect[bot]@users.noreply.github.com>
Co-authored-by: melpike <melpike.dev@gmail.com>
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: melpike <79950145+melpike@users.noreply.github.com>
2026-05-12 12:03:08 -06:00
Rajendra kadam ace3804086 Add tests for serve.go pure helpers (#33370) (#44929)
First PR in the staged plan from
[#33370](https://github.com/fleetdm/fleet/issues/33370#issuecomment-4394807680).
Adds unit tests for several testable helpers in `cmd/fleet/serve.go` —
argument stringification, TLS profile config, license initialization,
and the missing-migrations warning.

The migrations-warning test required threading `io.Writer` through
`printMissingMigrationsWarning` so it can pass `*bytes.Buffer` instead
of mutating `os.Stdout`. The other two database-state print functions
stay as-is since they aren't tested in this PR.

**Related issue:** Part of #33370 (intentionally not using auto-close
keywords since this is the first of multiple PRs against this issue).

# Checklist for submitter

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

## Testing

- [x] Added/updated automated tests

## Database migrations

_N/A — no database migrations in this PR._

## New Fleet configuration settings

_N/A — no new configuration settings._

## fleetd/orbit/Fleet Desktop

_N/A — no agent code changes._
2026-05-12 08:57:10 -05:00
Magnus Jensen 2935856f37 validate apple payload scope conflict, and unknown variable use in dry-run (#45139)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #44456 

# Checklist for submitter

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

- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files)
for more information.

- [x] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements), JS
inline code is prevented especially for url redirects, and untrusted
data interpolated into shell scripts/commands is validated against shell
metacharacters.
- [x] Timeouts are implemented and retries are limited to avoid infinite
loops
- [x] If paths of existing endpoints are modified without backwards
compatibility, checked the frontend/CLI for any necessary changes

## Testing

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

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

* **Bug Fixes**
* Dry-run now performs Apple config profile payload scope conflict
validation and reports unknown Fleet variables for all profile types
before completing.

* **Tests**
* Added tests covering Apple config profile scope-conflict validation
and dry-run/batch profile workflows to ensure conflicts are detected in
both dry-run and live flows.

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45139)
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-12 08:51:30 +02:00
Scott Gress 348fa47c84 Improve name key validation in GitOps (#44553)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #

# Checklist for submitter

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

- [X] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files)
for more information.

## Testing

- [X] Added/updated automated tests
- [X] QA'd all new/changed functionality manually
  - [X] omitted `name:` from a file without `org_settings:`, got:
```
	* No `name` was provided in /tmp/testback/fleets/third-fleet.yml. If this file is intended to define org-level settings, add `org_settings:` as a top-level key. Otherwise, use `name` to specify the fleet name.
```
  - [X] omitted `name:` from a file with `org_settings:`, got no error.
  - [X] omitted `name:` from `no-team.yml`, got:
```
	* `name` must be `No Team` for `no-team.yml`
```
  - [X] omitted `name:` from `unassigned.yml`, got:
```
	* `name` must be `Unassigned` for `unassigned.yml`
```


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

## Summary by CodeRabbit

* **Bug Fixes**
* Improved error messages when GitOps YAML files omit the required
`name` field, with specific remediation guidance tailored to each
configuration file type
* Enhanced validation error messaging when top-level `org_settings` is
missing or incorrectly placed, providing clearer instructions on
required YAML structure

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-11 13:49:02 -05:00
Scott Gress 8b779110a8 Remove verb and url from gitops errors (#44555)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #43721 

# Checklist for submitter

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

- [X] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files)
for more information.

## Testing

- [X] Added/updated automated tests
- [X] QA'd all new/changed functionality manually
Added a Google Calendar integration to gitops .yml with `client_email`
missing from the `api_json_key`.
  - [X] on main, got error: 

```
Error: applying fleet config: PATCH /api/latest/fleet/config received status 422 Validation Failed: client_email is required (API time: 13ms)
```

  - [X] on this branch, got:

```
Error: applying fleet config: Validation Failed: client_email is required (API time: 134ms)
```



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

* **Bug Fixes**
* Cleaner CLI error messages: removed extraneous HTTP path/status-code
details from GitOps-related errors, making output easier to read.

* **Tests**
* Added tests to verify the improved error message handling and
nil/non-wrapped error behavior.

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/44555)
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-11 13:48:52 -05:00
Scott GressandCopilot Autofix powered by AI 4daed869ad Add API param linter (#44045)
Adds a linter to ensure we don't add new instances of `team` or `query`
in API params. This will be used incrementally, but this PR also adds
`nolint` directives to places that still have these terms, both to avoid
false-positives later and to help with full migration away from these
terms in in Fleet 5.

Example:

```
server/fleet/campaigns.go:51:16: json tag "team_id": uses deprecated "team"/"teams" — use "fleet"/"fleets" instead (apiparamcheck)
        Team  *uint   `json:"team_id,omitempty"`
```

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

* **New Features**
* Added a new static analyzer (apiparamcheck) to flag deprecated API
parameter names ("team/teams") and improper usages of "query/queries".

* **Chores**
  * Integrated the new check into CI tooling and configuration.
  * Added analyzer tests and plugin registration.
* Applied targeted lint-suppression annotations across code and tests
where legacy parameter names must remain.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-05-11 08:46:02 -05:00
Jonathan Katz d439cb1690 Fix missing deleted_policy activity for auto-cleaned patch policies (#45045)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #44286

Unset `patch_software_title_id` rather than deleting the policy in
`BatchSetSoftwareInstallers`, so the orphaned policy gets picked up by
the `policiesToDelete` loop in `server/service/client.go:3121`. As a
result, the `deleted_policy` activity is now created properly, and
gitops dry/real runs also report the deletion:

```
dry run:
[-] would've deleted policy macOS - 010 Editor up to date
[-] would've deleted 1 policy

real run:
[-] deleting policy macOS - 010 Editor up to date
[-] deleting 1 policy
[-] deleted 1 policy
```

# Checklist for submitter

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

- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files)
for more information.

- [ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements), JS
inline code is prevented especially for url redirects, and untrusted
data interpolated into shell scripts/commands is validated against shell
metacharacters.
- [ ] Timeouts are implemented and retries are limited to avoid infinite
loops
- [ ] If paths of existing endpoints are modified without backwards
compatibility, checked the frontend/CLI for any necessary changes

## Testing

- [x] Added/updated automated tests
- [ ] Where appropriate, [automated tests simulate multiple hosts and
test for host
isolation](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/reference/patterns-backend.md#unit-testing)
(updates to one hosts's records do not affect another)

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


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

* **Bug Fixes**
* Fixed missing deletion activity logs when patch policies are removed
via GitOps so policy deletion events are now recorded.

* **Behavior Changes**
* Batch-updating installers now retains obsolete patch policies but
clears their patch installer reference instead of deleting the policy.

* **Tests**
* Added integration coverage to verify deletion activities are emitted
and installer batch behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-09 00:33:00 -04:00
Tim Lee f2f0f703a4 Lower CVE-2025-0938 spot-check threshold to 1 (#45056) 2026-05-08 13:18:53 -06:00
Victor Lyuboslavsky 7012e70495 osquery_perf: add Windows-specific disk encryption query handling. (#44998) 2026-05-08 10:21:39 -04:00
Andrew Mellor 119feeda02 42218 updated ios version number to include supplemental extra (#44727)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #42218

# Checklist for submitter

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

- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files)
for more information.

- [x] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements), JS
inline code is prevented especially for url redirects, and untrusted
data interpolated into shell scripts/commands is validated against shell
metacharacters.

## Testing

- [x] Added/updated automated tests

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

Note: Sim update included and validated with and without supplemental,
screen shots attached

<img width="760" height="87" alt="Host List"
src="https://github.com/user-attachments/assets/c55f0ace-a205-4242-95da-510e8e6ec4ad"
/>
<img width="1511" height="523" alt="Standard"
src="https://github.com/user-attachments/assets/74a42e57-9391-4ce0-8b0a-ad3de6ab4745"
/>
<img width="1505" height="526" alt="Supplimental"
src="https://github.com/user-attachments/assets/392fc603-c7a2-4d6f-8ae0-87767cab7e3c"
/>


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

* **New Features**
* iOS/iPadOS devices managed via MDM now include reported supplemental
OS version text (e.g., Rapid Security Response suffixes) in the
displayed OS version string.
* **Bug Fixes**
* Supplemental extras are validated; invalid values are ignored.
Combined version strings are length-limited and safely truncated.
* **Tests**
* Added tests for supplemental handling, validation, fallback, and
truncation.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-07 15:16:31 +01:00
Scott Gress 684becade8 Allow disabling chart datasets: backend (#44769)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** For #44077 

# Details

This PR implements enforcement of the "disable dataset" feature.  

When a dataset is disabled globally, we:

* Stop collecting all data for that dataset (the `Collect` method for
that dataset is not called in the cron job)
* Remove all previously-collected data for the dataset via an
asynchronous job

When a dataset is disabled for one or more fleets, we:

* Provide the list of disabled fleets as an argument to each dataset's
`Collect` method. Each dataset is responsible for filtering out hosts in
the most efficient way possible
* Scrub the data for the relevant datasets using a bitmask, so that all
hosts from the disabled fleets are removed from the data. This is done
via an asynchronous job.

# Checklist for submitter

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

- [ ] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files)
for more information.
n/a, unreleased

- [X] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements), JS
inline code is prevented especially for url redirects, and untrusted
data interpolated into shell scripts/commands is validated against shell
metacharacters.
- [X] Timeouts are implemented and retries are limited to avoid infinite
loops

## Testing

- [X] Added/updated automated tests
- [X] Where appropriate, [automated tests simulate multiple hosts and
test for host
isolation](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/reference/patterns-backend.md#unit-testing)
(updates to one hosts's records do not affect another)

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

  ### Prerequisites / Test Setup

- [ ] Fleet running with at least 3 teams (call them T1, T2, T3) and ≥3
hosts in each, plus ≥2 hosts with no team
- [ ] At least one host on each team has reported recent uptime (within
the bucket window)
- [ ] At least one host in each team is affected by a tracked CVE (so
`host_scd_data` for `dataset='cve'` will have non-empty bitmaps)
- [ ] AppConfig: both `features.historical_data.uptime` and
`features.historical_data.vulnerabilities` start as `true`; same for
every team
- [ ] Let the collection cron run at least one full tick to populate
baseline rows in `host_scd_data` for both `uptime` and `cve`
- [ ] Note the current row count per dataset: `SELECT dataset, COUNT(*)
FROM host_scd_data GROUP BY dataset;`

  ---

  ### 1. Cron Skips Globally-Disabled Datasets

  #### 1.1 Global disable of `uptime`

- [x] Disable globally: `PATCH /api/v1/fleet/config` with
`features.historical_data.uptime = false`
- [x] Verify activity feed shows `disabled_historical_dataset` for
`uptime` (existing behavior)
- [x] Wait for next collection tick (or trigger it via fleetctl debug if
available)
  - [x] Confirm **no new rows** appear for `dataset='uptime'`:
`SELECT MAX(valid_from) FROM host_scd_data WHERE dataset='uptime';`
        should not advance after the disable
- [x] Confirm cron still writes `cve` rows on the same tick (per-dataset
isolation)
  - [x] Re-enable: PATCH `historical_data.uptime = true`
  - [x] Verify next tick resumes writing `uptime` rows

  #### 1.2 Global disable of `vulnerabilities`

  - [x] Repeat 1.1 with `features.historical_data.vulnerabilities`
  - [x] Confirm `cve` writes stop, `uptime` continues

  #### 1.3 Both disabled globally

  - [x] Disable both globally
  - [x] Confirm cron tick produces zero new rows for either dataset
  - [x] Confirm cron does not error or get stuck
  - [x] Re-enable both

  ---

  ### 2. Per-Fleet Disable — Cron Filters at SQL

  #### 2.1 Single team disabled for one dataset

  - [x] Disable uptime for T1 only: PATCH team T1 with
        `features.historical_data.uptime = false`
- [x] Verify scoped `disabled_historical_dataset` activity emitted for
T1
  - [x] Wait for next cron tick / trigger cron
- [x] Pick a host known to be in T1 (call it `H_T1`); confirm its bit is
NOT set in any `uptime` row written *after* the disable by filtering the
chart to that host
- [x] Pick a host in T2 (`H_T2`); confirm its bit IS still set in the
same rows (T2 is not disabled)
- [x] Pick a no-team host (`H_none`); confirm its bit IS still set
(no-team hosts follow the global value)

  #### 2.2 Same fleet, different dataset

- [x] With T1's uptime disabled, confirm T1's hosts ARE still written
into `cve` rows on subsequent ticks (per-dataset isolation)

  #### 2.3 All teams disabled, global on, no-team hosts

  - [x] Disable uptime on every team (T1, T2, T3)
- [x] Confirm next tick still writes a row containing only no-team
hosts' bits (global is on, no-team hosts always count)
  - [x] Re-enable uptime on all teams

  ---

  ### 3. Global Scrub — DELETE

  #### 3.1 Successful global scrub

  - [x] Note baseline:
        `SELECT COUNT(*) FROM host_scd_data WHERE dataset='uptime';`
        (should be > 5000 to exercise the loop; if not, manually
        insert filler rows or run multiple cron ticks)
  - [x] Disable uptime globally via the API
  - [x] Wait for the worker to pick up the scrub / trigger the job
  - [x] Confirm the count drops to 0:
        `SELECT COUNT(*) FROM host_scd_data WHERE dataset='uptime';`
  - [x] Confirm rows for **other datasets** are untouched
  - [ ] Test again but disable via GitOps

  ---

  ### 4. Per-Fleet Scrub — ANDNOT

  #### 4.1 Single-fleet scrub clears bits

  - [x] Identify hosts in T1 and record their IDs (call this set `S`)
- [x] Pre-disable, confirm at least one `host_scd_data` row for
`dataset='uptime'` has bits set at positions in `S` by filtering the
chart to those hosts
  - [x] Disable uptime on T1 only, via the API
  - [x] Wait for the scrub to run / trigger it
- [x] Confirm: every existing row for `dataset='uptime'` now has NO bits
set at any position in `S`. Spot-check by filtering the chart to those
hosts
- [x] Confirm rows for `dataset='cve'` (different dataset) are untouched
  - [x] Confirm bits for hosts in T2/T3 (not disabled) are still set
  - [x] Run test again but disable via GitOps

  #### 4.2 Multi-fleet scrub via GitOps batch

- [x] Apply a GitOps spec that flips cve to false on T1 and T3 in a
single apply
  - [x] Wait for scrub(s) to complete
- [x] Confirm bits for the union of T1∪T2 hosts are cleared from every
row of `dataset='cve'`
  - [x] Confirm T2 hosts' bits remain set

  ---

  ### 5. Activity Feed Cross-Check

  - [x] Each global flip emits exactly one `disabled_historical_dataset`
        activity (existing behavior, unchanged)
  - [x] Each per-team flip emits one scoped activity with the team's
        ID and name
  - [x] PATCH submitting unchanged values emits **no** activity and
        causes **no** scrub (no `host_scd_data` data change observed
        after the cron tick)
  - [x] No new "scrub completed" or "scrub started" activity is
        emitted (out of scope for v1)
  - [x] Re-enable flips emit `enabled_historical_dataset` activities
        and do NOT emit any scrub-related activity

  ---

  ### 6. Regression Spot Checks

  - [x] With everything enabled (default), the chart UI renders the
        same data as before this change (no behavior change in the
        "all on" case)
  - [x] AppConfig YAML round-trip (`fleetctl apply`) is benign:
        applying the unchanged config produces no scrub jobs and no
        activities
  - [x] GitOps apply with `historical_data` omitted from team specs
        defaults to `true` (per the gitops-api change) and does not
        trigger spurious scrubs
  - [x] After a full disable+scrub of cve, the `host_scd_data` table
        has no `dataset='cve'` rows; the chart UI for "vulnerable
        hosts over time" shows an empty/zero state without errors

  ---


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

* **New Features**
* Chart collection now supports per-dataset scoping and honors
team-level disables; new scrub jobs are registered and worker handlers
added.
* New dataset scrub operations: global and fleet-scoped scrubs; scrubs
can be enqueued and are deduplicated to avoid duplicate pending jobs.
Historical-data changes enqueue scrubs after save (errors logged,
non-blocking).
* **Tests**
* Added unit tests for scope resolution, scrub enqueue/dedup behavior,
scrub workers, scrub application, and low-level blob scrub logic.
* **Documentation**
  * Added OpenSpec metadata for the chart scrub change.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-07 08:52:35 -05:00
Steven Palmesano 359408b6b9 Fix broken links for setup_experience (#44903) 2026-05-07 06:50:01 -05:00
Jordan Montgomery 4910c450a4 43887 MLAPR backend (#44726)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #43887

Adds the password rotation state machine for macOS local admin accounts.
Changes file covered in prior PR

# Checklist for submitter

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

- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files)
for more information.

- [x] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements), JS
inline code is prevented especially for url redirects, and untrusted
data interpolated into shell scripts/commands is validated against shell
metacharacters.
- [x] Timeouts are implemented and retries are limited to avoid infinite
loops
- [x] If paths of existing endpoints are modified without backwards
compatibility, checked the frontend/CLI for any necessary changes

## Testing

- [x] Added/updated automated tests
- [x] Where appropriate, [automated tests simulate multiple hosts and
test for host
isolation](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/reference/patterns-backend.md#unit-testing)
(updates to one hosts's records do not affect another)
- [x] QA'd all new/changed functionality manually

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

* **New Features**
* Automatic macOS managed-local-account password rotation (5‑minute
scheduler) with queued SetAutoAdminPassword device commands
* Manual rotation API: POST /hosts/{id}/managed_local_account/rotate
(returns 204)
* API now reports auto-rotation timing and pending-rotation state
(auto_rotate_at, pending_rotation)
  * Activity records for successful and failed rotations

* **Behavior Changes**
* Password availability is based on stored encrypted password (broader
than before)
  * Rotate-while-in-flight is rejected to prevent duplicate rotations

* **Tests**
* New unit and integration tests for rotation flows, cron behavior, and
failure paths
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-07 06:36:30 -04:00
Magnus Jensen 9d96d6c76a add script output to GitOps (#44728)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #44082

# 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

* **New Features**
* Enhanced GitOps script logging: reports how many scripts would be
applied in dry‑run mode or were actually applied, with per-team and
per-fleet breakdowns.

* **Tests**
* Added test coverage validating logging output for both dry‑run and
real execution, ensuring reported script counts and per-team/fleet
messages are accurate.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-07 09:38:25 +02:00
Victor Lyuboslavsky c79d33a3a6 Add support for SAN in Android certificate templates. (#44690)
2/3rds of this PR is OpenSpec and tests. Use OpenSpec files as a
reference (if needed). They're there to help the review, and not to be a
review surface themselves.

- Backend implementation for `subject_alternative_name` in certificate
templates.
- Includes schema migration, variable expansion, GitOps support.
- Limits SAN types to `DNS`, `EMAIL`, `UPN`, `IP`, and `URI`.

<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #41472 

# 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

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


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

* **New Features**
* Android certificate templates support Subject Alternative Name (SAN)
with validation (DNS, EMAIL, UPN, IP, URI), Fleet-variable substitution,
runtime expansion, and delivery; SAN use is gated by Premium license
  * GitOps now validates and includes SAN in Android certificate flows

* **Chores**
  * Database schema updated to store SAN on certificate templates
  * Changelog entry added

* **Tests**
* Added unit and end-to-end tests covering SAN validation, variable
expansion, and GitOps behavior
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-06 14:43:09 -05:00
d38163db94 Setup experience for Windows. (#44306)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #43859 

This PR brings the Windows Autopilot setup experience to parity with
macOS DEP. Windows hosts that enroll
through Autopilot now coordinate with Fleet during the OOBE Enrollment
Status Page (ESP), so admin-defined
software installs run while the device is still waiting at the ESP
screen, before the user can sign in. Fleet
holds the device on the ESP until profiles and setup-experience software
all reach a terminal state, then
either releases the device to login or blocks it on a Reset PC failure
screen. A new team-level setting
controls the policy: when enabled, any critical software install failure
during ESP blocks the device with a
software-specific error message; when disabled, the device releases
regardless of install outcomes (best
effort). A pure 3-hour timeout also forces a finalize, with a
timeout-specific error message on the block
screen. The setting is premium-only and rejected when Windows MDM is not
configured.

Beyond the gating itself, the PR adds the supporting machinery:
orbit-driven setup-experience initialization
on Windows so installs are enqueued at the right moment,
defense-in-depth cancellation of pending software
installs (both queue rows and status rows) whenever the device is going
to block or time out, idempotent
re-enrollment cleanup so a device that resets and re-enrolls during ESP
starts from a clean state. Internally, finalize is structured so a
transient failure at any step (cancel, persist, or the state-machine
transition) leaves the device retriable on the next management session
rather than permanently stuck on "Working on it...". The behavior is
exercised by example-based tests, a property-based test that randomly
samples the wait/block/release decision matrix, and manual VM testing
across Autopilot edge cases.

<img width="1184" height="776" alt="image"
src="https://github.com/user-attachments/assets/5e48660d-235d-40bd-80b6-f8591c579279"
/>

# Checklist for submitter

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

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

* **Bug Fixes**
* Re-enrollment now clears stale setup-experience results and pending
activities so devices aren’t blocked by old work.
* Insert operations tolerate missing enrollments and return clear
not-found behavior.

* **New Features**
* ESP finalization waits for software installation results and can block
or release based on configurable “require all” behavior; blocking
cancels pending steps and shows prioritized error text.
  * Finalization persists batched final commands for consistent retries.
* Orbit config exposes setup-experience notification for pending/active
Windows hosts.

* **Tests**
* Expanded coverage for ESP flows, datastore awaiting-configuration,
Orbit config, and re-enrollment cascades.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Konstantin Sykulev <konst@sykulev.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-05-06 14:26:58 -05:00
Sharon Katz 9611bb87b7 Improve error message when referencing a bad label for a configuration profile (#44839)
Closes #39739

## Local reproduction

Reproduced the bug locally by running `fleetctl gitops --dry-run`
against a local Fleet server with a GitOps config that references a
nonexistent label on a configuration profile.

**Setup:**
1. Started a local Fleet server (`fleet serve` against Docker
MySQL/Redis on `https://localhost:8080`, fresh database).
2. Created a minimal `.mobileconfig` profile
(`test-profile.mobileconfig`).
3. Created a `default.yml` that references it under
`controls.macos_settings.custom_settings` with `labels_include_all:
["this-label-does-not-exist"]`.

**Reproduction:**
```bash
fleetctl gitops -f /tmp/repro-39739/default.yml --dry-run
```

**Result (before fix):**
```
[!] Unknown label 'this-label-does-not-exist' is referenced by MDM Profile '/tmp/repro-39739/profiles/test-profile.mobileconfig'
Error: Please create the missing labels, or update your settings to not refer to these labels.
```

Two problems visible:
- Says "MDM Profile" — internal jargon, not the user-facing term
- Shows the full absolute path — noisy and unhelpful

---

## Code changes

**Summary:** Two lines changed in `cmd/fleetctl/fleetctl/gitops.go`
inside the `getLabelUsage()` function. Both fix how configuration
profile label errors are displayed to the user during `fleetctl gitops`
runs.

### `cmd/fleetctl/fleetctl/gitops.go`

**Line 851 — "multiple label keys" error message:**
Changed `"MDM profile"` → `"configuration profile"` and wrapped
`setting.Path` in `filepath.Base()` so the error shows just the filename
instead of the full absolute path.

```diff
- err := fmt.Errorf("MDM profile '%s' has multiple label keys; ...", setting.Path)
+ err := fmt.Errorf("configuration profile '%s' has multiple label keys; ...", filepath.Base(setting.Path))
```

**Line 869 — label usage tracking entry:**
Changed the type string from `"MDM Profile"` → `"configuration profile"`
and the identifier from the full `setting.Path` to
`filepath.Base(setting.Path)`. This feeds into the error message on line
458:
`[!] Unknown label '<name>' is referenced by <type> '<identifier>'`

```diff
- updateLabelUsage(labels, setting.Path, "MDM Profile", result)
+ updateLabelUsage(labels, filepath.Base(setting.Path), "configuration profile", result)
```

**After fix:**
```
[!] Unknown label 'this-label-does-not-exist' is referenced by configuration profile 'test-profile.mobileconfig'
```

---

## Testing

### Manual testing

1. Started a local Fleet server (fresh DB, `fleet serve` on
`https://localhost:8080`).
2. Created a minimal `.mobileconfig` profile and a `default.yml` GitOps
config that references it with `labels_include_all:
["this-label-does-not-exist"]`.
3. Built `fleetctl` from the **unfixed** code (`git stash`) and ran
`fleetctl gitops -f default.yml --dry-run`. Confirmed the old error
message:
   ```
[!] Unknown label 'this-label-does-not-exist' is referenced by MDM
Profile '/tmp/repro-39739/profiles/test-profile.mobileconfig'
   ```
4. Built `fleetctl` from the **fixed** code and ran the same command.
Confirmed the new error message:
   ```
[!] Unknown label 'this-label-does-not-exist' is referenced by
configuration profile 'test-profile.mobileconfig'
   ```

### Unit tests added

New file: `cmd/fleetctl/fleetctl/gitops_label_usage_test.go` — two tests
that exercise `getLabelUsage()` directly (no Redis/MySQL needed):

- **`TestGetLabelUsageProfilePathShortened`**: Creates a `GitOps` config
with a macOS profile using a full absolute path and a nonexistent label.
Asserts the label usage entry has the basename (not the full path) and
the type is `"configuration profile"` (not `"MDM Profile"`).
- **`TestGetLabelUsageMultipleLabelKeysError`**: Creates a config with
both `labels_include_all` and `labels_include_any` on the same profile.
Asserts the error contains `"configuration profile"` and the short
filename, and does **not** contain the directory path.

Both tests were verified to **fail on unfixed code** and **pass on the
fix** via a `git stash` round-trip.

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

## Summary by CodeRabbit

* **Bug Fixes**
* Enhanced error messages for MDM configuration profile label validation
to display concise filenames instead of full file paths, improving user
experience.

* **Refactor**
* Updated internal label usage tracking to use configuration profile
base filenames for consistency and clarity.

* **Tests**
* Added test coverage for configuration profile path shortening and
error message validation in label key scenarios.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-06 13:08:27 -04:00
Marko LisicaandCarlo e988dd4756 Support VPP apps from non-US App Store regions (#44368)
**Related issue:** Resolves #43846

---------

Co-authored-by: Carlo <1778532+cdcme@users.noreply.github.com>
2026-05-06 12:01:07 -04:00
Carlo b9933f45a2 Fix gitops 500 when software title icon bytes are missing (#44735)
Fixes #43511
2026-05-05 18:47:16 -04:00
Sharon Katz 1c522097d0 Fix missing GitOps label validation for invalid field combinations (#44410)
**Related issue:** Closes #34229

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

---

`fleetctl gitops` silently accepted labels with invalid parameter
combinations (e.g. manual labels with query/criteria/platform). Added
per-type field validation in a centralized
`fleet.ValidateLabelMembershipFields` function, called from the GitOps
parser, `ApplyLabelSpecs`, and `NewLabel`.

| Type | Allowed | Now rejects |
|------|---------|-------------|
| `manual` | `name`, `description`, `hosts` | `query`, `criteria`,
`platform` |
| `dynamic` | `name`, `description`, `query`, `platform` | `criteria`,
`hosts`; validates platform value |
| `host_vitals` | `name`, `description`, `criteria` | `query`,
`platform`, `hosts` |

### Automated tests

- `TestLabelInvalidFieldCombinations` in `pkg/spec/gitops_test.go` — 17
sub-tests covering every invalid combination per label type, plus 3
valid happy-path cases.
- `TestNewLabelFieldValidation` in `server/service/labels_test.go` — 4
cases for NewLabel validation.
- `TestApplyLabelSpecsManualLabelNilHosts` — 10 sub-cases for
ApplyLabelSpecs field validation.
- `TestWhenCreatingNewLabelsPlatformIsValidated` — platform validation
across NewLabel and ApplyLabelSpecs.

All existing `pkg/spec` and `server/service` label tests pass.

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

* **Bug Fixes**
* Labels now reject invalid field combinations for manual, dynamic, and
host_vitals types with clear error responses instead of failing
silently.
* **Tests**
* Added comprehensive tests covering valid and invalid label
configurations across membership types.
* **Documentation**
  * Changelog entry describing the behavioral fix.  
* **Chores**
* Removed an unnecessary platform constraint from a label configuration.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---

### Manual test results

Ran against a local Fleet server with the built binary.

**API - NewLabel (POST /api/latest/fleet/labels)**

| Test | Input | Expected | Result |
|------|-------|----------|--------|
| 1 | manual + platform=darwin | 422, field=`platform` | PASS |
| 2 | dynamic + platform=invalidplatform | 422, field=`platform` | PASS
|
| 3 | dynamic + platform=darwin + query | 200 | PASS |
| 4 | manual (no platform) | 200 | PASS |
| 5 | host_vitals + platform=darwin | 422, field=`platform` | PASS |
| 6 | dynamic + whitespace-only query | 422, field=`query` | PASS |

**API - ApplyLabelSpecs (POST /api/latest/fleet/spec/labels)**

| Test | Input | Expected | Result |
|------|-------|----------|--------|
| 7 | manual + query | 422, field=`query` | PASS |
| 8 | dynamic + hosts | 422, field=`hosts` | PASS |
| 9 | valid dynamic | 200 | PASS |

**Round-trip: get labels --yaml then apply**

| Test | Scenario | Result |
|------|----------|--------|
| 10 | Legacy manual label with platform=darwin in DB | Platform
stripped from YAML, re-apply succeeds — PASS |
| 11 | Dynamic label with platform=darwin | Platform preserved in YAML,
re-apply succeeds — PASS |

**GitOps parser (fleetctl gitops --dry-run)**

| Test | Input | Result |
|------|-------|--------|
| 12 | manual + query + platform + criteria | All 3 errors surfaced at
once — PASS |
| 13 | valid manual label | No validation errors — PASS |
| 14 | dynamic + invalid platform | Error surfaced — PASS |

---

### Code walkthrough

**`server/fleet/labels.go`** — Added
`ValidateLabelMembershipFields(*LabelSpec) *InvalidArgumentError`. This
is the single source of truth for label field validation, returning
field-specific errors (`platform`, `query`, `criteria`, `hosts`). Lives
here because this package defines the label types both callers import.
Also uses `strings.TrimSpace` to reject whitespace-only queries.

**`server/service/labels.go`** — Three changes: (1) Removed the early
blanket platform check from `NewLabel` that ran before the membership
type was known. (2) Added `ValidateLabelMembershipFields` call in
`NewLabel` after type inference, so the API rejects invalid combos at
creation time. (3) Replaced three incomplete inline checks in
`ApplyLabelSpecs` with a single call to the centralized function, using
`err.WithStatus(422)` to preserve field-specific error shape in the API
response.

**`pkg/spec/gitops.go`** — Replaced the inline validation switch and a
standalone `ValidLabelPlatformVariants` check with a call to
`ValidateLabelMembershipFields`. Unwraps the returned errors
individually into `multiError` so all validation problems are reported
to the user at once.

**`cmd/fleetctl/fleetctl/generate_gitops.go`** — Gated platform emission
on `LabelMembershipTypeDynamic` so legacy manual/host_vitals labels with
a stored platform don't produce YAML that fails re-import.

**`cmd/fleetctl/fleetctl/get.go`** — Added `stripMismatchedLabelFields`
which clears type-inappropriate fields (query, platform, criteria,
hosts) per membership type before YAML output. Called in both code
paths: listing all labels and fetching a single label by name. Ensures
the `get labels --yaml` → `apply` round-trip works for legacy data.

**`server/datastore/mysql/labels.go`** — Added missing `l.criteria`
column to `GetLabelSpec` SELECT, matching `GetLabelSpecs`. Without it,
host_vitals labels fetched by name lost their criteria in the YAML
output, causing re-import to fail with the new validation.
2026-05-05 16:19:41 -04:00
Juan Fernandez 7088dfa32c Add include_all label scope to GitOps and fleetctl (#41566)
Resolves #41566 

Wires labels_include_all to GitOps and fleetctl for policies and reports.
2026-05-05 15:13:22 -04:00
Nico f2b2e23b0a GitOps changes for custom org's logo uploads (#44550)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #44333

# 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. Also added some integration tests
as a follow-up of the first PR
(https://github.com/fleetdm/fleet/pull/44390).

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

#### generate-gitops

- Branched off to main, no URLs set, then ran generate-gitops on this
branch. Deprecated keys gone, new keys present.

<img width="447" height="170" alt="nourls_new"
src="https://github.com/user-attachments/assets/61931615-d61b-44d3-8095-f7a2b9bd8871"
/>

- Branched off to main, set external URLs for both light and dark modes,
then ran generate-gitops on this branch. Deprecated keys gone, new keys
set with the external URLs.

<img width="637" height="471" alt="externalurl_main"
src="https://github.com/user-attachments/assets/c3782756-acc2-4b99-812d-86e145f11ad5"
/>

<img width="459" height="168" alt="externalurl_new"
src="https://github.com/user-attachments/assets/aa2d8825-3c47-40ba-ab91-bb8202afe81a"
/>

- Within this branch, after uploading a custom logo for light mode, ran
generate-gitops. The logo was saved in lib/org_logo/light.webp

<img width="1510" height="639" alt="Screenshot 2026-05-04 at 4 06 59 PM"
src="https://github.com/user-attachments/assets/13318c24-8fa4-4e29-b629-ff723d4afe5a"
/>
<img width="786" height="172" alt="Screenshot 2026-05-04 at 4 07 30 PM"
src="https://github.com/user-attachments/assets/b46bd1df-7dcd-4489-b7da-4cbad77b25b8"
/>


#### gitops

- Applied gitops with two external URLs. Verified in the UI that those
are still present

<img width="944" height="189" alt="Screenshot 2026-05-04 at 7 54 53 AM"
src="https://github.com/user-attachments/assets/a34813ca-beb1-403e-9793-d42cc9c72f8b"
/>
<img width="637" height="259" alt="Screenshot 2026-05-04 at 8 01 04 AM"
src="https://github.com/user-attachments/assets/74c2cd56-ab1d-4ddd-9b8e-22c49e9ae9d5"
/>

- Applied gitops with "" as the URLs to clear them. Verified the default
fleet logo is shown.

<img width="460" height="201" alt="Screenshot 2026-05-04 at 8 15 11 AM"
src="https://github.com/user-attachments/assets/dcbafea3-b4ea-44aa-9045-08c4f5a64e98"
/>
<img width="648" height="269" alt="Screenshot 2026-05-04 at 8 15 50 AM"
src="https://github.com/user-attachments/assets/451a28f9-e929-4b84-93d3-a7dd9afd5eca"
/>

- Applied gitops with a custom logo for light theme, using
**org_logo_path_light_mode**:

<img width="948" height="207" alt="Screenshot 2026-05-04 at 4 10 05 PM"
src="https://github.com/user-attachments/assets/b1418cd4-31cc-4e53-b566-9af11ec21970"
/>
<img width="774" height="168" alt="Screenshot 2026-05-04 at 4 10 35 PM"
src="https://github.com/user-attachments/assets/63f596eb-308f-4122-ad86-e1d718e9b525"
/>



## 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/43808.
- [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)
- [x] Verified that any relevant UI is disabled when GitOps mode is
enabled

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

* **New Features**
* GitOps support for uploading custom org logos (dark/light) via local
files.
* `fleetctl generate-gitops` exports Fleet-hosted logos as local files
and inserts path references.
  * New API endpoints to upload, delete, and fetch org logos.

* **Deprecated**
* Legacy logo keys consolidated into mode-specific URL keys
(`org_logo_url_dark_mode`, `org_logo_url_light_mode`).

* **Bug Fixes / Validation**
* Validation/error when both a path and URL are provided for the same
mode; file size and image-format checks enforced.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-05 18:18:08 +02:00
Scott Gress c3b82539a5 Allow disabling historical data collection (GitOps / API) (#44488)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** For #44077

# Details

* Adds `historical_data` key to app and team config (and gitops) with
`uptime` and `vulnerabilities` subkeys. Keys default to `true`, meaning
"collect this data"
* Adds `enabled_historical_dataset` and `disabled_historical_dataset`
activities when these values are flipped via GitOps or the config APIs

The majority of the file changes in here are GitOps test files that need
to be updated to have the new config in them.

**This PR does _not_ implement using these configs to actually disable
data collection or purge data; that will come in a follow-up PR (as well
as the front-end)**

# 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
- [ ] QA'd all new/changed functionality manually
  #### Defaults
- [X] Fresh install: `GET /api/v1/fleet/config` returns
`features.historical_data.uptime: true` and
`features.historical_data.vulnerabilities: true`
- [X] Created a new fleet via `POST /api/v1/fleet/teams`, then `GET
/api/v1/fleet/fleets/{id}` returns `features.historical_data.uptime:
true` and `features.historical_data.vulnerabilities: true`

  #### Global PATCH (`POST /api/v1/fleet/config`)
- [X] PATCHed `{"features": {"historical_data": {"vulnerabilities":
false}}}` — `vulnerabilities` flipped to `false`, `uptime` unchanged at
`true`
- [X] PATCHed `{"features": {"historical_data": {"uptime": false,
"vulnerabilities": true}}}` — both values applied as sent
- [X] PATCHed `{"features": {"historical_data": {"vulnerabilites":
false}}}` (typo in sub-key) — request rejected with 4xx, stored config
unchanged

  #### Fleet PATCH (`PATCH /api/v1/fleet/fleets/{id}`)
- [X] PATCHed a fleet with `{"features": {"historical_data": {"uptime":
false}}}` — fleet's `uptime` flipped to `false`, `vulnerabilities`
unchanged
- [X] Subsequent `GET /api/v1/fleet/fleets/{id}` returns the toggled
values under `features.historical_data` (storage shape is symmetric with
global)
- [X] PATCHed a fleet with `{"features": {"enable_host_users": false}}`
(a non-`historical_data` features sub-field) — request returned 200 but
the fleet's `enable_host_users` is unchanged (silently ignored, per
existing endpoint convention)

  #### GitOps — global (`fleetctl gitops -f global.yml`)
- [X] Applied a YAML with `features.historical_data: {uptime: true,
vulnerabilities: false}` — `vulnerabilities` is `false` after apply,
`uptime` is `true`
- [X] Applied a YAML whose `org_settings` omits `features` entirely —
both sub-keys are `true` after apply (defaults injected even if
previously disabled)
- [X] Applied a YAML where `historical_data` only contains `uptime:
false` — `uptime: false` is honored, `vulnerabilities` defaults to
`true`
- [X] Disabled `vulnerabilities` via the API, then ran `fleetctl gitops`
with a YAML that doesn't pin it — `vulnerabilities` flips back to `true`
(this is intentional; gitops is the source of truth)

  #### GitOps — fleet
- [X] Applied a fleet YAML with `features.historical_data: {uptime:
false}` — that fleet has `uptime: false`, `vulnerabilities: true` after
apply
- [X] Applied a fleet YAML whose `team_settings.features` omits
`historical_data` — both sub-keys are `true` after apply
- [X] Applied a fleet YAML that omits `features` entirely — both
sub-keys are `true` after apply

  #### `fleetctl apply` (legacy, partial-merge)
- [ ] Disabled `vulnerabilities` via the API, then ran `fleetctl apply`
with a YAML that doesn't mention `historical_data` — `vulnerabilities`
is still `false` (apply leaves omitted fields alone)

  #### Activities — global
- [X] After PATCHing global to disable `vulnerabilities`, the latest
activity is `disabled_historical_dataset` with payload `{"dataset":
"vulnerabilities", "fleet_id": null, "fleet_name": null}`
- [X] After PATCHing global with both sub-keys flipping in one request,
two activities are emitted (one per sub-key)
- [X] After PATCHing global with the same values that are already
stored, zero new activities are emitted
- [X] After re-enabling a previously disabled dataset, the activity type
is `enabled_historical_dataset`

  #### Activities — per fleet
- [X] After PATCHing fleet `workstations` to disable `uptime`, the
activity is `disabled_historical_dataset` with payload `{"dataset":
"uptime", "fleet_id": <workstations id>, "fleet_name": "workstations"}`
- [X] Toggling the same dataset on two different fleets produces two
distinct activities, one per fleet
- [X] After a fleet PATCH with the same values already stored, zero new
activities are emitted

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

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

## New Fleet configuration settings

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

If you didn't check the box above, follow this checklist for
GitOps-enabled 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)
  - https://github.com/fleetdm/fleet/pull/44703
- [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)
- [X] Verified that any relevant UI is disabled when GitOps mode is
enabled


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

* **New Features**
* Historical-data controls: per-org and per-team toggles for uptime and
vulnerability time‑series, with defaults applied when keys are omitted
and enable/disable activities emitted on changes.

* **Bug Fixes**
* Partial updates and PATCH/GitOps flows preserve unspecified
historical-data sub-keys instead of clearing them.

* **Tests**
* Expanded unit and integration tests covering defaults, partial
PATCH/GitOps behavior, idempotency, and activity emission.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-05 11:12:23 -05:00
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
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 SykulevandCopilot 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