Skip to content

Fix OIB assignment safety - #40

Merged
jorgeasaurus merged 6 commits into
mainfrom
agent/oib-assignment-safety
Jul 26, 2026
Merged

Fix OIB assignment safety#40
jorgeasaurus merged 6 commits into
mainfrom
agent/oib-assignment-safety

Conversation

@jorgeasaurus

Copy link
Copy Markdown
Owner

Summary

  • add guarded OIB Settings Catalog assignment automation for managed policies
  • fail closed on filtered and policy-set-owned targets
  • keep WinGet bootstrap logs out of executable-path output
  • rev the module to v1.3.1

Root cause

WinGet detection emitted bootstrap logs through the success stream, and Settings Catalog assignment automation needed explicit ownership and target-scope boundaries before replaying assignments.

Validation

  • ./build.ps1 -Task CI
  • 1,096 Pester tests passed; 0 failed
  • PSScriptAnalyzer: 0 errors (existing repository warnings remain)
  • built module validated at v1.3.1

Copilot AI review requested due to automatic review settings July 26, 2026 20:57

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 tightens operational safety around two areas in IntuneHydrationKit: (1) preventing WinGet detection bootstrap logs from contaminating success-stream output used as the resolved executable path, and (2) adding a guarded Settings Catalog assignment script for Windows OIB policies that enforces ownership/target boundaries and fails closed in unsafe cases. It also revs the module metadata and changelog to v1.3.1.

Changes:

  • Added scripts/Set-WindowsOIBSettingsCatalogAssignments.ps1 plus Pester coverage to safely automate intended All Users/All Devices assignments for managed OIB Settings Catalog policies while refusing filtered or policy-set-owned targets.
  • Updated WinGet detection script generation to emit bootstrap logging via Write-Verbose instead of the success stream.
  • Bumped version/release notes and updated CHANGELOG.md for 1.3.1.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
Tests/Scripts/Set-WindowsOIBSettingsCatalogAssignments.Tests.ps1 New Pester tests covering OIB policy selection and guarded assignment behavior.
Tests/Private/Get-WinGetDetectionScriptContent.Tests.ps1 Adds an assertion that bootstrap logging stays out of the success stream.
scripts/Set-WindowsOIBSettingsCatalogAssignments.ps1 New guarded assignment automation for Windows OIB Settings Catalog policies.
scripts/AssignmentHelpers.ps1 Extends graph connect helper to accept a required scope (but currently has a scope-variable bug).
Private/WinGet/Get-WinGetDetectionScriptContent.ps1 Switches detection logging from Write-Output to Write-Verbose.
IntuneHydrationKit.psd1 Version bump to 1.3.1 and updated release notes content.
CHANGELOG.md Adds 1.3.1 entry describing the fixes.

Comment thread scripts/AssignmentHelpers.ps1 Outdated
Copilot AI review requested due to automatic review settings July 26, 2026 21:06
@jorgeasaurus

Copy link
Copy Markdown
Owner Author

@copilot Please review the latest commit e1a20bd, specifically the scope-handling regression fix and its test coverage.

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

Copilot reviewed 7 out of 7 changed files in this pull request and generated no new comments.

Copilot AI commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

@copilot Please review the latest commit e1a20bd, specifically the scope-handling regression fix and its test coverage.

The fix in e1a20bd is correct and the test coverage is solid.

The bug: Connect-AssignmentGraph declared $RequiredScope as the parameter name but referenced the undefined $requiredScope (lowercase r) in all three call sites — the initial Connect-MgGraph, the $context.Scopes -notcontains guard, and the reconnect Connect-MgGraph. This meant the scope passed to Graph was always $null.

The fix: All three occurrences are consistently updated to $RequiredScope, matching the declared parameter.

Test coverage: The two new Connect-AssignmentGraph tests intentionally use 'DeviceManagementConfiguration.ReadWrite.All' (not the default scope), so any regression where the value doesn't propagate from the parameter would cause the ParameterFilter assertions to fail. Both paths — initial connection and reconnect — are covered. All 11 tests pass (verified locally).

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

Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.

Comment thread scripts/Set-WindowsOIBSettingsCatalogAssignments.ps1 Outdated
Copilot AI review requested due to automatic review settings July 26, 2026 21:37
@jorgeasaurus

Copy link
Copy Markdown
Owner Author

@copilot Please review the latest commit 92eb474, focusing on policy-set ownership detection before existing-target handling.

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

