Files
fleet/cmd
Rajendra kadam 2395d06e5b Extract early config validation from runServeCmd into testable helpers (#45583)
Extracts early config-validation logic out of `runServeCmd` and puts it
on the relevant config types in `server/config/`, following the existing
pattern used by `ConditionalAccessConfig.Validate(initFatal)` and
`AndroidAgentConfig.Validate(initFatal)`. (First commit on this branch
did the extraction into a separate file in `cmd/fleet/`; reshaped per
review.)

`runServeCmd` is now a series of `config.X.Validate(initFatal)` calls:

- `config.Logging.Validate(initFatal)` — OTEL logs requires tracing
enabled
- `config.Osquery.Validate(initFatal)` — `host_identifier` must be one
of `provided`, `instance`, `uuid`, `hostname`
- `config.Server.NormalizeURLPrefix()` +
`config.Server.ValidateURLPrefix(initFatal)` — Normalize mutates,
ValidateURLPrefix is pure
- `config.Server.Validate(initFatal)` — `private_key` vs
`private_key_arn` mutex check (called before Secrets Manager retrieval
so a misconfig fails fast without paying for an external lookup)
- `config.Server.ValidatePrivateKeyLength(initFatal)` — minimum 32 bytes
(called after Secrets Manager retrieval so an SM-provided short key is
also caught)

The private-key checks are split into two methods rather than folded
into one because the XOR check has to fire before the SM call, and SM
retrieval populates `PrivateKey` — so a single Validate called twice
would false-positive the XOR check post-SM whenever the user originally
configured only `private_key_arn`. Open to feedback if a different split
is preferred.

Tests live in `server/config/config_test.go` next to the existing config
Validate tests, structured as one smoke case plus error branches per the
existing convention.

Behavior is preserved: `runServeCmd` still calls `initFatal` at the same
points with the same descriptions.

## Broader plan

Issue #33370 calls for moving logic out of `serve.go` ("should only
contain critical config and dependency injection logic"). This PR is one
slice. Follow-ups, each in their own small PR:

- Extract more config validations (Apple APNs/SCEP both-or-neither,
etc.)
- Use the `initFatal` injection from #45343 to cover runtime failure
paths (datastore init, Redis init, MDM init)
- Larger extractions (license init, MDM wiring, mailer init)

**Related issue:** Refs #33370

# Checklist for submitter

- [x] Added/updated automated tests
- [x] Input data is properly validated (validators added, no
SQL/JS/shell paths involved)
- Changes file: not applicable — internal refactor with no user-visible
behavior change


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

* **Bug Fixes & Improvements**
  * Centralized and strengthened startup configuration validation.
* Enforced mutual exclusivity for private key sources and minimum
private-key length.
* Added URL-prefix normalization (ensure leading slash, trim trailing
slash) and validation.
  * Ensured OTEL logging requires tracing when enabled.
  * Restricted osquery host identifier to supported values.

* **Tests**
* Added tests covering validation rules and URL-prefix
normalization/validation.

<!-- 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/45583?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-21 12:33:37 -05:00
..