Skip to content

validate apple payload scope conflict, and unknown variable use in dry-run - #45139

Merged
MagnusHJensen merged 8 commits into
mainfrom
44456-validate-payload-scope-dry-run
May 12, 2026
Merged

validate apple payload scope conflict, and unknown variable use in dry-run#45139
MagnusHJensen merged 8 commits into
mainfrom
44456-validate-payload-scope-dry-run

Conversation

@MagnusHJensen

@MagnusHJensen MagnusHJensen commented May 11, 2026

Copy link
Copy Markdown
Member

Related issue: Resolves #44456

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

  • Added/updated automated tests
  • QA'd all new/changed functionality manually

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

Copilot AI review requested due to automatic review settings May 11, 2026 14:09
@MagnusHJensen
MagnusHJensen requested a review from a team as a code owner May 11, 2026 14:09

@claude claude 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.

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review to trigger a review and subscribe this PR to future pushes, or @claude review once for a one-time review.

Tip: disable this comment in your organization's Code Review settings.

@coderabbitai

coderabbitai Bot commented May 11, 2026

Copy link
Copy Markdown
Contributor

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

The PR adds a datastore API and MySQL implementation to verify Apple config profile PayloadScope conflicts, refactors the DB helper for reuse, and invokes this verification from Apple MDM and cross-platform MDM batch flows before honoring dry-run. Service validation order was adjusted so Fleet-variable and PayloadScope checks run during dry-run, and unit/integration tests and mocks were added or updated to cover conflict detection, edits/implicit-scope changes, legacy coercion, and dry-run invocation.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main changes: validating Apple payload scope conflicts and unknown variable use during dry-run mode, which matches the primary objectives of the PR.
Description check ✅ Passed The PR description includes all required checklist items marked as complete, including changes file addition, input validation, testing, and manual QA. The related issue is properly linked.
Linked Issues check ✅ Passed The PR successfully addresses issue #44456 by implementing validation that detects PayloadScope conflicts in both dry-run and real-run modes, which was the core requirement.
Out of Scope Changes check ✅ Passed All changes are directly related to the stated objectives: refactoring scope validation into a reusable datastore method, updating service-layer logic to call it before dry-run returns, and adding comprehensive test coverage.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 44456-validate-payload-scope-dry-run

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

Comment @coderabbitai help to get the list of available commands and usage tips.

@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: 1

🧹 Nitpick comments (1)
server/service/apple_mdm_test.go (1)

2756-2760: ⚡ Quick win

Add a no-write assertion for this dry-run failure path.

This test verifies the conflict is surfaced, but it doesn’t assert that persistence stays untouched when dry-run fails. Please also assert ds.BatchSetMDMAppleProfilesFuncInvoked is false here.

Suggested test hardening
  err := svc.BatchSetMDMAppleProfiles(ctx, nil, nil, [][]byte{mobileconfigForTest("N1", "I1")}, true, false)
  require.Error(t, err)
  require.ErrorContains(t, err, "scope conflict")
  require.True(t, ds.VerifyAppleConfigProfileScopesDoNotConflictFuncInvoked)
+ require.False(t, ds.BatchSetMDMAppleProfilesFuncInvoked)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@server/service/apple_mdm_test.go` around lines 2756 - 2760, Add a no-write
assertion after the dry-run failure call so the test also verifies persistence
was not invoked: after calling svc.BatchSetMDMAppleProfiles and the existing
require.Error/require.ErrorContains/require.True assertions, add
require.False(t, ds.BatchSetMDMAppleProfilesFuncInvoked) to ensure the
BatchSetMDMAppleProfiles persistence hook on the mock data store
(ds.BatchSetMDMAppleProfilesFuncInvoked) was not invoked during the dry-run path
that surfaced the scope conflict.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@server/datastore/mysql/apple_mdm.go`:
- Around line 2426-2427: Reintroduce datastore-level scope conflict validation
inside batchSetMDMAppleProfilesDB: before performing the DB write, iterate the
incoming profiles and validate their scopes the same way the service layer does
(reject conflicting or overlapping scope assignments), returning an error if any
conflict is detected so the write is aborted; locate the validation logic used
by the service layer and replicate or call it from batchSetMDMAppleProfilesDB to
enforce the invariant at the datastore boundary.

---

Nitpick comments:
In `@server/service/apple_mdm_test.go`:
- Around line 2756-2760: Add a no-write assertion after the dry-run failure call
so the test also verifies persistence was not invoked: after calling
svc.BatchSetMDMAppleProfiles and the existing
require.Error/require.ErrorContains/require.True assertions, add
require.False(t, ds.BatchSetMDMAppleProfilesFuncInvoked) to ensure the
BatchSetMDMAppleProfiles persistence hook on the mock data store
(ds.BatchSetMDMAppleProfilesFuncInvoked) was not invoked during the dry-run path
that surfaced the scope conflict.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 4b35e875-e220-4759-b204-f017a8596ca2

📥 Commits

Reviewing files that changed from the base of the PR and between 89517cc and 462c42c.

