Auditing Admin Activities - reporting purposes

In many organizations that I visit, they have multiple administrators. If in case something breaks anytime, not a lot of administrators have any clear information on what was changed, what object was modified, who did the change and when was the change done.

This is not only applicable to customers who are on on-premises Exchange servers but also for the customers who are already on Exchange Online.

So, I thought of writing a script to get these information. Although it just uses our age old (yeah, since Exchange 2010 days) method of searching Admin audit logs, it gives it in a clear format for both admin to consume and understand the changes in the environment from Exchange admin console or Exchange management shell. So that if they review it, there is a clear information of what was changed from the Exchange environment perspective.

Use cases:

Exchange Admin takes permissions over another mailbox or adds user to permissions on another mailbox (can be sendas permission or full mailbox permission).

Exchange Admin makes a change with Exchange management shell/Exchange management Console/Exchange administration Center on a change in transport rule etc.

 


 

################################ Disclaimer ###################################

<# This software (or sample code) is not supported under any Microsoft standard support program or service.
The software is provided AS IS without warranty of any kind.
Microsoft further disclaims all implied warranties including, without limitation, any implied warranties of merchantability or of fitness for a particular purpose.
The entire risk arising out of the use or performance of the software and documentation remains with you.
In no event shall Microsoft, its authors, or anyone else involved in the
creation, production, or delivery of the software be liable for any damages whatsoever
(including, without limitation, damages for loss of business profits, business interruption, loss of business information, or other pecuniary loss)
arising out of the use of or inability to use the software or documentation, even if Microsoft has been advised of the possibility of such damages. #>
# Version 1.0
############################## Start of the script #################################

$smtp = "HTServer1.contoso.com" # This should be a Hub transport server in the environment.
# $smtp has the server name which can be used as a server to connect from the script and submit the email. This can be either an Exchange server/IIS SMTP server/Any other third party servers.
$from = "AdminAuditLogReport@domain.com" #This is just an email address that it shows up in the sender field - can be any email address.
# $from has the name that needs to appear in the from field of the email.
$users = "AuditManager@contoso.com"; # this can be any email address you would like to have.
#$users = "Auditmanageruser1@contoso.com","Auditmanageruser2@contoso.com"; #You can add any other users also who would like to receive this alert email for Admin Audit logs
$AdminAuditCount = 0
$Begin = $null
$Begin = Get-Date
$Start = $Begin.AddDays(-1)
$end = $Begin
$Filename = $null
$Filename = ".\AdminAuditLogSearch_" + $Begin.Hour + $Begin.Minute + "_" + $Begin.Day + "-" + $Begin.Month + "-" + $Begin.Year + ".htm"