Copilot reviewed 7 out of 7 changed files in this pull request and generated no new comments.

Copilot AI commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

@copilot Please review the latest commit 92eb474, focusing on policy-set ownership detection before existing-target handling.

The fix in 92eb474 is correct and the regression test directly targets the failure path that was missing.

The bug: The policy-set ownership check ($indirectAssignments) ran after the unfiltered-target early return. So when the existing All Users/All Devices assignment happened to be policy-set-owned, the function hit return 'Skipped' first and never reached the throw.

The fix: The ownership check is now the first thing evaluated after fetching existing assignments. Any policy-set-owned assignment on the policy — regardless of target type — throws before any "safe" early return can be reached.

Test coverage: The new 'Should fail when an existing intended target is owned by a policy set' test mocks Get-ConfigurationPolicyAssignment to return exactly this case: an allLicensedUsersAssignmentTarget with source = 'policySets'. Under the old ordering this test would have returned 'Skipped'; with the fix it correctly throws '*owned by a policy set*' and the Invoke-MgGraphRequest assertion confirms no Graph write was attempted.

Copilot AI review requested due to automatic review settings July 26, 2026 22:27
@jorgeasaurus

Copy link
Copy Markdown
Owner Author

@copilot Please review the latest commit 86e0e12, which adds the system-context PsTools WinGet template and its template-contract update.

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

Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.

Comment thread scripts/Set-WindowsOIBSettingsCatalogAssignments.ps1
Copilot AI review requested due to automatic review settings July 26, 2026 22:35

Copilot AI commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

@copilot Please review the latest commit 86e0e12, which adds the system-context PsTools WinGet template and its template-contract update.

The reviewer's finding was valid — $PSCmdlet.ShouldProcess() returns $false for both -WhatIf and an interactive user cancellation, so the hardcoded 'WhatIf' status was wrong for the cancellation path.

Fixed in the latest commit: Set-OIBSettingsCatalogAssignment now checks $WhatIfPreference to pick the correct status:

$status = if ($WhatIfPreference) { 'WhatIf' } else { 'Cancelled' }

All 12 focused tests and 1,099 total tests pass.

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

Copilot reviewed 9 out of 9 changed files in this pull request and generated no new comments.

Copilot AI review requested due to automatic review settings July 26, 2026 22:47
@jorgeasaurus

Copy link
Copy Markdown
Owner Author

@copilot Please review the latest commit 34b6c73, including the cancellation-status regression coverage.

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

Copilot reviewed 9 out of 9 changed files in this pull request and generated no new comments.

Copilot AI commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

@copilot Please review the latest commit 34b6c73, including the cancellation-status regression coverage.

The cancellation-status regression coverage in 34b6c73 is solid.

The refactor: Get-OIBAssignmentSkipStatus cleanly isolates the 'WhatIf'/'Cancelled' decision into a testable helper. The $WasWhatIf parameter defaults to $WhatIfPreference, so calling it without arguments in Set-OIBSettingsCatalogAssignment correctly captures the caller-scope preference — and callers can pass an explicit bool to force either branch in tests without manipulating $WhatIfPreference.

Test coverage: Both branches are exercised directly by the new 'Should distinguish WhatIf from an interactive cancellation' test, and the existing ShouldProcess WhatIf assertion at line 174 continues to validate the end-to-end path. No gaps.

@jorgeasaurus
jorgeasaurus marked this pull request as ready for review July 26, 2026 22:59
@jorgeasaurus
jorgeasaurus requested a review from Copilot July 26, 2026 22:59
@jorgeasaurus

Copy link
Copy Markdown
Owner Author

@copilot Please review the latest commit 34b6c73.

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

Copilot reviewed 9 out of 9 changed files in this pull request and generated no new comments.

Copilot AI commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

@copilot Please review the latest commit 34b6c73.

Reviewed 34b6c7373e589489c11b9bd5cd298c6285bb5be5 and it looks correct. The cancellation-path behavior is now explicit via Get-OIBAssignmentSkipStatus, and the regression test covers both outcomes (WhatIf vs Cancelled) directly. I re-ran Tests/Scripts/Set-WindowsOIBSettingsCatalogAssignments.Tests.ps1 locally: 13/13 passing.

@jorgeasaurus
jorgeasaurus merged commit d44ec05 into main Jul 26, 2026
13 checks passed
@jorgeasaurus
jorgeasaurus deleted the agent/oib-assignment-safety branch July 26, 2026 23:06
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.

3 participants