Skip to content
The Lazy Administrator
  • Home
  • Disclaimer
  • Contact
  • About Me
  • Search Icon

The Lazy Administrator

Finding ways to do the most work with the least effort possible

Monitor Share and NTFS Permissions and E-Mail Changes

Monitor Share and NTFS Permissions and E-Mail Changes

March 17, 2018 Brad Wyatt Comments 1 comment

Recently I set out to find a way to get PowerShell to monitor NTFS and File permissions on a folder and file share. I wanted to know when permissions changed, how they changed (Read permission changed to Write permission), keep historical permission data I can reference, and lastly e-mail me the changes when they changed.

To keep historical data I made it create a new folder for each day it runs. The folder name is the date which is formatted as MMddyyyy. The next day it will run it will import the previous days results and compare them to the results of that day’s. 

A folder is created each day its ran with the name that follows MMddyyyy

Each time the script runs it will append any permission changes to the results CSV file instead of overwriting any previous results. This allows you to get an overview what has changed and when, that will span more than a single day. The CSV file also shows you what permission changed and what it changed to in the From and To column. The Account column will show you which account the permission changed for.

When the script sees that permissions have changed for either NTFS or Share it will e-mail you and the attachment like the one pictured above. If both NTFS and Share permissions changed it will e-mail you both attachments, if only one (NTFS or Share) changed it will only e-mail you the one that changed.

In my example I had it send mail using Office 365 by specifying my smtp server as smtp.office365.com in the script. To send mail we used the Send-MailMessage cmdlet. Since Office 365 requires authentication the script will create a credential PSObject and export it, this will allow it to import the credential object the next time it runs to authenticate to Office 365 without it being stored in plain text. 

The body of the e-mail will tell you which folder/share had a permission change. This can come in handy if you have it monitor multiple files/shares

When the script runs the console will show what it is doing each step of the way. This is helpful if you need to troubleshoot an issue when setting it up in your environment.

 

For best results I recommend setting up a scheduled task that will run this script daily. If you want to monitor multiple folders/shares then set up a separate scheduled task for each and don’t forget to change the path where the results are stored and make it different than where other ones are stored so they do not overwrite one another. 

The script does require the NTFSSecurity module which you can install by launching PowerShell and running

Install-Module -Name NTFSSecurity

 

Script:

<#	
	.NOTES
	===========================================================================
	 Created with: 	SAPIEN Technologies, Inc., PowerShell Studio 2018 v5.5.150
	 Created on:   	3/16/2018 10:33 PM
	 Created by:   	Bradley Wyatt
	 Version:		1.0.1     	
	===========================================================================
	.DESCRIPTION
		This script is best ran as a scheduled task set daily. It will monitor a share and a file for NTFS and Share permissions.
		Each day it is ran it will check to see if it has ran the day previously
		If it has it will run again, compare todays NTFS and Share permissions to yesterday's and export to a CSV file what has changed
		
		If only one item changed (NTFS and not shared for example) it will export the NTFS changes to the results file and 
		in the folder for today it will add a log text file letting you know that share permissions did not change from the previous day

		Each day it runs it will create a folder with the date formated as MMddyyyy
		The results file will also be formatted with MMddyyyy

		This file requires the NTFSSecurity module which can be installed by running Install-Module -Name NTFSSecurity

		The changes for both NTFS and Share will continusly be added to a single results csv. From there you can see what changed each day
		that there was a change. It will not create a new file everytime 

			Line 39: Creates a variable that will be the folder name of that days results. 
			Line 46: The location where the results will be stored
			Line 52: The share it will monitor permissions for
			Line 58: The folder it will monitor NTFS permissions for
			Line 67: The person the results will be email to
			Line 69: The email the results are emailed from
			Line 71: The SMTP server it will send through
			Line 73: The SMTP Port

#>


###VARIABLES#####
Write-Host "Getting today's date..." -ForegroundColor Yellow
$ResultsFolderName = ((get-date).ToString("MMddyyyy"))

#CSV path where the results will be stored
$CSVPath = "C:\Results\"

#Creates todays folder to store results in
Write-Host "Creating today's folder to store results in..." -ForegroundColor Yellow
$TodayResultFolder = New-Item -ItemType Directory ($CSVPath + $ResultsFolderName) -ErrorAction SilentlyContinue
Write-Host "Created folder $TodayResultFolder located at $CSVPath" -ForegroundColor Yellow

#The share name you want to monitor share permissions on
Write-Host "Getting Share..." -ForegroundColor Yellow
#Share Name
$ShareName = "1"
Write-Host "Share name is $ShareName" -ForegroundColor Yellow

