Description
The Active Directory identity provider fails at runtime when resolving an identity by sAMAccountName. The error indicates that the helper function Protect-LdapFilterValue is not recognized, causing identity resolution to fail and consequently breaking steps like IdLE.Step.DisableIdentity.
This is a regression/defect in the AD adapter implementation: Protect-LdapFilterValue is defined as a nested function within New-IdleADAdapter, but it is referenced from ScriptMethod members (e.g., GetUserBySam). When these ScriptMethods are invoked later, the nested function is out of scope, so PowerShell cannot resolve it.
Impact: AD-based workflows (e.g., Leaver DisableIdentity) cannot execute reliably.
Steps to Reproduce
- Install/import IdLE modules including the AD provider.
- Configure an AD identity provider and run a workflow containing
IdLE.Step.DisableIdentity with an IdentityKey that resolves via sAMAccountName (e.g., foo.bar).
- Build and invoke the plan.
Example minimal workflow step:
@{
Name = 'Leave Account Test'
LifecycleEvent = 'Leaver'
Steps = @(
@{
Name = 'Disable AD account'
Type = 'IdLE.Step.DisableIdentity'
With = @{
AuthSessionName = 'AD'
IdentityKey = 'foo.bar'
}
}
)
}
Example plan creation (provider setup omitted here, see Additional Context):
$leaverReq = New-IdleLifecycleRequest -LifecycleEvent 'Leaver'
$leaverPlan = New-IdlePlan -WorkflowPath .\leaver.psd1 -Request $leaverReq -Providers $providers
Invoke-IdlePlan -Plan $leaverPlan
Expected Behavior
IdLE.Step.DisableIdentity resolves the identity using the AD provider and disables the AD account.
- No missing-command errors occur.
- LDAP filter values are properly escaped prior to querying AD.
Actual Behavior
The step fails with an exception chain that ends in:
The term 'Protect-LdapFilterValue' is not recognized as a name of a cmdlet, function, script file, or executable program.
Example error (truncated):
Exception calling "DisableIdentity" ...
Exception calling "ResolveIdentity" ...
Exception calling "GetUserBySam" ...
The term 'Protect-LdapFilterValue' is not recognized ...
Environment
- PowerShell version: (fill in)
- OS: (fill in)
- IdLE version / commit: (fill in; e.g., 0.9.2)
- Execution context (CLI / Service / CI): (fill in)
- Provider: IdLE.Provider.AD
Root Cause Analysis (Proposed)
Protect-LdapFilterValue is implemented as a nested function inside New-IdleADAdapter.ps1.
- AD adapter operations are exposed as
ScriptMethods (e.g., GetUserBySam) on an object created by New-IdleADAdapter.
- When a
ScriptMethod runs, it does not retain the lexical scope of New-IdleADAdapter, therefore the nested function is not visible.
- Result: calling
Protect-LdapFilterValue inside the ScriptMethod throws a command not recognized error.
Proposed Fix
Make the LDAP escaping helper available in the execution scope of the adapter ScriptMethods in a testable, non-global way.
Preferred approach (Option A):
- Add a
ScriptMethod on the adapter object, e.g. ProtectLdapFilterValue, implemented directly on the adapter.
- Update all adapter ScriptMethods that need escaping (e.g.,
GetUserBySam, GetUserByUpn, any search methods) to call:
$this.ProtectLdapFilterValue($value)
- Remove the nested function version to avoid future scope confusion.
Alternative approach (Option B):
- Move
Protect-LdapFilterValue to a private module function file (e.g., Private/Protect-LdapFilterValue.ps1) within the AD provider module and ensure it is dot-sourced/exported appropriately for internal use (no global pollution), then reference it from ScriptMethods.
Acceptance Criteria
Test Plan
Unit Tests (Pester)
Regression Coverage
Documentation Updates
Example Updates
Additional Context
User report (failure object):
@{Name=Disable AD account; Type=IdLE.Step.DisableIdentity; Status=Failed; Error=... Protect-LdapFilterValue is not recognized ...}
Notes:
- The failure is triggered during identity resolution (
ResolveIdentity) inside the AD provider.
- This blocks basic Joiner/Mover/Leaver scenarios using AD.
Description
The Active Directory identity provider fails at runtime when resolving an identity by sAMAccountName. The error indicates that the helper function
Protect-LdapFilterValueis not recognized, causing identity resolution to fail and consequently breaking steps likeIdLE.Step.DisableIdentity.This is a regression/defect in the AD adapter implementation:
Protect-LdapFilterValueis defined as a nested function withinNew-IdleADAdapter, but it is referenced fromScriptMethodmembers (e.g.,GetUserBySam). When these ScriptMethods are invoked later, the nested function is out of scope, so PowerShell cannot resolve it.Impact: AD-based workflows (e.g., Leaver
DisableIdentity) cannot execute reliably.Steps to Reproduce
IdLE.Step.DisableIdentitywith anIdentityKeythat resolves via sAMAccountName (e.g.,foo.bar).Example minimal workflow step:
Example plan creation (provider setup omitted here, see Additional Context):
Expected Behavior
IdLE.Step.DisableIdentityresolves the identity using the AD provider and disables the AD account.Actual Behavior
The step fails with an exception chain that ends in:
Example error (truncated):
Environment
Root Cause Analysis (Proposed)
Protect-LdapFilterValueis implemented as a nested function insideNew-IdleADAdapter.ps1.ScriptMethods (e.g.,GetUserBySam) on an object created byNew-IdleADAdapter.ScriptMethodruns, it does not retain the lexical scope ofNew-IdleADAdapter, therefore the nested function is not visible.Protect-LdapFilterValueinside theScriptMethodthrows a command not recognized error.Proposed Fix
Make the LDAP escaping helper available in the execution scope of the adapter ScriptMethods in a testable, non-global way.
Preferred approach (Option A):
ScriptMethodon the adapter object, e.g.ProtectLdapFilterValue, implemented directly on the adapter.GetUserBySam,GetUserByUpn, any search methods) to call:$this.ProtectLdapFilterValue($value)Alternative approach (Option B):
Protect-LdapFilterValueto a private module function file (e.g.,Private/Protect-LdapFilterValue.ps1) within the AD provider module and ensure it is dot-sourced/exported appropriately for internal use (no global pollution), then reference it from ScriptMethods.Acceptance Criteria
IdLE.Step.DisableIdentityagainst AD no longer fails with missingProtect-LdapFilterValue.Test Plan
Unit Tests (Pester)
GetUserBySamdoes not throw due to missing helper function.ProtectLdapFilterValuebehavior (escape sequences for\,*,(,), null byte).ResolveIdentitycan callGetUserBySamsuccessfully.Regression Coverage
DisableIdentitystep invocation path (using mocks) and asserts the call chain does not throw missing-command exceptions.Documentation Updates
Example Updates
DisableIdentitystill run.DisableIdentitywith AD provider configuration.Additional Context
User report (failure object):
Notes:
ResolveIdentity) inside the AD provider.