Skip to content

Commit

Permalink
Merge pull request #1889 from microsoft/main
Browse files Browse the repository at this point in the history
Release 11-21-2023
  • Loading branch information
dpaulson45 authored Nov 21, 2023
2 parents 34ee62c + ac99778 commit dc10261
Show file tree
Hide file tree
Showing 53 changed files with 1,529 additions and 1,531 deletions.
2 changes: 1 addition & 1 deletion .build/Build.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ $unreferencedScriptFiles = @($allScriptFiles | Where-Object {
}

return $true
});
})

$unreferencedSharedScriptFiles = @($unreferencedScriptFiles | Where-Object {
$_.StartsWith("$repoRoot\Shared\")
Expand Down
2 changes: 1 addition & 1 deletion .build/CodeFormatterChecks/CheckScriptFileHasBOM.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ function CheckScriptFileHasBOM {
Write-Host "Added BOM: $($FileInfo.FullName)"
$false
} catch {
Write-Warning "File has no BOM and couldn't be fixed automatically: $($FileInfo.FullName). Exception: $($_.Exception)";
Write-Warning "File has no BOM and couldn't be fixed automatically: $($FileInfo.FullName). Exception: $($_.Exception)"
$true
}
} else {
Expand Down
1 change: 1 addition & 0 deletions .build/cspell-words.txt
Original file line number Diff line number Diff line change
Expand Up @@ -158,4 +158,5 @@ vuln
wbxml
Webex
Weve
wevtutil
windir
6 changes: 3 additions & 3 deletions Admin/Find-AmbiguousSids.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ begin {
Write-Host "Using GC $GCName"
$ldapConn = New-Object System.DirectoryServices.Protocols.LdapConnection("$($GCName):3268")
$searchReq = New-Object System.DirectoryServices.Protocols.SearchRequest("", $filter, "Subtree", $null)
$prc = New-Object System.DirectoryServices.Protocols.PageResultRequestControl($pageSize);
[void]$searchReq.Controls.Add($prc);
$prc = New-Object System.DirectoryServices.Protocols.PageResultRequestControl($pageSize)
[void]$searchReq.Controls.Add($prc)

$sidProperties = @("objectSid", "sidHistory", "msExchMasterAccountSid")
$containersToIgnore = @(",CN=WellKnown Security Principals,", ",CN=Builtin,", ",CN=ForeignSecurityPrincipals,")
Expand Down Expand Up @@ -99,7 +99,7 @@ process {

$objectsProcessed++
}
} while ($prc.Cookie.Length -gt 0);
} while ($prc.Cookie.Length -gt 0)
}

end {
Expand Down
2 changes: 1 addition & 1 deletion Admin/Update-Engines.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ function ExtractCab($sourceCabPath, $destinationDirectory) {
# Process each item in the cab. Determine if the destination
# is a sub directory and create if necessary.
for ($i=0; $i -lt $itemCount; $i++) {
$lastPathIndex = $source.item($i).Path.LastIndexOf("\");
$lastPathIndex = $source.item($i).Path.LastIndexOf("\")

# If the file inside the zip file should be extracted
# to a subfolder, then we need to reset the destination
Expand Down
326 changes: 326 additions & 0 deletions Calendar/Check-SharingStatus.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,326 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
#
# .DESCRIPTION
# This script runs a variety of cmdlets to establish a baseline of the sharing status of a Calendar.
#
# .PARAMETER Identity
# Owner Mailbox to query, owner of the Mailbox sharing the calendar.
# Receiver of the shared mailbox, often the Delegate.
#
# .EXAMPLE
# Check-SharingStatus.ps1 -Owner [email protected] -Receiver [email protected]

# Define the parameters
[CmdletBinding()]
param(
[Parameter(Mandatory=$true)]
[string]$Owner,
[Parameter(Mandatory=$true)]
[string]$Receiver
)

$BuildVersion = ""

. $PSScriptRoot\..\Shared\ScriptUpdateFunctions\Test-ScriptVersion.ps1

if (Test-ScriptVersion -AutoUpdate) {
# Update was downloaded, so stop here.
Write-Host "Script was updated. Please rerun the command." -ForegroundColor Yellow
return
}

Write-Verbose "Script Versions: $BuildVersion"

$script:PIIAccess = $true #Assume we have PII access until we find out otherwise

<#
.SYNOPSIS
Formats the CalendarSharingInvite logs from Export-MailboxDiagnosticLogs for a given identity.
.DESCRIPTION
This function processes calendar sharing accept logs for a given identity and outputs the most recent update for each recipient.
.PARAMETER Identity
The SMTP Address for which to process calendar sharing accept logs.
#>
function ProcessCalendarSharingInviteLogs {
param (
[string]$Identity
)

# Define the header row
$header = "Timestamp", "Mailbox", "Entry MailboxOwner", "Recipient", "RecipientType", "SharingType", "DetailLevel"
$csvString = @()
$csvString = $header -join ","
$csvString += "`n"

Write-Output "------------------------"
Write-Output "Looking for modern calendar sharing accept data for [$Identity]."

# Call the Export-MailboxDiagnosticLogs cmdlet and store the output in a variable
try {
# Call the Export-MailboxDiagnosticLogs cmdlet and store the output in a variable
# -ErrorAction is not supported on Export-MailboxDiagnosticLogs
# $logOutput = Export-MailboxDiagnosticLogs $Identity -ComponentName CalendarSharingInvite -ErrorAction SilentlyContinue

$logOutput = Export-MailboxDiagnosticLogs $Identity -ComponentName CalendarSharingInvite
} catch {
# Code to run if an error occurs
Write-Error "An error occurred: $_"
}

# check if the output is empty
if ($null -eq $logOutput.MailboxLog) {
Write-Output "No data found for [$Identity]."
return
}

$logLines =@()
# Split the output into an array of lines
$logLines = $logOutput.MailboxLog -split "`r`n"

# Loop through each line of the output
foreach ($line in $logLines) {
if ($line -like "*RecipientType*") {
$csvString += $line + "`n"
}
}

# Clean up output
$csvString = $csvString.Replace("Mailbox: ", "")
$csvString = $csvString.Replace("Entry MailboxOwner:", "")
$csvString = $csvString.Replace("Recipient:", "")
$csvString = $csvString.Replace("RecipientType:", "")
$csvString = $csvString.Replace("Handler=", "")
$csvString = $csvString.Replace("ms-exchange-", "")
$csvString = $csvString.Replace("DetailLevel=", "")

# Convert the CSV string to an object
$csvObject = $csvString | ConvertFrom-Csv

# Access the values as properties of the object
foreach ($row in $csvObject) {
Write-Debug "$($row.Recipient) - $($row.SharingType) - $($row.detailLevel)"
}

#Filter the output to get the most recent update foreach recipient
$mostRecentRecipients = $csvObject | Sort-Object Recipient -Unique | Sort-Object Timestamp -Descending

# Output the results to the console
Write-Output "User [$Identity] has shared their calendar with the following recipients:"
Write-Output $mostRecentRecipients | Format-Table -a Timestamp, Recipient, SharingType, DetailLevel
}

<#
.SYNOPSIS
Formats the AcceptCalendarSharingInvite logs from Export-MailboxDiagnosticLogs for a given identity.
.DESCRIPTION
This function processes calendar sharing invite logs.
.PARAMETER Identity
The SMTP Address for which to process calendar sharing accept logs.
#>
function ProcessCalendarSharingAcceptLogs {
param (
[string]$Identity
)

# Define the header row
$header = "Timestamp", "Mailbox", "SharedCalendarOwner", "FolderName"
$csvString = @()
$csvString = $header -join ","
$csvString += "`n"

Write-Output "------------------------"
Write-Output "Looking for Modern Calendar Sharing Accept data for [$Identity]."

# Call the Export-MailboxDiagnosticLogs cmdlet and store the output in a variable
try {
# Call the Export-MailboxDiagnosticLogs cmdlet and store the output in a variable
# -ErrorAction is not supported on Export-MailboxDiagnosticLogs
# $logOutput = Export-MailboxDiagnosticLogs $Identity -ComponentName AcceptCalendarSharingInvite -ErrorAction SilentlyContinue

$logOutput = Export-MailboxDiagnosticLogs $Identity -ComponentName AcceptCalendarSharingInvite
} catch {
# Code to run if an error occurs
Write-Error "An error occurred: $_"
}

# check if the output is empty
if ($null -eq $logOutput.MailboxLog) {
Write-Output "No AcceptCalendarSharingInvite Logs found for [$Identity]."
return
}

$logLines =@()
# Split the output into an array of lines
$logLines = $logOutput.MailboxLog -split "`r`n"

# Loop through each line of the output
foreach ($line in $logLines) {
if ($line -like "*CreateInternalSharedCalendarGroupEntry*") {
$csvString += $line + "`n"
}
}

# Clean up output
$csvString = $csvString.Replace("Mailbox: ", "")
$csvString = $csvString.Replace("Entry MailboxOwner:", "")
$csvString = $csvString.Replace("Entry CreateInternalSharedCalendarGroupEntry: ", "")
$csvString = $csvString.Replace("Creating a shared calendar for ", "")
$csvString = $csvString.Replace("calendar name ", "")

# Convert the CSV string to an object
$csvObject = $csvString | ConvertFrom-Csv

# Access the values as properties of the object
foreach ($row in $csvObject) {
Write-Debug "$($row.Timestamp) - $($row.SharedCalendarOwner) - $($row.FolderName) "
}

# Filter the output to get the most recent update for each recipient
# $mostRecentSharedCalendars = $csvObject |sort-object SharedCalendarOwner -Unique | Sort-Object Timestamp -Descending

# Output the results to the console
Write-Host "User [$Identity] has accepted copies of the shared calendar from the following recipients on these dates:"
#Write-Host $csvObject | Format-Table -a Timestamp, SharedCalendarOwner, FolderName
$csvObject | Format-Table -a Timestamp, SharedCalendarOwner, FolderName
}

<#
.SYNOPSIS
Display Calendar Owner information.
.DESCRIPTION
This function displays key Calendar Owner information.
.PARAMETER Identity
The SMTP Address for Owner of the shared calendar.
#>
function GetOwnerInformation {
param (
[string]$Owner
)
#Standard Owner information
Write-Host -ForegroundColor DarkYellow "------------------------------------------------"
Write-Host -ForegroundColor DarkYellow "Key Owner Mailbox Information:"
$script:OwnerMB = Get-Mailbox $Owner
# Write-Host "`t DisplayName:" $script:OwnerMB.DisplayName
# Write-Host "`t Database:" $script:OwnerMB.Database
# Write-Host "`t ServerName:" $script:OwnerMB.ServerName
# Write-Host "`t LitigationHoldEnabled:" $script:OwnerMB.LitigationHoldEnabled
# Write-Host "`t CalendarVersionStoreDisabled:" $script:OwnerMB.CalendarVersionStoreDisabled
# Write-Host "`t CalendarRepairDisabled:" $script:OwnerMB.CalendarRepairDisabled
# Write-Host "`t RecipientTypeDetails:" $script:OwnerMB.RecipientTypeDetails
# Write-Host "`t RecipientType:" $script:OwnerMB.RecipientType
Get-Mailbox $Owner | Format-List DisplayName, Database, ServerName, LitigationHoldEnabled, CalendarVersionStoreDisabled, CalendarRepairDisabled, RecipientType*

if ($null -eq $script:OwnerMB) {
Write-Host -ForegroundColor Red "Could not find Owner Mailbox [$Owner]."
exit
}

Write-Host -ForegroundColor DarkYellow "Send on Behalf Granted to :"
foreach ($del in $($script:OwnerMB.GrantSendOnBehalfTo)) {
Write-Host -ForegroundColor Blue "`t$($del)"
}
Write-Host "`n`n`n"

if ($script:OwnerMB.DisplayName -like "Redacted*") {
Write-Host -ForegroundColor Yellow "Do Not have PII information for the Owner."
Write-Host -ForegroundColor Yellow "Get PII Access for $($script:OwnerMB.Database)."
$script:PIIAccess = $false
}

Write-Host -ForegroundColor DarkYellow "Owner Calendar Folder Statistics:"
$OwnerCalendar = Get-MailboxFolderStatistics -Identity $Owner -FolderScope Calendar
$OwnerCalendarName = ($OwnerCalendar | Where-Object FolderPath -EQ "/Calendar").Name

Get-MailboxFolderStatistics -Identity $Owner -FolderScope Calendar | Format-Table -a FolderPath, ItemsInFolder, FolderAndSubfolderSize

Write-Host -ForegroundColor DarkYellow "Owner Calendar Permissions:"
Get-mailboxFolderPermission "${Owner}:\$OwnerCalendarName" | Format-Table -a User, AccessRights, SharingPermissionFlags

Write-Host -ForegroundColor DarkYellow "Owner Root MB Permissions:"
Get-mailboxPermission $Owner | Format-Table -a User, AccessRights, SharingPermissionFlags

# Write-Host -ForegroundColor DarkYellow "Owner Recoverable Items Folder Statistics: "
# Get-MailboxFolderStatistics -Identity $Owner -FolderScope RecoverableItems | Where-Object FolderPath -Like *Calendar* | Format-Table FolderPath, ItemsInFolder, FolderAndSubfolderSize

Write-Host -ForegroundColor DarkYellow "Owner Modern Sharing Sent Invites"
ProcessCalendarSharingInviteLogs -Identity $Owner
}

<#
.SYNOPSIS
Displays key information from the receiver of the shared Calendar.
.DESCRIPTION
This function displays key Calendar Receiver information.
.PARAMETER Identity
The SMTP Address for Receiver of the shared calendar.
#>
function GetReceiverInformation {
param (
[string]$Receiver
)
#Standard Receiver information
Write-Host -ForegroundColor Cyan "`r`r`r------------------------------------------------"
Write-Host -ForegroundColor Cyan "Key Receiver Information: [$Receiver]"
Get-Mailbox $Receiver | Format-List DisplayName, Database, LitigationHoldEnabled, CalendarVersionStoreDisabled, CalendarRepairDisabled, RecipientType*

Write-Host -ForegroundColor Cyan "Receiver Calendar Folders (look for a copy of [$Owner] Calendar):"
$CalStats = Get-MailboxFolderStatistics -Identity $Receiver -FolderScope Calendar
$CalStats | Format-Table -a FolderPath, ItemsInFolder, FolderAndSubfolderSize
$ReceiverCalendarName = ($CalStats | Where-Object FolderType -EQ "Calendar").Name

if ($CalStats | Where-Object Name -Like $owner* ) {
Write-Host -ForegroundColor Yellow "Looks like we might have found a copy of the Owner Calendar in the Receiver Calendar."
$CalStats | Where-Object Name -Like $owner* | Format-Table -a FolderPath, ItemsInFolder, FolderAndSubfolderSize
if (($CalStats | Where-Object Name -Like $owner*).count -gt 1) {
Write-Host -ForegroundColor Yellow "Warning :Might have found more than one copy of the Owner Calendar in the Receiver Calendar."
}
} else {
Write-Host -ForegroundColor Yellow "Warning: Could not Identify the Owner Calendar in the Receiver Calendar."
}

if ($ReceiverCalendarName -like "REDACTED-*" ) {
Write-Host -ForegroundColor Yellow "Do Not have PII information for the Receiver"
$script:PIIAccess = $false
}

Write-Host -ForegroundColor Cyan "`n`nReceiver Accepted the Following Modern Calendar Sharing Accept Logs:"
ProcessCalendarSharingAcceptLogs -Identity $Receiver

if (Get-Command -Name Get-CalendarEntries -ErrorAction SilentlyContinue) {
Write-Verbose "Found Get-CalendarEntries cmdlet. Running cmdlet: Get-CalendarEntries -Identity $Receiver"
# ToDo: Check each value for proper sharing permissions (i.e. $X.CalendarSharingPermissionLevel -eq "ReadWrite" )
$ReceiverCalEntries = Get-CalendarEntries -Identity $Receiver
Write-Host "CalendarGroupName : $($ReceiverCalEntries.CalendarGroupName)"
Write-Host "CalendarName : $($ReceiverCalEntries.CalendarName)"
Write-Host "OwnerEmailAddress : $($ReceiverCalEntries.OwnerEmailAddress)"
Write-Host "SharingModelType: $($ReceiverCalEntries.SharingModelType)"
Write-Host "IsOrphanedEntry: $($ReceiverCalEntries.IsOrphanedEntry)"

# need to check if Get-CalendarValidationResult in the PS Workspace
if ((Get-Command -Name Get-CalendarValidationResult -ErrorAction SilentlyContinue) -and
$null -ne $ReceiverCalEntries) {
Write-Host "Running cmdlet: Get-CalendarValidationResult -Version V2 -Identity $Receiver -SourceCalendarId $($ReceiverCalEntries[0].LocalFolderId) -TargetUserId $Owner -IncludeAnalysis 1 -OnlyReportErrors 1"
$ewsId_del= $ReceiverCalEntries[0].LocalFolderId
Get-CalendarValidationResult -Version V2 -Identity $Receiver -SourceCalendarId $ewsId_del -TargetUserId $Owner -IncludeAnalysis 1 -OnlyReportErrors 1
}
}

if ($script:PIIAccess) {
Write-Host "Checking for Owner copy Calendar in Receiver Calendar:"
Write-Host "Running cmdlet:"
Write-Host -NoNewline -ForegroundColor Yellow "Get-MailboxCalendarFolder -Identity ${Receiver}:\$ReceiverCalendarName\$($script:OwnerMB.DisplayName)"
try {
Get-MailboxCalendarFolder -Identity "${Receiver}:\$ReceiverCalendarName\$($script:OwnerMB.DisplayName)" | Format-List Identity, CreationTime, ExtendedFolderFlags, ExtendedFolderFlags2, CalendarSharingFolderFlags, CalendarSharingOwnerSmtpAddress, CalendarSharingPermissionLevel, SharingLevelOfDetails, SharingPermissionFlags, LastAttemptedSyncTime, LastSuccessfulSyncTime, SharedCalendarSyncStartDate
} catch {
Write-Error "Failed to get the Owner Calendar from the Receiver Mailbox. This is fine if not using Modern Sharing."
}
} else {
Write-Host "Do Not have PII information for the Receiver."
Write-Host "Get PII Access for $($script:OwnerMB.Database)."
}
}

# Main
GetOwnerInformation -Owner $Owner
GetReceiverInformation -Receiver $Receiver
Loading

0 comments on commit dc10261

Please sign in to comment.