Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added M365 connections to shared #2090

Open
wants to merge 22 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
150 changes: 150 additions & 0 deletions Shared/M365/EXOConnection.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

<#
.SYNOPSIS
This script defines a function `Connect-EXOAdvanced` that establishes a connection to Exchange Online.
It ensures that the required ExchangeOnlineManagement module (version 3.0.0 or higher by default) is installed and loaded.
The function supports single and multiple session connections, with optional parameters to control the connection details display and session prefix.
If the required module is not found, the script attempts to install it.
The function returns the connection information or null if the connection fails.

.PARAMETER DoNotShowConnectionDetails
Optional switch to hide connection details.
.PARAMETER AllowMultipleSessions
Optional switch to allow multiple sessions.
.PARAMETER Prefix
Optional string to specify a prefix for the session.
.PARAMETER MinModuleVersion
Optional parameter to specify the minimum version of the ExchangeOnlineManagement module (default and minimum supported version is 3.0.0).

.OUTPUTS
Microsoft.Exchange.Management.ExoPowershellSnapin.ConnectionInformation. The connection information object for the Exchange Online session.

.EXAMPLE
$exoConnection = Connect-EXOAdvanced
This example establishes a connection to Exchange Online using the default settings.

.EXAMPLE
$exoConnection = Connect-EXOAdvanced -AllowMultipleSessions
This example establishes a connection to Exchange Online and allows multiple sessions.

.EXAMPLE
$exoConnection = Connect-EXOAdvanced -AllowMultipleSessions -Prefix Con2
This example establishes a connection to Exchange Online, allows multiple sessions, and specifies a prefix "Con2" for the session.

.EXAMPLE
$exoConnection2 = Connect-EXOAdvanced -minModuleVersion 3.5.0
This example establishes a connection to Exchange Online and specifies a minimum module version of 3.5.0.
#>

. $PSScriptRoot\..\ModuleHandle.ps1

iserrano76 marked this conversation as resolved.
Show resolved Hide resolved
function Connect-EXOAdvanced {
[CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = "High")]
param (
[Parameter(Mandatory = $false, ParameterSetName = 'SingleSession')]
[Parameter(Mandatory = $false, ParameterSetName = 'AllowMultipleSessions')]
[switch]$DoNotShowConnectionDetails,
[Parameter(Mandatory = $true, ParameterSetName = 'AllowMultipleSessions')]
[switch]$AllowMultipleSessions,
[Parameter(Mandatory = $false, ParameterSetName = 'AllowMultipleSessions')]
[string]$Prefix = $null,
[ValidateScript({
if ($_ -lt [System.Version]'3.0.0.0') {
throw "Minimum supported version: 3.0.0.0"
}
$true
})]
[Parameter(Mandatory = $false, ParameterSetName = 'SingleSession')]
[Parameter(Mandatory = $false, ParameterSetName = 'AllowMultipleSessions')]
[System.Version]$MinModuleVersion = '3.0.0.0'
)

#Validate EXO 3.0 is installed and loaded
$requestModule = Request-Module -Modules "ExchangeOnlineManagement" -MinModuleVersion $MinModuleVersion

if (-not $requestModule) {
Write-Host "We cannot continue without ExchangeOnlineManagement Powershell module" -ForegroundColor Red
return $null
}

#Validate EXO is connected or try to connect
$connections = $null
$newConnection = $null
try {
$connections = Get-ConnectionInformation -ErrorAction Stop | Where-Object { $_.State -eq 'Connected' }
} catch {
Write-Host "We cannot check connections. Error:`n$_" -ForegroundColor Red
return $null
}

