none
Powershell script to find ACL's on network drives with paths over the 255 character limit.

    Întrebare

  • Hiya,

    I'm working on a long needed tidy up of our AD, after 12 years of different admins, 3 company aquisitions and no Standard practices.

    We have multiple File Servers, and Security groups scattered across them.  I've so far, from the 3000 Domain Local/Global groups, cleared out 500 empty groups.  The rest, which mostly relate to folder security, have naming conventions which leave no clue as to what they control.

    As such I thought the best thing to try and do was to rename these with names that are relavent to the Division/Dept/Drive that they sit on. 

    The problem I face having written a script (I'm still learning!) is running into the 260 Char path limit.  This script is designed to just get the Group and Folder it relates to and eventually export this to file, then I'll write another script to rename the groups as per our new standards.

    I've ended up hacking out alot of stuff from my script to try and give the bare bones here.  I figured that I only need look at Folders, domain accounts and ACLs that weren't inherited.  Any ideas on how to get around the 260 character limit within this, and still output its full path?  I'm having a look at error handling to see if I can get the failed path, then I guess map it briefly to continue the search, and remap it on the next loop...  Any ideas at all would be really helpful!

    Foreach ($Shareddrive in $Shareddrivelist){

    $folderslist = gci -recurse -force $Shareddrive |Where-Object {$_.PSIsContainer}

    foreach($folder in $folderslist){
    $acls = get-acl $folder.fullname

    foreach($acl in $acls){

    $ac = $acl.access
     
    foreach($a in $ac){
    if ($a.IsInherited){continue}


    $domainacc = $a.IdentityReference |Select-String "domainname" |Out-String


    if($domainacc -eq ""){continue}
    Write-host $domainacc $folder.fullname

    }

    }
    }

    }

    19 martie 2012 13:08

Răspunsuri

Toate mesajele

  • One way around this is by using net use loops, which create temporary folders when the scripts detects a path of x-numbers long. This is what I have used in the past but it is a cumbersome process. If you just want to list the ACL's of the remote folders then using a tool to do this for you would perhaps be an easier solution. I have both used FileACL and Setacl for this in the past. I have seen recommendations for SUBinACL from Microsoft as well, but I have not used it so I cannot vouch for that one working with +255 characters in path.

    Have a look at FileACL, if you want to test it on one of the folders containing a long path simply run:

    fileacl.exe /files /sub <path>

    Download links for tools:

    FileACL: http://www.gbordier.com/gbtools/downloadform.asp?VERSION=3.0.1.6

    SetACL: http://sourceforge.net/projects/setacl/files/

    SubinACL: http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=23510 

    19 martie 2012 13:53
    Moderator
  • I might have a look at that!   I would like to keep it all in one script and preferably all in Powershell if possible, but I'll try and download FileACL now see what I can get from it!

    19 martie 2012 15:13
  • For me scripting should make my life easier, in this case I would leverage PowerShell by parsing the output ,if required, into a format you prefer. It should be possible to do in PowerShell but you will be using workarounds to get there which will inevitably be slower. Let me know how you get along with any of the tools I listed!

    19 martie 2012 15:59
    Moderator
  • Hi Jaap,

    I'm testing fileacl now, it certainly seems to do the job to a degree, the problem is just the level of output still seems high mainly due to some porgrams seemingly adding rights without inheritence across it's subfolders...  Getting the feeling I've bitten off more than my PC can chew :-)

    It would be nice to have this all within Powershell to be honest, if only for the learning curve.   I have tried to tackle the file length issue, and failed so far a few times.

    I've tried to build a method of recursive searching through child directories, but my lack of programming skills are letting me down.

    One idea I was trying was to enter a root directory (i.e. fileserver\e$), find folders, check acls on those folders, then map that first folder, check that for folders, check acls of those folders, then so on and so on down the tree, when there are no folders, go back and check the next folder etc but it's way out of my league at the moment. 

    The thing is, it's just a resurse with a "New-PSDrive" stuck in it and a removal of that drive afterwards... Ideas do spring about how to do it, but I'm over or under thinking it...

    I could output each set of folders to an array then delete once checked I guess...  one of many options no doubt..

    20 martie 2012 13:06
  • Can you some of the code you have been working on, if you want to learn it would be best if you try to explain your thought process and post some code then you can get advice on both and improve your coding because of it.

    Also I would advise running Fileacl.exe on smaller subsections if you have a big amount of files of folders to index. Because in 99% of the cases files inherit permissions from their parent object you could probably just scan for folders and do a file and folder scan for 'suspicious' folders. Another alternative is to run fileacl with /NOINHERIT to limit the output to explicit permissions only. That should make your pc happy again.

    20 martie 2012 13:50
    Moderator
  • Hi Jaap,

    Sorry, I've been pulled off onto another issue, I've been revisiting this when I get a chance, I'll post my code back once I've tweaked it.

    I was using the /noinherited switch in fileacl, but it really does seem that some badyl written program has created a large quantity if sub-directories in alot of our trees, and so really skew the results.

    I've nearly sussed it though in Powershell, and will post once I get time!

    Regards,

    Neil.

    22 martie 2012 13:44
  • Hiya,

    Sorry I unmarked that as the answer,  as I did finally build a workaround script, what do you think?  I can see why you said it was cumbersome!

    This script will output to a Spreadsheet, map to long file name shares, but so far, has failed to make my tea...  What do you think?

    $domain = "DOMAIN"

    $startpath = "\\Servername\share"

    # Create Ecxcel spreadsheet for Data Collection
    $excel = new-object -comobject Excel.Application
    $workbooks = $excel.Workbooks.Add()
    $worksheets = $workbooks.worksheets
    $worksheet = $worksheets.Item(1)
    $worksheet.Name = “Assigned Permissions”
    $excel.Visible = $True
    $worksheet.Cells.Item(1,4) = “Assigned Permissions in ”
    $worksheet.Cells.Item(2,1) = “AD Group”
    $worksheet.Cells.Item(2,2) = “Folder applied to”
    [long]$column=1
    [long]$row= 3


    $stores = New-Object System.Collections.ArrayList


    # Adds $startpath to the array twice to allow for array item removal at start of While loop
    $stores.add($startpath)
    $stores.add($startpath)
    #While's through the store count till 0.
    while ($stores.count -gt 0){

    $stores.RemoveRange(0,1)
    $tostore = gci $stores[0]|?{$_.PSIsContainer}
    if ($tostore -eq $Null){continue}
    foreach ($path in $tostore){
    $path = $path.fullname
    $stores.Add($path)
    }
    if ($stores[0].length -gt 250){
    $testedpath = Test-path P:
    if ($testedpath -eq $True){Remove-PSDrive P:}

    New-PSDrive P -PSProvider Filesytem -Root $stores[0]
    $filepath = "P:"
    }
    else {$filepath = $stores[0]}
    $acls = get-acl $filepath
    foreach ($acl in $acls.access){
    if (!$acl.Isinherited){
    if ($acl.IdentityReference -match $domain){
    Write-host $acl.IdentityReference " in " $stores[0]
    $folderfullname = $stores[0] |Out-string
    $group = $acl.IdentityReference | ft -HideTableHeaders |Out-string
    $group = $group -replace $Domain,""
    $group = $group -replace "//",""  ##  CHANGE THESE  // TO BACKSLASHES!

    $worksheet.Cells.Item($row,$column)  = $group
    $column++
    $worksheet.Cells.Item($row,$column)  = $folderfullname
    $column = "1"
    $row++
    }
    }
    }

    }


    • Editat de Neil-C 26 martie 2012 16:05
    26 martie 2012 15:34
  • And then re-wrote it :P

     

    27 martie 2012 16:13