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