Add Entra Connect directory sync step pack and provider#95
Conversation
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>
Co-authored-by: blindzero <13959569+blindzero@users.noreply.github.com>
Co-authored-by: blindzero <13959569+blindzero@users.noreply.github.com>
…ce nesting in Test-IdleProviderMethodParameter Co-authored-by: blindzero <13959569+blindzero@users.noreply.github.com>
|
@copilot |
…ctorySync step pack Co-authored-by: blindzero <13959569+blindzero@users.noreply.github.com>
…y removed Co-authored-by: blindzero <13959569+blindzero@users.noreply.github.com>
Fixed in commits 599e75d and 7877f1f. Updated |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7877f1fee5
ℹ️ 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".
There was a problem hiding this comment.
Pull request overview
This PR adds first-party support for triggering Entra ID Connect (ADSync) directory sync cycles on on-premises servers via remote execution. The implementation consists of a new step pack (IdLE.Steps.DirectorySync.EntraConnect) that provides the step logic, and a new provider (IdLE.Provider.DirectorySync.EntraConnect) that executes ADSync commands remotely.
Changes:
- New step type
IdLE.Step.TriggerDirectorySyncfor triggering sync cycles with optional blocking until completion - New provider contract for remote directory sync operations with AuthSession-based execution
- Integration of the step pack into IdLE meta-module with comprehensive test coverage (34 new tests passing)
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/IdLE.Steps.DirectorySync.EntraConnect/IdLE.Steps.DirectorySync.EntraConnect.psd1 | Module manifest for the new step pack |
| src/IdLE.Steps.DirectorySync.EntraConnect/IdLE.Steps.DirectorySync.EntraConnect.psm1 | Module loader for public and private functions |
| src/IdLE.Steps.DirectorySync.EntraConnect/Public/Invoke-IdleStepTriggerDirectorySync.ps1 | Step implementation with input validation, provider interaction, and wait/poll logic |
| src/IdLE.Steps.DirectorySync.EntraConnect/Public/Get-IdleStepMetadataCatalog.ps1 | Metadata catalog advertising required capabilities |
| src/IdLE.Steps.DirectorySync.EntraConnect/Private/Invoke-IdleProviderMethod.ps1 | Helper for invoking provider methods with AuthSession support (duplicates Common) |
| src/IdLE.Steps.DirectorySync.EntraConnect/Private/Test-IdleProviderMethodParameter.ps1 | Helper for parameter introspection (duplicates Common, uses guard clauses) |
| src/IdLE.Provider.DirectorySync.EntraConnect/IdLE.Provider.DirectorySync.EntraConnect.psd1 | Provider module manifest |
| src/IdLE.Provider.DirectorySync.EntraConnect/IdLE.Provider.DirectorySync.EntraConnect.psm1 | Provider module loader |
| src/IdLE.Provider.DirectorySync.EntraConnect/Public/New-IdleEntraConnectDirectorySyncProvider.ps1 | Provider factory implementing StartSyncCycle and GetSyncCycleState methods |
| tests/Invoke-IdleStepTriggerDirectorySync.Tests.ps1 | Comprehensive step tests covering validation, trigger, wait, and event emission |
| tests/Providers/EntraConnectDirectorySyncProvider.Tests.ps1 | Provider contract tests validating methods and capability advertisement |
| src/IdLE/IdLE.psd1 | Added step pack to NestedModules (provider module not added) |
| tests/_testHelpers.ps1 | Import both new modules for test discoverability |
| tools/Generate-IdleStepReference.ps1 | Added new step module to default scan list |
| examples/workflows/joiner-with-entraid-sync.psd1 | Example workflow demonstrating sync triggering with wait |
| docs/reference/steps.md | Generated documentation for TriggerDirectorySync step |
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
… in IdLE.Steps.Common Co-authored-by: blindzero <13959569+blindzero@users.noreply.github.com>
Summary
Implements first-party step pack and provider for triggering Entra ID Connect (ADSync) sync cycles on on-premises servers via remote execution.
Motivation
Enables workflows to trigger directory sync cycles between on-premises AD and Entra ID, with optional blocking until completion. Required for JML scenarios where cloud provisioning depends on identity synchronization completing before subsequent steps can execute.
Type of Change
Changes
New Step Pack:
IdLE.Steps.DirectorySync.EntraConnectIdLE.Step.TriggerDirectorySyncIdLE.Steps.Commoncatalog:RequiredCapabilities:IdLE.DirectorySync.Trigger,IdLE.DirectorySync.StatusAuthSessionName(required),PolicyType(Delta/Initial),Wait(bool),TimeoutSeconds,PollIntervalSeconds,AuthSessionOptionsDirectorySyncTriggered,DirectorySyncWaiting,DirectorySyncPoll,DirectorySyncCompleted,DirectorySyncFailedIdLE.Steps.CommonviaRequiredModulesfor shared helper functionsNew Provider:
IdLE.Provider.DirectorySync.EntraConnectStartSyncCycle(PolicyType, AuthSession),GetSyncCycleState(AuthSession)InvokeCommand(CommandName, Parameters)method for remote executionStart-ADSyncSyncCycleandGet-ADSyncScheduleron target server.OUTPUTSdocumentation in comment-based helpAuthSession Remote Execution Contract
Module Integration & Code Consolidation
IdLE.psd1NestedModulesRequiredModulesfor shared functionalityIdLE.Steps.CommonIdLE.Steps.Commoncatalog (single source of truth)Generate-IdleStepReference.ps1default modules to includeIdLE.Steps.DirectorySync.EntraConnectCode Quality Improvements
Test-IdleProviderMethodParameterto use guard clauses, reducing nesting depth from 4-5 levels to 2 levelsInvoke-IdleProviderMethodto useAllowEmptyCollectionfor proper empty array handlingInvoke-IdleProviderMethod,Test-IdleProviderMethodParameter) now shared from CommonKind = 'Group'entitlement (currently supported) instead of licensesTesting
Coverage
All 230 repository tests pass (including 34 new tests). PSScriptAnalyzer clean. CI docs-step-reference check passes.
How to test & review
New-IdleEntraConnectDirectorySyncProviderreturns object withGetCapabilities(),StartSyncCycle(PolicyType, AuthSession),GetSyncCycleState(AuthSession)and includes.OUTPUTSdocumentationInvokeCommandmethodIdLE.Steps.Common\Get-IdleStepMetadataCatalogexamples/workflows/joiner-with-entraid-sync.psd1demonstrates workflow usage with Group entitlementGenerate-IdleStepReference.ps1includes new step module by default and produces no diff when runChecklist
Related Issues
Implements remote directory sync triggering capability for Entra Connect environments.
Original prompt
This section details on the original issue you should resolve
<issue_title>provider: trigger and wait for Entra Connect sync cycles (remote)</issue_title>
<issue_description>## Goal
Provide a first-party step pack that can trigger an Entra ID Connect (ADSync) sync cycle on an on-premises server and optionally wait until the cycle is finished.
Constraints:
Start-ADSyncSyncCycletypically requires an elevated/admin execution context.Scope
In scope
IdLE.Steps.DirectorySync.EntraConnectIdLE.Provider.DirectorySync.EntraConnectOut of scope
Design
1) Step Type and module
IdLE.Step.TriggerDirectorySyncInvoke-IdleStepTriggerDirectorySyncsrc/IdLE.Steps.DirectorySync.EntraConnect/2) Step metadata (RequiredCapabilities)
Because #89 removes workflow
RequiresCapabilities, the step pack must provide metadata for this step:RequiredCapabilities = @('IdLE.DirectorySync.Trigger', 'IdLE.DirectorySync.Status')Rationale:
With.Wait = $false, advertisingIdLE.DirectorySync.Statusis acceptable and keeps planning deterministic.3) Step inputs (With.*)
Withmust be a hashtable and is validated by the step.Required:
With.AuthSessionName(string)EntraConnect).With.PolicyType(string)Delta,Initial(case-insensitive).Optional:
With.Provider(string) — provider alias inContext.Providers(default:DirectorySync).With.Wait(bool) — default:$false.With.TimeoutSeconds(int) — default:600.With.PollIntervalSeconds(int) — default:10.With.AuthSessionOptions(hashtable, data-only) — forwarded to broker (e.g.,{ Role = 'EntraConnectAdmin' }).4) Provider contract
The step calls a provider instance via
Context.Providers[<ProviderAlias>].Provider must implement:
StartSyncCycle(PolicyType, AuthSession)Started(bool)Message(string, optional)GetSyncCycleState(AuthSession)InProgress(bool)State(string; e.g.,Idle,InProgress,Unknown)Details(hashtable or null; optional)Notes:
Get-ADSyncScheduler). The EntraConnect provider may useGet-ADSyncScheduleror another reliable signal; the contract only cares aboutInProgress.5) AuthSession contract (Wrapper / Handle)
The host’s AuthSessionBroker must return an AuthSession whose payload is a remote execution handle for the Entra Connect server.
Minimum expected shape (trusted runtime object; not part of workflow data):
Method:
InvokeCommand(CommandName, Parameters)CommandNameis a string.Parametersis a hashtable (data-only).Method:
Dispose()(optional but recommended)The provider uses only this handle (via
AuthSession) and does not create its own sessions.6) Elevation requirement (explicit)
If the remote execution context is not privileged enough to call
Start-ADSyncSyncCycle, the provider must fail deterministically:No interactive escalation (no UAC prompts, no credential prompts).
7) Step behavior
Context.AcquireAuthSession(With.AuthSessionName, With.AuthSessionOptions)StartSyncCycle(With.PolicyType, AuthSession).With.Waitis$true:GetSyncCycleState(AuthSession)untilInProgress = $falseor timeoutTimeoutSeconds, last known state)8) Events
Use the standard event sink:
DirectorySyncTriggered(after trigger call returns)DirectorySyncWaiting(first poll)DirectorySyncPoll(optional, only if not too chatty; include attem...✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.