File Share inventory for all DFS shares via PowerShell – Permissions and Size

Managing file servers in a large environment where there are more than one administrators might be a tough job if you do not have audit tool keeping track of changes in File Shares. Similar problematic part is migrating stuff from one server to another. DFS helps, but how to document everything??

What about PowerShelling it??

# Author : Nitish Kumar
# Performs an audit of Sita departmental file shares
# Outputs the results to a csv file. 
# version 1.0
# 26 March 2018

$AllDFS = (Get-DFSNRoot | ?{$_.State -eq 'Online'}).Path
$DFSInfo = @()

ForEach($DFS in $AllDFS){
	$DFS = $DFS + "\*"
	$DFSInfo += Get-DFSNFolder -path  $DFS | Get-DFSNFolderTarget | Select-object Path, Targetpath

Function GetShareDetails
    Param (
	$array = @()
	$Share = Get-WmiObject -class Win32_Share -Computername $Server |Where-object {$ -eq $ShareName}	
	$BaseShare = "\\" + $Server + "\" + $ShareName
	$Postfix = $FullPath.Replace($BaseShare,"")	
	Try { $ShareSec = Get-WmiObject -Class Win32_LogicalShareSecuritySetting -ComputerName $Server  -filter "Name='$($Share.Name)'"  -ErrorAction silentlycontinue  }
	Catch {}
	if ($shareSec) {
		$SD = $sharesec.GetSecurityDescriptor()
		$ShareInfo = $SD.Descriptor.DACL | % {$_ | select AccessMask,AceFlags,AceType,@{e={$_.trustee.Name};n='User'},@{e={$_.trustee.Domain};n='Domain'},@{e={$_.trustee.SIDString};n='SID'}}
		#Convert the current output into something more readable
		Switch ($ShareInfo.AceType) 
			0 {$AceType = "Allow"} 
			1 {$AceType = "Deny"} 
			2 {$AceType = "Audit"} 
		$ShareInfo | Add-Member NoteProperty AccessType $AceType 
		#Convert the current output into something more readable
		Switch ($ShareInfo.AccessMask) 
			2032127 {$AccessMask = "FullControl"} 
			1179785 {$AccessMask = "Read"} 
			1180063 {$AccessMask = "Read, Write"} 
			1179817 {$AccessMask = "ReadAndExecute"} 
			-1610612736 {$AccessMask = "ReadAndExecuteExtended"}
			1245631 {$AccessMask = "ReadAndExecute, Modify, Write"}
			1180095 {$AccessMask = "ReadAndExecute, Write"} 
			268435456 {$AccessMask = "FullControl (Sub Only)"} 
			default {$AccessMask = $DACL.AccessMask} 
		$ShareInfo | Add-Member NoteProperty Access $AccessMask
	} else {
		Write-Warning "Specified share not exist or you may not have sufficient rights to access them!"
	$SharePath = $Share.Path + $Postfix
	$Details = Get-Item $SharePath
	$Files = Get-ChildItem -Recurse $SharePath -ErrorAction SilentlyContinue | Where-Object {!$_.PSIsContainer}
	$SharePermissions = (Get-ACL -path $SharePath).Access | Select-object IdentityReference, FileSystemRights, AccessControlType
	$Size = [Math]::Round(($Files | Measure-Object Length -Sum -ErrorAction SilentlyContinue).Sum / 1MB, 2) 		
	$obj = New-Object PSObject       		 	
	$obj |Add-Member -MemberType NoteProperty -Name "ServerName" $env:Computername
	$obj |Add-Member -MemberType NoteProperty -Name "ShareName" $Share.Name
	$obj |Add-Member -MemberType NoteProperty -Name "Path" $SharePath	
	$obj |Add-Member -MemberType NoteProperty -Name "PermittedOnShare" $($ShareInfo.User -join ',')
	$obj |Add-Member -MemberType NoteProperty -Name "SharePermissionType" $($ShareInfo.AccessType -join ',')
	$obj |Add-Member -MemberType NoteProperty -Name "SharePermissionLevel" $($ShareInfo.Access -join ',')
	$obj |Add-Member -MemberType NoteProperty -Name "Allowedusers" $($SharePermissions.IdentityReference -join ',')
	$obj |Add-Member -MemberType NoteProperty -Name "Accesstype" $($SharePermissions.FileSystemRights -join ',')
	$obj |Add-Member -MemberType NoteProperty -Name "SizeinMB" $Size 
	$obj |Add-Member -MemberType NoteProperty -Name "Filescount" $Files.count	
	$obj |Add-Member -MemberType NoteProperty -Name "DateModified" $Details.LastWritetime 
	$obj |Add-Member -MemberType NoteProperty -Name "DateLastAccessed" $Details.LastAccesstime 
	$array +=$obj 
	$array | select-object ServerName,ShareName,Path,PermittedOnShare,SharePermissionType,SharePermissionLevel,Allowedusers,AccessType,SizeinMB, Filescount, DateModified, DateLastAccessed

$Result = @()
$k = 0

ForEach ($DFSObject in $DFSInfo)
	$Server = [String]$DFSObject.TargetPath.Split("\")[2]
	$Sharename = [String]$DFSObject.TargetPath.Split("\")[3]
	$FullPath = [String]$DFSObject.TargetPath
	Write-Progress -activity "Getting File Shares Details ($k / $($DFSInfo.Count)):" -status "Percent Done: " -PercentComplete (($k / $DFSInfo.Count)  * 100) -CurrentOperation "Now processing $($DFSObject.Path)"	
	$temp = Invoke-Command -ComputerName $Server -ScriptBlock ${Function:GetShareDetails} -ArgumentList $Server, $ShareName, $FullPath -ErrorAction Continue
	$temp | Add-Member -MemberType NoteProperty "DFSShareName" -Value $DFSObject.Path 
	$temp |  select-object ServerName,DFSShareName,ShareName,Path,PermittedOnShare,SharePermissionType,SharePermissionLevel,Allowedusers,AccessType,SizeinMB, Filescount,DateModified, DateLastAccessed
	$Result += $temp
$Result | Select-object ServerName,DFSShareName,ShareName,Path,PermittedOnShare,SharePermissionType,SharePermissionLevel,Allowedusers,AccessType,SizeinMB, Filescount,DateModified, DateLastAccessed|export-csv -nti $env:userprofile\desktop\FileSharedata_$(get-date -Uformat "%Y%m%d-%H%M%S").csv

Share your feedback


PowerShell: Quickly finding source of Brute Force attack on O365 Tenant

A small PowerShell Script to quickly find out source IPs in case of a brute force attack on O365 Infra. This can save manual efforts and can improve turnaround time to mitigate the issue in Infrastructures which still not using MFA or ExtraNetLockOut. This is just a basic code. One can set email alerts basis the thresholds or even can write a custom event on any of the server to be picked by SCOM or OMS.

Pre-requisites: Auditing should be enabled on Federation servers

# To investigate Account lockouts on Federation Servers
# Author: Nitish Kumar
# v1.0

# Thresholds
$Period = 1
$LockedAccountsThreshold = 50

#federation Servers
$FServers = ("XYZ01", "ABC01") # Replace the name with actual federation server names
$LastEvents = @()
$LockEvents = @()

#collect events from all federation servers
ForEach($Server in $FServers){
$Events = Get-WinEvent -Computername $Server -FilterHashtable @{LogName='Security';ID=411; StartTime=$((get-date).addhours(-($Period)))}| ?{$_.message -like "*Locked*"} | Select-object MachineName, TimeCreated, Message
$LastEvents += $Events

ForEach($Ev in $LastEvents){
$Array = $Ev.Message.split("`n")
$a = $Array[13].split("@")
$Temp = New-Object -TypeName PSObject -Property @{
FederationServer = $Ev.MachineName
TimeWritten = $Ev.TimeCreated
IPAddress = [string]$Array[10]
UserAccount = $a[0]
$LockEvents += $Temp

# Find unique users from the lockouts
$LockedAccounts = $LockEvents.UserAccount | sort-object -unique
write-host "A total $($LockedAccounts.count) Accounts locked out in last $($Period) hours: `n$($LockedAccounts -join ",")" -foregroundcolor RED

$Logfile = "c:\temp\Lockouts_$((Get-Date).ToString('MM-dd-yyyy_hh-mm-ss')).csv"
$LockEvents | Select-object FederationServer, TimeWritten, UserAccount, IPAddress | Export-csv -nti $Logfile

PowerShell script for DNS Inventory

Here goes the PowerShell script for DNS Inventory for AD Integrated DNS zones. This script needs to be altered to set variable for DC Name and once ran, it would fetch details from each zone and would save it in separate files.

Updated the code to provide option to dynamic selection of DNS Server. Thanks for input from @singhalyogi22

Note: Skipping SOA records etc to avoid complexity

Continue reading “PowerShell script for DNS Inventory”

PowerShell Script for DHCP settings, leases and reservations inventory

Another day, another PowerShell script.. this time to get DHCP settings, leases and reservations from all DHCP Servers in current domain. Pre-requisite is all DHCP Servers should be Windows 2012 based and WinRM should be enabled on all of them.

Continue reading “PowerShell Script for DHCP settings, leases and reservations inventory”

PowerShell Script for patching Domain Servers remotely

In line with the last post on File Server inventory, here comes the another script to perform patching for Domain Servers from a remote machine.

PowerShell already has methods to perform patching on any server, where we can list what all patches are available and create a downloader to download and install them all, but a limitation to the capability is, the same can not be done remotely. As a workaround for that, we would be creating schedule task on the remote machine via the script and performing the patching via triggering that schedule task.

It would involve two scripts InstallPatches.ps1 and PatchServer.ps1, whose code I would be listing below. It would make use of c:\temp directory and would be keeping logs and scripts in the same location. Also we would need any shared location, where we would keep a copy of InstallPatches.ps1, which then would be copied dynamically over the servers during patching. I have kept script source path as “\\ABCXYZ\sources\installpatches.ps1” while it can be changed as per your environment.

Continue reading “PowerShell Script for patching Domain Servers remotely”

PowerShell Script for File Share inventory of all File Servers

Managing a large infra never happens to be easy without right kind of tools and tools usually come with cost. In past Unix users used to taunt Windows users on this point as they used to enjoy many open source products and scripts which Windows users weren’t privy of. Things changed a lot since PowerShell.

Presenting you a script to have a size and permission inventory of all your shares on all file servers. Below would be the pre-requisites:

1. Names of all file servers.
2. All the file servers should have WinRM enabled (Windows 2012 servers have it on by default and for Windows 2008, winrm quickconfig may do the trick).
3. Obviously Local Administrator permissions on all File Servers, which should have permissions on shares as well.

After that just change the variable $RemoteComputers value with the name of file servers in place of dummy values placed in form of array right now. That’s it.

This script lists names of all servers (provided by you), shares on them, NTFS permissions, Size in MB, Last modified date and Last accessed date.

Continue reading “PowerShell Script for File Share inventory of all File Servers”

In embrace of sea and greenery of South-Memoirs from day 7, 8 and 9


Munnar was the only location, where we were scheduled to stay for two nights means full one day for the place as the day next, we were to leave as early as possible to reach Bangalore in time.

When we woke up, it was raining but nevertheless, we got ready and then by 7.30 AM, we would have been on nearby restaurant for a heavy breakfast. After which we started driving after 8.30 AM. This time we had hired a guide to drive with us and show us around @ 500Rs.


It continued to rain though we had hopes that it would settle till the time we reach to the viewpoints and luckily it happened that way.

Continue reading “In embrace of sea and greenery of South-Memoirs from day 7, 8 and 9”