Public/Functions/Session/Connect-Me.ps1
# Module: TeamsFunctions # Function: Session # Author: David Eberhardt # Updated: 01-DEC-2020 # Status: Live #CHECK Activation of Roles via PIM / reconnect Skype if it failed before? function Connect-Me { <# .SYNOPSIS Connect to SkypeOnline and AzureActiveDirectory and optionally also to Teams and Exchange .DESCRIPTION One function to connect them all. This function solves the requirement for individual authentication prompts for SkypeOnline and AzureAD (and optionally also to MicrosoftTeams and ExchangeOnline) when multiple connections are required. For SkypeOnline, the Skype for Business Legacy Administrator Roles is required For AzureAD, no particular role is needed as GET-commands are available without a role. For MicrosoftTeams, a Teams Administrator Role is required (ideally Teams Service Administrator or Teams Communication Admin) Actual administrative capabilities are dependent on actual Office 365 admin role assignments (displayed as output) Disconnects current sessions (if found) in order to establish a clean new session to each desired service. By default SkypeOnline and AzureAD are selected (without parameters). Combine as desired, if Parameters are specified, only connections to these services are established. Available: SkypeOnline, AzureAD, MicrosoftTeams and ExchangeOnline .PARAMETER UserName Required. UserPrincipalName or LoginName of the Office365 Administrator .PARAMETER SkypeOnline Optional. Connects to SkypeOnline. Requires Office 365 Admin role Skype for Business Legacy Administrator .PARAMETER AzureAD Optional. Connects to Azure Active Directory (AAD). Requires no Office 365 Admin roles (Read-only access to AzureAD) .PARAMETER MicrosoftTeams Optional. Connects to MicrosoftTeams. Requires Office 365 Admin role for Teams, e.g. Microsoft Teams Service Administrator .PARAMETER ExchangeOnline Optional. Connects to Exchange Online Management. Requires Exchange Admin Role .PARAMETER OverrideAdminDomain Optional. Only used if managing multiple Tenants or SkypeOnPrem Hybrid configuration uses DNS records. NOTE: The OverrideAdminDomain is handled by Connect-SkypeOnline (prompts if no connection can be established) Using the Parameter here is using it explicitly .PARAMETER Silent Optional. Suppresses output session information about established sessions. Used for calls by other functions .EXAMPLE Connect-SkypeTeamsAndAAD -Username admin@domain.com Connects to SkypeOnline & AzureAD prompting ONCE for a Password for 'admin@domain.com' .EXAMPLE Connect-SkypeTeamsAndAAD -Username admin@domain.com -SkypeOnline -AzureAD -MicrosoftTeams Connects to SkypeOnline, AzureAD & MicrosoftTeams prompting ONCE for a Password for 'admin@domain.com' .EXAMPLE Connect-SkypeTeamsAndAAD -Username admin@domain.com -SkypeOnline -ExchangeOnline Connects to SkypeOnline and ExchangeOnline prompting ONCE for a Password for 'admin@domain.com' .EXAMPLE Connect-SkypeTeamsAndAAD -Username admin@domain.com -SkypeOnline -OverrideAdminDomain domain.co.uk Connects to SkypeOnline prompting ONCE for a Password for 'admin@domain.com' using the explicit OverrideAdminDomain domain.co.uk .FUNCTIONALITY Connects to one or multiple Office 365 Services with as few Authentication prompts as possible .NOTES The base command (without any ) .LINK Connect-Me Connect-SkypeOnline Connect-AzureAD Connect-MicrosoftTeams Disconnect-Me Disconnect-SkypeOnline Disconnect-AzureAD Disconnect-MicrosoftTeams #> [CmdletBinding()] [Alias('con')] param( [Parameter(Mandatory = $true, Position = 0, HelpMessage = 'UserPrincipalName, Administrative Account')] [string]$UserName, [Parameter(Mandatory = $false, HelpMessage = 'Establishes a connection to SkypeOnline. Prompts for new credentials.')] [Alias('SfBO')] [switch]$SkypeOnline, [Parameter(Mandatory = $false, HelpMessage = 'Establishes a connection to Azure AD. Reuses credentials if authenticated already.')] [Alias('AAD')] [switch]$AzureAD, [Parameter(Mandatory = $false, HelpMessage = 'Establishes a connection to MicrosoftTeams. Reuses credentials if authenticated already.')] [Alias('Teams')] [switch]$MicrosoftTeams, [Parameter(Mandatory = $false, HelpMessage = 'Establishes a connection to Exchange Online. Reuses credentials if authenticated already.')] [Alias('Exchange')] [switch]$ExchangeOnline, [Parameter(Mandatory = $false, HelpMessage = 'Domain used to connect to for SkypeOnline if DNS points to OnPrem Skype')] [AllowNull()] [string]$OverrideAdminDomain, [Parameter(Mandatory = $false, HelpMessage = 'Suppresses Session Information output')] [switch]$NoFeedback ) #param begin { Show-FunctionStatus -Level Live Write-Verbose -Message "[BEGIN ] $($MyInvocation.MyCommand)" $WarningPreference = "Continue" # Initialising counters for Progress bars [int]$step = 0 [int]$sMax = 0 # Preparing variables if ($PSBoundParameters.ContainsKey('SkypeOnline') -or $PSBoundParameters.ContainsKey('AzureAD') -or $PSBoundParameters.ContainsKey('MicrosoftTeams') -or $PSBoundParameters.ContainsKey('ExchangeOnline')) { # No parameter provided. Assuming connection to both Skype and AzureAD! $ConnectDefault = $false } else { Write-Host "No Parameters for individual Services provided. Connecting to SkypeOnline and AzureAD (default)" -ForegroundColor Cyan $ConnectDefault = $true $sMax = $sMax + 2 } if ($PSBoundParameters.ContainsKey('SkypeOnline')) { $ConnectToSkype = $true $sMax++ } if ($PSBoundParameters.ContainsKey('AzureAD')) { $ConnectToAAD = $true $sMax++ } if ($PSBoundParameters.ContainsKey('MicrosoftTeams')) { $sMax++ } if ($PSBoundParameters.ContainsKey('ExchangeOnline')) { $sMax++ } if ( -not $NoFeedback ) { $sMax = $sMax + 2 } [System.Collections.ArrayList]$ConnectedTo = @() # Cleaning up existing sessions $Status = "Preparation" $Operation = "Loading Modules; Cleaning up existing Sessions" Write-Progress -Id 0 -Status $Status -CurrentOperation $Operation -Activity $MyInvocation.MyCommand -PercentComplete ($step / $sMax * 100) Write-Verbose -Message "$Status - $Operation" -Verbose $null = (Disconnect-Me -ErrorAction SilentlyContinue) #Loading Modules $AzureAdModule, $AzureAdPreviewModule, $TeamsModule, $SkypeModule = Get-NewestModule AzureAd, AzureAdPreview, MicrosoftTeams, SkypeOnlineConnector if ( $TeamsModule.Version -ge "1.1.6" ) { # Connect-SkypeOnline will also connect to Microsoft Teams if ($PSBoundParameters.ContainsKey('MicrosoftTeams')) { [void]$PSBoundParameters.Keys.Remove('MicrosoftTeams') $sMax-- } } # Privileged Identity Management if ( $ActivateAdminRole ) { # Determining options $Command = "Get-AzureADMSPrivilegedRoleAssignment" try { $PIMavailable = Get-Command -Name $Command -ErrorAction Stop } catch { Write-Warning -Message "Command '$Command' not available. Privileged Identity Management functions cannot be executed" } } } #begin process { Write-Verbose -Message "[PROCESS] $($MyInvocation.MyCommand)" # Activating Admin Roles if ( $ActivateAdminRole -and $PIMavailable ) { } else { } #region Connections #region SkypeOnline if ($ConnectDefault -or $ConnectToSkype) { $Status = "Establishing Connection" $step++ $Operation = "SkypeOnline" Write-Progress -Id 0 -Status $Status -CurrentOperation $Operation -Activity $MyInvocation.MyCommand -PercentComplete ($step / $sMax * 100) Write-Verbose -Message "$Status to $Operation" -Verbose try { if ($PSBoundParameters.ContainsKey('OverrideAdminDomain')) { $null = (Connect-SkypeOnline -UserName $Username -OverrideAdminDomain $OverrideAdminDomain -ErrorAction STOP) } else { $null = (Connect-SkypeOnline -UserName $Username -ErrorAction STOP) } } catch { if ( -not $_.Exception.Message.Contains("does not have permission to manage this tenant") ) { Write-Host "Could not establish Connection to SkypeOnline, please verify Username, Password, OverrideAdminDomain and Session Exhaustion (2 max!)" -ForegroundColor Red Write-ErrorRecord $_ #This handles the error message in human readable format. } else { Write-Host "User does not have permission to manage this tenant. Do you need to activate your Admin Roles in Privileged Identity Management" -ForegroundColor Cyan #TODO Call Role Activation command, then call Connection again <# $ActivateRoles = $true Rework this to do the following: Activate Skype is a function Call Function, if errors, connect AzureAd, then Activate Roles with $EnabledRoles = Enable-AzureAdAdminRole -Identity $Username -PassThru Then Call Function again! try { if ($PSBoundParameters.ContainsKey('OverrideAdminDomain')) { $null = (Connect-SkypeOnline -UserName $Username -OverrideAdminDomain $OverrideAdminDomain -ErrorAction STOP) } else { $null = (Connect-SkypeOnline -UserName $Username -ErrorAction STOP) } } catch { Write-Host "Could not establish Connection to SkypeOnline, please verify Username, Password, OverrideAdminDomain and Session Exhaustion (2 max!)" -ForegroundColor Red Write-ErrorRecord $_ #This handles the error message in human readable format. } #> } } Start-Sleep 1 if (Test-SkypeOnlineConnection) { $ConnectedTo += "SkypeOnline" if ( -not $NoFeedback) { $Status = "Providing Feedback" $step++ $Operation = "Displaying Tenant Information" Write-Progress -Id 0 -Status $Status -CurrentOperation $Operation -Activity $MyInvocation.MyCommand -PercentComplete ($step / $sMax * 100) Write-Verbose -Message "$Status - $Operation" $PSSkypeOnlineSession = Get-PSSession | Where-Object { ($_.ComputerName -like "*.online.lync.com" -or $_.Computername -eq "api.interfaces.records.teams.microsoft.com") -and $_.State -eq "Opened" -and $_.Availability -eq "Available" } -WarningAction STOP -ErrorAction STOP $TenantInformation = Get-CsTenant -WarningAction SilentlyContinue -ErrorAction STOP $TenantDomain = $TenantInformation.Domains | Select-Object -Last 1 $Timeout = $PSSkypeOnlineSession.IdleTimeout / 3600000 $Environment = $PSSkypeOnlineSession.Name.split('_')[0] if (-not $Environment) { $Environment = 'SfBPowerShellSession' } $PSSkypeOnlineSessionInfo = [PSCustomObject][ordered]@{ Account = $UserName Environment = $Environment Tenant = $TenantInformation.DisplayName TenantId = $TenantInformation.TenantId TenantDomain = $TenantDomain ComputerName = $PSSkypeOnlineSession.ComputerName IdleTimeoutInHours = $Timeout TeamsUpgradeEffectiveMode = $TenantInformation.TeamsUpgradeEffectiveMode } $PSSkypeOnlineSessionInfo } } } #endregion #region AzureAD if ($ConnectDefault -or $ConnectToAAD) { $Status = "Establishing Connection" $step++ $Operation = "AzureAd" Write-Progress -Id 0 -Status $Status -CurrentOperation $Operation -Activity $MyInvocation.MyCommand -PercentComplete ($step / $sMax * 100) Write-Verbose -Message "$Status to $Operation" -Verbose try { if ( -not (Test-AzureADConnection)) { $ConnectedTo += "AzureAd" $null = (Connect-AzureAD -AccountId $Username) if ( -not $NoFeedback ) { Start-Sleep -Seconds 1 Get-AzureADCurrentSessionInfo | Format-List } } else { Write-Verbose "Already Connected to AzureAd, if reconnect is desired, please disconnect this seesion first!" -Verbose } } catch { Write-Host "Could not establish Connection to AzureAD, please verify Module and run Connect-AzureAD manually" -ForegroundColor Red } } #endregion #region MicrosoftTeams #TODO Rework/Remove: Not required if connection to Skype is established with New-CsOnlineSession with MicrosoftTeams. if ($PSBoundParameters.ContainsKey('MicrosoftTeams')) { $Status = "Establishing Connection" $step++ $Operation = "MicrosoftTeams" Write-Progress -Id 0 -Status $Status -CurrentOperation $Operation -Activity $MyInvocation.MyCommand -PercentComplete ($step / $sMax * 100) Write-Verbose -Message "$Status to $Operation" -Verbose try { if ( -not (Test-Module MicrosoftTeams)) { Import-Module MicrosoftTeams -Force -ErrorAction SilentlyContinue } if ( -not (Test-MicrosoftTeamsConnection)) { if ( -not $NoFeedback ) { Connect-MicrosoftTeams -AccountId $Username } else { $null = (Connect-MicrosoftTeams -AccountId $Username) } } else { Write-Verbose "Already Connected to MicrosoftTeams, if reconnect is desired, please disconnect this seesion first!" -Verbose } } catch { Write-Host "Could not establish Connection to MicrosoftTeams, please verify Module and run Connect-MicrosoftTeams manually" -ForegroundColor Red } } if (Test-MicrosoftTeamsConnection) { $ConnectedTo += "Microsoft Teams" } #endregion #region ExchangeOnline if ($PSBoundParameters.ContainsKey('ExchangeOnline')) { $Status = "Establishing Connection" $step++ $Operation = "ExchangeOnline" Write-Progress -Id 0 -Status $Status -CurrentOperation $Operation -Activity $MyInvocation.MyCommand -PercentComplete ($step / $sMax * 100) Write-Verbose -Message "$Status to $Operation" -Verbose try { if ( -not (Test-Module ExchangeOnlineManagement)) { Import-Module ExchangeOnlineManagement -Force -ErrorAction SilentlyContinue } if ( -not (Test-ExchangeOnlineConnection)) { if ( -not $NoFeedback) { Connect-ExchangeOnline -UserPrincipalName $Username -ShowProgress:$true -ShowBanner:$false } else { $null = (Connect-ExchangeOnline -UserPrincipalName $Username -ShowProgress:$true -ShowBanner:$false) } } else { Write-Verbose "Already Connected to ExchangeOnlineManagement, if reconnect is desired, please disconnect this seesion first!" -Verbose } } catch { Write-Host "Could not establish Connection to ExchangeOnlineManagement, please verify Module and run Connect-ExchangeOnline manually" -ForegroundColor Red } } if (Test-ExchangeOnlineConnection) { $ConnectedTo += "Exchange" } #endregion #endregion #region Display Admin Roles if ( ("AzureAd" -in $ConnectedTo) -and -not $NoFeedback ) { $Status = "Providing Feedback" $step++ $Operation = "Querying assigned Admin Roles" Write-Progress -Id 0 -Status $Status -CurrentOperation $Operation -Activity $MyInvocation.MyCommand -PercentComplete ($step / $sMax * 100) Write-Verbose -Message "$Status - $Operation" #Get-AzureAdAssignedAdminRoles (Get-AzureADCurrentSessionInfo).Account | Select-Object DisplayName, Description | Format-Table -AutoSize $Roles = $(Get-AzureAdAssignedAdminRoles (Get-AzureADCurrentSessionInfo).Account).DisplayName Write-Host "Assigned Admin Roles for '$Username'" -ForegroundColor Magenta Write-Host "" Write-Host "$($Roles -join ', ')" Write-Progress -Id 0 -Status $Status -CurrentOperation $Operation -Activity $MyInvocation.MyCommand -PercentComplete ($step / $sMax * 100) } #endregion Write-Progress -Id 0 -Status "Complete" -Activity $MyInvocation.MyCommand -Completed #Output Write-Host "$(Get-Date -Format 'dd MMM yyyy HH:mm') | Connected to: " -ForegroundColor Green -NoNewline Write-Host "$($ConnectedTo -join ', ')" } #process end { Write-Verbose -Message "[END ] $($MyInvocation.MyCommand)" } #end } #Connect-Me |