📒 Files selected for processing (9)
  • changes/44456-validate-payload-scope-dry-run
  • server/datastore/mysql/apple_mdm.go
  • server/datastore/mysql/apple_mdm_test.go
  • server/fleet/datastore.go
  • server/mock/datastore_mock.go
  • server/service/apple_mdm.go
  • server/service/apple_mdm_test.go
  • server/service/mdm.go
  • server/service/mdm_test.go

Comment on lines +2426 to 2427
// We don't verify profile scopes conflict, as we have already done it at the service level

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.

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Re-add datastore-level scope validation in batch set path

On Line 2426, removing validation from batchSetMDMAppleProfilesDB makes correctness depend on every caller doing service-layer prechecks. Keeping the datastore guard here preserves the invariant at the write boundary and avoids accidental bypasses.

Suggested patch
-	// We don't verify profile scopes conflict, as we have already done it at the service level
+	// Keep datastore-level verification as a write-path safeguard (service may also pre-validate).
+	if err := ds.verifyAppleConfigProfileScopesDoNotConflictDB(ctx, tx, profiles); err != nil {
+		return false, err
+	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@server/datastore/mysql/apple_mdm.go` around lines 2426 - 2427, Reintroduce
datastore-level scope conflict validation inside batchSetMDMAppleProfilesDB:
before performing the DB write, iterate the incoming profiles and validate their
scopes the same way the service layer does (reject conflicting or overlapping
scope assignments), returning an error if any conflict is detected so the write
is aborted; locate the validation logic used by the service layer and replicate
or call it from batchSetMDMAppleProfilesDB to enforce the invariant at the
datastore boundary.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This is a trade-off, and I'm unsure which direction we want to go.

Start doing more work in the:

if dryRun {
  // More work here
  return
}

And also keep it around, which IMO makes it harder to track, when it was called and not, but as called out it requires services to ensure validation has happened.

Comment thread server/service/mdm.go
}

// Verify Apple Config profiles PaylodScope conflicts
err = svc.ds.VerifyAppleConfigProfileScopesDoNotConflict(ctx, appleProfilesSlice)

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.

Would it make sense to call this only in the dry-run case? Since it will be called again during the actual insert call and it can potentially be expensive(large number of teams with duplicate profiles)?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

It should not, I removed it from the DB call (where we did this check before), so it would run once for both dry-run and actual runs. If one is left behind, that is a mistake.

Copilot AI 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.

Pull request overview

This PR updates the MDM profile batch apply flow so that GitOps dry-run performs the same key validations as a real run—specifically catching Apple configuration profile PayloadScope conflicts and validating Fleet variable usage—matching the behavior reported in #44456.

Changes:

  • Move the dryRun early-return in BatchSetMDMProfiles to occur after Fleet variable validation and Apple PayloadScope conflict checks.
  • Add a new datastore-level API (VerifyAppleConfigProfileScopesDoNotConflict) and call it from both the modern batch endpoint and the deprecated Apple-only endpoint, including dry-run paths.
  • Add/adjust unit tests and a new MySQL datastore test suite for scope-conflict validation logic.

Reviewed changes

Copilot reviewed 8 out of 9 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
server/service/mdm.go Runs Apple PayloadScope conflict verification (and variable validation) before returning on dry-run.
server/service/mdm_test.go Adds dry-run coverage for variable validation and scope-conflict validation.
server/service/apple_mdm.go Runs Apple PayloadScope conflict verification before returning on dry-run in the deprecated endpoint.
server/service/apple_mdm_test.go Adds dry-run coverage ensuring scope-conflict validation triggers.
server/mock/datastore_mock.go Adds mock datastore method for scope-conflict verification.
server/fleet/datastore.go Extends the datastore interface with the new verification method.
server/datastore/mysql/apple_mdm.go Exposes and refactors the scope-conflict verification implementation.
server/datastore/mysql/apple_mdm_test.go Adds focused tests for scope-conflict detection and legacy migration behavior.
changes/44456-validate-payload-scope-dry-run Adds a release note entry for the fix.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread server/service/mdm.go Outdated
Comment thread server/service/mdm.go
Comment thread server/service/apple_mdm.go
Comment thread server/datastore/mysql/apple_mdm.go
Comment thread server/mock/datastore_mock.go
Comment thread changes/44456-validate-payload-scope-dry-run
Comment thread server/service/mdm_test.go Outdated
@codecov

codecov Bot commented May 11, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 66.81%. Comparing base (b5cb2e2) to head (8fac049).
⚠️ Report is 14 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main   #45139   +/-   ##
=======================================
  Coverage   66.80%   66.81%           
=======================================
  Files        2720     2721    +1     
  Lines      218985   218994    +9     
  Branches    10747    10747           
=======================================
+ Hits       146296   146319   +23     
+ Misses      59520    59509   -11     
+ Partials    13169    13166    -3     
Flag Coverage Δ
backend 68.67% <100.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@MagnusHJensen
MagnusHJensen merged commit 2935856 into main May 12, 2026
59 checks passed
@MagnusHJensen
MagnusHJensen deleted the 44456-validate-payload-scope-dry-run branch May 12, 2026 06:51
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.

GitOps error for PayloadScope change should show up in dry run and "real" run

3 participants