Public/Functions/ResourceAccount/Get-TeamsResourceAccount.ps1
# Module: TeamsFunctions # Function: ResourceAccount # Author: David Eberhardt # Updated: 01-OCT-2020 # Status: PreLive function Get-TeamsResourceAccount { <# .SYNOPSIS Returns Resource Accounts from AzureAD .DESCRIPTION Returns one or more Resource Accounts based on input. This runs Get-CsOnlineApplicationInstance but reformats the Output with friendly names .PARAMETER Identity Required. Positional. One or more UserPrincipalNames to be queried. .PARAMETER DisplayName Optional. Search parameter. Alternative to Find-TeamsResourceAccount .PARAMETER ApplicationType Optional. Returns all Call Queues or AutoAttendants .PARAMETER PhoneNumber Optional. Returns all ResourceAccount with a specific string in the PhoneNumber .EXAMPLE Get-TeamsResourceAccount Returns all Resource Accounts. NOTE: Depending on size of the Tenant, this might take a while. .EXAMPLE Get-TeamsResourceAccount -Identity ResourceAccount@TenantName.onmicrosoft.com Returns the Resource Account with the Identity specified, if found. .EXAMPLE Get-TeamsResourceAccount -DisplayName "Queue" Returns all Resource Accounts with "Queue" as part of their Display Name. Use Find-TeamsResourceAccount / Find-CsOnlineApplicationInstance for finer search .EXAMPLE Get-TeamsResourceAccount -ApplicationType AutoAttendant Returns all Resource Accounts of the specified ApplicationType. .EXAMPLE Get-TeamsResourceAccount -PhoneNumber +1555123456 Returns the Resource Account with the Phone Number specified, if found. .INPUTS System.String .OUTPUTS System.Object .NOTES CmdLet currently in testing. Pipeline input possible, though untested. Requires figuring out :) Please feed back any issues to david.eberhardt@outlook.com .FUNCTIONALITY Returns one or more Resource Accounts .LINK Get-TeamsResourceAccountAssociation New-TeamsResourceAccountAssociation Remove-TeamsResourceAccountAssociation New-TeamsResourceAccount Get-TeamsResourceAccount Find-TeamsResourceAccount Set-TeamsResourceAccount Remove-TeamsResourceAccount #> [CmdletBinding(DefaultParameterSetName = "Identity")] [Alias('Get-TeamsRA')] [OutputType([System.Object])] param ( [Parameter(ParameterSetName = "Identity", Position = 0, ValueFromPipelineByPropertyName = $true, HelpMessage = "User Principal Name of the Object.")] [Alias("UPN", "UserPrincipalName")] [string[]]$Identity, [Parameter(ParameterSetName = "DisplayName", Position = 0, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, HelpMessage = "Searches for AzureAD Object with this Name")] [ValidateLength(3, 255)] [string]$DisplayName, [Parameter(ParameterSetName = "AppType", HelpMessage = "Limits search to specific Types: CallQueue or AutoAttendant")] [ValidateSet("CallQueue", "AutoAttendant", "CQ", "AA")] [Alias("Type")] [string]$ApplicationType, [Parameter(ParameterSetName = "Number", ValueFromPipelineByPropertyName = $true, HelpMessage = "Telephone Number of the Object")] [ValidateLength(3, 16)] [Alias("Tel", "Number", "TelephoneNumber")] [string]$PhoneNumber ) #param begin { Show-FunctionStatus -Level PreLive Write-Verbose -Message "[BEGIN ] $($MyInvocation.MyCommand)" # Asserting AzureAD Connection if (-not (Assert-AzureADConnection)) { break } # Asserting SkypeOnline Connection if (-not (Assert-SkypeOnlineConnection)) { break } # Setting Preference Variables according to Upstream settings if (-not $PSBoundParameters.ContainsKey('Verbose')) { $VerbosePreference = $PSCmdlet.SessionState.PSVariable.GetValue('VerbosePreference') } if (-not $PSBoundParameters.ContainsKey('Confirm')) { $ConfirmPreference = $PSCmdlet.SessionState.PSVariable.GetValue('ConfirmPreference') } if (-not $PSBoundParameters.ContainsKey('WhatIf')) { $WhatIfPreference = $PSCmdlet.SessionState.PSVariable.GetValue('WhatIfPreference') } # Loading all Microsoft Telephone Numbers Write-Verbose -Message "Gathering Phone Numbers from the Tenant" $MSTelephoneNumbers = Get-CsOnlineTelephoneNumber -WarningAction SilentlyContinue } #begin process { Write-Verbose -Message "[PROCESS] $($MyInvocation.MyCommand)" $ResourceAccounts = $null #region Data gathering if ($PSBoundParameters.ContainsKey('Identity')) { # Default Parameterset [System.Collections.ArrayList]$ResourceAccounts = @() foreach ($I in $Identity) { Write-Verbose -Message "Querying Resource Account with UserPrincipalName '$I'" try { $RA = Get-CsOnlineApplicationInstance -Identity $I -ErrorAction Stop [void]$ResourceAccounts.Add($RA) } catch { Write-Verbose -Message "Not found: '$I'" -Verbose } } } elseif ($PSBoundParameters.ContainsKey('DisplayName')) { # Minimum Character length is 3 Write-Verbose -Message "DisplayName - Searching for Accounts with DisplayName '$DisplayName'" $ResourceAccounts = Get-CsOnlineApplicationInstance -WarningAction SilentlyContinue | Where-Object -Property DisplayName -Like -Value "*$DisplayName*" } elseif ($PSBoundParameters.ContainsKey('ApplicationType')) { Write-Verbose -Message "ApplicationType - Searching for Accounts with ApplicationType '$ApplicationType'" $AppId = GetAppIdFromApplicationType $ApplicationType $ResourceAccounts = Get-CsOnlineApplicationInstance -WarningAction SilentlyContinue | Where-Object -Property ApplicationId -EQ -Value $AppId } elseif ($PSBoundParameters.ContainsKey('PhoneNumber')) { Write-Verbose -Message "PhoneNumber - Searching for PhoneNumber '$PhoneNumber'" $ResourceAccounts = Get-CsOnlineApplicationInstance -WarningAction SilentlyContinue | Where-Object -Property PhoneNumber -Like -Value "*$PhoneNumber*" } else { Write-Verbose -Message "Querying all Resource Accounts, this may take some time..." -Verbose $ResourceAccounts = Get-CsOnlineApplicationInstance -WarningAction SilentlyContinue } # Stop script if no data has been determined if ($ResourceAccounts.Count -eq 0) { Write-Verbose -Message "No Data found." return } #endregion #region OUTPUT # Creating new PS Object try { Write-Verbose -Message "Parsing Resource Accounts, please wait..." foreach ($ResourceAccount in $ResourceAccounts) { # readable Application type Write-Verbose -Message "'$($ResourceAccount.DisplayName)' Parsing: ApplicationType" if ($PSBoundParameters.ContainsKey('ApplicationType')) { $ResourceAccountApplicationType = $ApplicationType } else { $ResourceAccountApplicationType = GetApplicationTypeFromAppId $ResourceAccount.ApplicationId } # Usage Location from Object Write-Verbose -Message "'$($ResourceAccount.DisplayName)' Parsing: Usage Location" $AzureAdUser = Get-AzureADUser -ObjectId "$($ResourceAccount.UserPrincipalName)" -WarningAction SilentlyContinue # Parsing CsOnlineUser Write-Verbose -Message "'$($ResourceAccount.DisplayName)' Parsing: Online Voice Routing Policy" try { $CsOnlineUser = Get-CsOnlineUser -Identity "$($ResourceAccount.UserPrincipalName)" -WarningAction SilentlyContinue -ErrorAction Stop | Select-Object OnlineVoiceRoutingPolicy } catch { Write-Verbose -Message "'$($ResourceAccount.DisplayName)' Parsing: Online Voice Routing Policy FAILED. CsOnlineUser not found" -Verbose } # Parsing TeamsUserLicense Write-Verbose -Message "'$($ResourceAccount.DisplayName)' Parsing: User Licenses" $ResourceAccountLicense = Get-TeamsUserLicense -Identity "$($ResourceAccount.UserPrincipalName)" # Phone Number Type Write-Verbose -Message "'$($ResourceAccount.DisplayName)' Parsing: PhoneNumber" if ($null -ne $ResourceAccount.PhoneNumber) { $PhoneNumberIsMSNumber = $null $PhoneNumberIsMSNumber = ($PhoneNumber -in $MSTelephoneNumbers) if ($PhoneNumberIsMSNumber) { $ResourceAccountPhoneNumberType = "Microsoft Number" } else { $ResourceAccountPhoneNumberType = "Direct Routing Number" } } else { $ResourceAccountPhoneNumberType = $null } # Associations $Association = Get-CsOnlineApplicationInstanceAssociation -Identity $AdUser.ObjectId -WarningAction SilentlyContinue -ErrorAction SilentlyContinue if ( $Association ) { Write-Verbose -Message "'$($ResourceAccount.DisplayName)' Parsing: Association" $AssociationObject = switch ($Association.ConfigurationType) { "CallQueue" { Get-CsCallQueue -Identity $Association.ConfigurationId -WarningAction SilentlyContinue -ErrorAction SilentlyContinue } "AutoAttendant" { Get-CsAutoAttendant -Identity $Association.ConfigurationId -WarningAction SilentlyContinue -ErrorAction SilentlyContinue } } $AssociationStatus = Get-CsOnlineApplicationInstanceAssociationStatus -Identity $ResourceAccount.ObjectId -WarningAction SilentlyContinue -ErrorAction SilentlyContinue } # creating new PS Object (synchronous with Get and Set) $ResourceAccountObject = [PSCustomObject][ordered]@{ ObjectId = $ResourceAccount.ObjectId UserPrincipalName = $ResourceAccount.UserPrincipalName DisplayName = $ResourceAccount.DisplayName ApplicationType = $ResourceAccountApplicationType UsageLocation = $AzureAdUser.UsageLocation License = $ResourceAccountLicense.LicensesFriendlyNames PhoneNumberType = $ResourceAccountPhoneNumberType PhoneNumber = $ResourceAccount.PhoneNumber OnlineVoiceRoutingPolicy = $CsOnlineUser.OnlineVoiceRoutingPolicy AssociatedTo = $AssociationObject.Name AssociatedAs = $Association.ConfigurationType AssociationStatus = $AssociationStatus.Status } Write-Output $ResourceAccountObject } } catch { Write-Warning -Message "Object Output could not be determined. Please verify manually with Get-CsOnlineApplicationInstance" Write-ErrorRecord $_ #This handles the error message in human readable format. } #endregion } #process end { Write-Verbose -Message "[END ] $($MyInvocation.MyCommand)" } #end } #Get-TeamsResourceAccount |