Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions docs/reference/providers/provider-ad.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,3 +141,10 @@ Mover scenarios are intentionally folded into Joiner/Leaver (as optional pattern

- **Group membership changes are risky**
Prefer removing only explicit “managed groups” (allow-list) to avoid breaking access unexpectedly.

## Scenarios (link-only)

Cross-provider orchestration examples are valuable, but should not be embedded in a single provider reference page.
Keep them as **link-only** and collect them on a central Examples/Scenarios page:

- `examples/workflows/templates/ad-joiner-entraconnect-entraid.psd1` - Joiner workflow that creates an AD account, triggers Entra Connect sync, and assigns Entra ID groups
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,10 @@ This provider has no admin-facing option bag. Configuration is done through:
- **“AuthSession must implement InvokeCommand”**: your host must provide an AuthSession object with an `InvokeCommand()` method.
- **Get-ADSyncScheduler not found**: ensure ADSync cmdlets are available in the remote session (module installed/accessible).
- **Timeout waiting for completion**: increase `TimeoutSeconds` or check the scheduler state on the server.

## Scenarios (link-only)

Cross-provider orchestration examples are valuable, but should not be embedded in a single provider reference page.
Keep them as **link-only** and collect them on a central Examples/Scenarios page:

- `examples/workflows/templates/ad-joiner-entraconnect-entraid.psd1` - Joiner workflow that creates an AD account, triggers Entra Connect sync, and assigns Entra ID groups
8 changes: 8 additions & 0 deletions docs/reference/providers/provider-entraID.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,3 +126,11 @@ Mover scenarios are integrated as **optional patterns** in the Joiner template.
- **Auth session not found**: check `AuthSessionName` matches your runtime/broker configuration.
- **Delete doesn’t work**: deletion is opt-in. Create the provider with `-AllowDelete` and only use delete with a privileged auth role.
- **Group cleanup is disruptive**: only enable revoke/remove operations when you fully understand the impact (prefer managed allow-lists).

## Scenarios (link-only)

Cross-provider orchestration examples are valuable, but should not be embedded in a single provider reference page.
Keep them as **link-only** and collect them on a central Examples/Scenarios page:

- `examples/workflows/templates/ad-joiner-entraconnect-entraid.psd1` - Joiner workflow that creates an AD account, triggers Entra Connect sync, and assigns Entra ID groups
- `examples/workflows/templates/entraid-exo-leaver.psd1` - Leaver workflow that disables Entra ID account, converts mailbox to shared, and enables Out of Office
52 changes: 6 additions & 46 deletions examples/workflows/mock/mock-identity-and-entitlements.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,12 @@

# In the mock provider, entitlements are just stored in-memory.
# Use this to validate your workflow logic and template placeholders.
Desired = @(
@{
Kind = 'Group'
Id = '{{Request.Input.GroupId}}'
DisplayName = '{{Request.Input.GroupName}}'
}
)
Entitlement = @{
Kind = 'Group'
Id = '{{Request.Input.GroupId}}'
DisplayName = '{{Request.Input.GroupName}}'
}
State = 'Present'
}
}

Expand All @@ -47,42 +46,3 @@
}
)
}

```

### File: examples/workflows/mock/mock-onfailure.psd1

```powershell
@{
Name = 'Mock Provider - OnFailure handling (Demo)'
LifecycleEvent = 'Joiner'
Description = 'Demonstrates OnFailureSteps for cleanup/notification when primary steps fail (using Mock provider).'

Steps = @(
@{
Name = 'Emit start'
Type = 'IdLE.Step.EmitEvent'
With = @{
Message = 'Starting workflow with OnFailure handling.'
}
}

@{
Name = 'Primary action (will fail intentionally)'
Type = 'IdLE.Step.Fail'
With = @{
Message = 'Intentional failure to demonstrate OnFailureSteps.'
}

OnFailureSteps = @(
@{
Name = 'Emit failure notification'
Type = 'IdLE.Step.EmitEvent'
With = @{
Message = 'Primary action failed for {{Request.Input.IdentityKey}}.'
}
}
)
}
)
}
91 changes: 0 additions & 91 deletions examples/workflows/templates/exo-joiner.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -30,94 +30,3 @@
}
)
}

