Skip to content

Conversation

@lrfalslev
Copy link

@lrfalslev lrfalslev commented Jan 9, 2026

Description

Collect EnrollmentAgent Restrictions For AllTemplates, add CertAbuseProcessor Tests

Motivation and Context

BED-7044

How Has This Been Tested?

Ran tests.

Verified that EnrollmentAgentRestriction was collected when CertificateTemplates is set to All.
image
image

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

  • Refactor

    • Abstracted registry and SAM server access patterns with new accessor interfaces for improved error handling, timeout management, and code maintainability.
  • Tests

    • Expanded test coverage for certificate operations with comprehensive mocking and platform-specific test scenarios.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Jan 9, 2026

Walkthrough

This PR refactors registry and SAM server access by extracting direct utility methods from Helpers.cs and SHRegistryKey into new dependency-injectable IRegistryAccessor and ISAMServerAccessor interfaces with concrete implementations (RegistryAccessor and SAMServerAccessor). Processors are updated to use these accessors via constructor injection instead of calling static utility methods directly.

Changes

Cohort / File(s) Summary
Registry Abstraction Layer
src/CommonLib/IRegistryAccessor.cs
New interface defining GetRegistryKeyData, OpenRemoteRegistry, and async Connect methods; RegistryAccessor implementation adds AdaptiveTimeout and structured error handling with exception logging and result reporting
Registry Key Interface Updates
src/CommonLib/IRegistryKey.cs
IRegistryKey now extends IDisposable; SHRegistryKey constructor made public, Connect method and MockRegistryKey class removed; AdaptiveTimeout field removed
Helpers Cleanup
src/CommonLib/Helpers.cs
Removed public GetRegistryKeyData and OpenRemoteRegistry methods (functionality moved to RegistryAccessor)
SAM Server Accessor Layer
src/SharpHoundRPC/Wrappers/ISAMServerAccessor.cs
New interface and SAMServerAccessor implementation wrapping SAMMethods.SamConnect for opening remote SAM servers
SAM Server Updates
src/SharpHoundRPC/Wrappers/SAMServer.cs
Removed public static OpenServer factory method; remaining instance methods unchanged
Processor Refactoring
src/CommonLib/Processors/CertAbuseProcessor.cs
Added IRegistryAccessor and ISAMServerAccessor dependency injection; IsUserSpecifiesSanEnabled and IsRoleSeparationEnabled made public async with new parameters; GetMachineSid and CreateEnrollmentAgentRestriction exposed as internal; registry/SAM access updated to use accessors; added ComputerStatus event reporting on success and failure paths
Processor Updates
src/CommonLib/Processors/ComputerSessionProcessor.cs, src/CommonLib/Processors/DCRegistryProcessor.cs, src/CommonLib/Processors/LocalGroupProcessor.cs
Added IRegistryAccessor or ISAMServerAccessor instantiation; replaced static method calls (Helpers, SHRegistryKey.Connect, SAMServer.OpenServer) with accessor method calls
Test Infrastructure
test/unit/Utils.cs
Added WindowsOnlyTheory attribute class for OS-specific Theory-based tests
Comprehensive Test Suite
test/unit/CertAbuseProcessorTest.cs
Replaced placeholder scaffold with full CertAbuseProcessorTest class; added 20+ unit tests covering IsUserSpecifiesSanEnabled, IsRoleSeparationEnabled, ProcessEAPermissions, ProcessRegistryEnrollmentPermissions, ProcessCertTemplates, GetRegistryPrincipal, OpenSamServer, GetMachineSid, and CreateEnrollmentAgentRestriction with various data scenarios and ComputerStatusEvent validation
Test Utilities
test/unit/Facades/MockLdapUtils.cs
Minor formatting adjustments
Build Cleanup
src/SharpHoundRPC/SAMRPCNative/SAMMethods.cs
Removed unused using directives (System.Collections.Generic, System.Security.Principal)

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

enhancement

Suggested reviewers

  • ktstrader
  • MikeX777

