我需要将 100 多个用户的主文件夹从一个 AD 移动到另一个 AD。每个用户的 samAccountName 在两个 AD 中都相同,但 ObjectGUID 不同,因为用户是使用 CSV 文件而不是信任导出和导入的。
复制不是真正的问题——我相信我有一条可用的 robocopy 线路,但我更担心在移动后设置文件夹的权限。我想遍历每个主文件夹,并将所有权和完全控制权分配给 samAccountName 与文件夹名称匹配的用户。
但是,我对 Powershell Get-ACL 和 Set-ACL 命令不太熟悉。如果我理解正确的话,我需要先将文件夹中的 ACL 抓取到变量中,然后操作变量上的权限,然后使用 Set-ACL 应用正确的权限。
我的设想是:
- 从文件夹获取 ACL 到 $UserACL
- 获取用户文件夹的名称
- 看看我是否可以将文件夹名称与 samAccountName 匹配
- 如果是,则将用户权限添加到 $UserACL
- 通过在用户文件夹上运行 Set-ACL 来设置文件夹的权限
- 如果不匹配,请设置权限,以便只有管理员才能访问该文件夹(有许多不活动的帐户不能被删除)
伪代码:
$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
}
}
}
这只是设置权限而不是所有权,所以我不确定是否可以立即使用 powershell 来实现这一点。或者我需要查看 cacls 和 takeown 吗?
答案1
我找到了一个解决方案,经过一些调整后,它对我有用:救命!我继承了重定向文件夹/主目录的权限噩梦
我完成的脚本大致如下所示:
#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
}