Avatar of Albert Widjaja
Albert Widjaja
Flag for Australia asked on

Modifying Powershell script to list the SYSVOL NTFS & Share permission directory from all Domain controllers ?

Hi All,

Can anyone here please assist me in modifying the PowerShell script below to list all domain controllers SYSVOL directory NTFS and Share security ?

Get-ADComputer -LDAPFilter "(&(objectCategory=computer)(userAccountControl:1.2.840.113556.1.4.803:=8192))" | ForEach-Object {
    "Processing $($_.DNSHostName) ..." | Write-Host
	....................
	
} | Export-Csv -Path C:\TEMP\Result.csv -NoTypeInformation -UseCulture

Open in new window


and this one:

################################################################################
# AUDIT FILE & FOLDER PERMISSIONS v1.1
# by Roman Zarka | Microsoft Services
################################################################################

$ErrorActionPreference = "Continue" 
$strComputer = $env:ComputerName 
$colDrives = Get-PSDrive -PSProvider Filesystem 
ForEach ($DriveLetter in $colDrives) { 
    $StartPath = "$DriveLetter`:\" 
    # Get-ChildItem -LiteralPath $StartPath -Recurse | 
	# Folder only not including the files
	 Get-ChildItem -LiteralPath $StartPath -Recurse | ?{ $_.PSIsContainer } |
    ForEach { 
      $FullPath = Get-Item -LiteralPath (Get-Item -LiteralPath $_.PSPath) 
      (Get-Item -LiteralPath $FullPath).GetAccessControl() | 
      Select * -Expand Access | 
      Select @{N='Server Name';E={$strComputer}}, 
             @{N='Full Path';E={$FullPath}}, 
             @{N='Type';E={If($FullPath.PSIsContainer -eq $True) {'D'} Else {'F'}}}, 
             @{N='Owner';E={$_.Owner}}, 
             @{N='Trustee';E={$_.IdentityReference}}, 
             @{N='Inherited';E={$_.IsInherited}}, 
             @{N='Inheritance Flags';E={$_.InheritanceFlags}}, 
             @{N='Ace Flags';E={$_.PropagationFlags}}, 
             @{N='Ace Type';E={$_.AccessControlType}}, 
             @{N='Access Masks';E={$_.FileSystemRights}} } | 
      Export-CSV -NoTypeInformation -Delimiter "|" –Path C:\TEMP\"$strComputer`_$DriveLetter.csv" }

Open in new window


Thanks in advance,
PowershellActive DirectorySecurity

Avatar of undefined
Last Comment
Ben Personick (Previously QCubed)

8/22/2022 - Mon
Ben Personick (Previously QCubed)

Here you go:

## Script Name: DCSysVol_ACLs.ps1
## Version: 1.0.0
#

# =================================== #
# = Define Parameters				= #

param(
	$DebugPreference="SilentlyContinue"
	# $DebugPreference="Continue"
) 
# Set Debug Level, Continue shows debug messages, SilentlyContinue is Default
Write-Debug "Debug-Preferences:"
Write-Debug "DebugPreference = $DebugPreference"

# =================================== #
# = Begin Functions					= #

## Function: Get-IsISE
function Get-IsISE {
# Tests whether the current environment contains the $psISE Variable which is normally only set when running in ISE
    try {    
        return $psISE -ne $null;
    }
    catch {
        return $false;
    }
}

# =================================== #
# = Initialize Variables			= #

## 0.1: Set the script Path (If in ISE, set it to a manual value, otherwise use script location value)
$scriptPath = 'C:\Admin\Scripts\Experts-Exchange\29015623_Modifying-Powershell-script-to-list-the-SYSVOL-NTFS-Share-permission-directory-from-all-Domain-controllers'
if ( -not ( Get-IsISE ) ) {
	# Get Path for this script File and set it to a variable
	$scriptPath = split-path -parent $MyInvocation.MyCommand.Definition
}

## 0.2: Set CSV Output name
$CSV_Path = "$ScriptPath\All_Domain_Controllers_ACLs.csv"

## 0.3: Set Group Search base to check specific groups for thier users.
$Group_SearchBase = "OU=Groups,OU=Root,DC=Domain,DC=com"

## 0.4: Initialize Results variable
$Results = @()

# =================================== #
# = Begin Main						= #