Poem

🐰 A Registry refactored, dependencies untangled bright,
Accessors and interfaces, dependency injection done right,
SAM servers open through elegant abstraction,
Processors now inject, bringing backward traction,
Hoppy tests validate the path forward—hoorah! 🎉

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 15.94% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main changes: collecting EnrollmentAgent restrictions for AllTemplates and adding CertAbuseProcessor tests, with the issue reference.
Description check ✅ Passed The description covers all key sections: motivation (BED-7044 issue link), testing approach, type of change (bug fix), and relevant checklist items completed.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

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

Comment @coderabbitai help to get the list of available commands and usage tips.

@lrfalslev lrfalslev changed the title Lfalslev/bed 7044 Collect EnrollmentAgent Restrictions For AllTemplates, add CertAbuseProcessor Tests BED-7044 Jan 12, 2026
@lrfalslev lrfalslev marked this pull request as ready for review January 12, 2026 22:49
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: 1

🤖 Fix all issues with AI agents
In @test/unit/CertAbuseProcessorTest.cs:
- Line 701: The test passes an incorrect value for the computerDomain parameter
to CreateEnrollmentAgentRestriction: it uses nameof(Label.User) ("User") instead
of the domain string; update the call in the test to pass DomainName (e.g.,
"TEST.LOCAL") as the computerDomain argument so CreateEnrollmentAgentRestriction
receives a valid domain consistent with other tests.
🧹 Nitpick comments (2)
src/CommonLib/Processors/ComputerSessionProcessor.cs (1)

27-27: Pass the logger to RegistryAccessor for consistent logging.

DCRegistryProcessor passes the logger to RegistryAccessor(log), but here the logger is omitted. This causes logging inconsistency across processors.

Additionally, consider accepting IRegistryAccessor as an optional constructor parameter (defaulting to new RegistryAccessor(_log)) to enable unit testing with mocks.

♻️ Suggested improvement
-        private readonly IRegistryAccessor _registryAccessor;
+        private readonly IRegistryAccessor _registryAccessor;

         public ComputerSessionProcessor(ILdapUtils utils,
             NativeMethods nativeMethods = null, ILogger log = null, string currentUserName = null,
             bool doLocalAdminSessionEnum = false,
-            string localAdminUsername = null, string localAdminPassword = null) {
+            string localAdminUsername = null, string localAdminPassword = null,
+            IRegistryAccessor registryAccessor = null) {
             _utils = utils;
             _nativeMethods = nativeMethods ?? new NativeMethods();
             _currentUserName = currentUserName ?? WindowsIdentity.GetCurrent().Name.Split('\\')[1];
             _log = log ?? Logging.LogProvider.CreateLogger("CompSessions");
             _doLocalAdminSessionEnum = doLocalAdminSessionEnum;
             _localAdminUsername = localAdminUsername;
             _localAdminPassword = localAdminPassword;
             _readUserSessionsAdaptiveTimeout = new AdaptiveTimeout(maxTimeout: TimeSpan.FromMinutes(2), Logging.LogProvider.CreateLogger(nameof(ReadUserSessions)));
             _readUserSessionsPriviledgedAdaptiveTimeout = new AdaptiveTimeout(maxTimeout: TimeSpan.FromMinutes(2), Logging.LogProvider.CreateLogger(nameof(ReadUserSessionsPrivileged)));
-            _registryAccessor = new RegistryAccessor();
+            _registryAccessor = registryAccessor ?? new RegistryAccessor(_log);
         }

Also applies to: 42-42

src/CommonLib/IRegistryAccessor.cs (1)

59-61: Consider adding a synchronous overload or documenting blocking behavior.

OpenRemoteRegistry blocks synchronously via GetAwaiter().GetResult(). While this works, it could cause deadlocks if called from certain synchronization contexts (e.g., UI threads or ASP.NET classic). Since this is a Windows-specific library primarily used in console applications, this is likely acceptable, but consider documenting this behavior.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8837f50 and b93c93d.

📒 Files selected for processing (13)
  • src/CommonLib/Helpers.cs
  • src/CommonLib/IRegistryAccessor.cs
  • src/CommonLib/IRegistryKey.cs
  • src/CommonLib/Processors/CertAbuseProcessor.cs
  • src/CommonLib/Processors/ComputerSessionProcessor.cs
  • src/CommonLib/Processors/DCRegistryProcessor.cs
  • src/CommonLib/Processors/LocalGroupProcessor.cs
  • src/SharpHoundRPC/SAMRPCNative/SAMMethods.cs
  • src/SharpHoundRPC/Wrappers/ISAMServerAccessor.cs
  • src/SharpHoundRPC/Wrappers/SAMServer.cs
  • test/unit/CertAbuseProcessorTest.cs
  • test/unit/Facades/MockLdapUtils.cs
  • test/unit/Utils.cs
💤 Files with no reviewable changes (2)
  • src/SharpHoundRPC/Wrappers/SAMServer.cs
  • src/SharpHoundRPC/SAMRPCNative/SAMMethods.cs
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2025-07-15T17:45:25.688Z
Learnt from: definitelynotagoblin
Repo: SpecterOps/SharpHoundCommon PR: 222
File: src/CommonLib/Processors/LocalGroupProcessor.cs:19-27
Timestamp: 2025-07-15T17:45:25.688Z
Learning: In SharpHoundCommon, the team prefers to keep code simple rather than implement perfect resource management when the resources being managed are non-critical. Specifically, they accept not implementing IDisposable for AdaptiveTimeout instances when the Dispose method is primarily for flushing analytics logs from ExecutionTimeSampler, viewing it as a courtesy rather than a safety requirement.

Applied to files:

  • src/CommonLib/Processors/DCRegistryProcessor.cs
  • src/CommonLib/IRegistryKey.cs
📚 Learning: 2025-06-26T16:37:09.005Z
Learnt from: definitelynotagoblin
Repo: SpecterOps/SharpHoundCommon PR: 217
File: src/CommonLib/Timeout.cs:21-21
Timestamp: 2025-06-26T16:37:09.005Z
Learning: In SharpHoundCommonLib's Timeout.cs, the team prefers to use TaskScheduler.Current instead of TaskScheduler.Default in Task.Factory.StartNew calls to maintain flexibility for custom schedulers, even though this requires awareness of potential deadlock risks in certain contexts.

Applied to files:

  • src/CommonLib/Processors/DCRegistryProcessor.cs
📚 Learning: 2025-06-26T16:38:49.677Z
Learnt from: definitelynotagoblin
Repo: SpecterOps/SharpHoundCommon PR: 217
File: src/CommonLib/Timeout.cs:17-36
Timestamp: 2025-06-26T16:38:49.677Z
Learning: In SharpHoundCommonLib's Timeout.cs, the team initially had concerns about disposing CancellationTokenSource instances before tasks could check cancellation tokens, but they understand that orphaned tasks (those that exceed timeout) won't be impacted by disposed tokens since their results are already ignored by the timeout handler. They prefer proper resource management with using statements for CancellationTokenSource disposal.

Applied to files:

  • src/CommonLib/Processors/DCRegistryProcessor.cs
📚 Learning: 2025-10-17T13:43:46.833Z
Learnt from: MikeX777
Repo: SpecterOps/SharpHoundCommon PR: 241
File: src/CommonLib/Processors/LdapPropertyProcessor.cs:168-169
Timestamp: 2025-10-17T13:43:46.833Z
Learning: Properties added to dictionaries returned by methods in SharpHoundCommon (such as those in LdapPropertyProcessor) may be consumed by dependent projects like SharpHound (SH) and SharpHoundEnterprise (SHE), even if they are not used within the SharpHoundCommon repository itself.

Applied to files:

  • src/CommonLib/Processors/DCRegistryProcessor.cs
  • src/CommonLib/Processors/CertAbuseProcessor.cs
