Skip to content

Commit a4d3f08

Browse files
authored
Merge pull request #2264 from MarcoLFrancisco/FreeBusyChecker
FreeBusyChecker Final Version
2 parents c8e54dd + b54bf8d commit a4d3f08

13 files changed

+3414
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,297 @@
1+
# Copyright (c) Microsoft Corporation.
2+
# Licensed under the MIT License.
3+
<#
4+
.SYNOPSIS
5+
6+
.\FreeBusyChecker.ps1
7+
8+
.DESCRIPTION
9+
10+
This script can be used to validate the Availability configuration of the following Exchange Server Versions:
11+
12+
- Exchange Server
13+
- Exchange Online
14+
15+
Required Permissions:
16+
17+
- Organization Management
18+
- Domain Admin
19+
20+
Please make sure that the account used is a member of the Local Administrator group. This should be fulfilled on Exchange Servers by being a member of the Organization Management group. However, if the group membership was adjusted, or in case the script is executed on a non-Exchange system like a management Server, you need to add your account to the Local Administrator group.
21+
22+
How To Run:
23+
24+
This script must be run as Administrator in Exchange Management Shell on an Exchange Server. You can provide no parameters, and the script will just run against Exchange On-Premises and Exchange Online to query for OAuth and DAuth configuration settings. It will compare existing values with standard values and provide details of what may not be correct.
25+
Please take note that though this script may output that a specific setting is not a standard setting, it does not mean that your configurations are incorrect. For example, DNS may be configured with specific mappings that this script cannot evaluate.
26+
27+
To collect information for Exchange Online a connection to Exchange Online must be established before running the script using Connection Prefix "EO".
28+
29+
Example:
30+
31+
PS C:\scripts\FreeBusyChecker> Connect-ExchangeOnline -Prefix EO
32+
33+
.PARAMETER Auth
34+
Allows you to choose the authentication type to validate.
35+
.PARAMETER Org
36+
Allows you to choose the organization type to validate.
37+
.PARAMETER OnPremUser
38+
Specifies the Exchange On Premise User that will be used to test Free Busy Settings.
39+
.PARAMETER OnlineUser
40+
Specifies the Exchange Online User that will be used to test Free Busy Settings.
41+
.PARAMETER OnPremDomain
42+
Specifies the domain for on-premises Organization.
43+
.PARAMETER OnPremEWSUrl
44+
Specifies the EWS (Exchange Web Services) URL for on-premises Exchange Server.
45+
.PARAMETER OnPremLocalDomain
46+
Specifies the local AD domain for the on-premises Organization.
47+
.PARAMETER Help
48+
Show help for this script.
49+
50+
.EXAMPLE
51+
.\FreeBusyChecker.ps1
52+
This cmdlet will run the Free Busy Checker script and Check Availability OAuth and DAuth Configurations both for Exchange On-Premises and Exchange Online.
53+
.EXAMPLE
54+
.\FreeBusyChecker.ps1 -Auth OAuth
55+
This cmdlet will run the Free Busy Checker Script against OAuth Availability Configurations.
56+
.EXAMPLE
57+
.\FreeBusyChecker.ps1 -Auth DAuth
58+
This cmdlet will run the Free Busy Checker Script against DAuth Availability Configurations.
59+
.EXAMPLE
60+
.\FreeBusyChecker.ps1 -Org ExchangeOnline
61+
This cmdlet will run the Free Busy Checker Script for Exchange Online Availability Configurations.
62+
.EXAMPLE
63+
.\FreeBusyChecker.ps1 -Org ExchangeOnPremise
64+
This cmdlet will run the Free Busy Checker Script for Exchange On-Premises OAuth or DAuth Availability Configurations.
65+
.EXAMPLE
66+
.\FreeBusyChecker.ps1 -Org All
67+
This cmdlet will run the Free Busy Checker Script for Exchange On-Premises and Exchange Online OAuth or DAuth Availability Configurations.
68+
.EXAMPLE
69+
.\FreeBusyChecker.ps1 -Org ExchangeOnPremise -Auth OAuth
70+
This cmdlet will run the Free Busy Checker Script for Exchange On-Premises Availability OAuth Configurations
71+
#>
72+
73+
# Exchange On-Premises
74+
#>
75+
#region Properties and Parameters
76+
77+
#Requires -Module ExchangeOnlineManagement
78+
#Requires -Module ActiveDirectory
79+
80+
[CmdletBinding(DefaultParameterSetName = "FreeBusyInfo_OP", SupportsShouldProcess)]
81+
82+
param(
83+
[Parameter(Mandatory = $false, ParameterSetName = "Test")]
84+
[ValidateSet('DAuth', 'OAuth', 'All', '')]
85+
[string[]]$Auth,
86+
[Parameter(Mandatory = $false, ParameterSetName = "Test")]
87+
[ValidateSet('ExchangeOnPremise', 'ExchangeOnline')]
88+
[string[]]$Org,
89+
[Parameter(Mandatory = $true, ParameterSetName = "Help")]
90+
[switch]$Help,
91+
[Parameter(Mandatory = $false, ParameterSetName = "Test")]
92+
[string]$OnPremisesUser,
93+
[Parameter(Mandatory = $false, ParameterSetName = "Test")]
94+
[string]$OnlineUser,
95+
[Parameter(Mandatory = $false, ParameterSetName = "Test")]
96+
[string]$OnPremDomain,
97+
[Parameter(Mandatory = $false, ParameterSetName = "Test")]
98+
[string]$OnPremEWSUrl,
99+
[Parameter(Mandatory = $false, ParameterSetName = "Test")]
100+
[string]$OnPremLocalDomain,
101+
[Parameter(Mandatory = $true, ParameterSetName = "ScriptUpdateOnly", HelpMessage = "Update only script.")]
102+
[switch]$ScriptUpdateOnly,
103+
[Parameter(Mandatory = $false, ParameterSetName = "SkipVersionCheck", HelpMessage = "Skip version check.")]
104+
[switch]$SkipVersionCheck
105+
)
106+
begin {
107+
. $PSScriptRoot\Functions\OnPremDAuthFunctions.ps1
108+
. $PSScriptRoot\Functions\OnPremOAuthFunctions.ps1
109+
. $PSScriptRoot\Functions\ExoDAuthFunctions.ps1
110+
. $PSScriptRoot\Functions\ExoOAuthFunctions.ps1
111+
. $PSScriptRoot\Functions\htmlContent.ps1
112+
. $PSScriptRoot\Functions\hostOutput.ps1
113+
. $PSScriptRoot\Functions\CommonFunctions.ps1
114+
. $PSScriptRoot\..\..\Shared\Confirm-ExchangeShell.ps1
115+
. $PSScriptRoot\..\..\Shared\ScriptUpdateFunctions\GenericScriptUpdate.ps1
116+
} end {
117+
$Script:countOrgRelIssues = (0)
118+
$Script:WebServicesVirtualDirectory = $null
119+
$Script:Server = hostname
120+
$Script:startingDate = (Get-Date -Format yyyyMMdd_HHmmss)
121+
$Script:htmlFile = "$PSScriptRoot\FBCheckerOutput_$($Script:startingDate).html"
122+
123+
loadingParameters
124+
#Parameter input
125+
126+
if (-not $OnlineUser) {
127+
$Script:UserOnline = Get-RemoteMailbox -ResultSize 1 -WarningAction SilentlyContinue
128+
$Script:UserOnline = $Script:UserOnline.RemoteRoutingAddress.SmtpAddress
129+
} else {
130+
$Script:UserOnline = Get-RemoteMailbox $OnlineUser -ResultSize 1 -WarningAction SilentlyContinue -ErrorAction SilentlyContinue
131+
$Script:UserOnline = $Script:UserOnline.RemoteRoutingAddress.SmtpAddress
132+
}
133+
134+
$Script:ExchangeOnlineDomain = ($Script:UserOnline -split "@")[1]
135+
136+
if ($Script:ExchangeOnlineDomain -like "*.mail.onmicrosoft.com") {
137+
$Script:ExchangeOnlineAltDomain = (($Script:ExchangeOnlineDomain.Split(".")))[0] + ".onmicrosoft.com"
138+
} else {
139+
$Script:ExchangeOnlineAltDomain = (($Script:ExchangeOnlineDomain.Split(".")))[0] + ".mail.onmicrosoft.com"
140+
}
141+
$Script:temp = "*" + $Script:ExchangeOnlineDomain
142+
$Script:UserOnPrem = ""
143+
if (-not $OnPremisesUser) {
144+
$Script:UserOnPrem = Get-mailbox -ResultSize 2 -WarningAction SilentlyContinue -Filter 'EmailAddresses -like $temp -and HiddenFromAddressListsEnabled -eq $false' -ErrorAction SilentlyContinue
145+
if ($Script:UserOnPrem) {
146+
$Script:UserOnPrem = $Script:UserOnPrem[1].PrimarySmtpAddress.Address
147+
}
148+
} else {
149+
$Script:UserOnPrem = Get-mailbox $OnPremisesUser -WarningAction SilentlyContinue -Filter 'EmailAddresses -like $temp -and HiddenFromAddressListsEnabled -eq $false' -ErrorAction SilentlyContinue
150+
$Script:UserOnPrem = $Script:UserOnPrem.PrimarySmtpAddress.Address
151+
}
152+
$Script:ExchangeOnPremDomain = ($Script:UserOnPrem -split "@")[1]
153+
154+
if (-not $OnPremEWSUrl) {
155+
FetchEWSInformation
156+
} else {
157+
FetchEWSInformation
158+
$Script:ExchangeOnPremEWS = ($OnPremEWSUrl)
159+
}
160+
161+
if (-not $OnPremDomain) {
162+
$ADDomain = Get-ADDomain
163+
$Script:ExchangeOnPremLocalDomain = $ADDomain.forest
164+
} else {
165+
$Script:ExchangeOnPremLocalDomain = $OnPremDomain
166+
}
167+
168+
$Script:ExchangeOnPremLocalDomain = $ADDomain.forest
169+
if ([string]::IsNullOrWhitespace($ADDomain)) {
170+
$Script:ExchangeOnPremLocalDomain = $exchangeOnPremDomain
171+
}
172+
173+
if ($ExchangeOnPremDomain) {
174+
$Script:FedInfoEOP = Get-federationInformation -DomainName $ExchangeOnPremDomain -BypassAdditionalDomainValidation -ErrorAction SilentlyContinue -WarningAction SilentlyContinue | Select-Object *
175+
}
176+
#endregion
177+
178+
if ($Help) {
179+
PrintDynamicWidthLine
180+
ShowHelp
181+
PrintDynamicWidthLine
182+
exit
183+
}
184+
#region Show Parameters
185+
$Script:IntraOrgCon = Get-IntraOrganizationConnector -WarningAction SilentlyContinue -ErrorAction SilentlyContinue | Where-Object { $_.TargetAddressDomains -contains $Script:ExchangeOnlineDomain } | Select-Object Name, TarGetAddressDomains, DiscoveryEndpoint, Enabled
186+
ShowParameters
187+
CheckParameters
188+
if ($Script:IntraOrgCon.enabled -eq $true) {
189+
$Auth = hostOutputIntraOrgConEnabled($Auth)
190+
}
191+
if ($Script:IntraOrgCon.enabled -eq $false) {
192+
hostOutputIntraOrgConNotEnabled
193+
}
194+
# Free busy Lookup methods
195+
PrintDynamicWidthLine
196+
$Script:OrgRel = Get-OrganizationRelationship | Where-Object { ($_.DomainNames -like $Script:ExchangeOnlineDomain) } -WarningAction SilentlyContinue -ErrorAction SilentlyContinue | Select-Object Enabled, Identity, DomainNames, FreeBusy*, TarGet*
197+
$Script:EDiscoveryEndpoint = Get-IntraOrganizationConfiguration -WarningAction SilentlyContinue -ErrorAction SilentlyContinue | Select-Object OnPremiseDiscoveryEndpoint
198+
$Script:SPDomainsOnprem = Get-SharingPolicy -WarningAction SilentlyContinue -ErrorAction SilentlyContinue | Format-List Domains
199+
$Script:SPOnprem = Get-SharingPolicy -WarningAction SilentlyContinue -ErrorAction SilentlyContinue | Select-Object *
200+
201+
if ($Org -contains 'ExchangeOnPremise' -or -not $Org) {
202+
#region DAuth Checks
203+
if ($Auth -like "DAuth" -or -not $Auth -or $Auth -like "All") {
204+
Write-Host " Testing DAuth Configuration"
205+
OrgRelCheck -OrgRelParameter $Script:OrgRel
206+
PrintDynamicWidthLine
207+
FedInfoCheck
208+
FedTrustCheck
209+
AutoDVirtualDCheck
210+
PrintDynamicWidthLine
211+
EWSVirtualDirectoryCheck
212+
AvailabilityAddressSpaceCheck
213+
TestFedTrust
214+
TestOrgRel
215+
}
216+
#endregion
217+
#region OAuth Check
218+
if ($Auth -like "OAuth" -or -not $Auth -or $Auth -like "All") {
219+
Write-Host " Testing OAuth Configuration"
220+
IntraOrgConCheck
221+
PrintDynamicWidthLine
222+
AuthServerCheck
223+
PrintDynamicWidthLine
224+
PartnerApplicationCheck
225+
PrintDynamicWidthLine
226+
ApplicationAccountCheck
227+
PrintDynamicWidthLine
228+
ManagementRoleAssignmentCheck
229+
PrintDynamicWidthLine
230+
AuthConfigCheck
231+
PrintDynamicWidthLine
232+
CurrentCertificateThumbprintCheck
233+
PrintDynamicWidthLine
234+
AutoDVirtualDCheckOAuth
235+
PrintDynamicWidthLine
236+
EWSVirtualDirectoryCheckOAuth
237+
PrintDynamicWidthLine
238+
AvailabilityAddressSpaceCheckOAuth
239+
PrintDynamicWidthLine
240+
OAuthConnectivityCheck
241+
PrintDynamicWidthLine
242+
}
243+
#endregion
244+
}
245+
# EXO Part
246+
if ($Org -contains 'ExchangeOnline' -or -not $Org) {
247+
#region ConnectExo
248+
$Exo = Test-ExchangeOnlineConnection
249+
if (-not ($Exo)) {
250+
Write-Host -ForegroundColor Red "`n Please connect to Exchange Online Using the EXO V3 module using EO as connection Prefix to collect Exchange OnLine Free Busy configuration Information."
251+
Write-Host -ForegroundColor Cyan "`n`n Example: PS C:\Connect-ExchangeOnline -Prefix EO"
252+
Write-Host -ForegroundColor Yellow "`n More Info at:https://learn.microsoft.com/en-us/powershell/exchange/exchange-online-powershell-v2?view=exchange-ps"
253+
exit
254+
}
255+
Write-Host " Connected to Exchange Online."
256+
$Script:ExoOrgRel = Get-EOOrganizationRelationship | Where-Object { ($_.DomainNames -like $ExchangeOnPremDomain ) } | Select-Object Enabled, Identity, DomainNames, FreeBusy*, TarGet*
257+
$Script:ExoIntraOrgCon = Get-EOIntraOrganizationConnector | Select-Object Name, TarGetAddressDomains, DiscoveryEndpoint, Enabled
258+
$Script:tarGetAddressPr1 = ("https://AutoDiscover." + $ExchangeOnPremDomain + "/AutoDiscover/AutoDiscover.svc/WSSecurity")
259+
$Script:tarGetAddressPr2 = ("https://" + $ExchangeOnPremDomain + "/AutoDiscover/AutoDiscover.svc/WSSecurity")
260+
exoHeaderHtml
261+
262+
#endregion
263+
264+
#region ExoDAuthCheck
265+
if ($Auth -like "DAuth" -or -not $Auth -or $Auth -like "All") {
266+
PrintDynamicWidthLine
267+
Write-Host $TestingExoDAuthConfiguration
268+
ExoOrgRelCheck
269+
PrintDynamicWidthLine
270+
ExoFedOrgIdCheck
271+
PrintDynamicWidthLine
272+
ExoTestOrgRelCheck
273+
SharingPolicyCheck
274+
}
275+
#endregion
276+
277+
#region ExoOauthCheck
278+
if ($Auth -like "OAuth" -or -not $Auth -or $Auth -like "All") {
279+
Write-Host $TestingExoOAuthConfiguration
280+
ExoIntraOrgConCheck
281+
PrintDynamicWidthLine
282+
EXOIntraOrgConfigCheck
283+
PrintDynamicWidthLine
284+
EXOAuthServerCheck
285+
PrintDynamicWidthLine
286+
ExoTestOAuthCheck
287+
PrintDynamicWidthLine
288+
}
289+
#endregion
290+
291+
Write-Host -ForegroundColor Green $ThatIsAllForTheExchangeOnlineSide
292+
293+
PrintDynamicWidthLine
294+
}
295+
296+
Stop-Transcript
297+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# Copyright (c) Microsoft Corporation.
2+
# Licensed under the MIT License.
3+
function Test-ExchangeOnlineConnection {
4+
Write-Host -ForegroundColor Green " Checking Exchange Online Configuration"
5+
Write-Host " Testing Connection to Exchange Online with EO Prefix."
6+
try {
7+
$CheckExoMailbox = Get-EOMailbox $Script:UserOnline -ErrorAction Stop
8+
if ($null -ne $CheckExoMailbox) {
9+
return $true
10+
} else {
11+
return $false
12+
}
13+
} catch {
14+
return $false
15+
}
16+
}
17+
function FetchAutoDiscoverInformation {
18+
if (-not $Script:AutoDiscoveryVirtualDirectory -or -not $Script:AutoDiscoveryVirtualDirectoryOAuth) {
19+
$Script:AutoDiscoveryVirtualDirectory = Get-AutoDiscoverVirtualDirectory -Server $Script:Server | Select-Object Identity, Name, ExchangeVersion, *authentication* -ErrorAction SilentlyContinue
20+
$Script:AutoDiscoveryVirtualDirectoryOAuth = $Script:AutoDiscoveryVirtualDirectory
21+
}
22+
}
23+
function FetchEWSInformation {
24+
if (-not $Script:WebServicesVirtualDirectory -or -not $Script:WebServicesVirtualDirectoryOAuth) {
25+
$Script:WebServicesVirtualDirectory = Get-WebServicesVirtualDirectory -Server $Script:Server | Select-Object Identity, Name, ExchangeVersion, *Authentication*, *url -ErrorAction SilentlyContinue
26+
$Script:WebServicesVirtualDirectoryOAuth = $Script:WebServicesVirtualDirectory
27+
$Script:ExchangeOnPremEWS = ($Script:WebServicesVirtualDirectory.externalURL.AbsoluteUri)
28+
}
29+
}
30+
function CheckIfExchangeServer {
31+
$exchangeShell = Confirm-ExchangeShell
32+
if (-not($exchangeShell.ShellLoaded)) {
33+
Write-Host "$Server is not an Exchange Server. This script should be run in Exchange Server Management Shell"
34+
exit
35+
}
36+
}
37+
function CheckParameters {
38+
$MissingParameters = @()
39+
if ([string]::IsNullOrWhiteSpace($Script:ExchangeOnlineDomain)) {
40+
$MissingParameters += "Exchange Online Domain. Example: contoso.mail.onmicrosoft.com"
41+
}
42+
if ([string]::IsNullOrWhiteSpace($Script:ExchangeOnPremLocalDomain)) {
43+
$MissingParameters += "Exchange On Premises Local Domain. Example: . 'C:\scripts\FreeBusyChecker\FreeBusyChecker.ps1' -OnPremisesUser John@Contoso.com"
44+
}
45+
if ([string]::IsNullOrWhiteSpace($exchangeOnPremDomain)) {
46+
$MissingParameters += "Exchange On Premises Domain. Example: -OnPremLocalDomain Contoso.local"
47+
}
48+
if ([string]::IsNullOrWhiteSpace($exchangeOnPremEWS)) {
49+
$MissingParameters += "Exchange On Premises EWS Virtual Directory External URL. Example: 'C:\FreeBusyChecker.ps1' -OnPremEWSUrl https://mail.contoso.com/EWS/Exchange.asmx"
50+
}
51+
if ([string]::IsNullOrWhiteSpace($Script:UserOnPrem)) {
52+
$MissingParameters += "On Premises User Mailbox. Example: 'C:\FreeBusyChecker.ps1' -OnPremisesUser John@Contoso.com"
53+
}
54+
if ([string]::IsNullOrWhiteSpace($Script:UserOnline)) {
55+
$MissingParameters += "Exchange Online Mailbox. Example: 'C:\FreeBusyChecker.ps1' -OnlineUser John@Contoso.onmicrosoft.com"
56+
}
57+
58+
if ($MissingParameters.Count -gt 0) {
59+
foreach ($param in $MissingParameters) {
60+
Write-Host -ForegroundColor Red "Please provide a value for $param."
61+
}
62+
exit 1
63+
}
64+
Write-Host -ForegroundColor Cyan "`n All parameters are valid."
65+
return
66+
}

0 commit comments

Comments
 (0)