$Domain_Controllers = Get-ADComputer -LDAPFilter "(&(objectCategory=computer)(userAccountControl:1.2.840.113556.1.4.803:=8192))"
$Domain_Controllers | ForEach-Object {
	$ServerName = $($_.DNSHostName)
	Write-Host "Processing $($_.DNSHostName) "
	$StartPath = "\\$($_.DNSHostName)\Sysvol\"
	Write-Host " Start Path: $StartPath "
	$DC_SysVol_Paths = Get-ChildItem -LiteralPath $StartPath -Recurse |  where-object { $_.PSIsContainer } 
	foreach ($D_S_P in $DC_SysVol_Paths ){
		$Fullpath = $(Get-Item -LiteralPath (Get-Item -LiteralPath  $D_S_P.PSPath))
		Write-Host "Fullpath:  $Fullpath"
		$Path_ACLs = (Get-Item -LiteralPath $FullPath).GetAccessControl()| Select * -Expand Access
		foreach ($P_ACL in $Path_ACLs) {
			$Results += New-Object PSObject -Property @{
				ServerName = $ServerName
				FullPath = $Fullpath
				Type = 'Folder'
				Owner = $P_ACL.Owner
				Trustee = $P_ACL.IdentityReference
				Inherited = $P_ACL.IsInherited 
				Inheritance_Flags = $P_ACL.InheritanceFlags 
				Ace_Flags = $P_ACL.PropagationFlags 
				Ace_Type = $P_ACL.AccessControlType
				Access_Masks = $P_ACL.FileSystemRights
			}
		}
	}
}
$Results | Export-CSV $CSV_Path -NoTypeInformation

Open in new window

Ben Personick (Previously QCubed)

Just updated with the cleaned up version of the code with customary commenting and putting the output in the directory of the script.

Here is example output from my domain:

ServerName	Trustee	Type	FullPath	Owner	Ace_Flags	Inherited	Inheritance_Flags	Ace_Type	Access_Masks
DC01.Domain.Com	NT AUTHORITY\Authenticated Users	Folder	\\DC01.Domain.Com\Sysvol\Domain.Com	BUILTIN\Administrators	None	TRUE	None	Allow	ReadAndExecute, Synchronize
DC01.Domain.Com	NT AUTHORITY\Authenticated Users	Folder	\\DC01.Domain.Com\Sysvol\Domain.Com	BUILTIN\Administrators	InheritOnly	TRUE	ContainerInherit, ObjectInherit	Allow	-1610612736
DC01.Domain.Com	S-1-5-32-549	Folder	\\DC01.Domain.Com\Sysvol\Domain.Com	BUILTIN\Administrators	None	TRUE	None	Allow	ReadAndExecute, Synchronize
DC01.Domain.Com	S-1-5-32-549	Folder	\\DC01.Domain.Com\Sysvol\Domain.Com	BUILTIN\Administrators	InheritOnly	TRUE	ContainerInherit, ObjectInherit	Allow	-1610612736
DC01.Domain.Com	BUILTIN\Administrators	Folder	\\DC01.Domain.Com\Sysvol\Domain.Com	BUILTIN\Administrators	None	TRUE	None	Allow	Write, ReadAndExecute, ChangePermissions, TakeOwnership, Synchronize

Open in new window

Ben Personick (Previously QCubed)

I literally just noticed you wanted to see the share permissions as well as the NTFS permissions.  However the scripts you provided only find the DCs and give you the NTFS Permissions.

  Share permissions are tricky remotely, you need to use WMIC (Yuck) but there is a script available from Microsoft that just does this.

Link to MS Original Script: https://gallery.technet.microsoft.com/scriptcenter/List-Share-Permissions-83f8c419

The following is the above script built loops through all the domain controllers and executes against each of them to also give you the share permissions on every DC as a separate list for you:

$Domain_Controllers = Get-ADComputer -LDAPFilter "(&(objectCategory=computer)(userAccountControl:1.2.840.113556.1.4.803:=8192))"