🧬 Code graph analysis (8)
test/unit/Utils.cs (1)
test/unit/CertAbuseProcessorTest.cs (1)
  • WindowsOnlyTheory (237-278)
src/CommonLib/Processors/LocalGroupProcessor.cs (1)
src/SharpHoundRPC/Wrappers/ISAMServerAccessor.cs (1)
  • SAMServerAccessor (13-26)
src/CommonLib/Processors/DCRegistryProcessor.cs (1)
src/CommonLib/IRegistryAccessor.cs (4)
  • Task (13-13)
  • Task (75-80)
  • RegistryAccessor (16-81)
  • RegistryAccessor (20-23)
src/CommonLib/IRegistryAccessor.cs (1)
src/CommonLib/IRegistryKey.cs (2)
  • GetValue (6-6)
  • GetValue (17-20)
src/SharpHoundRPC/Wrappers/ISAMServerAccessor.cs (3)
src/CommonLib/Processors/CertAbuseProcessor.cs (1)
  • SharpHoundRPC (537-540)
src/CommonLib/Processors/LocalGroupProcessor.cs (1)
  • SharpHoundRPC (45-54)
src/SharpHoundRPC/SAMRPCNative/SAMEnums.cs (1)
  • SAMEnums (6-74)
test/unit/CertAbuseProcessorTest.cs (8)
src/CommonLib/Processors/CertAbuseProcessor.cs (12)
  • SharpHoundRPC (537-540)
  • CertAbuseProcessor (15-546)
  • CertAbuseProcessor (27-34)
  • Task (45-169)
  • Task (179-232)
  • Task (234-250)
  • Task (289-327)
  • Task (339-375)
  • Task (377-410)
  • Task (412-467)
  • Task (469-535)
  • Task (542-545)
test/unit/LDAPUtilsTest.cs (7)
  • Fact (40-43)
  • Fact (47-53)
  • Fact (55-59)
  • Fact (61-68)
  • Fact (70-79)
  • Fact (81-86)
  • WindowsOnlyFact (261-287)
src/CommonLib/LdapQueries/LdapFilter.cs (1)
  • IEnumerable (262-275)
test/unit/Utils.cs (4)
  • WindowsOnlyTheory (94-100)
  • WindowsOnlyTheory (96-99)
  • WindowsOnlyFact (86-92)
  • WindowsOnlyFact (88-91)
src/SharpHoundRPC/Wrappers/SAMServer.cs (8)
  • Result (25-33)
  • Result (35-42)
  • Result (44-74)
  • Result (76-90)
  • Result (92-115)
  • Result (117-131)
  • SAMServer (12-138)
  • SAMServer (17-21)
src/CommonLib/OutputTypes/CertTemplate.cs (1)
  • CertTemplate (5-7)
test/unit/WellKnownPrincipalTest.cs (1)
  • sid (48-117)
src/CommonLib/OutputTypes/LocalGroup.cs (1)
  • LocalGroup (3-8)
src/CommonLib/Processors/CertAbuseProcessor.cs (3)
src/CommonLib/CSVComputerStatus.cs (1)
  • CSVComputerStatus (6-47)
src/SharpHoundRPC/Wrappers/ISAMServerAccessor.cs (2)
  • Result (7-10)
  • Result (15-25)
src/SharpHoundRPC/Wrappers/SAMServer.cs (6)
  • Result (25-33)
  • Result (35-42)
  • Result (44-74)
  • Result (76-90)
  • Result (92-115)
  • Result (117-131)
src/CommonLib/IRegistryKey.cs (2)
src/CommonLib/IRegistryAccessor.cs (2)
  • IRegistryKey (12-12)
  • IRegistryKey (59-61)
src/SharpHoundRPC/Registry/RemoteRegistryStrategy.cs (1)
  • RegistryKey (61-72)
🔇 Additional comments (26)
test/unit/Utils.cs (1)

94-100: LGTM!

