Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting permissions on a windows fileshare

Tags:

powershell

I have the following code which is supposed to go through the folders in the fileshare and turn whatever permissions there are into read permissions. However, there is a problem: it doesn't replace the permissions already there it merely adds to them. Secondly, if the folder has not got inherited permissions it gives an error saying

Set-Acl : The process does not possess the 'SeSecurityPrivilege' privilege which is required for this operation.

I have checked the permissions and I have full control on them

function NotMigrated($SiteURL, $Folder) {
    try {
        $SiteString=[String]$SiteURL
        $pos = $SiteString.LastIndexOf("/")         
        $Site = $SiteString.Substring($pos+1)
        $parent=((get-item $Folder ).parent).Fullname

        $AllFolders = Get-ChildItem -Recurse -Path $Folder |? {$_.psIsContainer -eq $True}
        $FilesInRoot = Get-ChildItem -Path $Folder | ? {$_.psIsContainer -eq $False}
        $acl= get-acl $Folder
        foreach ($usr in $acl.access) {
            $acl.RemoveAccessRule($usr)
            $rule = New-Object System.Security.AccessControl.FileSystemAccessRule($usr.IdentityReference,"Read","none","none","Allow")
            $Acl.AddAccessRule($rule)
        }
        $acl | Set-Acl
     } catch { continue }

    #Loop through all folders (recursive) that exist within the folder supplied by the operator
    foreach ($CurrentFolder in $AllFolders) {
        #Set the FolderRelativePath by removing the path of the folder supplied by the operator from the fullname of the folder
        $FolderRelativePath = ($CurrentFolder.FullName).Substring($Folder.Length)
        $FileSource = $Folder + $FolderRelativePath

        try {
            $acl= get-acl $FileSource
            foreach ($usr in $acl.access) {
                $acl.RemoveAccessRule($usr)
                $rule = New-Object System.Security.AccessControl.FileSystemAccessRule($usr.IdentityReference,"Read","none","none","Allow")
                $acl.AddAccessRule($rule)
            }
            $acl | Set-Acl 
        } catch { continue }

        #For each file in the source folder being evaluated, call the UploadFile function to upload the file to the appropriate location
    }
}
like image 863
davetherave Avatar asked Jul 24 '15 12:07

davetherave


1 Answers

The biggest problem isn't with your code, but with the Set-Acl Cmdlet/FileSystem provider combination. When Set-Acl is being called, an attempt to write the entire security descriptor is being made. If you're not elevated (or if your administrator account hasn't been granted SeRestorePrivilege), that's not going to work. If you are elevated, though, there's a chance you're destroying your SACL on the file/folder that you're modifying.

For that reason, I'd avoid using Set-Acl at all costs until the bugs I've linked to above are fixed. Instead, you can use the SetAccessControl() method available to file and folder objects:

(Get-Item c:\path\to\folder).SetAccessControl()

Once you do that, you shouldn't see the SeSecurityPrivilege errors anymore. You'll still have these two problems, though:

  1. You're looking to make a new ACE for all ACEs contained in the folder. I think what you want to do is look for 'Allow' ACEs that aren't being inherited. If you have any 'Deny' ACEs, you'll end up with new 'Allow' ACEs granting 'Read' access, which I'm betting you don't want to do. Also, if you include inherited ACEs, you'll end up with a new explicit ACE for each one, and you can't removed the inherited ones unless you break inheritance...
  2. You're not copying the existing inheritance and propagation flags, and you're not using the defaults for a folder.

I think this modified version of a piece of your code should do what you're looking for:

try {
    $acl = get-acl $FileSource

    # Only look for explicit Allow ACEs
    foreach ($usr in ($acl.access | where { $_.IsInherited -eq $false -and $_.AccessControlType -eq 'Allow' })) {
        $rule = New-Object System.Security.AccessControl.FileSystemAccessRule(
            $usr.IdentityReference,
            "Read",
            $usr.InheritanceFlags,
            $usr.PropagationFlags,
            $usr.AccessControlType
        )

        # Calling SetAccessRule() is like calling Remove() then Add()
        $acl.SetAccessRule($rule)
    }
    (Get-Item $FileSource).SetAccessControl($acl)
} catch { continue }
like image 95
Rohn Edwards Avatar answered Nov 15 '22 08:11

Rohn Edwards