$Domain_Controllers | ForEach-Object {
	$computer  = $($_.DNSHostName)
	Write-Host "Processing $computer"
	$shares = gwmi -Class win32_share -ComputerName $computer | select -ExpandProperty Name
	
	foreach ($share in $shares) {  
		$acl = $null  
		Write-Host $share -ForegroundColor Green  
		Write-Host $('-' * $share.Length) -ForegroundColor Green  
		$objShareSec = Get-WMIObject -Class Win32_LogicalShareSecuritySetting -Filter "name='$Share'"  -ComputerName $computer 
		try {  
			$SD = $objShareSec.GetSecurityDescriptor().Descriptor    
			foreach($ace in $SD.DACL){   
				$UserName = $ace.Trustee.Name      
				If ($ace.Trustee.Domain -ne $Null) {$UserName = "$($ace.Trustee.Domain)\$UserName"}    
				If ($ace.Trustee.Name -eq $Null) {$UserName = $ace.Trustee.SIDString }      
				[Array]$ACL += New-Object Security.AccessControl.FileSystemAccessRule($UserName, $ace.AccessMask, $ace.AceType)  
				} #end foreach ACE            
			} # end try  
		catch  
			{ Write-Host "Unable to obtain permissions for $share" }  
		$ACL  
		Write-Host $('=' * 50)  
	} # end foreach $share
}

Open in new window


That should cover the other half of your request
Experts Exchange has (a) saved my job multiple times, (b) saved me hours, days, and even weeks of work, and often (c) makes me look like a superhero! This place is MAGIC!
Walt Forbes
Albert Widjaja

ASKER
Thanks Ben,

The script is running longer than I thought :-)
Can I still run it just for the SYSVOL directory?
Ben Personick (Previously QCubed)

I literally just noticed you wanted to see the share permissions as well as the NTFS permissions.  However the scripts you provided only find the DCs and give you the NTFS Permissions.

  Share permissions are tricky remotely, you need to use WMIC (Yuck) but there is a script available from Microsoft that just does this.

Link to MS Original Script: https://gallery.technet.microsoft.com/scriptcenter/List-Share-Permissions-83f8c419

The following code is the script from MS I just linked to, but I amended it to loop through your domain controllers to also give you the share permissions on every DC as a separate list in a separate CSV for you.

## Script Name: DCSysVol_ACLs.ps1
## Version: 1.0.0
#

# =================================== #
# = Define Parameters				= #

param(
	$DebugPreference="SilentlyContinue"
	# $DebugPreference="Continue"
) 
# Set Debug Level, Continue shows debug messages, SilentlyContinue is Default
Write-Debug "Debug-Preferences:"
Write-Debug "DebugPreference = $DebugPreference"

# =================================== #
# = Begin Functions					= #

## Function: Get-IsISE
function Get-IsISE {
# Tests whether the current environment contains the $psISE Variable which is normally only set when running in ISE
    try {    
        return $psISE -ne $null;
    }
    catch {
        return $false;
    }
}

# =================================== #
# = Initialize Variables			= #

## 0.1: Set the script Path (If in ISE, set it to a manual value, otherwise use script location value)
$scriptPath = 'C:\Admin\Scripts\Experts-Exchange\29015623_Modifying-Powershell-script-to-list-the-SYSVOL-NTFS-Share-permission-directory-from-all-Domain-controllers'
if ( -not ( Get-IsISE ) ) {
	# Get Path for this script File and set it to a variable
	$scriptPath = split-path -parent $MyInvocation.MyCommand.Definition
}

## 0.2: Set CSV Output name
$CSV_Path = "$ScriptPath\All_Domain_Controllers_Shares.csv"

## 0.3: Initialize Results variable
$Results = @()

# =================================== #
# = Begin Main						= #

$Domain_Controllers = Get-ADComputer -LDAPFilter "(&(objectCategory=computer)(userAccountControl:1.2.840.113556.1.4.803:=8192))"

