Skip to content

Cache risk-rating SID lookups#277

Open
SamErde wants to merge 4 commits intomainfrom
samerde/cache-risk-sid-lookups
Open

Cache risk-rating SID lookups#277
SamErde wants to merge 4 commits intomainfrom
samerde/cache-risk-sid-lookups

Conversation

@SamErde
Copy link
Copy Markdown
Collaborator

@SamErde SamErde commented May 6, 2026

Summary

Eliminates repeated Active Directory LDAP queries for the same SID during a Locksmith scan run.

Problem

Set-RiskRating had seven call sites all performing Get-ADObject -Filter { objectSid -eq $SID } | Select-Object objectClass. Common principals appear in many template ACLs and were re-queried on every issue.

Solution

New Get-SidObjectClass helper with $script:SidObjectClassCache in Private/Set-RiskRating.ps1. Transient ADWS errors are not cached (key stays absent for retry); errors re-emitted via Write-Error -ErrorRecord $_ so callers can detect failures and $ErrorActionPreference is honoured. All 7 call sites replaced.

Scope

  • Caches repeated SID lookups in Set-RiskRating.ps1
  • Preserves all risk score semantics
  • Invoke-Locksmith.ps1 manually updated for parity (Build/Build-Module.ps1 is NOT run in CI)
  • No Pester tests, no remediation/TLS changes, no broad refactoring

Static analysis

PSScriptAnalyzer: no new warnings introduced.

Replace seven identical Get-ADObject | Select-Object objectClass calls in
Private\Set-RiskRating.ps1 with a new Get-SidObjectClass helper that wraps
the query in a script-scoped hashtable cache (\).

During a Locksmith scan, the same SID (Domain Users, Authenticated Users,
Domain Computers, etc.) appears across many issues. Previously each issue
evaluation issued a separate LDAP query for each SID. With the cache, every
SID is resolved at most once per module session.

Changes:
- Add Get-SidObjectClass private helper at top of Set-RiskRating.ps1
- Replace all 7 Get-ADObject lookup sites with Get-SidObjectClass calls
- Preserve exact return types and semantics for all call sites:
  - Pattern A (6 sites): returns PSCustomObject with objectClass property
  - Pattern B (1 site, ESC5): extracts .objectClass from the PSCustomObject
- No changes to risk scoring logic, remediation, or test coverage

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@SamErde SamErde marked this pull request as ready for review May 6, 2026 09:25
Copilot AI review requested due to automatic review settings May 6, 2026 09:25
@SamErde SamErde marked this pull request as draft May 6, 2026 09:27
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR reduces repeated Active Directory lookups during a Locksmith scan by introducing a script-scoped SID→objectClass cache and routing existing Get-ADObject calls through a new helper in Set-RiskRating.

Changes:

  • Added Get-SidObjectClass helper that caches Get-ADObject SID lookups in a script-scoped hashtable.
  • Replaced 7 repeated Get-ADObject ... | Select-Object objectClass call sites with Get-SidObjectClass to reuse cached results.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread Private/Set-RiskRating.ps1
Comment thread Private/Set-RiskRating.ps1 Outdated
Use -ErrorAction Stop with try/catch so that a transient ADWS error
does not populate the cache with . Legitimate 'not found' (SID
absent from AD) still returns and caches  normally; transient
errors emit Write-Warning and leave the key absent, allowing retry
on the next call.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@SamErde SamErde requested a review from Copilot May 6, 2026 09:41
@SamErde SamErde marked this pull request as ready for review May 6, 2026 09:58
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

…nvoke-Locksmith.ps1

Invoke-Locksmith.ps1 is the manually-maintained monolithic script that
must stay in parity with the Private/*.ps1 sources. Apply the same
Get-SidObjectClass helper (with try/catch error-handling) and replace
the same 7 Get-ADObject | Select-Object objectClass call sites that
were already applied to Private\Set-RiskRating.ps1.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@SamErde SamErde requested a review from Copilot May 6, 2026 13:33
Copy link
Copy Markdown
Collaborator Author

@SamErde SamErde left a comment

Choose a reason for hiding this comment

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

@copilot please review

Copy link
Copy Markdown

Copilot AI commented May 6, 2026

@copilot please review

The current state of the PR looks good. Both issues from the previous review have been resolved:

  1. Transient error caching (commit a2961c4): Get-ADObject is now wrapped in try/catch with -ErrorAction Stop. Only successful results (including genuine "not found" $null) are stored in the cache; transient ADWS errors emit a Write-Warning and leave the key absent so the next call retries.

  2. Return type semantics: All 7 call sites preserve the same return type as the original Get-ADObject | Select-Object objectClass calls — 6 sites receive the PSCustomObject directly (Pattern A), and the ESC5 loop appends .objectClass to extract the raw value (Pattern B), matching the pre-existing behaviour exactly.

No new issues found.

Copilot finished work on behalf of SamErde May 6, 2026 13:35
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

Comment thread Private/Set-RiskRating.ps1 Outdated
Comment thread Invoke-Locksmith.ps1
Replace Write-Warning with Write-Error -ErrorRecord $_ in the
Get-SidObjectClass catch block so that AD lookup failures surface on
the error stream and callers' $ErrorActionPreference (including Stop)
is respected. Failed lookups are still not cached so each SID can be
retried on the next call. Applied to both Private\Set-RiskRating.ps1
and Invoke-Locksmith.ps1.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

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.

3 participants