-
Notifications
You must be signed in to change notification settings - Fork 1
AADSyncRuleCount: Add report-only rule-count DSC resource #32
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,105 @@ | ||
| [DscResource()] | ||
| class AADSyncRuleCount | ||
| { | ||
|
Comment on lines
+1
to
+3
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion | 🟠 Major | 🏗️ Heavy lift 🧩 Analysis chain🏁 Script executed: # First, let's examine the file being reviewed
cat -n source/Classes/AADSyncRuleCount.ps1Repository: dsccommunity/AADConnectDsc Length of output: 4633 🏁 Script executed: # Check if ResourceBase exists in the module
fd -type f "ResourceBase" source/Repository: dsccommunity/AADConnectDsc Length of output: 241 🏁 Script executed: # Check for existing DSC resources in the module to understand the pattern
find source/Classes -name "*.ps1" -type f | head -5 | xargs -I {} sh -c 'echo "=== {} ===" && head -15 {}'Repository: dsccommunity/AADConnectDsc Length of output: 1810 Restructure resource to follow the required DSC class pattern. The resource deviates from mandatory guidelines: missing Per coding guidelines:
🧰 Tools🪛 PSScriptAnalyzer (1.25.0)[warning] Missing BOM encoding for non-ASCII encoded file 'AADSyncRuleCount.ps1' (PSUseBOMForUnicodeEncodedFile) [info] 1-105: No examples found for resource 'AADSyncRuleCount' (PSDSCDscExamplesPresent) [info] 1-105: No tests found for resource 'AADSyncRuleCount' (PSDSCDscTestsPresent) 🤖 Prompt for AI Agents |
||
| <# | ||
| .SYNOPSIS | ||
| Verifies the number of Azure AD Connect synchronization rules. | ||
|
|
||
| .DESCRIPTION | ||
| Read-only / report-only DSC resource that compares the expected | ||
| number of AAD Connect sync rules against the current state and | ||
| reports a drift if they differ. The resource never attempts to | ||
| remediate drift because creating or removing rules to match a | ||
| count is not a meaningful operation; the user must investigate | ||
| and reconcile manually. | ||
|
|
||
| Use `ConnectorName` to scope the count to a specific connector. | ||
| Leave `ConnectorName` empty (or set it to `*`) to count every | ||
| sync rule across all connectors. | ||
| #> | ||
|
|
||
| # `ConnectorName` is the key. Empty string or '*' means "all connectors". | ||
| [DscProperty(Key = $true)] | ||
| [string]$ConnectorName | ||
|
|
||
| [DscProperty(Mandatory = $true)] | ||
| [uint32]$RuleCount | ||
|
|
||
| [DscProperty(NotConfigurable)] | ||
| [uint32]$CurrentRuleCount | ||
|
|
||
| [bool]Test() | ||
| { | ||
| $currentState = $this.Get() | ||
| $scope = $this.GetScopeDescription() | ||
|
|
||
| if ($currentState.CurrentRuleCount -eq $this.RuleCount) | ||
| { | ||
| Write-Verbose -Message "AADSyncRuleCount: $scope has the expected $($this.RuleCount) sync rule(s)." | ||
| $this.TryWriteEventLog('Information', 1100, "AADSyncRuleCount in desired state for $scope (count=$($this.RuleCount)).") | ||
| return $true | ||
| } | ||
|
|
||
| Write-Verbose -Message "AADSyncRuleCount: $scope has $($currentState.CurrentRuleCount) sync rule(s) but expected $($this.RuleCount)." | ||
| $this.TryWriteEventLog('Warning', 1101, "AADSyncRuleCount drift for $scope. Expected=$($this.RuleCount); Current=$($currentState.CurrentRuleCount).") | ||
|
Comment on lines
+38
to
+44
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Localize all user-facing and diagnostic messages. Hardcoded strings are used in As per coding guidelines, Also applies to: 78-78, 102-102 🧰 Tools🪛 PSScriptAnalyzer (1.25.0)[warning] Missing BOM encoding for non-ASCII encoded file 'AADSyncRuleCount.ps1' (PSUseBOMForUnicodeEncodedFile) 🤖 Prompt for AI Agents |
||
| return $false | ||
| } | ||
|
|
||
| [AADSyncRuleCount]Get() | ||
| { | ||
| $currentState = [AADSyncRuleCount]::new() | ||
| $currentState.ConnectorName = $this.ConnectorName | ||
| $currentState.RuleCount = $this.RuleCount | ||
|
|
||
| $rules = if ([string]::IsNullOrEmpty($this.ConnectorName) -or $this.ConnectorName -eq '*') | ||
| { | ||
| Get-ADSyncRule | ||
| } | ||
| else | ||
| { | ||
| Get-ADSyncRule -ConnectorName $this.ConnectorName | ||
| } | ||
|
|
||
| # Get-ADSyncRule may return $null when no rules match; coerce to 0. | ||
| $currentState.CurrentRuleCount = if ($null -eq $rules) { 0 } else { @($rules).Count } | ||
|
|
||
| return $currentState | ||
| } | ||
|
|
||
| [void]Set() | ||
| { | ||
| # This resource is report-only. Adjusting the rule count automatically | ||
| # is not safe and not meaningful — the operator must investigate which | ||
| # rules are missing or extra. Throw a clear error so the LCM marks the | ||
| # configuration as failed. | ||
|
|
||
| $currentState = $this.Get() | ||
| $scope = $this.GetScopeDescription() | ||
| $message = "AADSyncRuleCount drift detected for $scope. Expected $($this.RuleCount) sync rule(s) but found $($currentState.CurrentRuleCount). This resource does not remediate count drift; investigate the AAD Connect configuration manually." | ||
|
|
||
| $this.TryWriteEventLog('Error', 1102, $message) | ||
| throw $message | ||
| } | ||
|
Comment on lines
+80
to
+82
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: head -100 source/Classes/AADSyncRuleCount.ps1 | cat -nRepository: dsccommunity/AADConnectDsc Length of output: 4476 🏁 Script executed: wc -l source/Classes/AADSyncRuleCount.ps1Repository: dsccommunity/AADConnectDsc Length of output: 110 🏁 Script executed: sed -n '70,90p' source/Classes/AADSyncRuleCount.ps1 | cat -nRepository: dsccommunity/AADConnectDsc Length of output: 1107 🏁 Script executed: grep -n "throw " source/Classes/AADSyncRuleCount.ps1Repository: dsccommunity/AADConnectDsc Length of output: 96 🏁 Script executed: # Check if New-InvalidOperationException is available/used in this codebase
find source -name "*.ps1" -type f -exec grep -l "New-InvalidOperationException" {} \;Repository: dsccommunity/AADConnectDsc Length of output: 52 🏁 Script executed: # Check what DscResource.Common functions are imported or referenced
grep -r "New-.*Exception" source --include="*.ps1" | head -20Repository: dsccommunity/AADConnectDsc Length of output: 52 🏁 Script executed: # Check the module manifest for DscResource.Common dependencies
cat source/*.psd1 | grep -A 20 "RequiredModules"Repository: dsccommunity/AADConnectDsc Length of output: 947 🏁 Script executed: # Check if there are any imports at the top of the file
head -20 source/Classes/AADSyncRuleCount.ps1Repository: dsccommunity/AADConnectDsc Length of output: 848 🏁 Script executed: # Check if this module has any base classes or parent references
grep -n "inherit" source/Classes/AADSyncRuleCount.ps1Repository: dsccommunity/AADConnectDsc Length of output: 52 🏁 Script executed: # Check the psm1 file to see what's imported
head -50 source/AADConnectDsc.psm1 | grep -i "function\|require\|import\|module"Repository: dsccommunity/AADConnectDsc Length of output: 152 🏁 Script executed: # Check if there are other class-based resources in the source/Classes directory
find source/Classes -name "*.ps1" -type fRepository: dsccommunity/AADConnectDsc Length of output: 378 🏁 Script executed: # Check if the module uses DscResource.Base or DscResource.Common in any way
grep -r "DscResource\|ResourceBase" source --include="*.ps1"Repository: dsccommunity/AADConnectDsc Length of output: 1172 🏁 Script executed: # Check if this is actually an issue by looking at similar projects
# First, let's see what other classes exist
ls -la source/Classes/Repository: dsccommunity/AADConnectDsc Length of output: 772 🏁 Script executed: # Check the Prefix.ps1 file to see DscResource.Common loading
cat source/Prefix.ps1 | head -30Repository: dsccommunity/AADConnectDsc Length of output: 234 🏁 Script executed: # Check if the DscResource.Common module exists in the Modules directory
ls -la source/Modules/Repository: dsccommunity/AADConnectDsc Length of output: 133 🏁 Script executed: # Check what exception helpers are available in DscResource.Common
find source/Modules/DscResource.Common -name "*.ps1" -type f | grep -i exceptionRepository: dsccommunity/AADConnectDsc Length of output: 139 🏁 Script executed: # Let's verify the coding guideline applies to this class specifically
# Check if the class has [DscResource(...)] decoration
grep -A 2 "^class AADSyncRuleCount" source/Classes/AADSyncRuleCount.ps1Repository: dsccommunity/AADConnectDsc Length of output: 102 🏁 Script executed: # Check the context around line 81 to understand the error scenario
sed -n '69,82p' source/Classes/AADSyncRuleCount.ps1 | cat -nRepository: dsccommunity/AADConnectDsc Length of output: 879 🏁 Script executed: # Search for how other DSC resources in this repo handle errors
grep -r "New-InvalidOperationException\|New-InvalidDataException\|throw" source/Classes/*.ps1 | head -20Repository: dsccommunity/AADConnectDsc Length of output: 129 Replace raw Line 81 uses Since this resource is report-only and cannot remediate drift, 🧰 Tools🪛 PSScriptAnalyzer (1.25.0)[warning] Missing BOM encoding for non-ASCII encoded file 'AADSyncRuleCount.ps1' (PSUseBOMForUnicodeEncodedFile) 🤖 Prompt for AI Agents |
||
|
|
||
| hidden [string]GetScopeDescription() | ||
| { | ||
| if ([string]::IsNullOrEmpty($this.ConnectorName) -or $this.ConnectorName -eq '*') | ||
| { | ||
| return "all connectors" | ||
| } | ||
|
|
||
| return "connector '$($this.ConnectorName)'" | ||
| } | ||
|
|
||
| hidden [void]TryWriteEventLog([string]$EventType, [int]$EventId, [string]$Message) | ||
| { | ||
| try | ||
| { | ||
| Write-AADConnectEventLog -EventType $EventType -EventId $EventId -Message $Message -ConnectorName $this.ConnectorName | ||
| } | ||
| catch | ||
| { | ||
| Write-Verbose -Message "Failed to write event log entry: $($_.Exception.Message)" | ||
| } | ||
| } | ||
| } | ||
|
Comment on lines
+1
to
+105
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion | 🟠 Major | 🏗️ Heavy lift Add unit and integration tests for the new resource before merge. This PR adds a new DSC resource, but no corresponding resource tests are included in the reviewed changes. As per coding guidelines, 🧰 Tools🪛 PSScriptAnalyzer (1.25.0)[warning] Missing BOM encoding for non-ASCII encoded file 'AADSyncRuleCount.ps1' (PSUseBOMForUnicodeEncodedFile) [info] 1-105: No examples found for resource 'AADSyncRuleCount' (PSDSCDscExamplesPresent) [info] 1-105: No tests found for resource 'AADSyncRuleCount' (PSDSCDscTestsPresent) 🤖 Prompt for AI Agents |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| <# | ||
| .EXAMPLE 1 | ||
|
|
||
| Verifies that the 'contoso.com' connector has exactly 42 sync rules. | ||
| If the actual count differs, the resource throws an error during Set | ||
| and the LCM marks the configuration as failed. The resource never | ||
| attempts to add or remove rules to reach the expected count. | ||
| #> | ||
|
|
||
| configuration Example_AADSyncRuleCount_Basic | ||
| { | ||
| Import-DscResource -ModuleName AADConnectDsc | ||
|
|
||
| node localhost | ||
| { | ||
| AADSyncRuleCount 'ContosoRuleCount' | ||
| { | ||
| ConnectorName = 'contoso.com' | ||
| RuleCount = 42 | ||
| } | ||
|
|
||
| # Verify the total number of rules across all connectors. | ||
| AADSyncRuleCount 'TotalRuleCount' | ||
| { | ||
| ConnectorName = '*' | ||
| RuleCount = 168 | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use 1/1/1 ordered-list numbering to satisfy markdown rules.
This section currently uses
1.,2.,3.and triggers MD029 warnings.✅ Minimal fix
As per coding guidelines, Markdown requires "Use '1.' for all items in ordered lists (1/1/1 numbering style)".
📝 Committable suggestion
🧰 Tools
🪛 markdownlint-cli2 (0.22.1)
[warning] 26-26: Ordered list item prefix
Expected: 1; Actual: 2; Style: 1/1/1
(MD029, ol-prefix)
[warning] 27-27: Ordered list item prefix
Expected: 1; Actual: 3; Style: 1/1/1
(MD029, ol-prefix)
🤖 Prompt for AI Agents