Repository navigation
[BED-6027] - Filter GPOs with Computer Configuration Setting Disabled - #241
Conversation
WalkthroughThe LDAP query in GPOLocalGroupProcessor now requests GPCFileSysPath and Flags. Processing skips GPOs when Flags indicate disabled/computer-disabled (2 or 3). LdapPropertyProcessor reads Flags into gpostatus. A unit test validates enabled GPOs are applied and disabled ones are skipped. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant Caller
participant GPOLocalGroupProcessor
participant LDAP
participant FileSystem
Caller->>GPOLocalGroupProcessor: ReadGPOLocalGroups(gplink)
GPOLocalGroupProcessor->>LDAP: Query GPCFileSysPath, Flags
LDAP-->>GPOLocalGroupProcessor: path, flags
alt Missing path OR flags in {2,3}
GPOLocalGroupProcessor->>GPOLocalGroupProcessor: Cache current actions for link
GPOLocalGroupProcessor-->>Caller: Result (skipped)
else Enabled (flags in {0,1})
GPOLocalGroupProcessor->>FileSystem: Load Groups.xml / GptTmpl.inf
FileSystem-->>GPOLocalGroupProcessor: Data
GPOLocalGroupProcessor->>GPOLocalGroupProcessor: Process and cache actions
GPOLocalGroupProcessor-->>Caller: Result (applied)
end
note over GPOLocalGroupProcessor: New guard based on Flags
sequenceDiagram
autonumber
participant Caller
participant LdapPropertyProcessor
participant LDAP
Caller->>LdapPropertyProcessor: ReadGPOProperties(dn)
LdapPropertyProcessor->>LDAP: Query properties incl. Flags
LDAP-->>LdapPropertyProcessor: attributes
LdapPropertyProcessor-->>Caller: dict{..., gpostatus=Flags}
note over LdapPropertyProcessor: Adds gpostatus without changing signature
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (5)
src/CommonLib/Processors/LdapPropertyProcessor.cs (1)
168-169: Prefer numeric flags with derived boolean for clarity and future-proofingStoring Flags as a raw string works, but using a numeric type and exposing a derived boolean makes downstream logic simpler and less error-prone (e.g., bit tests). The GPO status field is bitwise: bit 1 indicates "computer configuration disabled," covering values 2 and 3.
Consider this change:
- entry.TryGetProperty(LDAPProperties.Flags, out var flags); - props.Add("gpostatus", flags); + if (entry.TryGetLongProperty(LDAPProperties.Flags, out var gpoFlags)) { + props.Add("gpostatus", gpoFlags); + // true when Computer Configuration is disabled (flags 2 or 3) + props.Add("gpocomputerconfigdisabled", (gpoFlags & 0x2) != 0); + }src/CommonLib/Processors/GPOLocalGroupProcessor.cs (1)
143-146: Use bitwise flag check and normalize cache key to avoid duplicate entriesTwo improvements:
- Flags check: interpret Flags numerically and test bit 1 to cover both "Computer Configuration Disabled" (2) and "All Settings Disabled" (3), instead of string comparisons.
- Cache key: you read from GpoActionCache using linkDn.ToLower(), but in this early-return branch you add with the original casing. This can create duplicate entries and unnecessary LDAP hits. Normalize the key consistently.
Apply:
- if (!result.Value.TryGetProperty(LDAPProperties.GPCFileSYSPath, out var filePath) || - // Filter out GPOs that are disabled or the computer configuration is disabled - (result.Value.TryGetProperty(LDAPProperties.Flags, out var flags) && flags is "2" or "3")) { - GpoActionCache.TryAdd(linkDn, actions); - continue; - } + if (!result.Value.TryGetProperty(LDAPProperties.GPCFileSYSPath, out var filePath)) { + GpoActionCache.TryAdd(linkDn.ToLower(), actions); + continue; + } + // Filter out GPOs whose computer configuration is disabled: bit 1 set (2 or 3) + if (result.Value.TryGetLongProperty(LDAPProperties.Flags, out var gpoFlags) && (gpoFlags & 0x2) != 0) { + GpoActionCache.TryAdd(linkDn.ToLower(), actions); + continue; + }test/unit/GPOLocalGroupProcessorTest.cs (3)
162-171: Use a unique temp subdirectory to avoid cross-test interferenceUsing Path.GetTempPath() as the root can cause collisions across parallel runs. Prefer a unique subdir per test.
- var gpcFileSysPath = Path.GetTempPath(); + var gpcFileSysPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(gpcFileSysPath);Optionally wrap the test body in try/finally and delete the directory in finally to keep the temp clean.
172-174: Remove unused variablemockComputerEntry is declared but never used.
- var mockComputerEntry = new Mock<IDirectoryObject>(); - var mockSearchResultEntry = new Mock<IDirectoryObject>(); + var mockSearchResultEntry = new Mock<IDirectoryObject>();
292-296: Assertions match intended behavior; consider asserting that actions are empty for skipped GPOsThe LocalAdmins asserts are good. For completeness, you could also assert that other groups (RemoteDesktopUsers, DcomUsers, PSRemoteUsers) are empty for flags 2/3 to guard against regressions in parsing.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (3)
src/CommonLib/Processors/GPOLocalGroupProcessor.cs(2 hunks)src/CommonLib/Processors/LdapPropertyProcessor.cs(1 hunks)test/unit/GPOLocalGroupProcessorTest.cs(1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (3)
src/CommonLib/Processors/LdapPropertyProcessor.cs (5)
src/CommonLib/DirectoryObjects/DirectoryEntryWrapper.cs (1)
TryGetProperty(35-50)src/CommonLib/DirectoryObjects/IDirectoryObject.cs (1)
TryGetProperty(8-8)src/CommonLib/DirectoryObjects/SearchResultEntryWrapper.cs (1)
TryGetProperty(22-38)test/unit/Facades/MockDirectoryObject.cs (1)
TryGetProperty(30-49)src/CommonLib/Enums/LDAPProperties.cs (1)
LDAPProperties(3-99)
src/CommonLib/Processors/GPOLocalGroupProcessor.cs (5)
src/CommonLib/Enums/LDAPProperties.cs (1)
LDAPProperties(3-99)src/CommonLib/DirectoryObjects/DirectoryEntryWrapper.cs (1)
TryGetProperty(35-50)src/CommonLib/DirectoryObjects/IDirectoryObject.cs (1)
TryGetProperty(8-8)src/CommonLib/DirectoryObjects/SearchResultEntryWrapper.cs (1)
TryGetProperty(22-38)test/unit/Facades/MockDirectoryObject.cs (1)
TryGetProperty(30-49)
test/unit/GPOLocalGroupProcessorTest.cs (4)
src/CommonLib/Processors/GPOLocalGroupProcessor.cs (6)
Task(52-58)Task(60-249)Task(346-374)TypedPrincipal(514-519)GPOLocalGroupProcessor(16-578)GPOLocalGroupProcessor(47-50)test/unit/Facades/MockDirectoryObject.cs (3)
TryGetSecurityIdentifier(137-140)MockDirectoryObject(12-180)MockDirectoryObject(18-23)src/CommonLib/LdapQueries/LdapFilter.cs (17)
LdapFilter(8-276)LdapFilter(47-51)LdapFilter(58-62)LdapFilter(69-75)LdapFilter(82-86)LdapFilter(93-97)LdapFilter(104-108)LdapFilter(115-119)LdapFilter(126-130)LdapFilter(137-141)LdapFilter(150-153)LdapFilter(160-163)LdapFilter(170-174)LdapFilter(181-184)LdapFilter(191-194)LdapFilter(201-204)GetFilter(237-256)src/CommonLib/Enums/LDAPProperties.cs (1)
LDAPProperties(3-99)
🔇 Additional comments (1)
src/CommonLib/Processors/GPOLocalGroupProcessor.cs (1)
134-135: Good: Requesting Flags alongside GPCFileSYSPathFetching both GPCFileSYSPath and Flags in the same query reduces roundtrips and enables early filtering. Looks good.
definitelynotagoblin
left a comment
There was a problem hiding this comment.
Holy moly those tests 👍
There was a problem hiding this comment.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/CommonLib/Processors/LdapPropertyProcessor.cs(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/CommonLib/Processors/LdapPropertyProcessor.cs (5)
src/CommonLib/DirectoryObjects/DirectoryEntryWrapper.cs (1)
TryGetProperty(35-50)src/CommonLib/DirectoryObjects/IDirectoryObject.cs (1)
TryGetProperty(8-8)src/CommonLib/DirectoryObjects/SearchResultEntryWrapper.cs (1)
TryGetProperty(22-38)test/unit/Facades/MockDirectoryObject.cs (1)
TryGetProperty(30-49)src/CommonLib/Enums/LDAPProperties.cs (1)
LDAPProperties(3-99)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build
Description
Filter GPOs that are disabled or, computer configuration disabled while doing local group processing. Adding the GPO status as one of the collected properties.
Motivation and Context
Resolves BED-6027
How Has This Been Tested?
This has been tested by running collection in an environment with and without the GPO enabled and monitoring the results of the collection to ensure that the results are affected.
Screenshots (if appropriate):
Types of changes
Checklist:
Summary by CodeRabbit
New Features
Bug Fixes
Tests