Skip to content

Added verification support for $FLEET_VAR_HOST_UUID - #31777

Merged
getvictor merged 7 commits into
mainfrom
victor/30879-host-uuid-verification
Aug 11, 2025
Merged

Added verification support for $FLEET_VAR_HOST_UUID#31777
getvictor merged 7 commits into
mainfrom
victor/30879-host-uuid-verification

Conversation

@getvictor

@getvictor getvictor commented Aug 10, 2025

Copy link
Copy Markdown
Member

Fixes #30879

Adds verification support for Windows profiles containing $FLEET_VAR_HOST_UUID, which was missing in previous PR.

Also added a license check since Fleet variables are a premium feature.

Also includes some refactoring.

Demo video: https://www.youtube.com/watch?v=HNWlu-uA20U

Checklist for submitter

Testing

  • Added/updated automated tests
  • Where appropriate, [automated tests simulate multiple hosts and test for host isolation]
  • QA'd all new/changed functionality manually

Summary by CodeRabbit

  • New Features

    • Improved detection and substitution of Fleet variables in Apple and Windows MDM profiles, supporting both braced and non-braced formats.
    • Centralized Fleet variable handling for more consistent and reliable profile processing.
  • Bug Fixes

    • Enhanced validation ensures that Fleet variables in MDM profiles require a premium license, with clear error messaging if requirements are not met.
    • Improved variable replacement logic to ensure accurate and secure profile deployment.
  • Tests

    • Added comprehensive tests to verify variable detection, replacement, and license enforcement in MDM profiles.
    • Expanded integration tests to cover variable substitution and profile verification scenarios.

@getvictor

Copy link
Copy Markdown
Member Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Aug 10, 2025

Copy link
Copy Markdown
Contributor
✅ Actions performed

Full review triggered.

@coderabbitai

coderabbitai Bot commented Aug 10, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

This change centralizes Fleet variable detection, parsing, and replacement logic into a new variables package, removing legacy and duplicated implementations throughout the codebase. It enforces premium license checks for using Fleet variables in both Apple and Windows MDM configuration profiles, updates validation and preprocessing flows to use the new package, and adds comprehensive unit and integration tests.

Changes

Cohort / File(s) Change Summary
Centralized Fleet Variable Logic
server/variables/variables.go, server/variables/variables_test.go
Introduced a new variables package with regexes and helper functions for finding, deduping, replacing, and detecting Fleet variables. Added comprehensive unit tests for all helper functions.
Apple MDM Profile Handling
server/service/apple_mdm.go, server/service/apple_mdm_test.go, server/mdm/apple/mobileconfig/mobileconfig.go
Replaced local Fleet variable detection and handling with calls to the new variables package. Added and updated tests to verify license enforcement and variable detection.
Windows MDM Profile Handling
server/service/mdm.go, server/service/mdm_test.go, server/mdm/microsoft/profile_verifier.go, server/mdm/microsoft/profile_verifier_test.go, server/service/integration_mdm_profiles_test.go
Updated Windows profile validation and preprocessing to use the variables package. Enforced license checks for variable usage. Added/updated tests for validation, substitution, and integration.
Removed Legacy Implementations
server/mdm/mdm.go, server/service/microsoft_mdm.go, server/service/microsoft_mdm_test.go
Removed legacy regexes and local variable substitution implementations. Delegated all variable logic to the new package. Removed redundant or replaced tests.
App Config Validation
server/service/appconfig.go
Updated validation logic to use the new variables package for Fleet variable detection.

Sequence Diagram(s)

sequenceDiagram
    participant Admin
    participant FleetServer
    participant VariablesPkg
    participant LicenseChecker
    participant Host

    Admin->>FleetServer: Uploads MDM profile with $FLEET_VAR_HOST_UUID
    FleetServer->>VariablesPkg: Find variables in profile
    VariablesPkg-->>FleetServer: Returns detected variables
    FleetServer->>LicenseChecker: Check if premium license required
    LicenseChecker-->>FleetServer: Returns license status
    alt License valid
        FleetServer->>VariablesPkg: Replace $FLEET_VAR_HOST_UUID with host UUID
        VariablesPkg-->>FleetServer: Returns processed profile
        FleetServer->>Host: Sends processed profile
    else License invalid
        FleetServer-->>Admin: Returns error (premium required)
    end
    Host->>FleetServer: Reports profile status
    FleetServer->>Admin: Shows profile verification status
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Assessment against linked issues