The WindowsOnlyTheory attribute correctly mirrors the existing WindowsOnlyFact pattern for parameterized [Theory] tests. The implementation is consistent with the established convention, and the relevant code snippet confirms it's already being used correctly in CertAbuseProcessorTest.cs.

test/unit/Facades/MockLdapUtils.cs (1)

747-747: LGTM!

Minor formatting adjustment with no functional impact.

src/CommonLib/Processors/ComputerSessionProcessor.cs (1)

298-298: LGTM!

The registry access is now correctly routed through the IRegistryAccessor abstraction, aligning with the PR's goal of centralizing remote registry access.

src/CommonLib/Processors/DCRegistryProcessor.cs (2)

11-21: LGTM!

The RegistryAccessor is correctly instantiated with the logger, and the constructor properly initializes all dependencies. The refactoring successfully replaces direct Helpers.GetRegistryKeyData calls with the new abstraction.


35-35: LGTM!

All three registry access calls are correctly updated to use _registryAccessor.GetRegistryKeyData, maintaining the existing method signatures and return value handling.

Also applies to: 67-67, 99-99

src/CommonLib/Helpers.cs (1)

149-156: LGTM!

Minor documentation comment formatting. The registry-related methods have been appropriately moved to RegistryAccessor as part of the refactoring.

src/CommonLib/Processors/LocalGroupProcessor.cs (3)

19-19: LGTM!

The ISAMServerAccessor abstraction is correctly integrated, enabling potential future testability improvements. The instantiation follows the established pattern in this PR.

Also applies to: 31-31


34-34: LGTM!

The logger name correctly reflects the new interface method ISAMServerAccessor.OpenServer.


45-54: LGTM!

The OpenSamServer method correctly delegates to _samServerAccessor.OpenServer and properly handles the result conversion.

src/SharpHoundRPC/Wrappers/ISAMServerAccessor.cs (1)

1-27: LGTM! Clean abstraction for SAM server access.

The interface and implementation correctly abstract the SAM server connection logic, enabling dependency injection and testability. The default access masks are appropriate for the enumeration and lookup operations used by consumers (CertAbuseProcessor, LocalGroupProcessor).

src/CommonLib/IRegistryKey.cs (1)

5-27: LGTM! Proper IDisposable implementation.

The addition of IDisposable to IRegistryKey and its implementation in SHRegistryKey correctly ensures the underlying RegistryKey is disposed. The public constructor enables the new RegistryAccessor to create instances. This aligns well with the using statement in RegistryAccessor.GetRegistryKeyData.

test/unit/CertAbuseProcessorTest.cs (7)

35-47: Good test setup with proper isolation.

The constructor correctly initializes mocks, creates the processor with injected dependencies, subscribes to the status event for verification, and resets the cache to ensure test isolation.


49-169: Comprehensive tests for registry-based flag checks.

Good coverage of IsUserSpecifiesSanEnabled and IsRoleSeparationEnabled with both successful lookups (parameterized values) and failure handling. The assertions correctly validate both the return values and the status event reporting.


171-278: Good edge case coverage for ProcessEAPermissions.

The tests cover empty registry values, failed lookups, and Windows-specific scenarios with null and empty DACLs. The MemberData pattern for parameterized tests is well-used.


338-385: LGTM! Test correctly validates empty result when no owner and no rules.

The test properly sets up a security descriptor with no owner and configures the mock to return empty access rules, validating that the processor handles this edge case gracefully.


408-537: Excellent coverage of GetRegistryPrincipal branching logic.

The tests thoroughly exercise each code path: filtered SIDs, domain controller resolution, well-known principal conversion, local SID resolution, and domain principal lookup. The VerifyNoOtherCalls() assertions ensure no unexpected LDAP calls are made.


632-779: Good coverage of CreateEnrollmentAgentRestriction scenarios.

The tests properly validate: null opaque data handling, unresolved template failure, all-templates path when no template is specified, and both canonical name and OID-based template resolution. The byte array constructions for opaque ACE data are well-commented.


