Repository navigation
[Resources] Keep overrides and resource selectors in Update-AzPolicyAssignment/Exemption - #30206
precondition wants to merge 7 commits into
Conversation
…ssignment Update-AzPolicyAssignment writes the whole assignment back with a PUT but did not carry over the existing overrides and resource selectors. The service clears both when they are omitted from the PUT, so updating an unrelated property such as the display name silently removed them. Carry them over the same way as NotScope: only when the parameter is not specified, so passing an empty collection still clears them. Add mock-based Pester tests for the merge; the existing Override and ResourceSelector tests are tagged LiveOnly and never run in playback. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
|
Thank you for your contribution precondition! We will review the pull request and get back to you soon. |
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Fix the -InputObject merge logic so explicitly supplied override and selector values are not replaced by existing values.
Review effort: Lite
Findings: 1
Open (1)
What changed in this PR
Updates Update-AzPolicyAssignment to preserve policy overrides and resource selectors during unrelated updates.
Changes:
- Adds preservation and explicit-clearing merge logic.
- Adds focused merge-behavior tests.
- Documents the fix in the changelog.
| File | Summary |
|---|---|
src/Resources/Resources/ChangeLog.md |
Documents the bug fix. |
src/Resources/Policy.Autorest/test/UpdatePolicyAssignmentOverridesSelectors.Tests.ps1 |
Tests preservation, precedence, and clearing behavior. |
src/Resources/Policy.Autorest/custom/Update-AzPolicyAssignment.ps1 |
Adds preservation logic; an unresolved -InputObject merge issue affects explicit override and selector updates. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
…selectors Test $calledParameters instead of the bound -Override/-ResourceSelector parameters, as Update-AzPolicyEnrollment does for its ResourceSelector, so values that end up in $calledParameters from any source take precedence over the existing assignment. Behavior is unchanged for command-line use: explicit values and empty collections are already in $calledParameters. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Update-AzPolicyExemption has the same problem as Update-AzPolicyAssignment: it writes the whole exemption back with a PUT but did not carry over the existing resource selectors, which the service clears when they are omitted. Updating an unrelated property such as the display name therefore removed them, widening the exemption to every resource of the assignment. Carry them over like Update-AzPolicyEnrollment does, only when -ResourceSelector is not specified, so an empty collection still clears them. Add mock-based Pester tests for the merge. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The cmdlet deliberately ignores Furthermore, it makes the parameters consistent. In the same cmdlet, The intended method for clearing the values is |
The change was subsequently reverted in Azure#30272.
Record Update-AzPolicyAssignment and Update-AzPolicyExemption keeping the existing overrides and resource selectors when another property is updated, replacing them when specified and clearing them with empty collections. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
NoriZC : since #30204 was reverted for lacking recorded tests in #30272, I added recorded tests here: Unlike #30204, this bug is visible on the service side: without the fix, the overrides and resource selectors are gone after an unrelated update. The recordings show them being sent in the I recorded against my own subscription and replaced the subscription, tenant and user ids in the recordings with the ones from the committed Separately: would you accept the |
| @@ -0,0 +1,100 @@ | |||
| # setup the Pester environment for policy tests | |||
There was a problem hiding this comment.
This added test hasn't been recorded. Please make sure all added/changed tests are recorded and can be palyback successfully
X Engineering Agent ReportReview — Comments Domain edge casesP2 — Honor empty selectors on a typed exemption InputObject. In Please preserve explicit empty collection values from the typed input object before applying the fallback, normalizing this property to the accepted array type and distinguishing absent/null values from empty collections. Add a deterministic unit case using a real typed exemption with an assigned empty selector list, a nonempty mocked live exemption, and Existing feedback
Author-provided recordings demonstrate ordinary preserve, replace and explicit-array clear request/response mappings, including subsequent GETs. They do not cover the typed empty-list InputObject case. The handoff reports 12/12 upstream checks passed, not proof of all production scenarios. Generated internals are excluded from this repository; their execution was not independently verified. Test validation
Risk assessment — 7/100 · LowThe Low rating reflects the detected change scope with no elevated security, reliability, customer, operational, dependency, sovereign-cloud, generated-output, or cross-component signal.
Posted by x-engineering-agent (Reviewer) |
Yes we will review the PR when it was raised agagin |