$Domain_Controllers | ForEach-Object {
	$computer  = $($_.DNSHostName)
	Write-Host "Processing $computer"
	$shares = gwmi -Class win32_share -ComputerName $computer | select -ExpandProperty Name
	
	foreach ($share in $shares) {  
		$acl = $null  
		Write-Host $share -ForegroundColor Green  
		Write-Host $('-' * $share.Length) -ForegroundColor Green  
		$objShareSec = Get-WMIObject -Class Win32_LogicalShareSecuritySetting -Filter "name='$Share'"  -ComputerName $computer 
		try {  
			$SD = $objShareSec.GetSecurityDescriptor().Descriptor    
			foreach($ace in $SD.DACL){   
				$UserName = $ace.Trustee.Name      
				If ($ace.Trustee.Domain -ne $Null) {$UserName = "$($ace.Trustee.Domain)\$UserName"}    
				If ($ace.Trustee.Name -eq $Null) {$UserName = $ace.Trustee.SIDString }      
				[Array]$ACL += New-Object Security.AccessControl.FileSystemAccessRule($UserName, $ace.AccessMask, $ace.AceType)  
				} #end foreach ACE            
			} # end try  
		catch  
			{ Write-Host "Unable to obtain permissions for $share" }  
		$Results +=$ACL
                $ACL | Out-String | Write-Debug
		Write-Debug "$('=' * 50)"
	} # end foreach $share
}
Write-Debug ""
Write-Debug "Results:"
$Results | Out-String | Write-Debug
$Results | Export-CSV $CSV_Path -NoTypeInformation

Open in new window

That should cover the other half of your request
Ben Personick (Previously QCubed)

Did you only want it for the root directory "Sysvol"?  It seemed you wanted all the permissions based off the scripts.

If so here is the simplified ACL script which only returns the info for the Sysvol directories

## Script Name: DCSysVolOnly_ACLs.ps1
## Version: 1.0.0
#

# =================================== #
# = Define Parameters				= #

param(
	$DebugPreference="SilentlyContinue"
	# $DebugPreference="Continue"
) 
# Set Debug Level, Continue shows debug messages, SilentlyContinue is Default
Write-Debug "Debug-Preferences:"
Write-Debug "DebugPreference = $DebugPreference"

# =================================== #
# = Begin Functions					= #

## Function: Get-IsISE
function Get-IsISE {
# Tests whether the current environment contains the $psISE Variable which is normally only set when running in ISE
    try {    
        return $psISE -ne $null;
    }
    catch {
        return $false;
    }
}

# =================================== #
# = Initialize Variables			= #

## 0.1: Set the script Path (If in ISE, set it to a manual value, otherwise use script location value)
$scriptPath = 'C:\Admin\Scripts\Experts-Exchange\29015623_Modifying-Powershell-script-to-list-the-SYSVOL-NTFS-Share-permission-directory-from-all-Domain-controllers'
if ( -not ( Get-IsISE ) ) {
	# Get Path for this script File and set it to a variable
	$scriptPath = split-path -parent $MyInvocation.MyCommand.Definition
}

## 0.2: Set CSV Output name
$CSV_Path = "$ScriptPath\All_Domain_Controllers_ACLs.csv"

## 0.3: Set Group Search base to check specific groups for thier users.
$Group_SearchBase = "OU=Groups,OU=Root,DC=Domain,DC=com"

## 0.4: Initialize Results variable
$Results = @()

# =================================== #
# = Begin Main						= #

$Domain_Controllers = Get-ADComputer -LDAPFilter "(&(objectCategory=computer)(userAccountControl:1.2.840.113556.1.4.803:=8192))"
$Domain_Controllers | ForEach-Object {
	$ServerName = $($_.DNSHostName)
	Write-Host "Processing $($_.DNSHostName) "
	$StartPath = "\\$($_.DNSHostName)\Sysvol\"
	Write-Host " Start Path: $StartPath "
	$DC_SysVol_Paths = Get-ChildItem -LiteralPath $StartPath |  where-object { $_.PSIsContainer } 
	foreach ($D_S_P in $DC_SysVol_Paths ){
		$Fullpath = $(Get-Item -LiteralPath (Get-Item -LiteralPath  $D_S_P.PSPath))
		Write-Host "Fullpath:  $Fullpath"
		$Path_ACLs = (Get-Item -LiteralPath $FullPath).GetAccessControl()| Select * -Expand Access
		foreach ($P_ACL in $Path_ACLs) {
			$Results += New-Object PSObject -Property @{
				ServerName = $ServerName
				FullPath = $Fullpath
				Type = 'Folder'
				Owner = $P_ACL.Owner
				Trustee = $P_ACL.IdentityReference
				Inherited = $P_ACL.IsInherited 
				Inheritance_Flags = $P_ACL.InheritanceFlags 
				Ace_Flags = $P_ACL.PropagationFlags 
				Ace_Type = $P_ACL.AccessControlType
				Access_Masks = $P_ACL.FileSystemRights
			}
		}
	}
}
$Results | Export-CSV $CSV_Path -NoTypeInformation
$Results | Format-Table -Auto

