Modules/IdLE.Provider.DirectorySync.EntraConnect/Public/New-IdleEntraConnectDirectorySyncProvider.ps1
|
function New-IdleEntraConnectDirectorySyncProvider { <# .SYNOPSIS Creates an Entra Connect directory sync provider for IdLE. .DESCRIPTION This provider triggers and monitors Entra ID Connect (ADSync) sync cycles on an on-premises server via remote execution. The provider uses an AuthSession object (remote execution handle) provided by the host. The AuthSession must implement InvokeCommand(CommandName, Parameters) to execute commands in an elevated/privileged context on the Entra Connect server. No interactive prompts are made; elevation and authentication are the host's responsibility via the AuthSessionBroker. .OUTPUTS PSCustomObject Provider instance with methods: GetCapabilities(), StartSyncCycle(PolicyType, AuthSession), GetSyncCycleState(AuthSession) .EXAMPLE $provider = New-IdleEntraConnectDirectorySyncProvider $provider.GetCapabilities() # Returns: @('IdLE.DirectorySync.Trigger', 'IdLE.DirectorySync.Status') .EXAMPLE # With a mock remote execution handle $mockAuthSession = [pscustomobject]@{ InvokeCommand = { param($CommandName, $Parameters) # Mock implementation return @{ Started = $true } } } $provider = New-IdleEntraConnectDirectorySyncProvider $result = $provider.StartSyncCycle('Delta', $mockAuthSession) #> [CmdletBinding()] param() $provider = [pscustomobject]@{ PSTypeName = 'IdLE.Provider.EntraConnectDirectorySync' Name = 'EntraConnectDirectorySyncProvider' } $provider | Add-Member -MemberType ScriptMethod -Name GetCapabilities -Value { <# .SYNOPSIS Advertises the capabilities provided by this provider instance. .DESCRIPTION Capabilities are stable string identifiers used by IdLE to validate that a workflow plan can be executed with the available providers. #> return @( 'IdLE.DirectorySync.Trigger' 'IdLE.DirectorySync.Status' ) } -Force $provider | Add-Member -MemberType ScriptMethod -Name StartSyncCycle -Value { <# .SYNOPSIS Triggers an Entra Connect sync cycle. .DESCRIPTION Triggers a sync cycle via Start-ADSyncSyncCycle on the remote Entra Connect server. .PARAMETER PolicyType The sync policy type: 'Delta' or 'Initial'. .PARAMETER AuthSession Remote execution handle provided by the host's AuthSessionBroker. Must implement InvokeCommand(CommandName, Parameters). .OUTPUTS PSCustomObject with properties: - Started (bool): indicates whether the sync cycle was triggered - Message (string, optional): additional information #> param( [Parameter(Mandatory)] [ValidateSet('Delta', 'Initial', IgnoreCase = $true)] [string] $PolicyType, [Parameter(Mandatory)] [ValidateNotNull()] [object] $AuthSession ) # Validate AuthSession contract if ($null -eq $AuthSession.PSObject.Methods['InvokeCommand']) { throw "AuthSession must implement InvokeCommand(CommandName, Parameters) method. " + ` "The host must provide an elevated remote session via AuthSessionBroker." } try { # Execute Start-ADSyncSyncCycle remotely # The remote session should already have ADSync module available or will import it $AuthSession.InvokeCommand('Start-ADSyncSyncCycle', @{ PolicyType = $PolicyType }) | Out-Null # Start-ADSyncSyncCycle returns a result object or throws on error # Success case: return Started = true return [pscustomobject]@{ Started = $true Message = "Sync cycle triggered with PolicyType: $PolicyType" } } catch { # Check for common privilege/elevation errors $errorMessage = $_.Exception.Message if ($errorMessage -match 'access.*denied|permission|privilege|elevation|administrator|unauthorized') { throw "Failed to start sync cycle. Missing privileges or elevation. " + ` "The AuthSession must provide an elevated execution context. Original error: $errorMessage" } # Re-throw other errors throw "Failed to start sync cycle: $errorMessage" } } -Force $provider | Add-Member -MemberType ScriptMethod -Name GetSyncCycleState -Value { <# .SYNOPSIS Retrieves the current state of Entra Connect sync cycles. .DESCRIPTION Queries the sync scheduler state via Get-ADSyncScheduler to determine if a sync cycle is currently in progress. .PARAMETER AuthSession Remote execution handle provided by the host's AuthSessionBroker. Must implement InvokeCommand(CommandName, Parameters). .OUTPUTS PSCustomObject with properties: - InProgress (bool): indicates whether a sync cycle is currently running - State (string): 'InProgress', 'Idle', or 'Unknown' - Details (hashtable, optional): additional state information #> param( [Parameter(Mandatory)] [ValidateNotNull()] [object] $AuthSession ) # Validate AuthSession contract if ($null -eq $AuthSession.PSObject.Methods['InvokeCommand']) { throw "AuthSession must implement InvokeCommand(CommandName, Parameters) method. " + ` "The host must provide an elevated remote session via AuthSessionBroker." } try { # Execute Get-ADSyncScheduler remotely $scheduler = $AuthSession.InvokeCommand('Get-ADSyncScheduler', @{}) # Determine if sync is in progress # Get-ADSyncScheduler returns an object with SyncCycleInProgress property $inProgress = $false $state = 'Unknown' $details = @{} if ($null -ne $scheduler) { # Extract relevant properties if ($scheduler.PSObject.Properties.Name -contains 'SyncCycleInProgress') { $inProgress = [bool]$scheduler.SyncCycleInProgress $state = if ($inProgress) { 'InProgress' } else { 'Idle' } } # Capture additional details for diagnostics if ($scheduler.PSObject.Properties.Name -contains 'AllowedSyncCycleInterval') { $details['AllowedSyncCycleInterval'] = $scheduler.AllowedSyncCycleInterval } if ($scheduler.PSObject.Properties.Name -contains 'NextSyncCyclePolicyType') { $details['NextSyncCyclePolicyType'] = $scheduler.NextSyncCyclePolicyType } } return [pscustomobject]@{ InProgress = $inProgress State = $state Details = $details } } catch { $errorMessage = $_.Exception.Message if ($errorMessage -match 'access.*denied|permission|privilege|elevation|administrator|unauthorized') { throw "Failed to get sync cycle state. Missing privileges or elevation. " + ` "The AuthSession must provide an elevated execution context. Original error: $errorMessage" } throw "Failed to get sync cycle state: $errorMessage" } } -Force return $provider } |