Description
Updating an unrelated property of a policy assignment with
Update-AzPolicyAssignment(e.g. just its display name) silently wipes out its overrides and resource selectors.Update-AzPolicyExemptiondoes the same to the resource selectors of a policy exemption, which widens the exemption to every resource covered by its assignment.I found this while working on #30204, which fixes the always-false
EnforcementModecondition in the same merge logic. That one turned out to be harmless because the service keeps the storedenforcementModewhen it is missing from thePUT, so it has no user impact. This one is a real bug with real impact: the service does not keep overrides and resource selectors, so they are actually lost.The cmdlet merges your parameters into the existing assignment and
PUTs it back, but it doesn't carry overOverrideandResourceSelector, and the service clears both when they're missing from thePUT(checked with raw requests on2025-03-01and2026-01-01-preview). As a result, the policy silently applies more widely or more strictly than intended.The
-Overrideand-ResourceSelectorparameters were added to both cmdlets in #26031 (Az.Resources 7.5.0), after their merge logic had already been written, and the merge logic was never extended to cover them, so both cmdlets have been affected since then.This PR carries them over the same way
NotScopeis carried over, i.e. only when the parameter is not specified, so that passing an empty collection (-Override @(),-ResourceSelector @()) still clears them like before. This mirrors whatUpdate-AzPolicyEnrollment(added in #29909) already does for its ownResourceSelector:Update-AzPolicyExemptionnow uses exactly that condition for itsResourceSelector.Reproduction
The following script creates an audit-only assignment (
DoNotEnforce) with one override and one resource selector, renames it, counts both properties before and after the rename, and deletes the assignment:Details
Output with the released module and with the module built from this branch (PowerShell 7.6 on Linux, each run in a fresh process):
I could also reproduce it on an assignment I created from the Azure portal: after running
Update-AzPolicyAssignment -DisplayName ...on it, both the Overrides and the Resource selectors sections were empty in the portal (Edit assignment > Basics). I also checked on a live subscription that-Override @() -ResourceSelector @()still clears both with this PR.The same script adapted to exemptions (a
Waiverexemption with a resource selector on that assignment, thenUpdate-AzPolicyExemption -DisplayName 'renamed') givesResourceSelector=1→ResourceSelector=0with 10.2.1 andResourceSelector=1→ResourceSelector=1with this PR.Tests
I added
UpdatePolicyAssignmentOverridesSelectors.Tests.ps1. The existingAssignmentOverrideandAssignmentResourceSelectortests are taggedLiveOnlyso they never run in playback, and they only ever pass-Override/-ResourceSelectorexplicitly anyway, which is probably why this went unnoticed.It covers four cases:
-is [array]check is dropped)UpdatePolicyExemptionResourceSelector.Tests.ps1covers the same four cases forUpdate-AzPolicyExemptionand-ResourceSelector.These two files mock
Get-/New-AzPolicyAssignmentandGet-/New-AzPolicyExemption, so they check the merge logic itself and need no recording.I also added two recorded scenario tests,
PolicyAssignmentOverridesSelectors.Tests.ps1andPolicyExemptionResourceSelector.Tests.ps1, with their.Recording.json. They run the real cmdlets against the service, at subscription scope with a built-in audit policy assigned withDoNotEnforce:GetIn the recordings, the
PUTof the display-name-only update carriesoverridesandresourceSelectors, and the followingGETreturns them.The full Policy suite passes through
test-module.ps1in playback on Linux (Pester 4.10.1): 922 passed, 0 failed, 2 skipped (both already skipped in the repo).Mandatory Checklist
Please choose the target release of Azure PowerShell. (⚠️ Target release is a different concept from API readiness. Please click below links for details.)
Check this box to confirm: I have read the Submitting Changes section of
CONTRIBUTING.mdand reviewed the following information:ChangeLog.mdfile(s) appropriatelysrc/{{SERVICE}}/{{SERVICE}}/ChangeLog.md.## Upcoming Releaseheader in the past tense.ChangeLog.mdif no new release is required, such as fixing test case only.