1

I need to move the home folders for 100+ users from one AD to another. The samAccountName for each user is the same in both AD’s but the ObjectGUID differs as the users were exported and imported with a CSV file rather than a trust.

The copying is no real problem – I believe I’ve got a working robocopy line, but I’m more worried about setting permissions on the folders after the move. I would like to iterate over each Home-folder and assign ownership and full control to the user whose samAccountName matches the folder name.

However, I’m not entirely comfortable with the Powershell Get-ACL and Set-ACL commands. If I understand it correctly I need to grab the ACL from a folder into a variable first, then manipulate the permissions on the variable and then apply the correct permissions with Set-ACL.

The way I envision it:

  1. Get-ACL from a folder to $UserACL
  2. Get the name of a user folder
  3. See if I can match a folder name with a samAccountName
  4. If so add the user permissions to the $UserACL
  5. Set permissions on the folder by running Set-ACL on the user folder
  6. If no match, set permissions so only Administrators have access to the folder (There are a number of inactive accounts that can't just be deleted)

Pseudo code:

$baseACL = Get-ACL -Path [ExampleDir]

$HomeFolders = Get-ChildItem [RootDir] | Where-Object {$_.PSIsContainer} | Foreach-Object {$_.Name}
$ADUsers=Import-csv 'UserCSV.csv' -Delimiter ';'

Foreach ($Folder in $HomeFolders) {
  ForEach ($User in $ADUsers) {
    if ($Folder -eq $($User.samAccountName)) {
      # Set properties
      $useridentity = "[AD]\$Folder"
      $admidentity = "BUILTIN\Administrators"
      $fileSystemRights = "FullControl"
      $type = "Allow"
      # Create new rule
      $fileSystemAccessRuleArgumentList = $useridentity, $admidentity, $fileSystemRights, $type
      $fileSystemAccessRule = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule -ArgumentList $fileSystemAccessRuleArgumentList
      # Apply new rule
      $baseACL.SetAccessRule($fileSystemAccessRule)
      Set-Acl -Path "[Path]\$Folder" -AclObject $baseACL
    }
    Else {
      $admidentity = "BUILTIN\Administrators"
      $fileSystemRights = "FullControl"
      $type = "Allow"
      # Create new rule
      $fileSystemAccessRuleArgumentList = $admidentity, $fileSystemRights, $type
      $fileSystemAccessRule = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule -ArgumentList $fileSystemAccessRuleArgumentList
      # Apply new rule
      $baseACL.SetAccessRule($fileSystemAccessRule)
      Set-Acl -Path "[Path]\$Folder" -AclObject $baseACL
    }
  }
}

This is only setting permissions not ownership, so I’m not sure if that’s even possible right off the bat with powershell. Or will I need to look at cacls and takeown?

1 Answer 1

0

I found a solution that with a bit of tweaking worked for me here: HALP! I've inherited a permissions nightmare for redirected folders/home directories

My finished script looks mostly like this:

#requires -PSEdition Desktop
#requires -version 5.1
#requires -Modules ActiveDirectory
#requires -RunAsAdministrator

[CmdLetBinding()]
Param ()

$AD = [DOMAIN CONTROLLER]

$Root = [HOME DIRECTORY]

$Paths = Get-ChildItem $Root -Directory | Select-Object -Property Name,FullName

# Local Admin access rule
$LASID = Get-LocalGroup -Name 'Administrators' | Select-Object -ExpandProperty SID
$LAAR = New-Object System.Security.AccessControl.FileSystemAccessRule($LASID, "FullControl", "ContainerInherit, ObjectInherit", "None", "Allow")

# Domain Admin access rule
$DASID = Get-ADGroup -Server $AD -Filter { Name -eq 'Domain Admins' } | Select-Object -ExpandProperty SID
$DAAR = New-Object System.Security.AccessControl.FileSystemAccessRule($DASID, "FullControl", "ContainerInherit, ObjectInherit", "None", "Allow")

# System Access rule
$SysAR = New-Object System.Security.AccessControl.FileSystemAccessRule("SYSTEM", "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow")

Try {
  foreach ($Directory in $Paths) {
    $samExists = $(try {Get-ADUser -Server $AD -Identity $($Directory.Name)} catch {$null})
    if ($samExists -ne $null) {
      # For error handling purposes - not all folders will map to a user of the exact same name
      Write-Output "Creating User ACL for $($Directory.FullName) ... "
      
      # Creates a blank ACL object to to add access rules into, also blanks out the ACL for each iteration of the loop
      $ACL = New-Object System.Security.AccessControl.DirectorySecurity

      # Creating the right type of user object to feed into our ACL and populating it with the user whose folder we're currently on
      $UserSID = Get-ADUser -Server $AD -Identity $($Directory.Name) | Select-Object -ExpandProperty SID
      # $objUser = New-Object System.Security.Principal.NTAccount($UserSID)

      # Access rule for the user whose folder we're dealing with this iteration
      $UserAR = New-Object System.Security.AccessControl.FileSystemAccessRule($UserSID, "FullControl","ContainerInherit,ObjectInherit", "None", "Allow")

      # Change the inheritance, propagation settings for the folder we're dealing with
      $ACL.SetOwner($UserSID)
      $ACL.SetAccessRuleProtection($true,$false)

      $ACL.SetAccessRule($UserAR)
      $ACL.SetAccessRule($LAAR)
      $ACL.SetAccessRule($DAAR)
      $ACL.SetAccessRule($SysAR)

      # For error handling purposes - not all folders will map to a user of the exact same name
      $ACL | Format-List

      Set-Acl -Path $Directory.FullName -AclObject $ACL
    }
    else {
      # For error handling purposes - not all folders will map to a user of the exact same name
      Write-Warning "Creating Admin ACL for $($Directory.FullName) ... "
      
      # Creates a blank ACL object to to add access rules into, also blanks out the ACL for each iteration of the loop
      $ACL = New-Object System.Security.AccessControl.DirectorySecurity

      # Creating the right type of user object to feed into our ACL and populating it with the user whose folder we're currently on
      # $objUser = New-Object System.Security.Principal.NTAccount($DASID)

      # Change the inheritance, propagation settings for the folder we're dealing with
      $ACL.SetOwner($DASID)
      $ACL.SetAccessRuleProtection($true,$false)

      $ACL.SetAccessRule($LAAR)
      $ACL.SetAccessRule($DAAR)
      $ACL.SetAccessRule($SysAR)

      # For error handling purposes - not all folders will map to a user of the exact same name
      $ACL | Format-List

      Set-Acl -Path $Directory.FullName -AclObject $ACL
    }
  }
}

Catch {
  Write-Host -BackgroundColor Red "Error: $($_.Exception)"
  Break
}

You must log in to answer this question.

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