Monday, January 21, 2013

Get Directory permission with powershell

One of my customers was facing a migration of their data to a new location. It was a cross domain migration so we don't want to take all the permissions with us in the migration (robocopy /DATS) and needed to find out the current situation.

Before I used the tool Security Explorer from Little Wonders.. And found out that through several take overs this is now Dell... (Scriptlogic -> Quest --> Dell)

since the software had gotten richer over the years with additional functions the price had also gone up, and is now only available in a time limited license..

So I thought, I can do this myself in PowerShell... And the result was very good (as I do say so myself)

I started out with the following script to get the permissions on the first 3 levels..
$OutFile = "C:\temp\folder-Permissions.csv"
$Header = "Folder Path,IdentityReference,AccessControlType,FileSystemRights,IsInherited"
Del $OutFile
Add-Content -Value $Header -Path $OutFile 

$RootPath = "z:\"

$Folders = get-CHildItem $RootPath | where {$_.psiscontainer -eq $true}

foreach ($Folder in $Folders){
 $ACLs = get-acl $Folder.fullname | ForEach-Object { $_.Access  }
 Foreach ($ACL in $ACLs){
  if ($ACL.IdentityReference -eq "BUILTIN\Administrators"){
  }else{
   $OutInfo = $Folder.Fullname + ";" + $ACL.IdentityReference  + ";" + $ACL.AccessControlType + ";" + $ACL.FileSystemRights + ";" + $ACL.IsInherited
   Add-Content -Value $OutInfo -Path $OutFile
  } 
 }
}

$Folders = get-CHildItem $RootPath\* | where {$_.psiscontainer -eq $true}

foreach ($Folder in $Folders){
 $ACLs = get-acl $Folder.fullname | ForEach-Object { $_.Access  }
 Foreach ($ACL in $ACLs){
  if ($ACL.IdentityReference -eq "BUILTIN\Administrators"){
  }else{
   $OutInfo = $Folder.Fullname + ";" + $ACL.IdentityReference  + ";" + $ACL.AccessControlType + ";" + $ACL.FileSystemRights + ";" + $ACL.IsInherited
   Add-Content -Value $OutInfo -Path $OutFile
  } 
 }
}

$Folders = get-CHildItem $RootPath\*\* | where {$_.psiscontainer -eq $true}

foreach ($Folder in $Folders){
 $ACLs = get-acl $Folder.fullname | ForEach-Object { $_.Access  }
 Foreach ($ACL in $ACLs){
  if ($ACL.IdentityReference -eq "BUILTIN\Administrators"){
  }else{
   $OutInfo = $Folder.Fullname + ";" + $ACL.IdentityReference  + ";" + $ACL.AccessControlType + ";" + $ACL.FileSystemRights + ";" + $ACL.IsInherited
   Add-Content -Value $OutInfo -Path $OutFile
  } 
 }
}

$Folders = get-CHildItem $RootPath\*\*\* | where {$_.psiscontainer -eq $true}

foreach ($Folder in $Folders){
 $ACLs = get-acl $Folder.fullname | ForEach-Object { $_.Access  }
 Foreach ($ACL in $ACLs){
  if ($ACL.IdentityReference -eq "BUILTIN\Administrators"){
  }else{
   $OutInfo = $Folder.Fullname + ";" + $ACL.IdentityReference  + ";" + $ACL.AccessControlType + ";" + $ACL.FileSystemRights + ";" + $ACL.IsInherited
   Add-Content -Value $OutInfo -Path $OutFile
  } 
 }
}

So since this worked, I started optimizing the code for posting on my blog.. and came up with the following. (Remember I want only the first 3 levels)

$OutFile = "C:\temp\folder-Permissions.csv"
$Header = "Folder Path,IdentityReference,AccessControlType,FileSystemRights,IsInherited"
Del $OutFile
Add-Content -Value $Header -Path $OutFile 

$RootPath = "z:\"