Open in new window

Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
Albert Widjaja

ASKER
Hi Ben,

Thanks for the Share Permission script as well, however, the script that you share does not show the Server name in the first column ?

## Script Name: DCSysVol_ACLs.ps1
## Version: 1.0.0
#

# =================================== #
# = Define Parameters				= #

param(
	$DebugPreference="SilentlyContinue"
	# $DebugPreference="Continue"
) 
# Set Debug Level, Continue shows debug messages, SilentlyContinue is Default
Write-Debug "Debug-Preferences:"
Write-Debug "DebugPreference = $DebugPreference"

# =================================== #
# = Begin Functions					= #

## Function: Get-IsISE
function Get-IsISE {
# Tests whether the current environment contains the $psISE Variable which is normally only set when running in ISE
    try {    
        return $psISE -ne $null;
    }
    catch {
        return $false;
    }
}

# =================================== #
# = Initialize Variables			= #

## 0.1: Set the script Path (If in ISE, set it to a manual value, otherwise use script location value)
$scriptPath = 'C:\Admin\Scripts\Experts-Exchange\29015623_Modifying-Powershell-script-to-list-the-SYSVOL-NTFS-Share-permission-directory-from-all-Domain-controllers'
if ( -not ( Get-IsISE ) ) {
	# Get Path for this script File and set it to a variable
	$scriptPath = split-path -parent $MyInvocation.MyCommand.Definition
}

## 0.2: Set CSV Output name
$CSV_Path = "$ScriptPath\All_Domain_Controllers_Shares.csv"

## 0.3: Initialize Results variable
$Results = @()

# =================================== #
# = Begin Main						= #

$Domain_Controllers = Get-ADComputer -LDAPFilter "(&(objectCategory=computer)(userAccountControl:1.2.840.113556.1.4.803:=8192))"

$Domain_Controllers | ForEach-Object {
	$computer  = $($_.DNSHostName)
	Write-Host "Processing $computer"
	$shares = gwmi -Class win32_share -ComputerName $computer | select -ExpandProperty Name
	
	foreach ($share in $shares) {  
		$acl = $null  
		Write-Host $share -ForegroundColor Green  
		Write-Host $('-' * $share.Length) -ForegroundColor Green  
		$objShareSec = Get-WMIObject -Class Win32_LogicalShareSecuritySetting -Filter "name='$Share'"  -ComputerName $computer 
		try {  
			$SD = $objShareSec.GetSecurityDescriptor().Descriptor    
			foreach($ace in $SD.DACL){   
				$UserName = $ace.Trustee.Name      
				If ($ace.Trustee.Domain -ne $Null) {$UserName = "$($ace.Trustee.Domain)\$UserName"}    
				If ($ace.Trustee.Name -eq $Null) {$UserName = $ace.Trustee.SIDString }      
				[Array]$ACL += New-Object Security.AccessControl.FileSystemAccessRule($UserName, $ace.AccessMask, $ace.AceType)  
				} #end foreach ACE            
			} # end try  
		catch  
			{ Write-Host "Unable to obtain permissions for $share" }  
		$Results +=$ACL
                $ACL | Out-String | Write-Debug
		Write-Debug "$('=' * 50)"
	} # end foreach $share
}
Write-Debug ""
Write-Debug "Results:"
$Results | Out-String | Write-Debug
$Results | Export-CSV $CSV_Path -NoTypeInformation

Open in new window

Ben Personick (Previously QCubed)

Hey, I just left off the Server name variable.

Here it includes it for you.

Thanks

## Script Name: DCS_Share_ACLs.ps1
## Version: 1.0.1
#

# =================================== #
# = Define Parameters				= #

param(
	$DebugPreference="SilentlyContinue"
	# $DebugPreference="Continue"
) 
# Set Debug Level, Continue shows debug messages, SilentlyContinue is Default
Write-Debug "Debug-Preferences:"
Write-Debug "DebugPreference = $DebugPreference"

# =================================== #
# = Begin Functions					= #

## Function: Get-IsISE
function Get-IsISE {
# Tests whether the current environment contains the $psISE Variable which is normally only set when running in ISE
    try {    
        return $psISE -ne $null;
    }
    catch {
        return $false;
    }
}

