From 6927f71c561fcc8253c320694e0cd5ba84b109de Mon Sep 17 00:00:00 2001 From: Rohan Vazarkar Date: Tue, 8 Oct 2024 18:04:21 -0400 Subject: [PATCH] fix: change from static to instance so tests work --- src/CommonLib/Processors/ACLProcessor.cs | 12 +-- test/unit/ACLProcessorTest.cs | 100 +++++++++++------------ 2 files changed, 56 insertions(+), 56 deletions(-) diff --git a/src/CommonLib/Processors/ACLProcessor.cs b/src/CommonLib/Processors/ACLProcessor.cs index dbb471fa..7afbb9d5 100644 --- a/src/CommonLib/Processors/ACLProcessor.cs +++ b/src/CommonLib/Processors/ACLProcessor.cs @@ -15,10 +15,10 @@ namespace SharpHoundCommonLib.Processors { public class ACLProcessor { private static readonly Dictionary BaseGuids; - private static readonly ConcurrentDictionary GuidMap = new(); + private readonly ConcurrentDictionary _guidMap = new(); private readonly ILogger _log; private readonly ILdapUtils _utils; - private static readonly ConcurrentHashSet BuiltDomainCaches = new(StringComparer.OrdinalIgnoreCase); + private readonly ConcurrentHashSet _builtDomainCaches = new(StringComparer.OrdinalIgnoreCase); static ACLProcessor() { //Create a dictionary with the base GUIDs of each object type @@ -76,7 +76,7 @@ private async Task BuildGuidCache(string domain) { if (name is LDAPProperties.LAPSPassword or LDAPProperties.LegacyLAPSPassword) { _log.LogInformation("Found GUID for ACL Right {Name}: {Guid} in domain {Domain}", name, guid, domain); - GuidMap.TryAdd(guid, name); + _guidMap.TryAdd(guid, name); } } else { _log.LogDebug("Error while building GUID cache for {Domain}: {Message}", domain, result.Error); @@ -227,8 +227,8 @@ public IEnumerable GetInheritedAceHashes(byte[] ntSecurityDescriptor, st public async IAsyncEnumerable ProcessACL(byte[] ntSecurityDescriptor, string objectDomain, Label objectType, bool hasLaps, string objectName = "") { - if (!BuiltDomainCaches.Contains(objectDomain)) { - BuiltDomainCaches.Add(objectDomain); + if (!_builtDomainCaches.Contains(objectDomain)) { + _builtDomainCaches.Add(objectDomain); await BuildGuidCache(objectDomain); } @@ -299,7 +299,7 @@ public async IAsyncEnumerable ProcessACL(byte[] ntSecurityDescriptor, strin aceInheritanceHash = CalculateInheritanceHash(ir, aceRights, aceType, ace.InheritedObjectType()); } - GuidMap.TryGetValue(aceType, out var mappedGuid); + _guidMap.TryGetValue(aceType, out var mappedGuid); _log.LogTrace("Processing ACE with rights {Rights} and guid {GUID} on object {Name}", aceRights, aceType, objectName); diff --git a/test/unit/ACLProcessorTest.cs b/test/unit/ACLProcessorTest.cs index eafd3422..a4d7c48b 100644 --- a/test/unit/ACLProcessorTest.cs +++ b/test/unit/ACLProcessorTest.cs @@ -1019,56 +1019,56 @@ public async Task ACLProcessor_ProcessACL_GenericWrite_Computer_WriteAllowedToAc Assert.Equal(actual.RightName, expectedRightName); } - // [Fact] - // public async Task ACLProcessor_ProcessACL_LAPS_Computer() { - // var expectedPrincipalType = Label.Group; - // var expectedPrincipalSID = "S-1-5-21-3130019616-2776909439-2417379446-512"; - // var expectedRightName = EdgeNames.ReadLAPSPassword; - // - // var mockLDAPUtils = new Mock(); - // var mockSecurityDescriptor = new Mock(MockBehavior.Loose, null); - // var mockRule = new Mock(MockBehavior.Loose, null); - // var collection = new List(); - // mockRule.Setup(x => x.AccessControlType()).Returns(AccessControlType.Allow); - // mockRule.Setup(x => x.IsAceInheritedFrom(It.IsAny())).Returns(true); - // mockRule.Setup(x => x.IdentityReference()).Returns(expectedPrincipalSID); - // mockRule.Setup(x => x.ActiveDirectoryRights()).Returns(ActiveDirectoryRights.ExtendedRight); - // var lapsGuid = Guid.NewGuid(); - // mockRule.Setup(x => x.ObjectType()).Returns(lapsGuid); - // collection.Add(mockRule.Object); - // - // mockSecurityDescriptor.Setup(m => m.GetAccessRules(It.IsAny(), It.IsAny(), It.IsAny())) - // .Returns(collection); - // mockSecurityDescriptor.Setup(m => m.GetOwner(It.IsAny())).Returns((string)null); - // mockLDAPUtils.Setup(x => x.MakeSecurityDescriptor()).Returns(mockSecurityDescriptor.Object); - // mockLDAPUtils.Setup(x => x.ResolveIDAndType(It.IsAny(), It.IsAny())) - // .ReturnsAsync((true, new TypedPrincipal(expectedPrincipalSID, expectedPrincipalType))); - // - // //Return a directory object from pagedquery for the schemaid to simulate LAPS - // var searchResults = new[] - // { - // LdapResult.Ok(new MockDirectoryObject( - // "abc123" - // , new Dictionary() - // { - // {LDAPProperties.SchemaIDGUID, lapsGuid.ToByteArray()}, - // {LDAPProperties.Name, LDAPProperties.LegacyLAPSPassword} - // }, null,null)), - // }; - // mockLDAPUtils.Setup(x => x.PagedQuery(It.IsAny(), It.IsAny())) - // .Returns(searchResults.ToAsyncEnumerable); - // - // var processor = new ACLProcessor(mockLDAPUtils.Object); - // var bytes = Utils.B64ToBytes(UnProtectedUserNtSecurityDescriptor); - // var result = await processor.ProcessACL(bytes, _testDomainName, Label.Computer, true).ToArrayAsync(); - // - // Assert.Single(result); - // var actual = result.First(); - // Assert.Equal(actual.PrincipalType, expectedPrincipalType); - // Assert.Equal(actual.PrincipalSID, expectedPrincipalSID); - // Assert.False(actual.IsInherited); - // Assert.Equal(actual.RightName, expectedRightName); - // } + [Fact] + public async Task ACLProcessor_ProcessACL_LAPS_Computer() { + var expectedPrincipalType = Label.Group; + var expectedPrincipalSID = "S-1-5-21-3130019616-2776909439-2417379446-512"; + var expectedRightName = EdgeNames.ReadLAPSPassword; + + var mockLDAPUtils = new Mock(); + var mockSecurityDescriptor = new Mock(MockBehavior.Loose, null); + var mockRule = new Mock(MockBehavior.Loose, null); + var collection = new List(); + mockRule.Setup(x => x.AccessControlType()).Returns(AccessControlType.Allow); + mockRule.Setup(x => x.IsAceInheritedFrom(It.IsAny())).Returns(true); + mockRule.Setup(x => x.IdentityReference()).Returns(expectedPrincipalSID); + mockRule.Setup(x => x.ActiveDirectoryRights()).Returns(ActiveDirectoryRights.ExtendedRight); + var lapsGuid = Guid.NewGuid(); + mockRule.Setup(x => x.ObjectType()).Returns(lapsGuid); + collection.Add(mockRule.Object); + + mockSecurityDescriptor.Setup(m => m.GetAccessRules(It.IsAny(), It.IsAny(), It.IsAny())) + .Returns(collection); + mockSecurityDescriptor.Setup(m => m.GetOwner(It.IsAny())).Returns((string)null); + mockLDAPUtils.Setup(x => x.MakeSecurityDescriptor()).Returns(mockSecurityDescriptor.Object); + mockLDAPUtils.Setup(x => x.ResolveIDAndType(It.IsAny(), It.IsAny())) + .ReturnsAsync((true, new TypedPrincipal(expectedPrincipalSID, expectedPrincipalType))); + + //Return a directory object from pagedquery for the schemaid to simulate LAPS + var searchResults = new[] + { + LdapResult.Ok(new MockDirectoryObject( + "abc123" + , new Dictionary() + { + {LDAPProperties.SchemaIDGUID, lapsGuid.ToByteArray()}, + {LDAPProperties.Name, LDAPProperties.LegacyLAPSPassword} + }, null,null)), + }; + mockLDAPUtils.Setup(x => x.PagedQuery(It.IsAny(), It.IsAny())) + .Returns(searchResults.ToAsyncEnumerable); + + var processor = new ACLProcessor(mockLDAPUtils.Object); + var bytes = Utils.B64ToBytes(UnProtectedUserNtSecurityDescriptor); + var result = await processor.ProcessACL(bytes, _testDomainName, Label.Computer, true).ToArrayAsync(); + + Assert.Single(result); + var actual = result.First(); + Assert.Equal(actual.PrincipalType, expectedPrincipalType); + Assert.Equal(actual.PrincipalSID, expectedPrincipalSID); + Assert.False(actual.IsInherited); + Assert.Equal(actual.RightName, expectedRightName); + } [Fact] public void GetInheritedAceHashes_NullSD_Empty() {