|
| 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