Objective Addressed Explanation
Allow specifying a host's hardware UUID in Windows configuration profiles (#30879)
Ensure UUID is populated when inspecting the profile on a host (#30879)
Resend profile when host UUID changes (#30879)
Enforce Fleet Premium tier for use of variables in profiles (#30879)

Assessment against linked issues: Out-of-scope changes

No out-of-scope changes found.

Possibly related PRs

Suggested labels

:ai

Suggested reviewers

  • lucasmrod
  • JordanMontgomery

Note

🔌 MCP (Model Context Protocol) integration is now available in Early Access!

Pro users can now connect to remote MCP servers under the Integrations page to get reviews and chat conversations that understand additional development context.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch victor/30879-host-uuid-verification

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

‼️ IMPORTANT
Auto-reply has been disabled for this repository in the CodeRabbit settings. The CodeRabbit bot will not respond to your replies unless it is explicitly tagged.

  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (17)
server/variables/variables.go (2)

47-61: Avoid recomputing named-group indices on every call

FindKeepDuplicates rebuilds nameToIndex for each invocation. Cache the subexp indices at package init to reduce per-call overhead.

Apply this diff within the function and use precomputed indices:

-	nameToIndex := make(map[string]int, 2)
-	for i, name := range fleetVariableRegex.SubexpNames() {
-		if name == "" {
-			continue
-		}
-		nameToIndex[name] = i
-	}
-
-	for _, match := range matches {
-		for _, i := range nameToIndex {
-			if match[i] != "" {
-				result = append(result, match[i])
-			}
-		}
-	}
+	for _, match := range matches {
+		if idxName1 >= 0 && match[idxName1] != "" {
+			result = append(result, match[idxName1])
+			continue
+		}
+		if idxName2 >= 0 && match[idxName2] != "" {
+			result = append(result, match[idxName2])
+		}
+	}

Add these cached indices once near the regex declarations:

var (
    idxName1 = fleetVariableRegex.SubexpIndex("name1")
    idxName2 = fleetVariableRegex.SubexpIndex("name2")
)

87-90: Expose a bytes-based Contains to avoid allocations at call sites

Many callers have []byte. Offer ContainsBytes([]byte) to skip converting to string.

Add this next to Contains:

 func Contains(contents string) bool {
   return fleetVariableRegex.MatchString(contents)
 }
+
+// ContainsBytes checks if the given content contains any Fleet variables (bytes version).
+func ContainsBytes(contents []byte) bool {
+  return fleetVariableRegex.Match(contents)
+}
server/service/appconfig.go (1)

1411-1468: De-duplicate allowed-variable validation across CACN/SeatID/UPNs

The same allowed-set loop appears in three validators. Consider extracting a small helper to validate an input string against the allowed set to reduce duplication and future drift.

For example:

func validateAllowedFleetVars(input string, field string, allowed map[string]struct{}, invalid *fleet.InvalidArgumentError) bool {
    vars := variables.Find(input)
    for v := range vars {
        if _, ok := allowed[v]; !ok {
            invalid.Append(field, "FLEET_VAR_"+v+" is not allowed in "+field)
            return false
        }
    }
    return true
}

Then call it with the appropriate field and allowed names for each validator.

server/mdm/apple/mobileconfig/mobileconfig.go (2)

123-125: Avoid string conversion when checking for variables in signed profiles

Use a bytes-based contains to skip allocation. If you add variables.ContainsBytes, this becomes a cheap Match.

-    if variables.Contains(string(mcBytes)) {
+    if variables.ContainsBytes(mcBytes) {
       return nil, errors.New("a signed profile cannot contain Fleet variables ($FLEET_VAR_*)")
     }

175-177: Repeat suggestion: use bytes-based contains

Same as above; switch to variables.ContainsBytes(mcBytes) if added.

-    if variables.Contains(string(mcBytes)) {
+    if variables.ContainsBytes(mcBytes) {
       return nil, errors.New("a signed profile cannot contain Fleet variables ($FLEET_VAR_*)")
     }
server/service/mdm_test.go (1)

2251-2287: Make error assertion robust to wrapping

Use require.ErrorIs instead of require.Equal for license checks to tolerate wrapped errors.

-        require.Error(t, err)
-        require.Equal(t, fleet.ErrMissingLicense, err)
+        require.ErrorIs(t, err, fleet.ErrMissingLicense)
server/mdm/microsoft/profile_verifier_test.go (1)

824-893: Optional: also assert the processed XML remains well-formed

As a safety net, you could unmarshal the resulting XML into a minimal struct (or decode to a token stream) to ensure replacements never break XML structure.

server/service/apple_mdm_test.go (1)

5082-5138: Strengthen assertions and tolerate empty map; consider t.Parallel()

  • Use ErrorIs for sentinel errors to be robust against wrapping.
  • Prefer Empty over Nil for maps (implementation may return an empty map).
  • Optional: add t.Parallel() at the test start for consistency with adjacent tests.
 func TestValidateConfigProfileFleetVariablesLicense(t *testing.T) {
+  t.Parallel()
   t.Run("requires premium license", func(t *testing.T) {
@@
-    require.Equal(t, fleet.ErrMissingLicense, err)
+    require.ErrorIs(t, err, fleet.ErrMissingLicense)
@@
-    vars, err = validateConfigProfileFleetVariables(appConfig, profileNoVars, freeLic)
+    vars, err = validateConfigProfileFleetVariables(appConfig, profileNoVars, freeLic)
     require.NoError(t, err)
-    require.Nil(t, vars)
+    require.Empty(t, vars)
   })
 }
server/service/microsoft_mdm.go (1)

2306-2307: Optional: use Contains when only presence matters

Since you only branch on whether any Fleet variable exists, using Contains avoids building a map:

- fleetVars := variables.Find(profileStr)
- if len(fleetVars) == 0 {
+ if !variables.Contains(profileStr) {
   // No Fleet variables...
server/variables/variables_test.go (1)

9-80: Solid coverage for Find and Contains; add a false-positive guard

Consider adding a case to ensure near-miss patterns don't match, e.g. "$FLEET_VARX_HOST_UUID" or "${FLEET_VAR_HOST_UUID" (missing brace), to guard against overmatching.

server/service/apple_mdm.go (2)

405-411: Consider simplifying license retrieval flow

Fetching license info here and passing it down is fine. If you end up needing license checks elsewhere for Apple profiles, consider centralizing inside the validator or accepting a context and using license.IsPremium(ctx) for consistency across the codebase.


5293-5299: Scoped variable replacement in CA items uses new finder

Refactor to variables.Find is consistent. Consider renaming caFleetVars to vars or foundVars for readability, but optional.

server/service/integration_mdm_profiles_test.go (3)

7263-7278: Mark test helper as a helper and keep failure locations crisp

Add t.Helper() at the start so failures point to the call site. The lookup-by-name is fine here, but if you expect future reuse, consider keying by profile UUID to avoid name collisions.

-	checkHostProfileStatus := func(hostUUID string, profileName string, expectedStatus fleet.MDMDeliveryStatus) {
+	checkHostProfileStatus := func(hostUUID string, profileName string, expectedStatus fleet.MDMDeliveryStatus) {
+		t.Helper()
 		profiles, err := s.ds.GetHostMDMWindowsProfiles(ctx, hostUUID)
 		require.NoError(t, err)

7348-7401: Tighten verification signal in simulateOsqueryProfileReport

Current matching relies on substring contains. To reduce false positives, assert LocURI matches and compare data for equality when possible.

-				{
-					"fleet_detail_query_mdm_config_profiles_windows": {
-						{"raw_mdm_command_output": string(rawResponse)},
-					},
-				},
+				{
+					"fleet_detail_query_mdm_config_profiles_windows": {
+						{"raw_mdm_command_output": string(rawResponse)},
+					},
+				},

And when validating in verifyProfileSubstitution:

-							if strings.Contains(item.Data.Content, expectedData) {
+							if item.Target != nil && *item.Target == locURI && item.Data.Content == expectedData {

Note: You can plumb locURI into verifyProfileSubstitution to assert both dimensions.


7417-7425: Make the global profile swap explicit with an assertion

You rely on ProfileNoVars replacing GlobalProfileWithVar for global hosts. Add a short assertion to confirm the swap so future refactors don’t silently change this behavior.

 	// Note: GlobalProfileWithVar was replaced by ProfileNoVars for global hosts
 	// since both are global profiles and Fleet only keeps one profile per host.
 	// So we need to simulate osquery reporting ProfileNoVars for global hosts.
+	{
+		profs, err := s.ds.GetHostMDMWindowsProfiles(ctx, hostGlobal1.UUID)
+		require.NoError(t, err)
+		var names []string
+		for _, p := range profs { names = append(names, p.Name) }
+		require.Contains(t, names, "ProfileNoVars")
+		require.NotContains(t, names, "GlobalProfileWithVar")
+	}
server/service/mdm.go (2)

1769-1773: Fleet vars validation in batch path wired correctly.

Passing license through to both Apple and Windows variable validators unifies enforcement. Consider documenting that profilesVariablesByIdentifierMap includes Apple entries even when no variables are found, while Windows entries are added only when variables exist, to avoid confusion.


1865-1895: validateFleetVariables: consistent behavior and clarity.

  • Consistency: For Apple, you add an entry even when no variables were found (profileVars may be nil). For Windows, you add an entry only if len(windowsVars) > 0. Consider standardizing this behavior (either only add when >0 for both or always add an entry) to make downstream handling predictable.
  • Naming: Using p.Name for Windows as identifier is fine (no PayloadIdentifier equivalent). A short comment noting this choice and its implications would help future readers.
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9d24f20 and 2ec1820.

📒 Files selected for processing (14)
  • server/mdm/apple/mobileconfig/mobileconfig.go (3 hunks)
  • server/mdm/mdm.go (0 hunks)
  • server/mdm/microsoft/profile_verifier.go (3 hunks)
  • server/mdm/microsoft/profile_verifier_test.go (1 hunks)
  • server/service/appconfig.go (4 hunks)
  • server/service/apple_mdm.go (9 hunks)
  • server/service/apple_mdm_test.go (2 hunks)
  • server/service/integration_mdm_profiles_test.go (1 hunks)
  • server/service/mdm.go (5 hunks)
  • server/service/mdm_test.go (2 hunks)
  • server/service/microsoft_mdm.go (3 hunks)
  • server/service/microsoft_mdm_test.go (0 hunks)
  • server/variables/variables.go (1 hunks)
  • server/variables/variables_test.go (1 hunks)
💤 Files with no reviewable changes (2)
  • server/mdm/mdm.go
  • server/service/microsoft_mdm_test.go
🧰 Additional context used
📓 Path-based instructions (1)
**/*.go

⚙️ CodeRabbit Configuration File

When reviewing SQL queries that are added or modified, ensure that appropriate filtering criteria are applied—especially when a query is intended to return data for a specific entity (e.g., a single host). Check for missing WHERE clauses or incorrect filtering that could lead to incorrect or non-deterministic results (e.g., returning the first row instead of the correct one). Flag any queries that may return unintended results due to lack of precise scoping.

Files:

  • server/mdm/microsoft/profile_verifier_test.go
  • server/mdm/apple/mobileconfig/mobileconfig.go
  • server/service/appconfig.go
  • server/mdm/microsoft/profile_verifier.go
  • server/service/mdm_test.go
  • server/variables/variables.go
  • server/variables/variables_test.go
  • server/service/microsoft_mdm.go
  • server/service/mdm.go
  • server/service/apple_mdm.go
  • server/service/apple_mdm_test.go
  • server/service/integration_mdm_profiles_test.go
🧠 Learnings (2)
📓 Common learnings
Learnt from: getvictor
PR: fleetdm/fleet#31695
File: server/datastore/mysql/apple_mdm_test.go:132-132
Timestamp: 2025-08-08T08:32:31.467Z
Learning: Datastore.NewMDMWindowsConfigProfile signature is: NewMDMWindowsConfigProfile(ctx context.Context, cp fleet.MDMWindowsConfigProfile, usesFleetVars []string) (*fleet.MDMWindowsConfigProfile, error). Passing nil for usesFleetVars in tests denotes “no Fleet variables referenced” and is used consistently across the repo.
📚 Learning: 2025-08-08T08:32:31.467Z
Learnt from: getvictor
PR: fleetdm/fleet#31695
File: server/datastore/mysql/apple_mdm_test.go:132-132
Timestamp: 2025-08-08T08:32:31.467Z
Learning: Datastore.NewMDMWindowsConfigProfile signature is: NewMDMWindowsConfigProfile(ctx context.Context, cp fleet.MDMWindowsConfigProfile, usesFleetVars []string) (*fleet.MDMWindowsConfigProfile, error). Passing nil for usesFleetVars in tests denotes “no Fleet variables referenced” and is used consistently across the repo.

Applied to files:

  • server/mdm/microsoft/profile_verifier_test.go
  • server/mdm/apple/mobileconfig/mobileconfig.go
  • server/mdm/microsoft/profile_verifier.go
  • server/service/mdm_test.go
  • server/service/microsoft_mdm.go
  • server/service/mdm.go
  • server/service/apple_mdm.go
  • server/service/apple_mdm_test.go
  • server/service/integration_mdm_profiles_test.go
🔇 Additional comments (25)
server/variables/variables.go (1)

17-17: Regex pattern looks solid and covers both braced and non-braced forms

Covers $FLEET_VAR_* and ${FLEET_VAR_*} with named groups for clean extraction. Good centralization.

server/service/appconfig.go (1)

1411-1420: Switched to variables.Find — behavior is consistent and safe

variables.Find returns names without prefix and range over a nil map is safe. Allowed set check is clear.

server/mdm/apple/mobileconfig/mobileconfig.go (2)

116-117: Good: strip out DigiCert data variables before parsing

Using the centralized variables.ProfileDataVariableRegex keeps logic consistent across the codebase.


168-169: Good duplication of DigiCert data variable stripping in payloadSummary

Consistent with ParseConfigProfile; avoids false positives due to DigiCert placeholders.

server/service/mdm_test.go (2)

2387-2390: Signature update covered in tests

Passing a premium license explicitly to validateWindowsProfileFleetVariables keeps the test focused on variable validation, not licensing.


1248-1249: Coverage for unsupported variables in Windows profiles looks good

Tests assert unsupported Fleet vars are rejected. Consider adding a positive test for $FLEET_VAR_HOST_UUID under free license via the higher-level profile creation path to ensure enforcement is wired end-to-end (if not already elsewhere).

Would you like me to add an integration-style test for NewMDMWindowsConfigProfile with $FLEET_VAR_HOST_UUID under both free and premium to assert license gating?

Also applies to: 1635-1644

server/mdm/microsoft/profile_verifier_test.go (1)

824-893: Thorough test coverage for $FLEET_VAR_HOST_UUID preprocessing

  • Covers braced/unbraced, multiplicity, and XML escaping including quotes and apostrophes.
  • Validates unsupported vars are left intact.

Nice work.

server/service/apple_mdm_test.go (1)

5433-5436: LGTM: passing license info to validation

Updating the call site to pass a premium license aligns with the new function signature and test intent.

server/mdm/microsoft/profile_verifier.go (3)

19-19: Centralized variables package import — good direction

Using the shared variables package helps keep detection/replacement consistent across the codebase.


47-51: Preprocess after secret expansion is correct

Expanding embedded secrets before Fleet variable replacement mirrors deployment behavior and ensures verification compares the actual on-device content.


281-324: Preprocessor logic is sound and already covered by tests

  • PreprocessWindowsProfileContents is exercised by TestPreprocessWindowsProfileContents in
    server/mdm/microsoft/profile_verifier_test.go:824–889.
  • To simplify and reduce allocations, consider replacing the loop with a short-circuit check and a direct bytes.Buffer:
    // only HOST_UUID is supported today
    if _, ok := variables.Find(profileContents)[string(fleet.FleetVarHostUUID)]; ok {
        var buf bytes.Buffer
        _ = xml.EscapeText(&buf, []byte(hostUUID))
        result = variables.Replace(result, string(fleet.FleetVarHostUUID), buf.String())
    }
  • This removes the extra slice allocation (make([]byte, 0, len(hostUUID))) and the loop overhead.
server/service/microsoft_mdm.go (2)

32-32: Import of variables is appropriate

Aligns this layer with centralized variable handling.


2329-2331: Per-host preprocessing is correct for $FLEET_VAR_HOST_UUID

Generating a unique command per host when variables are present ensures the device receives resolved content. This aligns with verification logic.

server/variables/variables_test.go (2)

81-116: LGTM: FindKeepDuplicates exercises ordering and duplication

Covers both unique and repeated variables as expected.


117-169: LGTM: Replace handles both syntaxes and empty values

Good assertions across absence and multiple occurrences.

server/service/apple_mdm.go (7)

56-56: Centralized variables handling import looks good

Importing server/variables here aligns this file with the new, shared Fleet variables package.


607-613: Dedup result set: good

Converting the duplicate-preserving slice to a set for datastore storage is correct and efficient.


619-621: Correct regex source for base64 data handling

Switching to variables.ProfileDataVariableRegex keeps behavior consistent across platforms. Good call.


759-759: Consistent data-field variable stripping

Using variables.ProfileDataVariableRegex here matches the earlier change and preserves unmarshal behavior.


972-975: Clear, centralized variable detection in DDM validation

Using variables.Contains keeps the validation concise and aligned with the new package.


2616-2620: Deprecated endpoint correctly rejects Fleet variables

Good guardrail to prevent variables from slipping through older API paths with a helpful error message.


4883-4886: Efficient profile preprocessing: only branch when variables exist

Early-exit pattern via variables.Find keeps preprocessing fast for profiles without variables.

server/service/mdm.go (3)

44-44: Import looks correct and consistent with usage.

The new variables package is used below for Fleet variable detection. No issues.


1480-1485: Good: fetch license early for precise validation.

Retrieving the license once here before validating the Windows profile keeps error reporting tight. No changes requested.


1763-1768: Good: license retrieval added before batch Fleet-vars validation.

This mirrors Apple handling and centralizes enforcement. No changes requested.

Comment thread server/service/apple_mdm.go
Comment thread server/service/integration_mdm_profiles_test.go Outdated
Comment thread server/service/mdm.go
Comment thread server/service/mdm.go
@getvictor
getvictor marked this pull request as ready for review August 10, 2025 14:37
@getvictor
getvictor requested a review from a team as a code owner August 10, 2025 14:37

@lucasmrod lucasmrod left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

Comment on lines +879 to +884
{
name: "fleet variable with both formats in same profile",
hostUUID: "test-host-1234-uuid",
profileContents: `<Replace><Data>ID1: $FLEET_VAR_HOST_UUID, ID2: ${FLEET_VAR_HOST_UUID}</Data></Replace>`,
expectedContents: `<Replace><Data>ID1: test-host-1234-uuid, ID2: test-host-1234-uuid</Data></Replace>`,
},

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Same test as multiple fleet variables.

@getvictor
getvictor merged commit bc36567 into main Aug 11, 2025
37 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Host vital variable in Windows configuration profiles: UUID

2 participants