Public/Auth/Connect-DataverseEnvironment.ps1
|
function Connect-DataverseEnvironment { <# .SYNOPSIS Connects to a Dataverse environment for plugin deployment operations. .DESCRIPTION Establishes an authenticated connection to a Dataverse environment using the authentication hierarchy: 1. Explicit parameters (ConnectionString or SPN credentials) 2. Environment variables (from .env file) 3. Interactive OAuth (if -Interactive specified) .PARAMETER ConnectionString Full connection string for Dataverse. .PARAMETER EnvironmentUrl The Dataverse environment URL (e.g., https://myorg.crm.dynamics.com). .PARAMETER ClientId Azure AD application (client) ID for service principal authentication. .PARAMETER ClientSecret Client secret for service principal authentication. .PARAMETER TenantId Azure AD tenant ID. .PARAMETER EnvFile Path to .env file with credentials. .PARAMETER Interactive Use interactive browser-based OAuth login. .EXAMPLE Connect-DataverseEnvironment -EnvironmentUrl "https://myorg.crm.dynamics.com" -Interactive Connects using browser-based authentication. .EXAMPLE Connect-DataverseEnvironment -ClientId $id -ClientSecret $secret -TenantId $tenant -EnvironmentUrl $url Connects using service principal credentials. .OUTPUTS Microsoft.Xrm.Tooling.Connector.CrmServiceClient #> [CmdletBinding()] param( [Parameter()] [string]$ConnectionString, [Parameter()] [string]$EnvironmentUrl, [Parameter()] [string]$ClientId, [Parameter()] [string]$ClientSecret, [Parameter()] [string]$TenantId, [Parameter()] [string]$EnvFile, [Parameter()] [switch]$Interactive ) # Ensure module is available if (-not (Get-Module -ListAvailable -Name Microsoft.Xrm.Data.PowerShell)) { Write-LogError "Microsoft.Xrm.Data.PowerShell module not found." Write-Log "Install with: Install-Module Microsoft.Xrm.Data.PowerShell -Scope CurrentUser" throw "Required module not installed" } Import-Module Microsoft.Xrm.Data.PowerShell -ErrorAction Stop # Load environment file if specified or by default if (-not [string]::IsNullOrWhiteSpace($EnvFile)) { Import-EnvFile -Path $EnvFile | Out-Null } elseif ([string]::IsNullOrWhiteSpace($ConnectionString) -and [string]::IsNullOrWhiteSpace($ClientId)) { Import-EnvFile | Out-Null } # Build connection string using hierarchy $finalConnectionString = $null $authMethod = $null # Priority 1: Explicit connection string if (-not [string]::IsNullOrWhiteSpace($ConnectionString)) { $finalConnectionString = $ConnectionString $authMethod = "Explicit Connection String" } # Priority 2: Explicit SPN parameters elseif (-not [string]::IsNullOrWhiteSpace($ClientId) -and -not [string]::IsNullOrWhiteSpace($ClientSecret) -and -not [string]::IsNullOrWhiteSpace($TenantId)) { $url = if (-not [string]::IsNullOrWhiteSpace($EnvironmentUrl)) { $EnvironmentUrl } else { Get-EnvVar "DATAVERSE_URL" } if ([string]::IsNullOrWhiteSpace($url)) { throw "EnvironmentUrl required when using service principal parameters" } $finalConnectionString = "AuthType=ClientSecret;Url=$url;ClientId=$ClientId;ClientSecret=$ClientSecret" $authMethod = "Service Principal (Parameters)" } # Priority 3: Environment variables for SPN else { $envUrl = Get-EnvVar "DATAVERSE_URL" $envClientId = Get-EnvVar "SP_APPLICATION_ID" $envClientSecret = Get-EnvVar "SP_CLIENT_SECRET" $envTenantId = Get-EnvVar "SP_TENANT_ID" $url = if (-not [string]::IsNullOrWhiteSpace($EnvironmentUrl)) { $EnvironmentUrl } else { $envUrl } if (-not [string]::IsNullOrWhiteSpace($envClientId) -and -not [string]::IsNullOrWhiteSpace($envClientSecret) -and -not [string]::IsNullOrWhiteSpace($url)) { $finalConnectionString = "AuthType=ClientSecret;Url=$url;ClientId=$envClientId;ClientSecret=$envClientSecret" $authMethod = "Service Principal (Environment)" } # Priority 4: Interactive OAuth elseif ($Interactive) { if ([string]::IsNullOrWhiteSpace($url)) { throw "EnvironmentUrl required for interactive authentication" } $finalConnectionString = "AuthType=OAuth;Url=$url;AppId=51f81489-12ee-4a9e-aaae-a2591f45987d;RedirectUri=http://localhost;LoginPrompt=Auto" $authMethod = "Interactive OAuth" } else { Write-LogError "No authentication method available." Write-Log "Options:" Write-Log " 1. Provide -ConnectionString parameter" Write-Log " 2. Provide -ClientId, -ClientSecret, -TenantId, -EnvironmentUrl parameters" Write-Log " 3. Create .env.dev file with SP_APPLICATION_ID, SP_CLIENT_SECRET, DATAVERSE_URL" Write-Log " 4. Use -Interactive flag for browser-based login" throw "No authentication credentials available" } } # Log connection attempt (redacted) $sanitized = $finalConnectionString -replace "(ClientSecret=)[^;]+", '$1***REDACTED***' Write-Log "Auth method: $authMethod" Write-LogDebug "Connection: $sanitized" # Connect try { Write-Log "Connecting to Dataverse..." $conn = Get-CrmConnection -ConnectionString $finalConnectionString if (-not $conn -or -not $conn.IsReady) { throw "Connection failed - IsReady is false" } Write-LogSuccess "Connected to: $($conn.ConnectedOrgFriendlyName)" return $conn } catch { Write-LogError "Connection failed: $($_.Exception.Message)" throw } } |