-
Notifications
You must be signed in to change notification settings - Fork 236
Reapply "feat: AdminSDHolder updates - BED-6221"" #176
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
Conversation
WalkthroughAdds per-domain, case-insensitive Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant Runner as Collector
participant Ldap as LdapProducer
participant AD as Domain LDAP
participant ACL as ACLProcessor
participant Ctx as Context
participant Proc as ObjectProcessors
Note over Ldap,Ctx: Start collection with ACLs enabled
Runner->>Ldap: Start LDAP collection
Ldap->>AD: Query domain NC for AdminSDHolder (SD, DN, SID)
AD-->>Ldap: AdminSDHolder entry (or none)
alt AdminSDHolder found
Ldap->>ACL: Compute authoritative SD hash
ACL-->>Ldap: adminSdHolderHash
Ldap->>Ctx: Store AdminSDHolderHash[domain] = hash
else Not found / error
Ldap-->>Runner: Warn and continue
end
Note over Ldap: Proceed with normal LDAP queries
loop For each directory object
Ldap-->>Proc: Emit entry for processing
Proc->>Ctx: Get AdminSDHolderHash[domain]
Proc->>ACL: IsAdminSDHolderProtected(entry, hash)
ACL-->>Proc: true/false/null
Proc-->>Runner: Emit object (+ adminsdholderprotected if set)
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (2 warnings)
✅ Passed checks (1 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Nitpick comments (4)
src/BaseContext.cs (1)
126-130: Optional: restrict mutability of the property.No external re-assignment needed; only per‑entry updates. Prefer get‑only to prevent accidental wholesale replacement.
- public ConcurrentDictionary<string, string> AdminSDHolderHash { get; set; } + public ConcurrentDictionary<string, string> AdminSDHolderHash { get; }Initialize in the constructor (already shown in the other diff).
src/Producers/LdapProducer.cs (3)
97-107: Lower log level for sensitive-ish hash and reduce noise.The computed hash needn’t be Info; Debug/Trace is sufficient.
- Context.Logger.LogInformation( - "AdminSDHolder ACL hash {Hash} calculated for {Domain}.", authoritativeSd, - domain.Name); + Context.Logger.LogDebug( + "AdminSDHolder ACL hash {Hash} calculated for {Domain}.", authoritativeSd, + domain.Name);
110-116: Log “collected” only on actual success.Currently logs Trace even if the SD wasn’t retrieved; gate it after the hash is stored.
- Context.Logger.LogTrace("AdminSDHolder data collected for {Domain}", domain.Name); + if (Context.AdminSDHolderHash.ContainsKey(domain.Name)) + { + Context.Logger.LogTrace("AdminSDHolder data collected for {Domain}", domain.Name); + }
97-99: Optional: reuse ACLProcessor instance.Instantiate once per producer (or per domain iteration) instead of per AdminSDHolder hit. Minor allocation win.
Example (outside the shown hunk):
// class field private readonly ACLProcessor _aclProcessor; // in constructor _aclProcessor = new ACLProcessor(Context.LDAPUtils); // here, replace new ACLProcessor(...) with _aclProcessor
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
Sharphound.csproj(1 hunks)src/BaseContext.cs(2 hunks)src/Client/Context.cs(1 hunks)src/Producers/LdapProducer.cs(4 hunks)src/Runtime/ObjectProcessors.cs(8 hunks)
🔇 Additional comments (7)
Sharphound.csproj (1)
47-47: No functional change.EOF newline tweak only. Nothing to review.
src/BaseContext.cs (1)
32-33: Good: case‑insensitive keying for domain names.Using StringComparer.OrdinalIgnoreCase avoids duplicate keys due to case differences.
src/Runtime/ObjectProcessors.cs (4)
123-132: Helper is fine; null‑safe and domain‑scoped.Lookup is efficient; leave absent key as null for downstream logic to skip.
149-168: Correct integration: exposes adminsdholderprotected for Users when available.Pattern matches existing ACL flags and avoids emitting when unknown.
227-244: Correct integration: adminsdholderprotected for Computers.Consistent with Users; no control‑flow side effects.
435-452: Correct integration: adminsdholderprotected for Groups.Consistent semantics across security principals.
src/Producers/LdapProducer.cs (1)
58-75: Good gating: only collect AdminSDHolder when ACL collection is enabled.Avoids extra LDAP round‑trip when unnecessary.
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.
Actionable comments posted: 0
♻️ Duplicate comments (1)
src/Producers/LdapProducer.cs (1)
103-106: Race fix confirmed: thread-safe update of AdminSDHolderHash.Using
ConcurrentDictionary.AddOrUpdateresolves the earlier concurrent write/read race onAdminSDHolderHash. Nice.Run to confirm the dictionary type and case-insensitive comparer in Context/BaseContext/IContext:
#!/bin/bash set -euo pipefail rg -n -C2 'AdminSDHolderHash' --hidden rg -nP 'ConcurrentDictionary\s*<\s*string\s*,\s*string\s*>' --hidden rg -nP 'new\s+ConcurrentDictionary<\s*string\s*,\s*string\s*>\s*\(\s*StringComparer\.OrdinalIgnoreCase' --hidden
🧹 Nitpick comments (3)
src/Producers/LdapProducer.cs (3)
58-125: AdminSDHolder prefetch: add guardrails and tighten logging.Solid flow and ACL gating. Recommend:
- Wrap hash compute/store in try/catch to avoid aborting domain on unexpected parsing errors.
- Guard against null/empty hashes before storing/logging.
- Log Trace only when SD processed; warn if SD missing.
- Consider downgrading the hash log to Debug to reduce noise.
Apply this diff within this block:
- // Create an instance of ACLProcessor - _aclProcessor from ObjectProcessors isn't in this context - var aclProcessor = new ACLProcessor(Context.LDAPUtils); - - // Calculate the authoritative SD based on a hash of the implicit ACLs & AclProtected - var authoritativeSd = aclProcessor.CalculateImplicitACLHash(sd); - - // Store the hashes in the Context for later use - Context.AdminSDHolderHash.AddOrUpdate( - domain.Name, - _ => authoritativeSd, - (_, _) => authoritativeSd); - - Context.Logger.LogInformation( - "AdminSDHolder ACL hash {Hash} calculated for {Domain}.", authoritativeSd, - domain.Name); + try + { + var aclProcessor = new ACLProcessor(Context.LDAPUtils); + var authoritativeSd = aclProcessor.CalculateImplicitACLHash(sd); + if (!string.IsNullOrEmpty(authoritativeSd)) + { + Context.AdminSDHolderHash.AddOrUpdate( + domain.Name, + _ => authoritativeSd, + (_, _) => authoritativeSd); + Context.Logger.LogDebug( + "AdminSDHolder ACL hash {Hash} calculated for {Domain}.", + authoritativeSd, domain.Name); + Context.Logger.LogTrace("AdminSDHolder data collected for {Domain}", domain.Name); + } + else + { + Context.Logger.LogWarning( + "Empty AdminSDHolder ACL hash for {Domain}; skipping store.", domain.Name); + } + } + catch (Exception ex) + { + Context.Logger.LogWarning(ex, + "Failed to compute/store AdminSDHolder hash for {Domain}", domain.Name); + } } - - Context.Logger.LogTrace("AdminSDHolder data collected for {Domain}", domain.Name); + else + { + Context.Logger.LogWarning("AdminSDHolder SD missing for {Domain}", domain.Name); + }
148-155: Use culture-invariant lowercasing for DN checks.Avoid culture-sensitive casing for protocol strings. Prefer
ToLowerInvariant().- var lower = distinguishedName.ToLower(); + var lower = distinguishedName.ToLowerInvariant();
166-166: Typo in flag name (non-blocking).
ParititonLdapQueriesappears misspelled. If not intentional, consider introducing a correctly spelled alias (PartitionLdapQueries) and deprecating the old name to avoid breaking configs/CLIs.Can you confirm if this name is public/serialized? If so, we can add a non-breaking alias.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/Producers/LdapProducer.cs(4 hunks)
🔇 Additional comments (2)
src/Producers/LdapProducer.cs (2)
10-10: Import looks correct.
SharpHoundCommonLib.Processorsis required forACLProcessor. No concerns.
127-139: Main query gating of security descriptors is correct.
IncludeSecurityDescriptortied toCollectionMethod.ACLis appropriate; avoids unnecessary SD fetches when ACLs aren’t collected.
Reverts #173 reapplying the work for BED-6221
Summary by CodeRabbit
New Features
Chores