Public/Connect-NLBaselineCA.ps1
|
function Connect-NLBaselineCA { <# .SYNOPSIS Connect to Microsoft 365 Graph API using App Registration .DESCRIPTION Authenticates with Microsoft 365 Graph API using App Registration credentials .EXAMPLE Connect-NLBaselineCA #> [CmdletBinding()] param() try { Write-Host "Connecting to Microsoft 365 using App Registration..." -ForegroundColor Yellow Write-Host "" # Get storage path from module config $moduleConfigPath = Get-ConfigPath if (-not (Test-Path $moduleConfigPath)) { Write-Error "Module configuration not found. Run Quick Start first." return $null } $moduleConfig = Get-Content $moduleConfigPath | ConvertFrom-Json $storagePath = $moduleConfig.StoragePath if (-not (Test-Path $storagePath)) { Write-Error "Storage path not found: $storagePath. Run Quick Start to configure." return $null } # Get config.json from storage path $configPath = Join-Path $storagePath "config.json" if (-not (Test-Path $configPath)) { Write-Error "Configuration file not found: $configPath. Run Quick Start to configure." return $null } $config = Get-Content $configPath | ConvertFrom-Json # Validate required fields if ([string]::IsNullOrWhiteSpace($config.TenantId)) { Write-Error "Tenant ID not configured. Run Quick Start to configure." return $null } if ([string]::IsNullOrWhiteSpace($config.ClientId)) { Write-Error "Client ID not configured. Run Quick Start to configure." return $null } if ([string]::IsNullOrWhiteSpace($config.ClientSecret)) { Write-Error "Client Secret not configured. Run Quick Start to configure." return $null } # Check if cmdlets are already available - this is the key! $hasConnectMgGraph = Get-Command Connect-MgGraph -ErrorAction SilentlyContinue $hasGetMgPolicy = Get-Command Get-MgIdentityConditionalAccessPolicy -ErrorAction SilentlyContinue if ($hasConnectMgGraph -and $hasGetMgPolicy) { Write-Host "Microsoft Graph cmdlets already available" -ForegroundColor Gray } else { Write-Host "Loading Microsoft Graph modules..." -ForegroundColor Yellow # Ensure modules are installed $requiredModules = @('Microsoft.Graph.Authentication', 'Microsoft.Graph.Identity.SignIns') foreach ($module in $requiredModules) { if (-not (Get-Module -ListAvailable -Name $module)) { Write-Host "Installing $module..." -ForegroundColor Yellow Install-Module -Name $module -Scope CurrentUser -Force -AllowClobber -ErrorAction Stop } } # Try importing - if it fails due to assembly conflict, check if cmdlets work anyway if (-not $hasConnectMgGraph) { try { Import-Module Microsoft.Graph.Authentication -Force -ErrorAction Stop $hasConnectMgGraph = Get-Command Connect-MgGraph -ErrorAction SilentlyContinue } catch { # Assembly conflict - but check if cmdlet works anyway Start-Sleep -Milliseconds 200 $hasConnectMgGraph = Get-Command Connect-MgGraph -ErrorAction SilentlyContinue if ($hasConnectMgGraph) { Write-Host "Using existing Microsoft.Graph.Authentication (assembly conflict resolved)" -ForegroundColor Gray } else { Write-Warning "Could not import Microsoft.Graph.Authentication: $_" Write-Host "Attempting to use cmdlets from loaded assemblies..." -ForegroundColor Yellow # Try to find and use the cmdlet from loaded assemblies $allCommands = Get-Command -ErrorAction SilentlyContinue | Where-Object { $_.Name -eq 'Connect-MgGraph' } if ($allCommands) { $hasConnectMgGraph = $allCommands[0] Write-Host "Found Connect-MgGraph in loaded assemblies" -ForegroundColor Gray } } } } if (-not $hasGetMgPolicy) { try { Import-Module Microsoft.Graph.Identity.SignIns -Force -ErrorAction Stop $hasGetMgPolicy = Get-Command Get-MgIdentityConditionalAccessPolicy -ErrorAction SilentlyContinue } catch { # Assembly conflict - but check if cmdlet works anyway Start-Sleep -Milliseconds 200 $hasGetMgPolicy = Get-Command Get-MgIdentityConditionalAccessPolicy -ErrorAction SilentlyContinue if ($hasGetMgPolicy) { Write-Host "Using existing Microsoft.Graph.Identity.SignIns (assembly conflict resolved)" -ForegroundColor Gray } else { Write-Warning "Could not import Microsoft.Graph.Identity.SignIns: $_" Write-Host "Attempting to use cmdlets from loaded assemblies..." -ForegroundColor Yellow # Try to find and use the cmdlet from loaded assemblies $allCommands = Get-Command -ErrorAction SilentlyContinue | Where-Object { $_.Name -eq 'Get-MgIdentityConditionalAccessPolicy' } if ($allCommands) { $hasGetMgPolicy = $allCommands[0] Write-Host "Found Get-MgIdentityConditionalAccessPolicy in loaded assemblies" -ForegroundColor Gray } } } } # Final check - if still not available, we need to fail gracefully if (-not $hasConnectMgGraph) { Write-Error "Connect-MgGraph cmdlet is not available." Write-Host "Please restart PowerShell session to resolve assembly conflicts." -ForegroundColor Yellow return $null } if (-not $hasGetMgPolicy) { Write-Error "Get-MgIdentityConditionalAccessPolicy cmdlet is not available." Write-Host "Please restart PowerShell session to resolve assembly conflicts." -ForegroundColor Yellow return $null } } # Connect using App Registration Write-Host "Connecting to tenant: $($config.TenantId)" -ForegroundColor Gray Write-Host "Using App Registration: $($config.ClientId)" -ForegroundColor Gray Write-Host "" # Connect using client credentials # Connect-MgGraph requires ClientSecretCredential (PSCredential object) $secureSecret = ConvertTo-SecureString $config.ClientSecret -AsPlainText -Force $clientSecretCredential = New-Object System.Management.Automation.PSCredential($config.ClientId, $secureSecret) try { # Connect-MgGraph doesn't return a value, it sets the context Connect-MgGraph ` -TenantId $config.TenantId ` -ClientSecretCredential $clientSecretCredential ` -NoWelcome ` -ErrorAction Stop # Verify connection by checking context Start-Sleep -Milliseconds 500 $context = Get-MgContext -ErrorAction Stop if ($context -and $context.TenantId) { Write-Host "" Write-Host "========================================" -ForegroundColor Green Write-Host " Successfully Connected!" -ForegroundColor Green Write-Host "========================================" -ForegroundColor Green Write-Host "Tenant: $($context.TenantId)" -ForegroundColor White Write-Host "App ID: $($config.ClientId)" -ForegroundColor White if ($context.Scopes) { Write-Host "Scopes: $($context.Scopes -join ', ')" -ForegroundColor White } Write-Host "========================================" -ForegroundColor Green Write-Host "" $script:ModuleConfig.GraphConnection = $context return $context } else { throw "Connection established but context is invalid" } } catch { throw "Failed to connect: $_" } } catch { Write-Error "Error connecting to Microsoft 365: $_" Write-Host "" Write-Host "Troubleshooting:" -ForegroundColor Yellow Write-Host "1. Verify your App Registration has the required API permissions:" -ForegroundColor Gray Write-Host " - Policy.Read.All" -ForegroundColor Gray Write-Host " - Policy.ReadWrite.ConditionalAccess" -ForegroundColor Gray Write-Host " - Directory.Read.All" -ForegroundColor Gray Write-Host "2. Make sure admin consent is granted for the permissions" -ForegroundColor Gray Write-Host "3. Verify the Client Secret is correct and not expired" -ForegroundColor Gray Write-Host "4. Check your Tenant ID and Client ID are correct" -ForegroundColor Gray Write-Host "5. If assembly conflicts persist, restart PowerShell session" -ForegroundColor Gray return $null } } |