7

We have a document management system that has million of files on a NTFS file system accessed through a network share. A single service account needs full permission to all of these files and the application brokers access using this service account.

During a migration of data, something happened and the permissions are now inconsistent.

I've been trying to write a script in PowerShell to identify which files don't have the appropriate ACE, but get-acl is somewhat...painful.

I've tried various combinations similar to:

get-childitem -recurse | get-acl | select -expandproperty access | 
where { $_.$_.IdentityReference -notcontains $principal

where $Principal is the user that needs permission in domain\user format.

There's got to be a way to do this, right? What is it? I'd like to keep it native to PowerShell and not use icacls or cacls if possible.

6
  • What you are trying to do is unclear: what do you mean "inconsistent" precisely and what is the end result you would like to obtain ? Also, why don't you want to use external tools if they do the job ?
    – Stephane
    Apr 16, 2014 at 14:56
  • What is unclear? One account needs full control to all files on the share. That one account doesn't have full control to all files on the share. The LOB application breaks inheritance in a lot of places, so explicit ACEs need to be used.
    – MDMarra
    Apr 16, 2014 at 15:05
  • 1
    It is unclear what state you are currently in, what you mean by "inconsistent" and what exactly you do require. Ironically, your comment added one (important) precision to what you want.
    – Stephane
    Apr 16, 2014 at 15:19
  • Right, so by "inconsistent" I mean some engineers from EMC used some process that I'm not familiar with to shuffle data between CIFS shares and now this service accounts is not listed in the ACEs of every ACL on the volume, which it should be. Hope that clarifies.
    – MDMarra
    Apr 16, 2014 at 16:08
  • Part of the issue with "inconsistent" is that I don't even know what it means at this point, and the data set is so massive that it doesn't lend itself to manual inspection.
    – MDMarra
    Apr 16, 2014 at 16:09

1 Answer 1

8

You could do it like this (breaking it in to more statements helps readability):

# Go to the directory and find the files
Push-Location "C:\MDMarrasFiles"
$Files = Get-ChildItem -Recurse

# Create an IdentityReference and a FullControl FileSystemAccessRule for said identity
$Principal = New-Object System.Security.Principal.NTAccount("DOMAIN\user")
$FullControlACERule = New-Object System.Security.AccessControl.FileSystemAccessRule -ArgumentList ($Principal,"FullControl","Allow")

# Go through the files
foreach($File in $Files)
{
    # Get the current ACL on the file
    $ACL = Get-ACL $File

    # Extract the ACEs, both explicit on the file and inherited 
    $ACEs = $ACL.GetAccessRules($true,$true,[System.Security.Principal.NTAccount])

    # Filter the ACEs to extract those giving FullControl to your target user
    $ACEsMatching = $ACEs |Where {`
        $_.FileSystemRights -eq "FullControl" -and `
        $_.IdentityReference -eq $objUser -and `
        $_.AccessControlType -eq "Allow"` 
    }

    # Test if there where no such ACE to be found
    if($ACEsMatching.Count -eq 0)
    {
        # Add the FullControl Rule to the current ACL
        $ACL.AddAccessRule($FullControlACERule)

        # Write the new ACL back to the file
        Set-ACL $File -AclObject $ACL 
    }
}
Pop-Location

Please test this on a smaller subset of files before running in production ;-)

If you want to make sure that a new explicit ACE is added even though the account might have the right inherited already, filter out inherited Access Rules like this:

$ACEs = $ACL.GetAccessRules($true, $false ,[System.Security.Principal.NTAccount])

Notice how the second boolean argument is now $false indicating that inherited rules should not be returned

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .