Private/Assert-SPOInteractiveSession.ps1
|
function Assert-SPOInteractiveSession { <# .SYNOPSIS Fails fast when system-browser sign-in cannot work in this session. .DESCRIPTION System-browser auth starts a loopback listener and opens a browser on this host. Interactive sign-in is the default when only -Url is given, so a script running over SSH, on a headless Linux box or in Azure Cloud Shell would otherwise hang until the sign-in times out. This check is deliberately conservative: it only refuses when the environment shows there is no display to open a browser on. Rules: - Azure Cloud Shell (ACC_CLOUD set): refuse; no local browser exists. - A display is present (DISPLAY or WAYLAND_DISPLAY): allow. This also covers SSH with X forwarding. - No display on Linux/FreeBSD: refuse. - No display on macOS: allow for a local terminal (macOS does not set DISPLAY), refuse inside an SSH session (SSH_CONNECTION/SSH_TTY set). Platform and Environment are parameters only so the rules can be unit tested; callers use the defaults. #> [CmdletBinding()] param( [ValidateSet('Linux', 'OSX', 'FreeBSD', 'Windows')] [string]$Platform = $( if ([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform([System.Runtime.InteropServices.OSPlatform]::OSX)) { 'OSX' } elseif ([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform([System.Runtime.InteropServices.OSPlatform]::FreeBSD)) { 'FreeBSD' } elseif ([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform([System.Runtime.InteropServices.OSPlatform]::Windows)) { 'Windows' } else { 'Linux' } ), [hashtable]$Environment = $( $map = @{} foreach ($entry in Get-ChildItem Env:) { $map[$entry.Name] = $entry.Value } $map ) ) # Names of variables that are set to a non-blank value. $present = @($Environment.Keys | Where-Object { -not [string]::IsNullOrWhiteSpace([string]$Environment[$_]) }) $reason = $null if ($present -contains 'ACC_CLOUD') { $reason = 'this is an Azure Cloud Shell session (ACC_CLOUD is set), which has no local browser' } elseif (-not ($present -contains 'DISPLAY' -or $present -contains 'WAYLAND_DISPLAY')) { $overSsh = $present -contains 'SSH_CONNECTION' -or $present -contains 'SSH_TTY' -or $present -contains 'SSH_CLIENT' if ($overSsh) { $reason = 'this is an SSH session with no forwarded display (SSH_CONNECTION/SSH_TTY set, DISPLAY not set)' } elseif ($Platform -ne 'OSX') { $reason = 'no DISPLAY or WAYLAND_DISPLAY is set, so there is no desktop to open a browser on' } } if ($reason) { throw "Interactive sign-in needs a local desktop session with a browser, but $reason. Interactive sign-in is the default when only -Url is given. For unattended or remote sessions use certificate auth: -ClientId, -TenantId and -CertificatePath (or -Certificate), or -UseEnvFile." } } |