#The NTFS folder you want to monitor NTFS permissions on
Write-Host "Getting NTFS Folder..." -ForegroundColor Yellow
#NTFS Folder
$NTFSFolder = "C:\1"
Write-Host "NTFS Folder is $NTFSFolder" -ForegroundColor Yellow

#Counter var's 
$var1 = 0
$var2 = 0

#EMAIL VARIABLES
#Who to send the email of changes to
$To = '[email protected]'
#Who the email is from
$From = '[email protected]'
#SMTP server to use
$SMTPServer = 'smtp.office365.com'
#SMTP port
$Port = 587

#Check for SMTP credentials
Write-Host "Checking for E-mail credentials..." -ForegroundColor Yellow
$SMTPCred = Test-Path ($CSVPath + "\" + "filemonitor.cred")
#if no credentials are found then prompt the user for them and save them
If ($SMTPCred -eq $false)
{
	$Credential = Get-Credential
	$Credential | Export-CliXml -Path ($CSVPath + "\" + "filemonitor.cred")
}


#CSV file name used to track share permissions
$CSVShare = "share_permissions.csv"
#CSV file name used to track NTFS permissions
$CSVNTFS = "ntfs_permissions.csv"

#Check for the NTFSSecurity module which is required
Write-Host "Checking for NTFSSecurity module..." -ForegroundColor Yellow
Import-Module NTFSSecurity -ErrorAction SilentlyContinue
$ModCheck = Get-Module | Where-Object { $_.Name -like "NTFSSecurity" }
If ($ModCheck -eq $Null)
{
	Write-Host "WARNING: NTFSSecurity module is not installed! 
Please install it by running 'Install-Module -Name NTFSSecurity' " -ForegroundColor Red
}
Else
{
	
	function Get-ChangeLog($referenceObject, $differenceObject, $identifier)
	{
		$props = $referenceObject | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name
		$diff = Compare-Object $referenceObject $differenceObject -Property $props -PassThru |
		Group-Object $identifier
		#capture modifications
		$today = (Get-Date).ToShortDateString()
		$modifications = ($diff | Where-Object Count -eq 2).Group | Group-Object $identifier
		foreach ($modification in $modifications)
		{
			#compare properties of each group
			foreach ($prop in $props)
			{
				if ($modification.Group[0].$prop -ne $modification.Group[1].$prop)
				{
					$output = $modification.Group | Where-Object { $_.SideIndicator -eq '<=' } |
					Select-Object (Write-Output Date $identifier ChangeType ChangedProperty From To)
					$output.Date = $today
					$output.ChangeType = "Modified"
					$output.ChangedProperty = $prop
					$output.From = ($modification.Group | Where-Object { $_.SideIndicator -eq '<=' }).$prop
					$output.To = ($modification.Group | Where-Object { $_.SideIndicator -eq '=>' }).$prop
					$output
				}
			}
		}
		#capture removals and additions
		$removalAdditions = $groupedDiff = ($diff | Where-Object Count -eq 1).Group | Group-Object $identifier
		foreach ($removalAddition in $removalAdditions)
		{
			$ht = [ordered]@{ }
			$ht.Add('Date', $today)
			$ht.Add($identifier, $removalAddition.Name)
			$ht.Add('ChangeType', '')
			$ht.Add('ChangedProperty', '')
			$ht.Add('From', '')
			$ht.Add('To', '')
			#addition
			if ($removalAddition.Group.SideIndicator -eq "=>")
			{
				$ht.ChangeType = 'Added'
			}
			#removal
			else
			{
				$ht.ChangeType = 'Removed'
			}
			New-Object PSObject -Property $ht
		}
	}
	
	
	Write-Host "Checking to see if yesterday's results are present..." -ForegroundColor Yellow
	If ((Test-Path -Path ($CSVPath + ((get-date).AddDays(-1).ToString("MMddyyyy")) + "\" + ((get-date).AddDays(-1).ToString("MMddyyyy")) + $CSVShare)) -eq $true -and (Test-Path -Path ($CSVPath + ((get-date).AddDays(-1).ToString("MMddyyyy")) + "\" + ((get-date).AddDays(-1).ToString("MMddyyyy")) + $CSVShare)) -eq $true)
	{
		Write-Host "Importing yesterday's share permissions result file..." -ForegroundColor Yellow
		#Import the last ran Share permissions CSV to the shell
		$YesterdaysShareCSV = Import-csv ($CSVPath + (get-date).AddDays(-1).ToString("MMddyyyy") + "\" + ((get-date).AddDays(-1).ToString("MMddyyyy")) + $CSVShare)
		Write-Host "Done!" -ForegroundColor Green
		
		Write-Host "Importing yesterday's NTFS permissions result file..." -ForegroundColor Yellow
		#Import last ran NTFS permissions csv to the shell
		$YesterdaysNTFSCSV = Import-csv ($CSVPath + (get-date).AddDays(-1).ToString("MMddyyyy") + "\" + ((get-date).AddDays(-1).ToString("MMddyyyy")) + $CSVNTFS)
		Write-Host "Done!" -ForegroundColor Green
		
		Write-Host "Getting today's share permissions..." -ForegroundColor Yellow
		#Gather todays share permissions
		$TodaysShareCSV = Get-SMBShareAccess -Name $ShareName | Select-Object Name, AccountName, AccessControlType, AccessRight | Export-Csv ($CSVPath + ((get-date).ToString("MMddyyyy")) + "\" + ((get-date).ToString("MMddyyyy")) + $CSVShare) -NoTypeInformation -Force
		Write-Host "Done!" -ForegroundColor Green
		
		Write-Host "Getting today's NTFS permissions..." -ForegroundColor Yellow
		#Gather todays NTFS Permissions 
		$TodaysNTFSCSV = Get-NTFSAccess -Path $NTFSFolder | Select-Object Account, AccessRights, AccessControlType | Export-Csv ($CSVPath + ((get-date).ToString("MMddyyyy")) + "\" + ((get-date).ToString("MMddyyyy")) + $CSVNTFS) -NoTypeInformation -Force
		Write-Host "Done!" -ForegroundColor Green
		
		Write-Host "Importing today's Share permissions..." -ForegroundColor Yellow
		#Import todays Share permissions
		$TodaysShare = Import-csv ($CSVPath + ((get-date).ToString("MMddyyyy")) + "\" + ((get-date).ToString("MMddyyyy")) + $CSVShare)
		Write-Host "Done!" -ForegroundColor Green
		
		Write-Host "Importing today's NTFS permissions..." -ForegroundColor Yellow
		#Import todays NTFS permissions
		$TodaysNFTS = Import-csv ($CSVPath + ((get-date).ToString("MMddyyyy")) + "\" + ((get-date).ToString("MMddyyyy")) + $CSVNTFS)
		Write-Host "Done!" -ForegroundColor Green
		
		Write-Host "Comparing yesterday's share permissions to today's..." -ForegroundColor Yellow
		#Compare yesterdays Share output to todays
		$ShareChange = Get-ChangeLog -differenceObject $TodaysShare -referenceObject $YesterdaysShareCSV ('AccountName')
		If ($ShareChange -eq $Null)
		{
			Write-Host "Share permissions haven't changed since yesterday's run..." -ForegroundColor Green
			"No Share permissions have changed since yesterday's results" | Out-File -FilePath ($CSVPath + ((get-date).ToString("MMddyyyy")) + "\" + "Sharelog.txt") -Force
		}
		Else
		{
			Write-Host "Share permissions have changed! Exporting the changed at $CSVPath" -ForegroundColor Green
			$var1 = 1
			$ShareChange | Export-Csv ($CSVPath + "DifferenceShares.csv") -NoTypeInformation -Append | Out-Null
		}
		
		Write-Host "Comparing yesterday's NTFS permissions to today's..." -ForegroundColor Yellow
		#Compare yesterdays NTFS output to todays
		$NTFSChange = Get-ChangeLog -differenceObject $TodaysNFTS -referenceObject $YesterdaysNTFSCSV ('Account')
		If ($NTFSChange -eq $Null)
		{
			Write-Host "NTFS permissions haven't changed since yesterday's run..." -ForegroundColor Green
			"No NTFS permissions have changed since yesterday's results" | Out-File -FilePath ($CSVPath + ((get-date).ToString("MMddyyyy")) + "\" + "NTFSlog.txt") -Force
		}
		Else
		{
			Write-Host "NTFS permissions have changed! Exporting the changed at $CSVPath" -ForegroundColor Green
			$var2 = 1
			$NTFSChange | Export-Csv ($CSVPath + "DifferenceNTFS.csv") -NoTypeInformation -Append | Out-Null
		}
		#IF both files changed, email both files
		If (($var1 -eq 1) -and ($var2 -eq 1))
		{
			Write-Host "NTFS and Share permissions changed, sending e-mail of changes to $To"
			Send-MailMessage `
							 -To $To `
							 -Subject 'Permission Monitor - NTFS + Share' `
							 -Body "NTFS and Share permissions changed for $ShareName and $NTFSFolder. Please see the attachment" `
							 -UseSsl `
							 -Port $Port `
							 -SmtpServer $SMTPServer `
							 -From $From `
							 -Credential (Import-CliXml -Path ($CSVPath + "\" + "filemonitor.cred"))`
							 -Attachments ($CSVPath + "\" + "DifferenceNTFS.csv"), ($CSVPath + "\" + "DifferenceShares.csv")
		}
		#IF NTFS permissions but Share permissions did not change
		ElseIf (($var1 -eq 0) -and ($var2 -eq 1))
		{
			Write-Host "NTFS permissions changed, sending e-mail of changes to $To"
			Send-MailMessage `
							 -To $To `
							 -Subject 'Permission Monitor - NTFS Only' `
							 -Body "NTFS permissions changed for $NTFSFolder. Please see the attachment" `
							 -UseSsl `
							 -Port $Port `
							 -SmtpServer $SMTPServer `
							 -From $From `
							 -Credential (Import-CliXml -Path ($CSVPath + "\" + "filemonitor.cred"))`
							 -Attachments ($CSVPath + "\" + "DifferenceNTFS.csv")
		}
		ElseIf (($var1 -eq 1) -and ($var2 -eq 0))
		{
			Write-Host "Share permissions changed, sending e-mail of changes to $To"
			Send-MailMessage `
							 -To $To `
							 -Subject 'Permission Monitor - Share Only' `
							 -Body "Share permissions changed for $ShareName. Please see the attachment" `
							 -UseSsl `
							 -Port $Port `
							 -SmtpServer $SMTPServer `
							 -From $From `
							 -Credential (Import-CliXml -Path ($CSVPath + "\" + "filemonitor.cred"))`
							 -Attachments ($CSVPath + "\" + "DifferenceShares.csv")
		}
		Else
		{
			Write-Host $_
		}
	}
	Else
	{
		Write-Host "No results from the previous day were found" -ForegroundColor Magenta
		
		Write-Host "Getting share permissions for today..." -ForegroundColor Yellow
		#Gather todays share permissions
		Get-SMBShareAccess -Name $ShareName | Select-Object Name, AccountName, AccessControlType, AccessRight | Export-Csv ($CSVPath + ((get-date).ToString("MMddyyyy")) + "\" + ((get-date).ToString("MMddyyyy")) + $CSVShare) -NoTypeInformation
		Write-Host "Done!" -ForegroundColor Green
		
		Write-Host "Getting NTFS permissions for today..." -ForegroundColor Yellow
		#Gather todays NTFS Permissions 
		Get-NTFSAccess -Path $NTFSFolder | Select-Object Account, AccessRights, AccessControlType | Export-Csv ($CSVPath + ((get-date).ToString("MMddyyyy")) + "\" + ((get-date).ToString("MMddyyyy")) + $CSVNTFS) -NoTypeInformation
		Write-Host "Done!" -ForegroundColor Green
	}
}

 

 

Brad Wyatt
Brad Wyatt

My name is Bradley Wyatt; I am a 5x Microsoft Most Valuable Professional (MVP) in Microsoft Azure and Microsoft 365. I have given talks at many different conferences, user groups, and companies throughout the United States, ranging from PowerShell to DevOps Security best practices, and I am the 2022 North American Outstanding Contribution to the Microsoft Community winner.


Permissions, PowerShell
Monitor, Permissions, PowerShell

Post navigation

NEXT
Create Bulk Office 365 Compliance Searches with PowerShell

One thought on “Monitor Share and NTFS Permissions and E-Mail Changes”

  1. Jamie says:
    August 16, 2018 at 3:21 am

    Hi,

    Love this script.
    I am looking for a way for this audit to carry on down child items of a folder and list that in the csv too.
    Could you think of a way to do this?

    Reply

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Subscribe

Email


Categories

  • Active Directory (8)
  • AI (3)
  • API (1)
  • AutoPilot (2)
  • Azure (15)
  • Bicep (4)
  • Connectwise (1)
  • Defender for Cloud Apps (1)
  • Delegated Admin (1)
  • DevOps (6)
  • Graph (6)
  • Intune (15)
  • LabTech (1)
  • Microsoft Teams (6)
  • Office 365 (19)
  • Permissions (2)
  • PowerShell (50)
  • Security (1)
  • SharePoint (3)
  • Skype for Business (1)
  • Terraform (1)
  • Uncategorized (2)
  • Yammer (1)

Recent Comments

  • MD SHARIQUE AKHTAR on Modern Active Directory – An update to PSHTML-AD-Report
  • TommyBoich on How The ConnectWise Manage API Handles Pagination with PowerShell
  • LOTTERY 365 LOGIN on Windows LAPS Management, Configuration and Troubleshooting Using Microsoft Intune
  • SPRUNKI PHASE 6 on Get a New Computer’s Auto Pilot Hash Without Going Through the Out of Box Experience (OOBE)
  • Mohammad Sherbaji on Get a New Computer’s Auto Pilot Hash Without Going Through the Out of Box Experience (OOBE)

1,738,813 People Reached

© 2025   All Rights Reserved.