if ($null -eq $connections -or $AllowMultipleSessions) {
if ($connections.ModulePrefix -contains $Prefix) {
Write-Host "You already have a session" -ForegroundColor Yellow -NoNewline
if ($Prefix) {
Write-Host " with the prefix $Prefix." -ForegroundColor Yellow
} else {
Write-Host " without prefix." -ForegroundColor Yellow
}
$newConnection = $connections | Where-Object { $_.ModulePrefix -eq $Prefix }
} else {
$prefixString = "."
if ($Prefix) { $prefixString = " with Prefix $Prefix." }
Write-Host "Not connected to Exchange Online$prefixString" -ForegroundColor Yellow

if ($PSCmdlet.ShouldProcess("Do you want to add it?", "Adding an Exchange Online Session")) {
Write-Verbose "Connecting to Exchange Online session"
try {
Connect-ExchangeOnline -ShowBanner:$false -Prefix $Prefix -ErrorAction Stop
} catch {
Write-Host "We cannot connect to Exchange Online. Error:`n$_" -ForegroundColor Red
return $null
}
try {
$newConnections = Get-ConnectionInformation -ErrorAction Stop
} catch {
Write-Host "We cannot check connections. Error:`n$_" -ForegroundColor Red
return $null
}
foreach ($testConnection in $newConnections) {
if ($connections -notcontains $testConnection) {
$newConnection = $testConnection
}
dpaulson45 marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
if ($newConnection.count -gt 1) {
Write-Host "You have more than one Exchange Online sessions with Prefix $Prefix." -ForegroundColor Red
return $null
}
} else {
Write-Verbose "You already have an Exchange Online session"
if ($connections.count -gt 1) {
Write-Host "You have more than one Exchange Online sessions please use just one session. You are not using AllowMultipleSessions" -ForegroundColor Red
return $null
}
$newConnection = $connections
}

Write-Verbose "Connected session to Exchange Online"
$newConnection.PSObject.Properties | ForEach-Object { Write-Verbose "$($_.Name): $($_.Value)" }
if (-not $DoNotShowConnectionDetails) {
Show-EXOConnection -Connection $newConnection
}
return $newConnection
dpaulson45 marked this conversation as resolved.
Show resolved Hide resolved
}

function Show-EXOConnection {
param (
[Parameter(Mandatory = $true)]
[Microsoft.Exchange.Management.ExoPowershellSnapin.ConnectionInformation]$Connection
dpaulson45 marked this conversation as resolved.
Show resolved Hide resolved
)
Write-Host "`nConnected to Exchange Online"
Write-Host "Session details"
Write-Host "Tenant Id: $($Connection.TenantId)"
Write-Host "User: $($Connection.UserPrincipalName)"
if ($($Connection.ModulePrefix)) {
Write-Host "Prefix: $($Connection.ModulePrefix)"
}
}
180 changes: 180 additions & 0 deletions Shared/M365/GraphConnection.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

<#
.SYNOPSIS
This script defines a function `Connect-GraphAdvanced` that establishes a connection to Microsoft Graph.
It ensures that the required modules are installed and loaded.
The function accepts a list of scopes and modules, with optional parameters for tenant ID and connection details display.
If the required modules are not found, the script attempts to install them.
The function returns the connection information or null if the connection fails.

.PARAMETER Scopes
Mandatory array of strings specifying the scopes for the connection.
.PARAMETER Modules
Mandatory array of strings specifying the modules required for the connection.
.PARAMETER TenantId
Optional array of strings specifying the tenant ID(s) for the connection.
.PARAMETER DoNotShowConnectionDetails
Optional switch to hide connection details.
.PARAMETER MinModuleVersion
Optional parameter to specify the minimum version of the Graph modules (default and minimum supported version 2.0.0).

.OUTPUTS
Microsoft.Graph.PowerShell.Authentication.AuthContext. The connection information object for the Microsoft Graph session.

.EXAMPLE
$graphConnection = Connect-GraphAdvanced -Scopes User.Read, Mail.Read -Modules Microsoft.Graph
This example establishes a connection to Microsoft Graph with the scopes "User.Read" and "Mail.Read" using the "Microsoft.Graph" module.

.EXAMPLE
$graphConnection = Connect-GraphAdvanced -Scopes Group.Read.All, User.Read.All -Modules Microsoft.Graph.Users, Microsoft.Graph.Groups
This example establishes a connection to Microsoft Graph with the scopes "Group.Read.All" and "User.Read.All" using the "Microsoft.Graph.Users" and "Microsoft.Graph.Groups" modules.

.EXAMPLE
$graphConnection = Connect-GraphAdvanced -Scopes Group.Read.All, User.Read.All -Modules Microsoft.Graph.Users, Microsoft.Graph.Groups -minModuleVersion 2.25.0
This example establishes a connection to Microsoft Graph with the scopes "Group.Read.All" and "User.Read.All" using the "Microsoft.Graph.Users" and "Microsoft.Graph.Groups" modules, and specifies a minimum module version of 2.25.0.
#>

. $PSScriptRoot\..\ModuleHandle.ps1

iserrano76 marked this conversation as resolved.
Show resolved Hide resolved
function Connect-GraphAdvanced {
param (
[Parameter(Mandatory = $true)]
[string[]]$Scopes,
[Parameter(Mandatory = $true)]
[string[]]$Modules,
[Parameter(Mandatory = $false)]
[string[]]$TenantId = $null,
[Parameter(Mandatory = $false)]
[switch]$DoNotShowConnectionDetails,
[ValidateScript({
if ($_ -lt [System.Version]'2.0.0.0') {
throw "Minimum supported version: 2.0.0.0"
}
$true
})]
[Parameter(Mandatory = $false)]
[System.Version]$MinModuleVersion = '2.0.0.0'
)

#Validate Graph is installed and loaded
$requestModule = Request-Module -Modules $Modules -MinModuleVersion $MinModuleVersion
if (-not $requestModule) {
Write-Host "We cannot continue without $Modules Powershell module" -ForegroundColor Red
return $null
}

#Validate Graph is connected or try to connect
$connection = $null
try {
$connection = Get-MgContext -ErrorAction Stop
} catch {
Write-Host "We cannot check context. Error:`n$_" -ForegroundColor Red
return $null
}

if ($null -eq $connection) {
Write-Host "Not connected to Graph" -ForegroundColor Yellow
$connection = Add-GraphConnection -Scopes $Scopes
} else {
Write-Verbose "You have a Graph sessions"
Write-Verbose "Checking scopes"
if (-not (Test-GraphScopeContext -Scopes $connection.Scopes -ExpectedScopes $Scopes)) {
Write-Host "Not connected to Graph with expected scopes" -ForegroundColor Yellow
$connection = Add-GraphConnection -Scopes $Scopes
} else {
Write-Verbose "All scopes are present"
}
}

if ($connection) {
Write-Verbose "Checking TenantId"
if ($TenantId) {
if ($connection.TenantId -ne $TenantId) {
Write-Host "Connected to $($connection.TenantId). Not expected tenant: $TenantId" -ForegroundColor Red
return $null
} else {
Write-Verbose "TenantId is correct"
}
}

$connection.PSObject.Properties | ForEach-Object { Write-Verbose "$($_.Name): $($_.Value)" }
if (-not $DoNotShowConnectionDetails) {
Show-GraphContext -Context $connection
}
}
return $connection
}

function Add-GraphConnection {
[CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = "High")]
param (
[Parameter(Mandatory = $true)]
[string[]]$Scopes
)

if ($PSCmdlet.ShouldProcess("Do you want to connect?", "We need a Graph connection with scopes $Scopes")) {
Write-Verbose "Connecting to Microsoft Graph API using scopes $Scopes"
try {
Connect-MgGraph -Scopes $Scopes -NoWelcome -ErrorAction Stop
} catch {
Write-Host "We cannot connect to Graph. Error:`n$_" -ForegroundColor Red
return $null
}
$connection = $null
try {
$connection = Get-MgContext -ErrorAction Stop
} catch {
Write-Host "We cannot check context. Error:`n$_" -ForegroundColor Red
return $null
}
Write-Verbose "Checking scopes"
if (-not $connection) {
Write-Host "We cannot continue without Graph Powershell session" -ForegroundColor Red
return $null
}
if (-not (Test-GraphScopeContext -Scopes $connection.Scopes -ExpectedScopes $Scopes)) {
Write-Host "We cannot continue without Graph Powershell session without Expected Scopes" -ForegroundColor Red
return $null
}
return $connection
}
}

function Test-GraphScopeContext {
[OutputType([bool])]
param (
[Parameter(Mandatory = $true)]
[string[]]$ExpectedScopes,
[Parameter(Mandatory = $true)]
[string[]]$Scopes
)

$foundError = $false
foreach ($expectedScope in $ExpectedScopes) {
if ($Scopes -notcontains $expectedScope) {
Write-Host "The following scope is missing: $expectedScope" -ForegroundColor Red
$foundError = $true
}
}

Write-Verbose "All expected scopes are $(if($foundError){ "NOT "})present."
return (-not $foundError)
}

function Show-GraphContext {
param (
[Parameter(Mandatory = $true)]
[Microsoft.Graph.PowerShell.Authentication.AuthContext]$Context
)
Write-Host "`nConnected to Graph"
Write-Host "Session details"
Write-Host "Tenant Id: $($Context.TenantId)"
if ($graphConnection.AuthType) {
Write-Host "AuthType: $($graphConnection.AuthType)"
}
if ($Context.Account) {
Write-Host "Account: $($Context.Account)"
}
}
Loading