Skip to content

Conversation

MikeX777
Copy link
Contributor

@MikeX777 MikeX777 commented Aug 20, 2025

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

  • Chore (a change that does not modify the application functionality)
  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • Documentation updates are needed, and have been made accordingly.
  • I have added and/or updated tests to cover my changes.
  • All new and existing tests passed.
  • My changes include a database migration.

Summary by CodeRabbit

  • New Features

    • GPO properties now include a status field (gpostatus) derived from LDAP Flags.
  • Bug Fixes

    • Local group processing now correctly skips GPOs that are disabled or have computer configuration disabled, preventing unintended application of settings and improving result accuracy.
  • Tests

    • Added unit test to verify enabled GPOs are applied while disabled or computer-disabled GPOs are skipped, improving coverage of GPO enablement behavior.

@MikeX777 MikeX777 self-assigned this Aug 20, 2025
@MikeX777 MikeX777 added bug Something isn't working enhancement New feature or request labels Aug 20, 2025
Copy link

coderabbitai bot commented Aug 20, 2025

Walkthrough

The 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

Cohort / File(s) Summary
Processors: LDAP flags handling
src/CommonLib/Processors/GPOLocalGroupProcessor.cs, src/CommonLib/Processors/LdapPropertyProcessor.cs
GPOLocalGroupProcessor: extend LDAP attributes (add Flags), guard to skip GPOs with Flags 2/3; preserve caching when skipped. LdapPropertyProcessor: read Flags and expose as gpostatus in returned properties.
Unit tests
test/unit/GPOLocalGroupProcessorTest.cs
Add test verifying ReadGPOLocalGroups applies enabled GPOs (Flags 0/1) and skips disabled/computer-disabled (Flags 2/3); uses temp files and mocked LDAP responses.

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

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

I hop through forests of policy trees,
Sniff flags and paths on a gentle breeze.
Enabled? I nibble the crunchy bytes;
Disabled? I pause my lunar nights.
With tidy paws I cache and go—
A rabbit auditor of GPO. 🐇✨

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch mcuomo/BED-6027

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

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

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

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

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

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

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

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

📥 Commits

Reviewing files that changed from the base of the PR and between ac60f8f and d919aa6.

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

Fetching both GPCFileSYSPath and Flags in the same query reduces roundtrips and enables early filtering. Looks good.

Copy link
Contributor

@definitelynotagoblin definitelynotagoblin left a comment

Choose a reason for hiding this comment

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

Holy moly those tests 👍

@MikeX777 MikeX777 enabled auto-merge (squash) September 24, 2025 19:13
@MikeX777 MikeX777 disabled auto-merge September 24, 2025 19:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants