同一PowerShell权限配置脚本在不同Windows系统执行结果异常求助
问题描述
编写了一套PowerShell脚本,用于在一台系统收集文件夹及NTFS权限,再到高受限环境的另一系统创建文件夹结构并应用权限。因无法使用robocopy,采用CSV存储权限配置(仅处理文件夹,文件后续通过FTP传输)。
本地Windows 10笔记本测试时,脚本可正常创建文件夹并配置权限;但在安全系统中使用相同CSV执行时,虽能创建文件夹结构,却会将CSV中所有显式权限应用到每个列出的文件夹。两台系统均为Windows 10、PowerShell版本一致,仅脚本内RootDir路径不同。
已确认在目标目录拥有完整NTFS权限,且安全系统中为选中代码执行(本地也采用相同操作排除此因素影响)。
CSV示例
| FolderPath | IdentityReference | FileSystemRights | InheritanceFlags |
|---|---|---|---|
| Activities | AD\User-ACTIVITIES.T | Read | None |
| Activities | AD\user.adm | FullControl | ContainerInherit, ObjectInherit |
| Activities\BWOVC1 | AD\User-BWOVC1 | Modify | ContainerInherit, ObjectInherit |
原执行脚本
# Location Where your folders are to be created $RootDir = "C:\Users\User1\Documents\ACL" Set-Location "$RootDir" # Import CSV file from location $Folders = Import-Csv "$RootDir\ACL-File.csv" # Create Folders from FolderPath column in csv; set ACL ForEach ($Folder in $Folders) { if(Test-Path $RootDir\$Folder.FolderPath) {continue} #{Write-Verbose "Folder: $Path Already Exists"} else{ New-Item $Folder.FolderPath -type directory } $IdentityReference = $Folder.IdentityReference $FileSystemRights = $Folder.FileSystemRights $InheritanceFlag = "ContainerInherit, ObjectInherit" $PropagationFlag = "None" $AccessControlType = "Allow" #From stackoverflow response; # Define the access rule(s) to add to the ACL $New_ACR = New-Object Security.AccessControl.FileSystemAccessRule $IdentityReference, $FileSystemRights, $InheritanceFlag, $PropagationFlag, $AccessControlType # Get Access Control List from directory $ACL = Get-Acl -Path ($RootDir + "\" + $Folder.FolderPath) # Add new rule to ACL $ACL.AddAccessRule($New_ACR) # Apply updated ACL to directory Set-Acl -Path ($RootDir + "\" + $Folder.FolderPath) -AclObject $ACL }
原因分析
问题根源在于脚本的两处语法/逻辑错误,本地测试因环境巧合未暴露,安全系统的环境则放大了这些错误:
路径拼接语法错误:
原脚本中$RootDir\$Folder.FolderPath和($RootDir + "\" + $Folder.FolderPath)的写法存在解析问题——PowerShell会将$Folder.FolderPath视为字符串拼接,而非访问对象的FolderPath属性。这会导致路径解析错误,在安全系统中可能所有操作都指向了同一个错误路径(比如根目录),最终所有权限都被重复添加到该路径下,看起来像是每个文件夹都被应用了所有权限。硬编码继承规则忽略CSV配置:
脚本中直接将$InheritanceFlag设为固定值"ContainerInherit, ObjectInherit",完全未使用CSV中定义的InheritanceFlags列。这不仅违背了CSV配置的初衷,还可能导致继承规则不符合预期,进一步加剧权限应用的异常。循环逻辑冗余:
原脚本逐行遍历CSV,同一个文件夹的多条权限会重复执行创建文件夹和获取ACL的操作,效率低下且容易引发路径解析相关的异常。
修复方案
修复后的脚本
# 目标根目录 $RootDir = "C:\Users\User1\Documents\ACL" Set-Location $RootDir # 导入CSV权限配置 $Folders = Import-Csv "$RootDir\ACL-File.csv" # 按文件夹路径分组,避免重复操作同一文件夹 $folderGroups = $Folders | Group-Object -Property FolderPath foreach ($group in $folderGroups) { # 正确拼接目标文件夹路径 $targetFolder = Join-Path $RootDir $group.Name # 创建文件夹(不存在时) if (-not (Test-Path $targetFolder)) { New-Item -Path $targetFolder -ItemType Directory | Out-Null } # 获取目标文件夹的当前ACL $acl = Get-Acl -Path $targetFolder # 遍历当前文件夹的所有权限规则 foreach ($ruleEntry in $group.Group) { # 从CSV读取并转换继承规则为枚举类型 $inheritanceFlags = [System.Security.AccessControl.InheritanceFlags]$ruleEntry.InheritanceFlags # 创建新的权限规则 $newAccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule( $ruleEntry.IdentityReference, $ruleEntry.FileSystemRights, $inheritanceFlags, [System.Security.AccessControl.PropagationFlags]::None, [System.Security.AccessControl.AccessControlType]::Allow ) # 添加权限规则到ACL $acl.AddAccessRule($newAccessRule) } # 应用更新后的ACL到目标文件夹 Set-Acl -Path $targetFolder -AclObject $acl }
关键修复点
- 使用
Join-Path正确拼接路径,彻底避免字符串解析错误 - 按
FolderPath分组处理,同一文件夹仅执行一次创建和ACL操作,提升效率 - 从CSV读取
InheritanceFlags并转换为正确的枚举类型,不再硬编码 - 明确指定枚举类型,避免字符串转换可能引发的异常
内容的提问来源于stack exchange,提问作者tr_cpc1

