Private/Connect-InforcerGraph.ps1
|
function Connect-InforcerGraph { <# .SYNOPSIS Connects to Microsoft Graph for documentation enrichment (group name resolution etc.). .DESCRIPTION Always performs a fresh interactive sign-in to Microsoft Graph. This ensures the session is current each time the module is used. Auto-installs Microsoft.Graph.Authentication if not present. The Graph session is stored in $script:InforcerGraphConnected so Disconnect-Inforcer knows to also disconnect Graph. Based on the Connect-ToMgGraph pattern from RKSolutions-Module. #> [CmdletBinding()] param( [Parameter(Mandatory = $false)] [string[]]$RequiredScopes = @('Directory.Read.All'), [Parameter(Mandatory = $false)] [string]$TenantId ) # Ask, don't install. This used to run Install-Module -Force -AllowClobber with no consent: # -Force suppresses the untrusted-repository prompt and -AllowClobber lets it overwrite # commands belonging to other modules. A read-only reporting module has no business mutating # the machine's module state, and on a locked-down or offline host it failed with a # PowerShellGet error instead of saying what was missing. Matches how the ImportExcel # dependency is already handled in Export-InforcerDocExcel. if (-not (Get-Module -ListAvailable -Name 'Microsoft.Graph.Authentication')) { # A warning, not an error: every caller already handles a null context by falling back to # raw ObjectIDs, and Write-Error here would terminate that graceful path for anyone running # with $ErrorActionPreference = 'Stop'. The ImportExcel dependency uses Write-Error because # Excel export has no fallback - this does. Write-Warning ('Microsoft.Graph.Authentication is not installed, so Graph enrichment is unavailable. ' + 'Install it with: Install-Module Microsoft.Graph.Authentication -Scope CurrentUser') $script:InforcerGraphConnected = $false return $null } if (-not (Get-Module -Name 'Microsoft.Graph.Authentication')) { Import-Module -Name 'Microsoft.Graph.Authentication' -Force -ErrorAction Stop } # Check if already connected to the correct tenant with sufficient scopes $existingCtx = Get-MgContext -ErrorAction SilentlyContinue if ($existingCtx -and $existingCtx.Account) { $tenantMatch = [string]::IsNullOrWhiteSpace($TenantId) -or $existingCtx.TenantId -eq $TenantId $scopesMissing = @($RequiredScopes | Where-Object { $existingCtx.Scopes -notcontains $_ }) if ($tenantMatch -and $scopesMissing.Count -eq 0) { Write-Host " Reusing existing Graph session: $($existingCtx.Account) (tenant: $($existingCtx.TenantId))" -ForegroundColor Green $script:InforcerGraphConnected = $true return $existingCtx } } # Fresh sign-in needed (different tenant or missing scopes) # Disconnect existing session first to avoid double-prompt when switching tenants if ($existingCtx -and $existingCtx.Account) { Write-Verbose " Disconnecting from previous Graph session ($($existingCtx.TenantId))..." Disconnect-MgGraph -ErrorAction SilentlyContinue | Out-Null } try { $connectParams = @{ Scopes = $RequiredScopes; NoWelcome = $true } if (-not [string]::IsNullOrWhiteSpace($TenantId)) { $connectParams['TenantId'] = $TenantId Write-Host " Targeting Azure AD tenant: $TenantId" -ForegroundColor Gray } Write-Host ' Complete the sign-in in your browser (Ctrl+C to cancel)...' -ForegroundColor Gray Connect-MgGraph @connectParams -ErrorAction Stop $newContext = Get-MgContext if ($newContext) { $script:InforcerGraphConnected = $true return $newContext } throw 'Connection attempt completed but unable to confirm connection' } catch { Write-Error "Error connecting to Microsoft Graph: $_" $script:InforcerGraphConnected = $false return $null } } |