```

### 2) Keep `entraid-exo-leaver.psd1` but update it to the standard placeholder style

This file is a **cross-provider scenario** (Entra ID + EXO). It should remain **link-only** (not embedded in a single provider page), but it should be consistent:

- Replace all `IdentityKey = @{ ValueFrom = 'Request.Input.X' }` with `IdentityKey = '{{Request.Input.X}}'`

Updated full content:

```powershell
@{
Name = 'Complete Leaver - EntraID + ExchangeOnline Offboarding'
LifecycleEvent = 'Leaver'
Description = 'Complete offboarding workflow: disables EntraID account, converts mailbox to shared, and enables Out of Office.'
Steps = @(
@{
Name = 'GetMailboxInfo'
Type = 'IdLE.Step.Mailbox.GetInfo'
With = @{
Provider = 'ExchangeOnline'
IdentityKey = '{{Request.Input.UserPrincipalName}}'
}
}
@{
Name = 'ConvertToSharedMailbox'
Type = 'IdLE.Step.Mailbox.EnsureType'
With = @{
Provider = 'ExchangeOnline'
IdentityKey = '{{Request.Input.UserPrincipalName}}'
MailboxType = 'Shared'
}
}
@{
Name = 'EnableOutOfOffice'
Type = 'IdLE.Step.Mailbox.EnsureOutOfOffice'
With = @{
Provider = 'ExchangeOnline'
IdentityKey = '{{Request.Input.UserPrincipalName}}'
Config = @{
Mode = 'Enabled'
InternalMessage = 'This person is no longer with the organization. For assistance, please contact their manager or the main office.'
ExternalMessage = 'This person is no longer with the organization. Please contact the main office for assistance.'
ExternalAudience = 'All'
}
}
}
@{
Name = 'RevokeAllGroupMemberships'
Type = 'IdLE.Step.EnsureEntitlement'
With = @{
Provider = 'Identity'
AuthSessionName = 'MicrosoftGraph'
AuthSessionOptions = @{ Role = 'Admin' }
IdentityKey = '{{Request.Input.UserObjectId}}'
Desired = @()
}
}
@{
Name = 'ClearManager'
Type = 'IdLE.Step.EnsureAttributes'
With = @{
Provider = 'Identity'
AuthSessionName = 'MicrosoftGraph'
AuthSessionOptions = @{ Role = 'Admin' }
IdentityKey = '{{Request.Input.UserObjectId}}'
Attributes = @{
Manager = $null
}
}
}
@{
Name = 'DisableEntraIDAccount'
Type = 'IdLE.Step.DisableIdentity'
With = @{
Provider = 'Identity'
AuthSessionName = 'MicrosoftGraph'
AuthSessionOptions = @{ Role = 'Admin' }
IdentityKey = '{{Request.Input.UserObjectId}}'
}
}
@{
Name = 'EmitCompletionEvent'
Type = 'IdLE.Step.EmitEvent'
With = @{
Message = 'Complete offboarding finished: Mailbox converted to Shared, OOF enabled, EntraID account disabled.'
}
}
)
}
14 changes: 12 additions & 2 deletions tests/Core/CapabilityDeprecation.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,21 @@ Describe 'Capability Deprecation and Migration' {
}

# Use a real workflow file that uses mailbox steps
$wfPath = Join-Path $PSScriptRoot '..' '..' 'examples' 'workflows' 'templates' 'exo-leaver-mailbox-offboarding.psd1'
$wfPath = Join-Path $PSScriptRoot '..' '..' 'examples' 'workflows' 'templates' 'exo-leaver.psd1'

# Verify the workflow file exists
$wfPath | Should -Exist

$req = New-IdleTestRequest -LifecycleEvent 'Leaver' -DesiredState @{
UserPrincipalName = 'testuser@contoso.com'
Manager = @{
DisplayName = 'IT Support'
Mail = 'support@contoso.com'
}
ServiceDesk = @{
DisplayName = 'Service Desk'
Mail = 'servicedesk@contoso.com'
}
}
$providers = @{ MockProvider = $mockProvider }

Expand Down Expand Up @@ -70,13 +75,18 @@ Describe 'Capability Deprecation and Migration' {
}

