#PSScriptInfo
.VERSION 1.0
.GUID 03a6a60d-01b5-49a8-adb9-ca890ea6f2eb
.AUTHOR Juan Granados
.COPYRIGHT 2021 Juan Granados
.TAGS Audit Report HTML csv mail File Access
.LICENSEURI https://raw.githubusercontent.com/juangranados/powershell-scripts/main/LICENSE
.PROJECTURI https://github.com/juangranados/powershell-scripts/tree/main/File%20Server%20Access%20Audit%20Report%20with%20PowerShell
.RELEASENOTES
Initial release
#>
<#
.DESCRIPTION
This PowerShell script allows to audit several file servers and send a report in CSV and HTML by mail.
CSV file can be import on Excel to generate a File Audit Report.
HTML report can filter and sorting rows by server, time, user, file or operation (read, delete or write).
Requirements:
Enable Audit in Windows and target folders, instructions: https://github.com/juangranados/powershell-scripts/tree/main/File%20Server%20Access%20Audit%20Report%20with%20PowerShell
Author: Juan Granados
#>
#########################################################################################################################################
#Variables to modify
#########################################################################################################################################
# List of servers to check audit events
$server = "SRVJ-FS01","SVMEN01"
# List of file extensions to ignore
$ignoredExtensions = "tmp","rgt","mta","tlg","nd","ps","log","ldb","crdownload","DS_Store","cdf-ms","ini"
# List of users to ignore. If you do not want to ignore users, leave it empty.
# Example: $skippedUsers = "administrator","audit-test"
$skippedUsers = ""
# List of files to audit if you are interested only in a few files. If empty, all files (except those with ignored extensions) will be included in report.
# For example: $filesToAudit = "MontlyReport.xlsx","Internal Database.mdb" -> Only this two files will be included in report.
$filesToAudit = ""
# Number of hours back in time to check audit events
$hoursBackToCheck = "24"
# Reports path
$timestamp = Get-Date -format yyyy-MM-dd_HH-mm-ss # Timestamp to add to report name
$htmlReportPath = "$PSScriptRoot\" + "$timestamp" + "_AuditReport.html" # default: html report path in script path.
$csvReportPath = "$PSScriptRoot\" + "$timestamp" + "_AuditReport.csv" # default: csv report path in script path.
$transcriptPath = "$PSScriptRoot\" + "$timestamp" + "_AuditReport.log" # default: PowerShell transcript in script path.
# Mail settings
[string]$SMTPServer="mail.contoso.com" # If "None", no mail is sending. Example: [string]$SMTPServer="mail.contoso.com"
[string[]]$Recipient="jgranados@contoso.com" # List of recipients. Example: [string[]]$Recipient="jdoe@contoso.com","fsmith@contoso.com"
[string]$Sender = "audit-reports@contoso.com" # Sender. Example: [string]$Sender="reports@contoso.com"
[string]$Username="audit-reports@contoso.com" # User name to authenticate with mail server. If "None", no auth is performed. Example: [string]$Username="jdoe@gmail.com"
[string]$Password="P@ssw0rd" # Password to to authenticate with mail server. If "None", no auth is performed. Example: [string]$Password="P@ssw0rd"
[string]$SSL="True" # Using TLS/SSL to authenticate. Example: [string]$SSL="True" (Is required for Gmail or Office365)
[int]$Port=25 # Port of mail server. Example: [int]$Port=587
#########################################################################################################################################
#Internal variables. Do not modify.
#########################################################################################################################################
$ErrorActionPreference = "Stop"
$startDate = (get-date).AddHours(-$hoursBackToCheck)
$ns = @{e = "http://schemas.microsoft.com/win/2004/08/events/event"}
$htmlEvents = [System.Collections.ArrayList]@()
$csvContents = @()
$accessMasks = [ordered]@{
'0x80' = 'Read'
'0x2' = 'Write'
'0x10000' = 'Delete'
}
$previousTimeCreated = ""
$previousSubjectUserName = ""
$previousObjectName = ""
$previousAccessMask = ""
$lastEventTimeCreated = ""
$evts = $null
#########################################################################################################################################
#Functions. Do not modify.
#########################################################################################################################################
Function getFileExtension($path) {
$file = (Split-Path -Path $path -Leaf).Split(".")
return $file[$file.Length-1]
}
# This function checks to see if the file should be ignored.
Function isTempFile($path) {
$fileName = (Split-Path -Path $path -Leaf)
$fileExtension = getFileExtension $path
If ($fileName.substring(0,1) -eq "~" -or $fileName -eq "thumbs.db" -or $fileName.Substring(0,1) -eq "$") {
return $true
}
ForEach($extension in $ignoredExtensions) {
if ($fileExtension -eq $extension) {
return $true
}
}
return $false
}
Function isUserToSkip($user) {
foreach ($svr in $server) {
$serverUser = $svr + '$'
if ($user -eq $serverUser) {
return $true
}
}
foreach ($skippedUser in $skippedUsers) {
if ($user -eq $skippedUser) {
return $true
}
}
return $false
}
Function isFileToAudit($path) {
if ($filesToAudit -eq "") {
return $true
} else {
$fileName = (Split-Path -Path $path -Leaf)
foreach ($file in $filesToAudit) {
if ($file -eq $fileName) {
return $true
}
}
return $false
}
}
Function isFile($path) {
try {
if ((Get-Item $path) -is [System.IO.FileInfo]) {
return $true
}
} catch {
if ((Split-Path -Path $path -Leaf) -like "*.*") {
return $true
}
}
}
function checkIfAddEvent($serverName, $timeCreated, $userName, $objectName, [string]$accessMask) {
if (-not [string]::IsNullOrEmpty($accessMask)){
if ($script:previousTimeCreated) {
if ($timeCreated -gt $script:previousTimeCreated.AddSeconds(1) -or $userName -ne $script:previousSubjectUserName -or $objectName -ne $script:previousObjectName) {
Write-Host "Adding event: $serverName | $script:previousTimeCreated | $script:previousSubjectUserName | $script:previousObjectName | $script:previousAccessMask" -ForegroundColor Green
# Add event to html
$htmlEvents.add("
`n") | Out-Null
$htmlEvents.add("
$($serverName)
`n") | Out-Null # Time of access
$htmlEvents.add("