├── Get-NonGroupPermissions.ps1 ├── README.md ├── gitattributes └── gitignore /Get-NonGroupPermissions.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Gets a list of folders within a share that have individual user permissions set, rather than the approved role groups from within AD 4 | .EXAMPLE 5 | .\Get-NonGroupPermissions.ps1 -Path '\\server\share\path' -Domain acmecorp -OutputFilepath C:\Temp\Test.csv -Email -To reciever@acme.com -From sender@acme.com -SmtpServer smtp.acme.com -Subject 'Test email' -Verbose -Recurse 6 | .NOTES 7 | Author - Robert Ainsworth - https://ainsey11.com 8 | Contributor - Shawn Esterman - https://github.com/ShawnEsterman 9 | #> 10 | 11 | function Get-NonGroupPermissions{ 12 | 13 | [CmdletBinding()] 14 | Param ( 15 | [Parameter(Mandatory = $true, 16 | ValueFromPipeline = $true, 17 | ValueFromPipelineByPropertyName = $true)] 18 | [ValidateScript({ $_ | ForEach-Object -Process { Test-Path -Path $_ } })] 19 | [String[]] 20 | $Path, 21 | [Parameter(Mandatory = $true)] 22 | [String] 23 | $Domain = "acme.com", 24 | [switch] 25 | $Recurse, 26 | [String] 27 | $OutputFilepath = "C:\Support\FoldersWithIndividualAccess.csv", 28 | [Parameter(Mandatory = $true, 29 | ParameterSetName = 'Email')] 30 | [Switch] 31 | $Email, 32 | [Parameter(ParameterSetName = 'Email')] 33 | [ValidateScript({ $_ | ForEach-Object -Process { try { New-Object System.Net.Mail.MailAddress($_) } catch { return $false } }; return $true })] 34 | [String[]] 35 | $To = 'defaultto@acme.com', 36 | [Parameter(ParameterSetName = 'Email')] 37 | [ValidateScript({ try { New-Object System.Net.Mail.MailAddress($_); return $true } catch { return $false } })] 38 | [String] 39 | $From = 'defaultfrom@acme.com', 40 | [Parameter(ParameterSetName = 'Email')] 41 | $SmtpServer = 'defaultsmtp.acme.com', 42 | [Parameter(ParameterSetName = 'Email')] 43 | $Subject = "Files and Folders found with individual permissions assigned" 44 | ) 45 | 46 | $PreContent = @" 47 | 48 | 49 | 50 | 78 | 79 | 80 | "@ 81 | 82 | $PostContent = @" 83 | 84 | 85 | "@ 86 | 87 | $Body = $PreContent 88 | $Body += "

$Subject

" 89 | 90 | $Data = @() 91 | 92 | if ($Recurse) 93 | { 94 | $Folderlist = get-ChildItem $Path -recurse | ?{ $_.PSIsContainer } 95 | foreach ( $p in $Folderlist ) { 96 | Write-Verbose "Checking path $P" 97 | $Data += (Get-ChildItem $Path -Recurse |Get-Acl).Access.Where{ $_.IdentityReference -like "$domain\*.*" } | 98 | Select-Object -Property FileSystemRights,IdentityReference,Isinherited | 99 | ForEach-Object -Process { 100 | Write-Verbose "Found $($_.FileSystemRights) on path $("$path\$Folderlist") for $($_.IdentityReference)" 101 | [pscustomobject] @{ 102 | Path = "$path\$p" 103 | FileSystemRights = $_.FileSystemRights 104 | IdentityReference = $_.IdentityReference 105 | IsInherited = $_.IsInherited 106 | } 107 | } 108 | } 109 | } 110 | 111 | else { 112 | 113 | foreach ( $P in $Path ) { 114 | Write-Verbose "Checking path $P" 115 | $Data += (Get-Acl -LiteralPath $Path).Access.Where{ $_.IdentityReference -like "$domain\*.*" } | 116 | Select-Object -Property FileSystemRights,IdentityReference,Isinherited | 117 | ForEach-Object -Process { 118 | Write-Verbose "Found $($_.FileSystemRights) on path $($P) for $($_.IdentityReference)" 119 | [pscustomobject] @{ 120 | Path = $P 121 | FileSystemRights = $_.FileSystemRights 122 | IdentityReference = $_.IdentityReference 123 | IsInherited = $_.IsInherited 124 | } 125 | } 126 | } 127 | 128 | } 129 | 130 | if ( $Data ) { 131 | 132 | if ( $OutputFilepath ) { 133 | Write-Verbose "Outputting data to $OutputFilePath" 134 | $Data | Export-Csv -LiteralPath $OutputFilepath -NoTypeInformation 135 | } 136 | 137 | if ( $Email ) { 138 | 139 | $Body += $Data | ConvertTo-Html -Fragment 140 | $Body += $PostContent 141 | 142 | $Params = @{ 143 | To = $To 144 | From = $From 145 | SmtpServer = $SmtpServer 146 | Subject = $Subject 147 | Priority = 'High' 148 | Body = $Body 149 | BodyAsHtml = $true 150 | } 151 | Send-MailMessage @Params 152 | } 153 | 154 | } 155 | } 156 | 157 | Get-NonGroupPermissions -Path '\\timicogroup.local\dfs01' -Domain timicogroup.local -OutputFilepath C:\Temp\Test.csv -Email -To rob@timico.co.uk -From sender@timico.co.uk -SmtpServer mail.timicogroup.local -Subject 'Test email' -Verbose -Recurse -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ainsey11's Powershell NTFS Individual User Permissions Report 2 | This bit of code scans over a folder set in a variable, then e-mails a set address if there are permissions for individual users. 3 | 4 | ### Installation Instructions : 5 | Place in any dir, then execute with the relevant arguments. 6 | 7 | ### Example : 8 | .\Get-NonGroupPermissions.ps1 -Path '\\server\share\path' -Domain acmecorp -OutputFilepath C:\Temp\Test.csv -Email -To reciever@acme.com -From sender@acme.com -SmtpServer smtp.acme.com -Subject 'Test email' -Verbose -Recurse 9 | 10 | ##### Improvement Plan: 11 | - Look into making a seperate script that writes to a database for logging and a scaled solutuion for large file servers. -------------------------------------------------------------------------------- /gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear in the root of a volume 35 | .DocumentRevisions-V100 36 | .fseventsd 37 | .Spotlight-V100 38 | .TemporaryItems 39 | .Trashes 40 | .VolumeIcon.icns 41 | 42 | # Directories potentially created on remote AFP share 43 | .AppleDB 44 | .AppleDesktop 45 | Network Trash Folder 46 | Temporary Items 47 | .apdisk 48 | --------------------------------------------------------------------------------