$report = $null
$report += "<html>"
$report += "<head>"
$report += "<meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'>"
$report += '<title>Admin Audit Log Search Report</title>'
$report += '<STYLE TYPE="text/css">'
$report += "<!--"
$report += "td {"
$report += "font-family: Tahoma;"
$report += "font-size: 11px;"
$report += "border-top: 1px solid #999999;"
$report += "border-right: 1px solid #999999;"
$report += "border-bottom: 1px solid #999999;"
$report += "border-left: 1px solid #999999;"
$report += "padding-top: 0px;"
$report += "padding-right: 0px;"
$report += "padding-bottom: 0px;"
$report += "padding-left: 0px;"
$report += "}"
$report += "body {"
$report += "margin-left: 5px;"
$report += "margin-top: 5px;"
$report += "margin-right: 0px;"
$report += "margin-bottom: 10px;"
$report += ""
$report += "table {"
$report += "border: thin solid #000000;"
$report += "}"
$report += "-->"
$report += "</style>"
$report += "</head>"
$report += "<body>"
$report += "<table width='100%'>"
$report += "<tr bgcolor='#CCCCCC'>"
$report += "<td colspan='7' height='25' align='center'>"
$report += "<font face='tahoma' color='#003399' size='4'><strong>These were the Admin Audit logs on the Exchange Environment from $Start till $end </strong></font>"
$report += "</td>"
$report += "</tr>"
$report += "</table>"
$report += "<table width='100%'>"
$report += "<tr bgcolor=#CCCCCC>"
$report += "<td width='10%' align='center'>Admin Who Ran the command</td>"
$report += "<td width='10%' align='center'>Commandlet Run</td>"
$report += "<td width='10%' align='center'>Modified Object</td>"
$report += "<td width='10%' align='center'>Succeeded</td>"
$report += "<td width='10%' align='center'>Run Date</td>"
$report += "<td width='10%' align='center'>Server on which the commandlet was run</td>"
$report += "</tr>"
$AdminAuditLog = Search-AdminAuditLog -StartDate $Start -EndDate $end | where{($_.cmdletname -notlike "New-Mailbox") -and ($_.cmdletname -notlike "enable-mailbox") -and ($_.cmdletname -notlike "Set-Mailbox") -and ($_.cmdletname -notlike "New-Mailcontact") -and ($_.cmdletname -notlike "Set-Mailcontact") -and ($_.CmdletName -notlike "Add-DistributionGroupMember") -and ($_.cmdletname -notlike "Remove-DistributionGroupMember") -and ($_.Cmdletname -notlike "Set-DistributionGroup") -and ($_.Cmdletname -notlike "New-DistributionGroup") -and ($_.Cmdletname -notlike "New-MoveRequest") -and ($_.CmdletName -notlike "New-MailboxExportRequest") -and ($_.CmdletName -notlike "New-MailboxImportRequest") -and ($_.CmdletName -notlike "Suspend-MoveRequest") -and ($_.CmdletName -notlike "Remove-MoveRequest") -and ($_.Cmdlet -notlike "Search-Mailbox")}
# The above line has a lot of conditions that should not go in the report. The reason being - Admin Audit logs keeps track of any command which modifies an object on the Exchange server (Set, enable, add, remove, move, new etc.)
# Having this all other information is too much junk every day. Only the major changes should be monitored.
if ($AdminAuditLog -ne $null)
{
foreach ($Entry in $AdminAuditLog)
{
Write-Host $Entry.caller `t $Entry.cmdletname `t $Entry.ObjectModified `t $entry.Succeeded `t $entry.RunDate `t $entry.OriginatingServer -ForegroundColor GREEN
$caller = $entry.caller
$cmdlet = $entry.cmdletName
$objmodified = $entry.objectmodified
$success = $entry.succeeded
$RunDate = $entry.RunDate
$servername = $entry.originatingServer
$report += "<tr>"
$report += "<td>$caller</td>"
$report += "<td bgcolor='Yellow' align=center>$cmdlet</td>"
$report += "<td>$objmodified</td>"
$report += "<td>$success</td>"
$report += "<td>$RunDate</td>"
$report += "<td>$Servername</td>"
$report += "</tr>"
$AdminAuditCount += 1
}
}
else
{
Write-Output "No Commands were run which modified any objects in AD from $start till $end."
}

$report += "</table>"
$report += "<br>"
$report += "Note: This will Not Include any changes done on the Edge servers/Any modifications done in AD directly logging into AD servers(eg: using ADSIEDIT/DSA/Any AD tools)"
$report += "</body>"
$report += "</html>"
Write-Output $AdminAuditCount
if ($AdminAuditCount -ge 1)
{
foreach ($user in $users)
{
Send-MailMessage -BodyAsHTML $report -SmtpServer $smtp -From "$from" -To "$user" -subject "Administrator Audit Logs" # send emails to all the users which you had specified in the $users
$report | out-file -encoding ASCII -filepath .\reports\AdminAuditLogs\$Filename
# The above line saves a copy of the report in the location. So, there needs to be folder structure created for this.
}
}

############################## End of the script #################################

 


 

The above commandlet checks for admin activities in any environment - in terms of what changes were performed by the admin except the actions excluded above and sends an email to all the email addresses that is mentioned in the $users.

Admin audit logs are saved for a period of 90 days by default - customizable in on-premises Exchange server.

 Hope this helps a few of the admins out there who want to know what all changes were done in terms of Exchange environment in a specific duration.