# =================================== #
# = Initialize Variables			= #

## 0.1: Set the script Path (If in ISE, set it to a manual value, otherwise use script location value)
$scriptPath = 'C:\Admin\Scripts\Experts-Exchange\29015623_Modifying-Powershell-script-to-list-the-SYSVOL-NTFS-Share-permission-directory-from-all-Domain-controllers'
if ( -not ( Get-IsISE ) ) {
	# Get Path for this script File and set it to a variable
	$scriptPath = split-path -parent $MyInvocation.MyCommand.Definition
}

## 0.2: Set CSV Output name
$CSV_Path = "$ScriptPath\All_Domain_Controllers_Shares.csv"

## 0.3: Initialize Results variable
$Results = @()

# =================================== #
# = Begin Main						= #

$Domain_Controllers = Get-ADComputer -LDAPFilter "(&(objectCategory=computer)(userAccountControl:1.2.840.113556.1.4.803:=8192))"

$Domain_Controllers | ForEach-Object {
	$ServerName  = $($_.DNSHostName)
	Write-Host "Processing $ServerName"
	$shares = gwmi -Class win32_share -ComputerName $ServerName | select -ExpandProperty Name
	
	foreach ($share in $shares) {  
		$acl = $null  
		Write-Host $share -ForegroundColor Green  
		Write-Host $('-' * $share.Length) -ForegroundColor Green  
		$objShareSec = Get-WMIObject -Class Win32_LogicalShareSecuritySetting -Filter "name='$Share'"  -ComputerName $ServerName 
		try {  
			$SD = $objShareSec.GetSecurityDescriptor().Descriptor    
			foreach($ace in $SD.DACL){   
				$UserName = $ace.Trustee.Name      
				If ($ace.Trustee.Domain -ne $Null) {$UserName = "$($ace.Trustee.Domain)\$UserName"}    
				If ($ace.Trustee.Name -eq $Null) {$UserName = $ace.Trustee.SIDString }      
				[Array]$ACL += New-Object Security.AccessControl.FileSystemAccessRule($ServerName, $UserName, $ace.AccessMask, $ace.AceType)  
				} #end foreach ACE            
			} # end try  
		catch  
			{ Write-Host "Unable to obtain permissions for $share" }  
		$Results +=$ACL
                $ACL | Out-String | Write-Debug
		Write-Debug "$('=' * 50)"
	} # end foreach $share
}
Write-Debug ""
Write-Debug "Results:"
$Results | Out-String | Write-Debug
$Results | Export-CSV $CSV_Path -NoTypeInformation

Open in new window

Albert Widjaja

ASKER
Hi Ben,

Thanks for the follow-up.
However, I got this error when I execute the script above for the share permission:

gwmi : The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)
At H:\Powershell scripts\Get-SYSVOL-Share-permission.ps1:54 char:12
+ ...   $shares = gwmi -Class win32_share -ComputerName $ServerName | selec ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [Get-WmiObject], COMException
    + FullyQualifiedErrorId : GetWMICOMException,Microsoft.PowerShell.Commands.GetWmiObjectCommand

Open in new window


The .CSV file is empty.
All of life is about relationships, and EE has made a viirtual community a real community. It lifts everyone's boat
William Peck
Ben Personick (Previously QCubed)

Hello OP,

  RPC errors are due to a whole host of issues not related to the script.

  Could be WMIC is not running on the remote servers, could be share and permissions or Firewall blocking ports for RPC/SM, could be the script runs an account without access right to the servers, could not make the process a little easier.

 Note: the access maps are a sum of permissions, that maps to the permissions I put into this version, but I  can;t easily calculate them on the fly.

 Sysvol has some basic standard positions and you should be able to see if they differ from one another in the results.

be the service on the remote machines been to be restarted, could be problems with DNS or NetBIOS, etc.

That said I did make a few typos and I have re-written the core of the script with testing to make sure we get results

## Script Name: DCS_Share_ACLs.ps1
## Version: 1.0.1
#

# =================================== #
# = Define Parameters				= #

param(
	#$DebugPreference="SilentlyContinue"
	 $DebugPreference="Continue"
) 
# Set Debug Level, Continue shows debug messages, SilentlyContinue is Default
Write-Debug "Debug-Preferences:"
Write-Debug "DebugPreference = $DebugPreference"

