Add Exchange Online PowerShell probe scripts
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
e304b2b3d4
commit
6741190342
@ -0,0 +1,135 @@
|
|||||||
|
[CmdletBinding()]
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory=$true)][string]$TenantId,
|
||||||
|
[Parameter(Mandatory=$true)][string]$ClientId,
|
||||||
|
[Parameter(Mandatory=$true)][string]$Organization,
|
||||||
|
[Parameter(Mandatory=$true)][string]$Mailbox,
|
||||||
|
[Parameter(Mandatory=$true)][string]$CertPath
|
||||||
|
)
|
||||||
|
|
||||||
|
$ErrorActionPreference = 'Stop'
|
||||||
|
$ProgressPreference = 'SilentlyContinue'
|
||||||
|
|
||||||
|
function Write-JsonResult {
|
||||||
|
param($Payload)
|
||||||
|
Write-Output ($Payload | ConvertTo-Json -Depth 6 -Compress)
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Import-Module ExchangeOnlineManagement -ErrorAction Stop
|
||||||
|
} catch {
|
||||||
|
Write-JsonResult @{ ok = $false; error = "ExchangeOnlineManagement module not available: $($_.Exception.Message)" }
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$pfxPwd = $env:CLEARVIEW_PFX_PASSWORD
|
||||||
|
if ([string]::IsNullOrEmpty($pfxPwd)) {
|
||||||
|
Write-JsonResult @{ ok = $false; error = "CLEARVIEW_PFX_PASSWORD not set in environment" }
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
$securePwd = ConvertTo-SecureString -String $pfxPwd -AsPlainText -Force
|
||||||
|
Connect-ExchangeOnline `
|
||||||
|
-AppId $ClientId `
|
||||||
|
-Organization $Organization `
|
||||||
|
-CertificateFilePath $CertPath `
|
||||||
|
-CertificatePassword $securePwd `
|
||||||
|
-ShowBanner:$false `
|
||||||
|
-ShowProgress:$false `
|
||||||
|
-ErrorAction Stop | Out-Null
|
||||||
|
} catch {
|
||||||
|
Write-JsonResult @{ ok = $false; error = "Connect-ExchangeOnline failed: $($_.Exception.Message)" }
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
$entries = New-Object System.Collections.Generic.List[object]
|
||||||
|
$warnings = New-Object System.Collections.Generic.List[string]
|
||||||
|
|
||||||
|
try {
|
||||||
|
$mb = Get-EXOMailbox -Identity $Mailbox -PropertySets All -ErrorAction Stop
|
||||||
|
|
||||||
|
# 1) Full Access (and other mailbox-level permissions)
|
||||||
|
try {
|
||||||
|
$perms = Get-EXOMailboxPermission -Identity $mb.UserPrincipalName -ErrorAction Stop |
|
||||||
|
Where-Object { $_.User -notlike 'NT AUTHORITY\SELF' -and $_.User -notlike 'S-1-5-*' -and -not $_.IsInherited -and $_.Deny -eq $false }
|
||||||
|
foreach ($p in $perms) {
|
||||||
|
$rights = @($p.AccessRights) -join ', '
|
||||||
|
$entries.Add([pscustomobject]@{
|
||||||
|
permission_type = 'FullAccess'
|
||||||
|
object_type = 'Mailbox'
|
||||||
|
object = $mb.UserPrincipalName
|
||||||
|
principal = [string]$p.User
|
||||||
|
role_name = $rights
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
$warnings.Add("MailboxPermission: $($_.Exception.Message)")
|
||||||
|
}
|
||||||
|
|
||||||
|
# 2) Send As
|
||||||
|
try {
|
||||||
|
$sendAs = Get-EXORecipientPermission -Identity $mb.UserPrincipalName -ErrorAction Stop |
|
||||||
|
Where-Object { $_.Trustee -notlike 'NT AUTHORITY\SELF' -and $_.Trustee -notlike 'S-1-5-*' -and $_.AccessControlType -eq 'Allow' }
|
||||||
|
foreach ($p in $sendAs) {
|
||||||
|
$rights = @($p.AccessRights) -join ', '
|
||||||
|
$entries.Add([pscustomobject]@{
|
||||||
|
permission_type = 'SendAs'
|
||||||
|
object_type = 'Mailbox'
|
||||||
|
object = $mb.UserPrincipalName
|
||||||
|
principal = [string]$p.Trustee
|
||||||
|
role_name = $rights
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
$warnings.Add("RecipientPermission: $($_.Exception.Message)")
|
||||||
|
}
|
||||||
|
|
||||||
|
# 3) Send on Behalf — from mailbox property
|
||||||
|
try {
|
||||||
|
if ($mb.GrantSendOnBehalfTo) {
|
||||||
|
foreach ($t in $mb.GrantSendOnBehalfTo) {
|
||||||
|
$entries.Add([pscustomobject]@{
|
||||||
|
permission_type = 'SendOnBehalf'
|
||||||
|
object_type = 'Mailbox'
|
||||||
|
object = $mb.UserPrincipalName
|
||||||
|
principal = [string]$t
|
||||||
|
role_name = 'SendOnBehalf'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
$warnings.Add("GrantSendOnBehalfTo: $($_.Exception.Message)")
|
||||||
|
}
|
||||||
|
|
||||||
|
# 4) Folder-level delegations on Calendar and Inbox
|
||||||
|
foreach ($folder in 'Calendar', 'Inbox') {
|
||||||
|
try {
|
||||||
|
$folderPath = "{0}:\{1}" -f $mb.UserPrincipalName, $folder
|
||||||
|
$fp = Get-EXOMailboxFolderPermission -Identity $folderPath -ErrorAction Stop |
|
||||||
|
Where-Object { $_.User.DisplayName -notin @('Default', 'Anonymous') -and $_.AccessRights -notcontains 'None' }
|
||||||
|
foreach ($p in $fp) {
|
||||||
|
$rights = @($p.AccessRights) -join ', '
|
||||||
|
$entries.Add([pscustomobject]@{
|
||||||
|
permission_type = "Folder:$folder"
|
||||||
|
object_type = 'MailboxFolder'
|
||||||
|
object = "$($mb.UserPrincipalName)/$folder"
|
||||||
|
principal = [string]$p.User.DisplayName
|
||||||
|
role_name = $rights
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
$warnings.Add("FolderPermission ${folder}: $($_.Exception.Message)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-JsonResult @{
|
||||||
|
ok = $true
|
||||||
|
mailbox = $mb.UserPrincipalName
|
||||||
|
entries = $entries
|
||||||
|
warnings = $warnings
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
Write-JsonResult @{ ok = $false; error = $_.Exception.Message }
|
||||||
|
} finally {
|
||||||
|
try { Disconnect-ExchangeOnline -Confirm:$false -InformationAction SilentlyContinue -ErrorAction SilentlyContinue | Out-Null } catch {}
|
||||||
|
}
|
||||||
@ -0,0 +1,67 @@
|
|||||||
|
[CmdletBinding()]
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory=$true)][string]$TenantId,
|
||||||
|
[Parameter(Mandatory=$true)][string]$ClientId,
|
||||||
|
[Parameter(Mandatory=$true)][string]$Organization,
|
||||||
|
[Parameter(Mandatory=$true)][string]$CertPath,
|
||||||
|
[Parameter(Mandatory=$false)][int]$MaxMailboxes = 50000
|
||||||
|
)
|
||||||
|
|
||||||
|
$ErrorActionPreference = 'Stop'
|
||||||
|
$ProgressPreference = 'SilentlyContinue'
|
||||||
|
|
||||||
|
function Write-JsonResult {
|
||||||
|
param($Payload)
|
||||||
|
Write-Output ($Payload | ConvertTo-Json -Depth 4 -Compress)
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Import-Module ExchangeOnlineManagement -ErrorAction Stop
|
||||||
|
} catch {
|
||||||
|
Write-JsonResult @{ ok = $false; error = "ExchangeOnlineManagement module not available: $($_.Exception.Message)" }
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$pfxPwd = $env:CLEARVIEW_PFX_PASSWORD
|
||||||
|
if ([string]::IsNullOrEmpty($pfxPwd)) {
|
||||||
|
Write-JsonResult @{ ok = $false; error = "CLEARVIEW_PFX_PASSWORD not set in environment" }
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
$securePwd = ConvertTo-SecureString -String $pfxPwd -AsPlainText -Force
|
||||||
|
Connect-ExchangeOnline `
|
||||||
|
-AppId $ClientId `
|
||||||
|
-Organization $Organization `
|
||||||
|
-CertificateFilePath $CertPath `
|
||||||
|
-CertificatePassword $securePwd `
|
||||||
|
-ShowBanner:$false `
|
||||||
|
-ShowProgress:$false `
|
||||||
|
-ErrorAction Stop | Out-Null
|
||||||
|
} catch {
|
||||||
|
Write-JsonResult @{ ok = $false; error = "Connect-ExchangeOnline failed: $($_.Exception.Message)" }
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$boxes = Get-EXOMailbox -ResultSize Unlimited -PropertySets Minimum -ErrorAction Stop |
|
||||||
|
Select-Object -ExpandProperty UserPrincipalName
|
||||||
|
|
||||||
|
if ($boxes.Count -gt $MaxMailboxes) {
|
||||||
|
Write-JsonResult @{
|
||||||
|
ok = $false
|
||||||
|
error = "Mailbox count $($boxes.Count) exceeds MaxMailboxes=$MaxMailboxes"
|
||||||
|
count = $boxes.Count
|
||||||
|
}
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-JsonResult @{
|
||||||
|
ok = $true
|
||||||
|
count = $boxes.Count
|
||||||
|
mailboxes = $boxes
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
Write-JsonResult @{ ok = $false; error = $_.Exception.Message }
|
||||||
|
} finally {
|
||||||
|
try { Disconnect-ExchangeOnline -Confirm:$false -InformationAction SilentlyContinue -ErrorAction SilentlyContinue | Out-Null } catch {}
|
||||||
|
}
|
||||||
@ -0,0 +1,57 @@
|
|||||||
|
[CmdletBinding()]
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory=$true)][string]$TenantId,
|
||||||
|
[Parameter(Mandatory=$true)][string]$ClientId,
|
||||||
|
[Parameter(Mandatory=$true)][string]$Organization,
|
||||||
|
[Parameter(Mandatory=$true)][string]$Mailbox,
|
||||||
|
[Parameter(Mandatory=$true)][string]$CertPath
|
||||||
|
)
|
||||||
|
|
||||||
|
$ErrorActionPreference = 'Stop'
|
||||||
|
$ProgressPreference = 'SilentlyContinue'
|
||||||
|
|
||||||
|
function Write-Result {
|
||||||
|
param([bool]$Ok, [string]$Message)
|
||||||
|
$obj = [pscustomobject]@{ ok = $Ok; message = $Message }
|
||||||
|
Write-Output ($obj | ConvertTo-Json -Compress)
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Import-Module ExchangeOnlineManagement -ErrorAction Stop
|
||||||
|
} catch {
|
||||||
|
Write-Result -Ok $false -Message "ExchangeOnlineManagement module not available: $($_.Exception.Message)"
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$pfxPwd = $env:CLEARVIEW_PFX_PASSWORD
|
||||||
|
if ([string]::IsNullOrEmpty($pfxPwd)) {
|
||||||
|
Write-Result -Ok $false -Message "CLEARVIEW_PFX_PASSWORD not set in environment"
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
$securePwd = ConvertTo-SecureString -String $pfxPwd -AsPlainText -Force
|
||||||
|
Connect-ExchangeOnline `
|
||||||
|
-AppId $ClientId `
|
||||||
|
-Organization $Organization `
|
||||||
|
-CertificateFilePath $CertPath `
|
||||||
|
-CertificatePassword $securePwd `
|
||||||
|
-ShowBanner:$false `
|
||||||
|
-ShowProgress:$false `
|
||||||
|
-ErrorAction Stop | Out-Null
|
||||||
|
} catch {
|
||||||
|
Write-Result -Ok $false -Message "Connect-ExchangeOnline failed: $($_.Exception.Message)"
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$box = Get-EXOMailbox -Identity $Mailbox -ErrorAction Stop -PropertySets Minimum
|
||||||
|
if ($null -eq $box) {
|
||||||
|
Write-Result -Ok $false -Message "Mailbox '$Mailbox' not found"
|
||||||
|
} else {
|
||||||
|
Write-Result -Ok $true -Message "OK"
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
Write-Result -Ok $false -Message "Get-EXOMailbox failed: $($_.Exception.Message)"
|
||||||
|
} finally {
|
||||||
|
try { Disconnect-ExchangeOnline -Confirm:$false -InformationAction SilentlyContinue -ErrorAction SilentlyContinue | Out-Null } catch {}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user