Quick Snippet to Copy NTFS Permissions Between SMB Shares

The experimental script below will sync permissions of a folder toward another.

WARNING: if sub-folders at the destination does NOT inherit permissions from its root directory parent, then any ACL changes to root or parent directory may render sub-folders ACL to be NULL. NO NOT use this script in production without knowing contexts!

The only good usage of this script is to run it before an initial data sync between 2 SMB servers. Be certain that new destination directories are empty prior to copying ACLs. Once the ACLs of root directories are copied, then data sync could be ran to copy sub-directories and data with explicit ACLs to those items.

# copyNtfsPermissions.ps1
# Version 0.02

$copyFromAndTo=@(
    [PSCustomObject]@{From='F:\';To='\\BISAS01L-SHR-23\F$'}
    [PSCustomObject]@{From='G:\';To='\\BISAS01L-SHR-23\G$'}
)

function copyAcl($from,$to){
    # Noting this command below doesn't work when an entity in Source ACL is invalid (e.g. orphaned accounts); hence, the long workaround to bypass those errors
    # Get-Acl $sourceDirectory|Set-Acl $destinationDirectory
    $sourceAcl=Get-Acl -path $from
    $destinationAcl=Get-Acl -path $to
    foreach($permission in $sourceAcl.Access){
        $identity=$permission.IdentityReference
        $rights=$permission.FileSystemRights
        $accessType=$permission.AccessControlType
        try{
            $accessRule=New-Object System.Security.AccessControl.FileSystemAccessRule($identity,$rights,$accessType) -ea Ignore
            $destinationAcl.AddAccessRule($accessRule)
        }catch{
            write-warning $_
        }        
    }
    write-warning "Are you sure you want to run this command: Set-Acl $to $($destinationAcl.Access|select IdentityReference,AccessControlType,FileSystemRights|ft -autosize|out-string) ?"
    pause
    Set-Acl $to $destinationAcl
    write-host "Root directory $from ACL has been set toward $to as:`r`n$($destinationAcl.Access|select IdentityReference,AccessControlType,FileSystemRights|ft -autosize|out-string)"
}

foreach($item in $copyFromAndTo){
    $from=$item.From
    $to=$item.To
    copyAcl $from $to
}
# copyNtfsPermissions.ps1
# Version 0.01

$arr=@();
$arr+=[PSCustomObject]@{Clustername='';From='D:\Accounting';To='\\NEWSERVER\Accounting'}
$arr+=[PSCustomObject]@{Clustername='';From='D:\Test';To='\\NEWSERVER\Test'}

$arr=@();
$arr+=[PSCustomObject]@{Clustername='';From='D:\Accounting';To='\\NEWSERVER\Accounting'}
$arr+=[PSCustomObject]@{Clustername='';From='D:\Test';To='\\NEWSERVER\Test'}

foreach ($item in $arr){
    $sourceDirectory=$item.From
    $destinationDirectory=$item.To
    # Noting this command here to remind us that command below doesn't work when an entity in Source ACL is invalid; hence, the long workaround to bypass those errors
    # Get-Acl $sourceDirectory|Set-Acl $destinationDirectory
    $sourceAcl=Get-Acl -path $sourceDirectory
    $destinationAcl=Get-Acl -path $destinationDirectory
    foreach($permission in $sourceAcl.Access){
        $identity=$permission.IdentityReference
        $rights=$permission.FileSystemRights
        $accessType=$permission.AccessControlType
        try{
            $accessRule=New-Object System.Security.AccessControl.FileSystemAccessRule($identity,$rights,$accessType) -ea Ignore
        }catch{
            write-warning $_
        }
        $destinationAcl.AddAccessRule($accessRule)
    }
    # Uncomment this line to run experiment
    # Set-Acl $destinationDirectory $destinationAcl
    write-host "Root directory $sourceDirectory ACL has been set toward $destinationDirectory as:`r`n$($destinationAcl|ft -wrap|out-string)"
}

Leave a Reply

Your email address will not be published. Required fields are marked *