Skip to content

Commit ae4c75b

Browse files
authored
Merge pull request #88 from blindzero/copilot/add-idle-provider-ad
Add IdLE.Provider.AD (On-Prem Active Directory) MVP with built-in lifecycle steps
2 parents c18a57b + e6a837d commit ae4c75b

22 files changed

Lines changed: 2838 additions & 4 deletions

docs/_sidebar.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
- [Cmdlet Reference](reference/cmdlets.md)
2121
- [Events and Observability](reference/events-and-observability.md)
2222
- [Providers and Contracts](reference/providers-and-contracts.md)
23+
- [Active Directory Provider](reference/provider-ad.md)
2324
- [Configuration](reference/configuration.md)
2425
- [Steps and Metadata](reference/steps-and-metadata.md)
2526
- [Step Catalog](reference/steps.md)

docs/reference/provider-ad.md

Lines changed: 310 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,310 @@
1+
# IdLE.Provider.AD - Active Directory Provider
2+
3+
## Overview
4+
5+
The Active Directory provider (`IdLE.Provider.AD`) is a built-in provider for on-premises Active Directory environments. It enables IdLE to perform identity lifecycle operations directly against Windows Active Directory domains.
6+
7+
**Platform:** Windows-only (requires RSAT/ActiveDirectory PowerShell module)
8+
9+
**Module:** IdLE.Provider.AD
10+
11+
**Factory Function:** `New-IdleADIdentityProvider`
12+
13+
---
14+
15+
## Capabilities
16+
17+
The AD provider implements the following IdLE capabilities:
18+
19+
### Identity Operations
20+
21+
- **IdLE.Identity.Read** - Query identity information
22+
- **IdLE.Identity.List** - List identities (provider API only, no built-in step)
23+
- **IdLE.Identity.Create** - Create new user accounts
24+
- **IdLE.Identity.Delete** - Delete user accounts (opt-in via `-AllowDelete`)
25+
- **IdLE.Identity.Disable** - Disable user accounts
26+
- **IdLE.Identity.Enable** - Enable user accounts
27+
- **IdLE.Identity.Move** - Move users between OUs
28+
- **IdLE.Identity.Attribute.Ensure** - Set/update user attributes
29+
30+
### Entitlement Operations
31+
32+
- **IdLE.Entitlement.List** - List group memberships
33+
- **IdLE.Entitlement.Grant** - Add users to groups
34+
- **IdLE.Entitlement.Revoke** - Remove users from groups
35+
36+
**Note:** AD only supports `Kind='Group'` for entitlements. This is a platform limitation - Active Directory only provides security groups and distribution groups, not arbitrary entitlement types (roles, licenses, etc.).
37+
38+
---
39+
40+
## Prerequisites
41+
42+
### Windows and RSAT
43+
44+
The provider requires Windows with the Active Directory PowerShell module (RSAT).
45+
46+
**Install RSAT on Windows Server:**
47+
```powershell
48+
Install-WindowsFeature -Name RSAT-AD-PowerShell
49+
```
50+
51+
**Install RSAT on Windows 10/11:**
52+
```powershell
53+
Get-WindowsCapability -Online -Name "Rsat.ActiveDirectory*" | Add-WindowsCapability -Online
54+
```
55+
56+
### Active Directory Permissions
57+
58+
The account running IdLE (or provided via `-Credential`) must have appropriate AD permissions:
59+
60+
| Operation | Required Permission |
61+
| --------- | ------------------- |
62+
| Read identity | Read access to user objects |
63+
| Create identity | Create user objects in target OU |
64+
| Delete identity | Delete user objects |
65+
| Disable/Enable | Modify user account flags |
66+
| Set attributes | Write access to specific attributes |
67+
| Move identity | Move objects between OUs |
68+
| Grant/Revoke group membership | Modify group membership |
69+
70+
Follow the principle of least privilege - grant only the permissions required for your workflows.
71+
72+
---
73+
74+
## Installation and Import
75+
76+
The AD provider is automatically imported when you import the main IdLE module:
77+
78+
```powershell
79+
Import-Module IdLE
80+
```
81+
82+
This makes `New-IdleADIdentityProvider` available in your session.
83+
84+
---
85+
86+
## Usage
87+
88+
### Basic Usage (Integrated Auth)
89+
90+
```powershell
91+
# Create provider using integrated authentication (run-as)
92+
$provider = New-IdleADIdentityProvider
93+
94+
# Use in workflows
95+
$plan = New-IdlePlan -WorkflowPath './workflow.psd1' -Request $request -Providers @{
96+
Identity = $provider
97+
}
98+
```
99+
100+
### With Explicit Credentials
101+
102+
```powershell
103+
$credential = Get-Credential
104+
$provider = New-IdleADIdentityProvider -Credential $credential
105+
```
106+
107+
### With Delete Capability (Opt-in)
108+
109+
By default, the Delete capability is **not** advertised for safety. Enable it explicitly:
110+
111+
```powershell
112+
$provider = New-IdleADIdentityProvider -AllowDelete
113+
```
114+
115+
### Multi-Provider Scenarios
116+
117+
```powershell
118+
$sourceAD = New-IdleADIdentityProvider -Credential $sourceCred
119+
$targetAD = New-IdleADIdentityProvider -Credential $targetCred -AllowDelete
120+
121+
$plan = New-IdlePlan -WorkflowPath './migration.psd1' -Request $request -Providers @{
122+
SourceAD = $sourceAD
123+
TargetAD = $targetAD
124+
}
125+
```
126+
127+
---
128+
129+
## Identity Resolution
130+
131+
The provider supports multiple identifier formats and resolves them deterministically:
132+
133+
1. **GUID** (ObjectGuid): Pattern matches `[System.Guid]::TryParse()` - most deterministic
134+
2. **UPN** (UserPrincipalName): Contains `@` symbol
135+
3. **sAMAccountName**: Fallback for simple usernames
136+
137+
**Resolution order:**
138+
```powershell
139+
# GUID format → resolve by ObjectGuid
140+
'a1b2c3d4-e5f6-7890-abcd-ef1234567890'
141+
142+
# Contains @ → resolve by UPN
143+
'john.doe@contoso.local'
144+
145+
# Otherwise → resolve by sAMAccountName
146+
'jdoe'
147+
```
148+
149+
**Canonical output:** The provider returns the input IdentityKey as-is in operation results to maintain workflow consistency.
150+
151+
**Error handling:** On ambiguous or missing identities, the provider throws deterministic errors (no best-effort guessing).
152+
153+
---
154+
155+
## Idempotency Guarantees
156+
157+
All operations are idempotent and safe for retries:
158+
159+
| Operation | Idempotent Behavior |
160+
| --------- | ------------------- |
161+
| Create | If identity exists, returns `Changed=$false` (no error) |
162+
| Delete | If identity already gone, returns `Changed=$false` (no error) |
163+
| Move | If already in target OU, returns `Changed=$false` |
164+
| Enable/Disable | If already in desired state, returns `Changed=$false` |
165+
| Grant membership | If already a member, returns `Changed=$false` |
166+
| Revoke membership | If not a member, returns `Changed=$false` |
167+
168+
This design ensures workflows can be re-run safely without causing duplicate operations or errors.
169+
170+
---
171+
172+
## Entitlement Model
173+
174+
Active Directory entitlements use:
175+
176+
- **Kind:** Always `'Group'` (AD limitation - only supports security and distribution groups)
177+
- **Id (canonical key):** DistinguishedName (DN)
178+
179+
**Input flexibility:** The provider MAY accept SID or sAMAccountName as input but MUST normalize to DN internally.
180+
181+
**Example:**
182+
```powershell
183+
@{
184+
Kind = 'Group'
185+
Id = 'CN=IT-Team,OU=Groups,DC=contoso,DC=local'
186+
}
187+
```
188+
189+
---
190+
191+
## Built-in Steps
192+
193+
The following built-in steps in `IdLE.Steps.Common` work with the AD provider:
194+
195+
- **IdLE.Step.CreateIdentity** - Create new user accounts
196+
- **IdLE.Step.DisableIdentity** - Disable user accounts
197+
- **IdLE.Step.EnableIdentity** - Enable user accounts
198+
- **IdLE.Step.MoveIdentity** - Move users between OUs
199+
- **IdLE.Step.DeleteIdentity** - Delete user accounts (requires `IdLE.Identity.Delete` capability)
200+
- **IdLE.Step.EnsureAttribute** - Set/update user attributes
201+
- **IdLE.Step.EnsureEntitlement** - Manage group memberships
202+
203+
All steps declare `RequiresCapabilities` for plan-time validation.
204+
205+
---
206+
207+
## Example Workflows
208+
209+
Complete example workflows are available in the repository:
210+
211+
- **examples/workflows/ad-joiner-complete.psd1** - Full joiner workflow (Create + Attributes + Groups + OU move)
212+
- **examples/workflows/ad-mover-department-change.psd1** - Mover workflow (Update attributes + Group delta + OU move)
213+
- **examples/workflows/ad-leaver-offboarding.psd1** - Leaver workflow (Disable + OU move + conditional Delete)
214+
215+
---
216+
217+
## Provider Aliases
218+
219+
The provider uses **provider aliases** - the hashtable key in the `Providers` parameter is an alias chosen by the host:
220+
221+
```powershell
222+
# Single provider scenario
223+
$plan = New-IdlePlan -Providers @{ Identity = $provider }
224+
225+
# Multi-provider scenario
226+
$plan = New-IdlePlan -Providers @{
227+
SourceAD = $sourceProvider
228+
TargetAD = $targetProvider
229+
}
230+
```
231+
232+
Workflow steps reference the alias via `With.Provider`:
233+
234+
```powershell
235+
@{
236+
Type = 'IdLE.Step.CreateIdentity'
237+
With = @{
238+
Provider = 'SourceAD' # Matches the alias in Providers hashtable
239+
IdentityKey = 'user@contoso.local'
240+
# ...
241+
}
242+
}
243+
```
244+
245+
Built-in steps default to `'Identity'` when `With.Provider` is omitted.
246+
247+
---
248+
249+
## Troubleshooting
250+
251+
### ActiveDirectory Module Not Found
252+
253+
**Error:** `The specified module 'ActiveDirectory' was not loaded...`
254+
255+
**Solution:** Install RSAT as described in Prerequisites.
256+
257+
### Insufficient Permissions
258+
259+
**Error:** `Insufficient access rights to perform the operation`
260+
261+
**Solution:** Verify the account has required AD permissions. Use a dedicated service account with least-privilege access.
262+
263+
### Identity Not Found
264+
265+
**Error:** `Identity with <identifier> not found`
266+
267+
**Solution:**
268+
- Verify the identifier format (GUID/UPN/sAMAccountName)
269+
- Check the user exists in AD
270+
- Ensure the account has read access to the user object
271+
272+
### Delete Capability Missing
273+
274+
**Error:** Plan validation fails with `Required capability 'IdLE.Identity.Delete' not available`
275+
276+
**Solution:** Create the provider with `-AllowDelete` parameter:
277+
```powershell
278+
$provider = New-IdleADIdentityProvider -AllowDelete
279+
```
280+
281+
---
282+
283+
## Architecture Notes
284+
285+
### Testability
286+
287+
The AD provider uses an internal adapter layer (`New-IdleADAdapter`) that isolates AD cmdlet dependencies. This design:
288+
289+
- Enables unit testing without real AD (unit tests inject fake adapters)
290+
- Keeps provider logic testable and deterministic
291+
- Separates provider contract from AD implementation details
292+
293+
### Security
294+
295+
- **No interactive prompts:** The provider never prompts for credentials (violates headless principle)
296+
- **Opt-in Delete:** Delete capability requires explicit `-AllowDelete` for safety
297+
- **Credential handling:** Credentials are passed to AD cmdlets securely via `-Credential` parameter
298+
299+
### Capability-Driven Design
300+
301+
The provider implements `GetCapabilities()` and announces all supported capabilities. The engine validates capabilities at plan-time before execution, enabling fail-fast behavior.
302+
303+
---
304+
305+
## Related Documentation
306+
307+
- [Providers and Contracts](providers-and-contracts.md) - Provider architecture and contracts
308+
- [Steps and Metadata](steps-and-metadata.md) - Built-in steps and capability requirements
309+
- [Provider Capability Rules](../advanced/provider-capabilities.md) - Capability naming and validation
310+
- [Security Model](../advanced/security.md) - Trust boundaries and security considerations

0 commit comments

Comments
 (0)