Function getSubFolderpermissions ($folders){
 foreach ($Folder in $Folders){
  $ACLs = get-acl $Folder.fullname | ForEach-Object { $_.Access  }
  Foreach ($ACL in $ACLs){
   if ($ACL.IdentityReference -eq "BUILTIN\Administrators"){
   }else{
    $OutInfo = $Folder.Fullname + ";" + $ACL.IdentityReference  + ";" + $ACL.AccessControlType + ";" + $ACL.FileSystemRights + ";" + $ACL.IsInherited
    Add-Content -Value $OutInfo -Path $OutFile
   } 
  }
 }
}


$Folders = get-CHildItem $RootPath | where {$_.psiscontainer -eq $true}
getSubFolderpermissions $folders

$Folders = get-CHildItem $RootPath\* | where {$_.psiscontainer -eq $true}
getSubFolderpermissions $folders

$Folders = get-CHildItem $RootPath\*\* | where {$_.psiscontainer -eq $true}
getSubFolderpermissions $folders

$Folders = get-CHildItem $RootPath\*\*\* | where {$_.psiscontainer -eq $true}
getSubFolderpermissions $folders


but still I didn't like this..

so after I little active rewriting I found this:
$OutFile = "C:\temp\folder-Permissions.csv"
$Header = "Folder Path,IdentityReference,AccessControlType,FileSystemRights,IsInherited"
remove-item $OutFile
Add-Content -Value $Header -Path $OutFile 

$RootPath = "\\san2\hdswbr$\Docs"
$levelsdeep = 3

Function getSubFolderpermissions ($Folders, $currentlevel){
 if ($currentlevel -lt ($levelsdeep + 1)){
  foreach ($map in $Folders){
   $subfolders = get-CHildItem $map.fullname | where {$_.psiscontainer -eq $true}
   if (!($subfolders -eq $null)){
    getSubFolderPermissions $subfolders ($currentlevel +1)
   }
   $ACLs = get-acl $map.fullname | ForEach-Object { $_.Access  }
   Foreach ($ACL in $ACLs){
    if ($ACL.IdentityReference -eq "BUILTIN\Administrators"){
    }else{
     $OutInfo = $map.Fullname + ";" + $ACL.IdentityReference  + ";" + $ACL.AccessControlType + ";" + $ACL.FileSystemRights + ";" + $ACL.IsInherited
     Add-Content -Value $OutInfo -Path $OutFile
    } 
   }
  }
 }
}

$Mappen = get-CHildItem $RootPath | where {$_.psiscontainer -eq $true}
getSubFolderpermissions $Mappen, 0

3 comments:

  1. Two comments:
    1) Change $Header to use same delimiter as $OutInfo
    $Header = "Folder Path;IdentityReference;AccessControlType;FileSystemRights;IsInherited"
    2) Recursion works but when run against a unc path after gettting all levels points back to C: drive and then resurses from there

    ReplyDelete
  2. Thanks for the comments..

    About your comment number 2, I didn't run into this, the recursion was working... I am currently searching for the actual script which I used, to see if I missed something in my post.

    Thanks for the feedback. I will update my post later.

    ReplyDelete
  3. I had problems with the recursion falling back to C:\ as well. I resolved it by eliminating the recursion:

    $MasterDirectory = "\\SERVERNAME\SHARENAME"
    $Date = "{0:yyyyMMdd-HHmm}" -f (Get-Date)
    $OutFile = $("C:\Output\FolderPermissions_" + $Date + ".txt")
    $Header = "Folder Path;IdentityReference;AccessControlType;FileSystemRights;IsInherited"

    remove-item $OutFile
    Add-Content -Value $Header -Path $OutFile

    $Directories = ls $MasterDirectory -directory -r | % {$_.FullName}

    ForEach ($Directory in $Directories){
    $ACLs = get-acl $Directory | % { $_.Access}
    ForEach ($ACL in $ACLs){
    If ($ACL.IdentityReference -eq "BUILTIN\Administrators"){
    }else{

    $OutInfo = $Directory + ";" + $Name.ToString() + ";" + $ACL.AccessControlType + ";" + $ACL.FileSystemRights + ";" + $ACL.IsInherited
    Add-Content -Value $OutInfo -Path $OutFile
    }
    }
    }

    ReplyDelete