Add IdLE.Provider.AD (On-Prem Active Directory) MVP with built-in lifecycle steps#88
Add IdLE.Provider.AD (On-Prem Active Directory) MVP with built-in lifecycle steps#88
Conversation
Co-authored-by: blindzero <13959569+blindzero@users.noreply.github.com>
…tity operations Co-authored-by: blindzero <13959569+blindzero@users.noreply.github.com>
Co-authored-by: blindzero <13959569+blindzero@users.noreply.github.com>
Co-authored-by: blindzero <13959569+blindzero@users.noreply.github.com>
…ributes dynamically Co-authored-by: blindzero <13959569+blindzero@users.noreply.github.com>
Co-authored-by: blindzero <13959569+blindzero@users.noreply.github.com>
Co-authored-by: blindzero <13959569+blindzero@users.noreply.github.com>
|
@copilot I am not sure about the failing contract tests. If it is expected behavior the test should be implemented in a way to succeed if the behavior is really like that (negated test?). Why does the provider only support "Group"? Do the entitlement tests need to be changed then as well? |
…roup tests Replace generic entitlement contract tests (which use Kind='Contract') with AD-specific tests that use Kind='Group'. Active Directory only supports group entitlements, not arbitrary entitlement kinds. Document this limitation in README. All 152 tests now passing (was 149/152 with 3 expected failures). Co-authored-by: blindzero <13959569+blindzero@users.noreply.github.com>
Fixed in commit 4e60142. Why AD only supports 'Group': What changed:
The AD-specific tests validate the same contract behaviors (idempotency, list/grant/revoke operations) but use |
|
@copilot you must execute the tools to Generate Step Reference and commit the change of the generated files of docs as well. |
Run Generate-IdleStepReference.ps1 to generate documentation for: - CreateIdentity - DeleteIdentity - DisableIdentity - EnableIdentity - MoveIdentity All new steps added in IdLE.Steps.Common are now documented in the step catalog. Co-authored-by: blindzero <13959569+blindzero@users.noreply.github.com>
Done in commit 9a46911. Generated step reference documentation for all 5 new steps added to IdLE.Steps.Common:
The generated file |
|
@copilot bei |
The key This is the established pattern in IdLE:
The naming follows the convention that the alias describes the provider's role/domain (identity management) rather than its implementation (AD, Entra, etc.). This allows workflows to remain provider-agnostic. However, if you prefer more explicit naming like |
|
@copilot Die Argumentation macht nur bedingt Sinn. Wenn der Key nicht die Implementierung abbildet, sollte es ja nicht Entra oder ADPeovider sein. |
There was a problem hiding this comment.
Pull request overview
This PR implements a production-ready Active Directory provider for IdLE, enabling real-world Joiner/Mover/Leaver workflows against on-premises AD environments. The implementation includes identity lifecycle operations, group management, built-in steps, and comprehensive documentation.
Changes:
- New
IdLE.Provider.ADmodule with complete AD integration (identity operations, group entitlements, opt-in delete capability) - Five new built-in lifecycle steps (CreateIdentity, DisableIdentity, EnableIdentity, MoveIdentity, DeleteIdentity) with capability-based validation
- Complete test coverage with fake adapter pattern, contract compliance, and idempotency tests
- Example JML workflows and comprehensive provider documentation
Reviewed changes
Copilot reviewed 22 out of 22 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/Providers/ADIdentityProvider.Tests.ps1 | Complete test suite with fake adapter, contract tests, and AD-specific validation |
| src/IdLE/IdLE.psd1 | Registers AD provider as nested module for auto-import |
| src/IdLE.Steps.Common/Public/Invoke-IdleStep*.ps1 | Five new lifecycle step implementations with consistent error handling |
| src/IdLE.Steps.Common/IdLE.Steps.Common.* | Module manifest and export updates for new steps |
| src/IdLE.Provider.AD/README.md | Minimal sub-module README following IdLE conventions |
| src/IdLE.Provider.AD/Public/New-IdleADIdentityProvider.ps1 | Main provider factory with identity resolution, entitlement operations, and capability management |
| src/IdLE.Provider.AD/Private/New-IdleADAdapter.ps1 | Internal adapter layer wrapping AD cmdlets for testability |
| src/IdLE.Provider.AD/IdLE.Provider.AD.* | Module manifest and loader with non-blocking import |
| src/IdLE.Core/Private/Get-IdleStepRegistry.ps1 | Step registry updates for new lifecycle steps |
| examples/workflows/*.psd1 | Three complete example workflows demonstrating JML scenarios |
| docs/reference/provider-ad.md | Comprehensive provider documentation with usage patterns and troubleshooting |
| docs/usage/providers.md | Provider alias documentation and multi-provider patterns |
| docs/reference/steps.md | Generated step catalog with new lifecycle steps |
| docs/_sidebar.md | Navigation update for AD provider documentation |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d202d43a41
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Adds missing LDAP injection prevention to complement existing error handling fixes: - Add Escape-LdapFilterValue helper function in New-IdleADAdapter.ps1 - Sanitize special LDAP characters: *, (, ), \, null byte - Apply escaping in GetUserByUpn, GetUserBySam, and ListUsers methods - Fix Delete error handling to work in test environments (type check + message fallback) This completes all security fixes from automated code review PR #88. Defense-in-depth security layer per docs/advanced/security.md. All 27 AD provider tests passing. Co-authored-by: blindzero <13959569+blindzero@users.noreply.github.com>
|
@copilot Make sure all Tests are green. |
All 27 AD provider tests are passing (100% pass rate): Test coverage includes:
All security fixes from automated code review are in place and validated. |
|
@copilot Make sure ALL Pester Tests are green (not only of this AD provider) and no PSSA errors occur. |
…ed verb Addressed all 3 PSScriptAnalyzer warnings: 1. Empty catch block (line 277): Added Write-Verbose message for debugging 2. Unused variable (line 286): Changed `$user =` to `$null =` to explicitly discard return value 3. Unapproved verb: Renamed `Escape-LdapFilterValue` to `Protect-LdapFilterValue` (approved verb) - Updated all 3 callsites in New-IdleADAdapter.ps1 All 152 Pester tests passing (100%), no PSScriptAnalyzer warnings. Co-authored-by: blindzero <13959569+blindzero@users.noreply.github.com>
All tests and linting checks passing in commit e6a837d: ✅ 152/152 Pester tests passing (100%)
✅ 0 PSScriptAnalyzer warnings
All security fixes from automated code review remain in place and validated. |
Summary
Implements production-ready Active Directory provider enabling real Joiner/Mover/Leaver workflows with identity lifecycle operations and group management.
Motivation
IdLE lacked a concrete provider implementation for on-premises Active Directory, limiting its use for real-world identity lifecycle automation. This provider enables organizations to run production JML workflows against AD out of the box.
Type of Change
Changes
Provider Module (
IdLE.Provider.AD)Changed=$falseif exists, Delete succeeds if already gone)AllowDeleteparameter for safetyProtect-LdapFilterValuehelper function (approved PowerShell verb) before filter constructionBuilt-in Steps (
IdLE.Steps.Common)IdLE.Step.CreateIdentity- create new user accountsIdLE.Step.DisableIdentity- disable user accountsIdLE.Step.EnableIdentity- enable user accountsIdLE.Step.MoveIdentity- move between OUsIdLE.Step.DeleteIdentity- delete accounts (requiresIdLE.Identity.Deletecapability)RequiresCapabilitiesfor plan-time validationGet-IdleStepRegistrydocs/reference/steps.mdExample Workflows
ad-joiner-complete.psd1- Create + attributes + groups + OU movead-mover-department-change.psd1- Attribute updates + group delta + OU movead-leaver-offboarding.psd1- Disable + OU move + conditional deleteActive Directory Entitlement Constraint
Kind = 'Group'for entitlements (security groups and distribution groups)ListEntitlementswill haveKind = 'Group'Kind='Group'Provider Alias Flexibility
-Providers @{ ... }hashtables are completely flexible and host-chosen'Identity'alias whenWith.Provideris omittedIdentity) for single provider, instance-based (SourceAD,TargetEntra) for multiple providersdocs/usage/providers.mdand provider documentationSecurity Improvements
Protect-LdapFilterValuesanitizes special LDAP filter characters (*, (, ), , null byte) in user inputs before filter string construction inGetUserByUpn,GetUserBySam, andListUsersmethodsTryParsereturn value instead of catching non-existent exceptions;GetUserByGuidexceptions handled separately with proper verbose loggingCode Quality Improvements
Protect-LdapFilterValueinstead ofEscape-LdapFilterValue)Documentation Structure
Usage Example
Testing
How to test & review
Prerequisites: Windows with RSAT/ActiveDirectory module for real AD testing. Unit tests use fake adapter and run on any platform.
Key test scenarios:
Kind='Group'Checklist
Original prompt
This section details on the original issue you should resolve
<issue_title>IdLE.Provider.AD (On-Prem AD) MVP (Windows-only)</issue_title>
<issue_description># Goal
Scope
IdLE.Provider.ADListIdentities([hashtable] $Filter)returns an array of identity keys (strings). Filtering is optional; providers may supportFilter.Search(string prefix match).IdLE.Identity.Deleteonly whenAllowDelete = $trueis set during provider construction. The built-in Delete step MUST declareRequiresCapabilities = @('IdLE.Identity.Delete').Built-in steps (out of the box workflows):
IdLE.Step.CreateIdentityProvider?,IdentityKey,Attributes(hashtable),Enabled?IdLE.Identity.CreateIdLE.Step.DisableIdentityProvider?, IdentityKeyIdLE.Identity.DisableIdLE.Step.EnableIdentityProvider?, IdentityKeyIdLE.Identity.EnableIdLE.Step.MoveIdentityProvider?,IdentityKey,TargetContainer(DN)IdLE.Identity.MoveIdLE.Step.DeleteIdentityProvider?,IdentityKeyIdLE.Identity.Delete(opt-in gated)Implementation approach:
GetUserByUpn,GetUserBySam,GetUserByGuid,NewUser,SetUser,DisableUser,EnableUser,MoveObject,GetGroupById,AddGroupMember,RemoveGroupMember,GetUserGroups.Docs / Examples (part of DoD)
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.