Search code examples
powershellpermissionsactive-directoryntfs

My powershell script to assign permissions to network share has to be run multiple times?


I have a script for provisioning various aspects of a new user account, including creating network folders on an NTFS share and assigning permissions to it.

The script runs and executes without errors, believes that the permissions are applied, and correctly shows that the permissions are applied. However, when checking the directory that was created, the permissions are not there.

There are two functions that execute as part of setting the permissions.

The variables from left to right are, Active Directory SAM Username, Active Directory User Principal Name, Folder Path 1, Folder Path 2, and Folder Path 3.

All folder paths for example are in the format "\ipaddressofserver\Folder\folder\User Folder"

$CheckPerms = Check-FolderPermissions $ADUserSAMUserN $UserNTAccountObject $ProUACLPath $UserFACLPath $ScansFACLPath

The "Check-FolderPermissions" Function is below. It should attempt to check and set the permissions 6 times before throwing an error that permissions weren't able to be applied.

function Check-FolderPermissions ($CPermUserSAM, $CPermUserUPN, $CPermProUACLPath, $CPermUserFACLPath, $CPermScansFACLPath) {
    $UserFPerms = $false
    $maxRetries = 5; $retrycount = 0

    while (-not $UserFPerms) {
        $CUserFPerms = get-acl -Path $CPermUserFACLPath | Select-Object -Property *
        if ($CUserFPerms.AccessToString.Contains($CPermUserSAM)) {
            $CUserFPerms.AccessToString
            Write-Host "User Folder Permissions for $CPermUserUPN found"
            $UserFPerms = $true
        }
        else {
            if ($retrycount -ge $maxRetries) {
                throw "Failed to set user folder permissions within '$maxRetries' retries"
            }
            else {
                Write-Host "User Folder permissions not found, trying to set permissions"
                Set-FolderPermissions $CPermUserUPN $CPermProUACLPath $CPermUserFACLPath $CPermScansFACLPath
                $retryCount++
                Write-Host 'Waiting for permissions to propogate, sleeping for 5 seconds'
                Start-Sleep '5'
            }
        }
    }
    return $UserFPerms
}

In the second Else Statement in the While loop a function "Set-FolderPermissions" is called which is below.

function Set-FolderPermissions ($SetPermUserUPN, $SetPermProUACLPath, $SetPermUserFACLPath, $SetPermScansFACLPath) {

    $FolderACL = New-Object System.Security.AccessControl.DirectorySecurity
    $AccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule(
    "$SetPermUserUPN","Modify", "ContainerInherit, ObjectInherit", "0", "Allow")
    $FolderACL.SetAccessRule($AccessRule)
    Set-Acl -Path "$SetPermProUACLPath" -AclObject $FolderACL
    Set-Acl -Path "$SetPermUserFACLPath" -AclObject $FolderACL
    Set-Acl -Path "$SetPermScansFACLPath" -AclObject $FolderACL
}

The output of the Write-Host statements is edited below, masking values.

The first loop of the while statement checks and finds that the user permissions are not applied as it hasn't attempted to set them yet.

The function to set the permissions is called and then it sleeps for 5 seconds to allow time for permissions to be applied.

The while statement then loops again and sees that the permissions for UserA have been applied, and prints out the contents of the Access Control List where UserA is the first entry listed.

Output Screenshot

I have tried probably 20 different iterations of functions and methods to try to get this to work but in all cases the behavior that occurs is below.

Almost everytime: The permissions are not set on the directory if you browse in a fileexplorer and check the advanced permissions list.

Most of the time: If I rerun the script again, I get errors that the directories it is trying to create already exist because they were created during the first run, but the script continues to execute and reapplies the permissions and they will now correctly show when browsing to the folder and confirming they are there.

Rarely > 5% : The script has to be ran more than two times to apply the permissions.

Is there something wrong with the way that I am trying to do this? I have tried forcing it to perform a hard loop where it applies the permissions, wait 5 seconds (tested up to 15 seconds), apply permissions again, and repeat this process 5 times to get around them seemingly vanishing from the folder.

Because I am doing a Get-ACL to the path of the folder to check that they are applied and they are listed as being there I am at a loss as to the tomfoolery that is occurring here.

Powershell version is 5.1


Solution

  • The solution to this had to do with a process running in the background.

    In my environment the server share that I am creating the folders and setting permissions on is a member of a Distributed File System (DFS) share. So all of the folders and permissions are replicated between member servers for load balancing and fault tolerance.

    The problem seems to have been that when the folders are created the Synchronization server that replicates all files and permissions between the members of the DFS share is still handling the new folders and propagating them to the other DFS share members. This caused the permissions from serverB to over-write the permissions of serverA because the time stamp of the folder being created on serverB and it's respective inherited permissions is newer than the time stamp of the folder and permissions on serverA.

    I had to write an additional loop to wait for the replication of the folders to finish before applying the permissions.

    '''

    foreach ($ReplicationPath in $ReplicationPermissionPaths) {
        foreach ($FolderRepStatus in $ReplicationStatus) {
            while (-not $FolderRepStatus) {
                Write-Host "Checking folder replication status for '$ReplicationPath'"
                $SharesPathTest = Test-Path $ReplicationPath
                if ($SharesPathTest -eq $true) {
                    Write-Host "Folder replication for '$ReplicationPath' is complete"
                    $FolderRepStatus = $true
                }
                else {
                    Write-Host "Folder replication for '$ReplicationPath' is not complete, waiting 2 seconds"
                    Start-Sleep '2'
                }
            }
        }
    }
    

    '''

    Once the permissions were applied after the replication was complete they applied successfully on the first run.