# =================================== #
# = Begin Functions					= #

## Function: Get-IsISE
function Get-IsISE {
# Tests whether the current environment contains the $psISE Variable which is normally only set when running in ISE
    try {    
        return $psISE -ne $null;
    }
    catch {
        return $false;
    }
}

# =================================== #
# = Initialize Variables			= #

## 0.1: Set the script Path (If in ISE, set it to a manual value, otherwise use script location value)
$scriptPath = 'C:\Admin\Scripts\Experts-Exchange\29015623_Modifying-Powershell-script-to-list-the-SYSVOL-NTFS-Share-permission-directory-from-all-Domain-controllers'
if ( -not ( Get-IsISE ) ) {
	# Get Path for this script File and set it to a variable
	$scriptPath = split-path -parent $MyInvocation.MyCommand.Definition
}

## 0.2: Set CSV Output name
$CSV_Path = "$ScriptPath\All_Domain_Controllers_Shares.csv"

## 0.3: Initialize Results variable
$Results = @()
$acmsk = DATA {
ConvertFrom-StringData -StringData @’
1 = Read/List
2 = Write/Create File
4 = Append/Create Subdirectory
8 = Read extended attributes.
16 = Write extended attributes.
32 = Execute file/Traverse directory
64 = Delete directory
128 = Read file attributes.
256 = Change file attributes.
65536 = Delete
131072 = Read access to the security descriptor and owner.
262144 = Write access to the discretionary access control list (DACL).
524288 = Assigns the write owner.
1048576 = Synchronizes access, allows a process to wait
for an object to enter the signaled state.
‘@
}
$flags = @(1,2,4,8,16,32,64,128,256,65536,131072,262144,524288,1048576)



# =================================== #
# = Begin Main						= #

$Domain_Controllers = Get-ADComputer -LDAPFilter "(&(objectCategory=computer)(userAccountControl:1.2.840.113556.1.4.803:=8192))"

$Domain_Controllers | ForEach-Object {
	$ServerName  = $($_.DNSHostName)
	Write-Host "Processing $ServerName"
	$shares = gwmi -Class win32_share -ComputerName $ServerName | select -ExpandProperty Name
	
	foreach ($share in $shares) {  
		#$ACL = @( )
		Write-Host $share -ForegroundColor Green  
		Write-Host $('-' * $share.Length) -ForegroundColor Green  
		$objShareSec = Get-WMIObject -Class Win32_LogicalShareSecuritySetting -Filter "name='$Share'"  -ComputerName $ServerName
       # $Results += 
       IF ($objShareSec -ne $null) {
       $Results += foreach ($DACL IN $objShareSec.GetSecurityDescriptor().Descriptor.DACL) {

        New-Object PSObject -Property @{
           ServerName = $ServerName
           #UserName = $UserName
           Share_Name = $Share
           Domain = $($DACL.trustee.Domain)
           UserName = $($DACL.trustee.Name)
           Access_Mask = $($DACL.AccessMask)
           ACE_Type = $($DACL.AceType)
        }
            
        } 
        }
		#$Results +=$ACL
        #$ACL | Out-String | Write-Debug
	} # end foreach $share
}
Write-Debug ""
Write-Debug "Results:"
$Results | Out-String | Write-Debug
$Results | Export-CSV $CSV_Path -NoTypeInformation

Open in new window

Albert Widjaja

ASKER
Hi Ben,

Is the typo located in line 62 on your code above:

	1048576 = Synchronizes access, allows a process to wait for an object to enter the signaled state.
	‘@

Open in new window

ASKER CERTIFIED SOLUTION
Ben Personick (Previously QCubed)

Log in or sign up to see answer
Become an EE member today7-DAY FREE TRIAL
Members can start a 7-Day Free trial then enjoy unlimited access to the platform
Sign up - Free for 7 days
or
Learn why we charge membership fees
We get it - no one likes a content blocker. Take one extra minute and find out why we block content.
Not exactly the question you had in mind?
Sign up for an EE membership and get your own personalized solution. With an EE membership, you can ask unlimited troubleshooting, research, or opinion questions.
ask a question
Albert Widjaja

ASKER
Many thanks Ben !
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
Ben Personick (Previously QCubed)

Very Welcome!  Glad to help :)