# Use a real workflow file
$wfPath = Join-Path $PSScriptRoot '..' '..' 'examples' 'workflows' 'templates' 'exo-leaver-mailbox-offboarding.psd1'
$wfPath = Join-Path $PSScriptRoot '..' '..' 'examples' 'workflows' 'templates' 'exo-leaver.psd1'

$req = New-IdleTestRequest -LifecycleEvent 'Leaver' -DesiredState @{
UserPrincipalName = 'testuser@contoso.com'
Manager = @{
DisplayName = 'IT Support'
Mail = 'support@contoso.com'
}
ServiceDesk = @{
DisplayName = 'Service Desk'
Mail = 'servicedesk@contoso.com'
}
}
$providers = @{ MockProvider = $mockProvider }

Expand Down
38 changes: 36 additions & 2 deletions tests/Examples/WorkflowSamples.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,19 @@ Describe 'Example workflows' {
foreach ($file in $mockWorkflows) {
$workflow = Import-PowerShellDataFile -Path $file.FullName
$lifecycleEvent = if ($workflow.ContainsKey('LifecycleEvent')) { $workflow.LifecycleEvent } else { 'Joiner' }
$request = New-IdleTestRequest -LifecycleEvent $lifecycleEvent -Actor 'test-user'

# Provide sample data for workflows that use templates
$desiredState = @{
IdentityKey = 'test-user'
GivenName = 'Test'
Surname = 'User'
Department = 'IT'
Title = 'Engineer'
GroupId = 'test-group-id'
GroupName = 'Test Group'
}

$request = New-IdleTestRequest -LifecycleEvent $lifecycleEvent -Actor 'test-user' -DesiredState $desiredState

{ New-IdlePlan -WorkflowPath $file.FullName -Request $request -Providers $providers } | Should -Not -Throw
}
Expand All @@ -43,7 +55,19 @@ Describe 'Example workflows' {
foreach ($file in $mockWorkflows) {
$workflow = Import-PowerShellDataFile -Path $file.FullName
$lifecycleEvent = if ($workflow.ContainsKey('LifecycleEvent')) { $workflow.LifecycleEvent } else { 'Joiner' }
$request = New-IdleTestRequest -LifecycleEvent $lifecycleEvent -Actor 'test-user'

# Provide sample data for workflows that use templates
$desiredState = @{
IdentityKey = 'test-user'
GivenName = 'Test'
Surname = 'User'
Department = 'IT'
Title = 'Engineer'
GroupId = 'test-group-id'
GroupName = 'Test Group'
}

$request = New-IdleTestRequest -LifecycleEvent $lifecycleEvent -Actor 'test-user' -DesiredState $desiredState

$plan = New-IdlePlan -WorkflowPath $file.FullName -Request $request -Providers $providers
$result = Invoke-IdlePlan -Plan $plan -Providers $providers
Expand All @@ -66,6 +90,16 @@ Describe 'Example workflows' {
It 'validates template workflows (if any exist)' {
if ($templateWorkflows) {
foreach ($file in $templateWorkflows) {
# Load the file to check its structure
$content = Import-PowerShellDataFile -Path $file.FullName

# Skip template library files (with Metadata + Workflow structure)
# These are documentation/reference templates, not executable workflows
if ($content.ContainsKey('Metadata') -and $content.ContainsKey('Workflow')) {
Write-Verbose "Skipping template library file: $($file.Name)"
continue
}

{ Test-IdleWorkflow -WorkflowPath $file.FullName } | Should -Not -Throw
}
} else {
Expand Down
10 changes: 10 additions & 0 deletions tools/import-idle.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,16 @@ if (-not $workflowPaths) {
}

foreach ($wf in $workflowPaths) {
# Load the file to check its structure
$content = Import-PowerShellDataFile -Path $wf

# Skip template library files (with Metadata + Workflow structure)
# These are documentation/reference templates, not executable workflows
if ($content.ContainsKey('Metadata') -and $content.ContainsKey('Workflow')) {
Write-Host "Skipping template library file: $wf" -ForegroundColor Yellow
continue
}

Test-IdleWorkflow -WorkflowPath $wf
}

Expand Down