628-628: The constants are equivalent and the assertion is correct. ComputerStatus.Success is a static string property that returns "Success", and CSVComputerStatus.StatusSuccess is a const string also set to "Success". Both resolve to the same value, so the test assertion at line 628 is valid.

src/CommonLib/IRegistryAccessor.cs (3)

10-14: Well-designed interface for registry access abstraction.

The interface provides a clean API for registry operations with clear method signatures. This enables dependency injection and testability for processors that need registry access.


25-57: Robust exception handling for registry operations.

The method correctly handles the common exceptions that can occur during remote registry access: IOException (connectivity), SecurityException and UnauthorizedAccessException (permissions), with a catch-all for unexpected errors. The using statement ensures proper disposal of the registry key.


75-80: Good use of AdaptiveTimeout for resilient registry connections.

The method properly wraps the registry connection in an adaptive timeout and throws a documented TimeoutException on failure. The error message includes the machine name and error details for diagnostics.

src/CommonLib/Processors/CertAbuseProcessor.cs (5)

21-34: Good dependency injection setup.

The constructor properly accepts and stores the new IRegistryAccessor and ISAMServerAccessor dependencies, enabling testability. The logger names for adaptive timeouts correctly reflect the operations they wrap.


53-69: Good addition of status reporting.

The status reporting on both failure and success paths enables operational monitoring of registry enrollment permission processing. Using nameof() for task names ensures consistency with method renames.


214-217: Important null guard for DiscretionaryAcl.

This check prevents a NullReferenceException when iterating over descriptor.DiscretionaryAcl on line 220. A security descriptor can have a null DACL (which means allow all access), so returning early with empty restrictions is the correct behavior.


469-535: Well-structured enrollment agent restriction parsing.

The method correctly:

  1. Guards against null opaque data
  2. Returns early with AllTemplates=true when no template is specified (indicated by index >= opaque.Length)
  3. Falls back from canonical name to OID resolution for template lookup
  4. Returns failure when template cannot be resolved

The -2 offset in the Unicode string extraction (line 509) correctly accounts for the 2-byte null terminator.


537-540: OpenSamServer correctly delegates to accessor.

The method properly wraps the accessor call with the adaptive timeout for resilience against slow or unresponsive servers.

_mockLdapUtils.Setup(x => x.ResolveIDAndType("S-1-3", It.IsAny<string>()))
.ReturnsAsync((true, new TypedPrincipal("S-1-3", Label.User)));

var result = await _certAbuseProcessor.CreateEnrollmentAgentRestriction(emptyOpaqueAce, nameof(Label.User), DomainName, false, TargetDomainSid, sid);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Incorrect parameter value for computerDomain.

nameof(Label.User) evaluates to "User", which is passed as the computerDomain parameter. This should likely be DomainName (i.e., "TEST.LOCAL") to be consistent with other tests and represent a valid domain.

Suggested fix
-            var result = await _certAbuseProcessor.CreateEnrollmentAgentRestriction(emptyOpaqueAce, nameof(Label.User), DomainName, false, TargetDomainSid, sid);
+            var result = await _certAbuseProcessor.CreateEnrollmentAgentRestriction(emptyOpaqueAce, DomainName, TargetName, false, TargetDomainSid, sid);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
var result = await _certAbuseProcessor.CreateEnrollmentAgentRestriction(emptyOpaqueAce, nameof(Label.User), DomainName, false, TargetDomainSid, sid);
var result = await _certAbuseProcessor.CreateEnrollmentAgentRestriction(emptyOpaqueAce, DomainName, TargetName, false, TargetDomainSid, sid);
🤖 Prompt for AI Agents
In @test/unit/CertAbuseProcessorTest.cs at line 701, The test passes an
incorrect value for the computerDomain parameter to
CreateEnrollmentAgentRestriction: it uses nameof(Label.User) ("User") instead of
the domain string; update the call in the test to pass DomainName (e.g.,
"TEST.LOCAL") as the computerDomain argument so CreateEnrollmentAgentRestriction
receives a valid domain consistent with other tests.

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.

2 participants