为何PowerShell设置文件夹ACL脚本仅部分电脑生效?求故障原因
PowerShell ACL脚本部分机器失效问题排查
问题现象
尝试将本地NT Authority\Authenticated Users添加到$env:ProgramData\MTSLogs文件夹的权限列表中,多数机器运行正常,但部分机器抛出错误:
Exception calling "SetAccessRule" with "1" argument(s): "Some or all identity references could not be translated."
已尝试以SYSTEM和管理员身份运行脚本,问题依旧。
原脚本代码:
$AuthenticatedUsersSID = New-Object System.Security.Principal.SecurityIdentifier 'S-1-5-11' $ACL = Get-Acl -Path "$($env:ProgramData)\MTSLogs" | select -ExpandProperty Access | where IdentityReference -eq "NT AUTHORITY\Authenticated Users" -ErrorAction SilentlyContinue if (!(($ACL.FileSystemRights -eq "Modify, Synchronize") -and($ACL.AccessControlType -eq "Allow") -and ($ACL.InheritanceFlags -eq "ContainerInherit, ObjectInherit"))) { Write-Output "ACL is incorrect. Remediating..." $NewACL = Get-Acl -Path "$($env:ProgramData)\MTSLogs" $AccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule($AuthenticatedUsersSID,"Modify","3","0","Allow") $NewACL.SetAccessRule($AccessRule) $NewACL | Set-Acl -Path "$($env:ProgramData)\MTSLogs" }
问题原因
- SID身份解析失败:虽然直接使用了
S-1-5-11(对应Authenticated Users的SID),但部分机器可能因系统语言/区域设置异常、本地安全标识符数据库损坏,导致无法将SID正确转换为对应的NT账户名称,触发身份引用翻译错误。 - 枚举值使用不规范:脚本中创建访问规则时用数字
3和0代表继承标志和传播标志,虽然对应ContainerInherit, ObjectInherit和None,但数字写法不够直观,且在部分特殊系统环境下可能存在解析偏差。 - ACL检查逻辑漏洞:如果目标文件夹原本没有
NT AUTHORITY\Authenticated Users的权限条目,$ACL会为空,此时直接访问$ACL.FileSystemRights会导致隐式错误,影响后续判断逻辑。
修复方案
1. 显式转换SID为NTAccount对象
先将SID转换为对应的NT账户对象,确保身份引用能被系统正确识别,避免SID直接解析失败:
$AuthenticatedUsersSID = New-Object System.Security.Principal.SecurityIdentifier 'S-1-5-11' $AuthenticatedUsersAccount = $AuthenticatedUsersSID.Translate([System.Security.Principal.NTAccount])
2. 使用枚举值替代数字
直接调用.NET枚举类型,提升代码可读性和兼容性:
$AccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule( $AuthenticatedUsersAccount, [System.Security.AccessControl.FileSystemRights]::Modify -bor [System.Security.AccessControl.FileSystemRights]::Synchronize, [System.Security.AccessControl.InheritanceFlags]::ContainerInherit -bor [System.Security.AccessControl.InheritanceFlags]::ObjectInherit, [System.Security.AccessControl.PropagationFlags]::None, [System.Security.AccessControl.AccessControlType]::Allow )
3. 优化ACL检查逻辑
先判断$ACL是否存在,避免空值引发的隐式错误:
$logPath = "$($env:ProgramData)\MTSLogs" $ACL = Get-Acl -Path $logPath | Select-Object -ExpandProperty Access | Where-Object { $_.IdentityReference.Value -eq $AuthenticatedUsersAccount.Value } -ErrorAction SilentlyContinue $isAclCorrect = $false if ($ACL) { $requiredRights = [System.Security.AccessControl.FileSystemRights]::Modify -bor [System.Security.AccessControl.FileSystemRights]::Synchronize $requiredInheritance = [System.Security.AccessControl.InheritanceFlags]::ContainerInherit -bor [System.Security.AccessControl.InheritanceFlags]::ObjectInherit $isAclCorrect = ($ACL.FileSystemRights -eq $requiredRights) ` -and ($ACL.AccessControlType -eq [System.Security.AccessControl.AccessControlType]::Allow) ` -and ($ACL.InheritanceFlags -eq $requiredInheritance) }
4. 增加文件夹存在检查
避免因目标文件夹不存在引发额外异常:
if (-not (Test-Path -Path $logPath)) { Write-Output "日志文件夹不存在,创建中..." New-Item -Path $logPath -ItemType Directory -Force | Out-Null }
修改后的完整脚本
$logPath = "$($env:ProgramData)\MTSLogs" $AuthenticatedUsersSID = New-Object System.Security.Principal.SecurityIdentifier 'S-1-5-11' $AuthenticatedUsersAccount = $AuthenticatedUsersSID.Translate([System.Security.Principal.NTAccount]) # 检查文件夹是否存在 if (-not (Test-Path -Path $logPath)) { Write-Output "日志文件夹不存在,创建中..." New-Item -Path $logPath -ItemType Directory -Force | Out-Null } # 检查现有ACL是否符合要求 $ACL = Get-Acl -Path $logPath | Select-Object -ExpandProperty Access | Where-Object { $_.IdentityReference.Value -eq $AuthenticatedUsersAccount.Value } -ErrorAction SilentlyContinue $isAclCorrect = $false if ($ACL) { $requiredRights = [System.Security.AccessControl.FileSystemRights]::Modify -bor [System.Security.AccessControl.FileSystemRights]::Synchronize $requiredInheritance = [System.Security.AccessControl.InheritanceFlags]::ContainerInherit -bor [System.Security.AccessControl.InheritanceFlags]::ObjectInherit $isAclCorrect = ($ACL.FileSystemRights -eq $requiredRights) ` -and ($ACL.AccessControlType -eq [System.Security.AccessControl.AccessControlType]::Allow) ` -and ($ACL.InheritanceFlags -eq $requiredInheritance) } # 修复ACL if (-not $isAclCorrect) { Write-Output "ACL配置异常,开始修复..." $NewACL = Get-Acl -Path $logPath $AccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule( $AuthenticatedUsersAccount, [System.Security.AccessControl.FileSystemRights]::Modify -bor [System.Security.AccessControl.FileSystemRights]::Synchronize, [System.Security.AccessControl.InheritanceFlags]::ContainerInherit -bor [System.Security.AccessControl.InheritanceFlags]::ObjectInherit, [System.Security.AccessControl.PropagationFlags]::None, [System.Security.AccessControl.AccessControlType]::Allow ) $NewACL.SetAccessRule($AccessRule) $NewACL | Set-Acl -Path $logPath Write-Output "ACL修复完成" }
内容的提问来源于stack exchange,提问作者Pete Mitchell
相关产品推荐
相关产品推荐

