powershell - 使用 Powershell 为域组设置文件夹权限时出现“顺序错误”错误消息
问题描述
我正在尝试通过 Powershell 设置文件夹的权限以下是代码:
$acl = Get-Acl $folderPath
$acl.SetAccessRuleProtection($True, $True)
$ruleOwner = New-Object System.Security.AccessControl.FileSystemAccessRule($group,"Modify", "ContainerInherit, ObjectInherit", "None", "Allow")
$acl.AddAccessRule($ruleOwner)
Set-Acl $folderPath $acl
运行此代码并尝试打开相关文件夹的安全选项卡后,我收到错误消息:
[文件夹名称]的权限排序不正确,可能导致部分条目无效。
将文件夹权限设置为特定组的正确方法是什么?
解决方案
访问规则 (ACE) 需要在ACL中以某种方式排序。基本上,顺序是
- 所有显式 ACE 都放在一个组中,位于任何继承的 ACE 之前。
- 在显式 ACE 组中,拒绝访问的 ACE 位于允许访问的 ACE 之前。
- 继承的 ACE 按照它们被继承的顺序放置。从子对象的父对象继承的 ACE 首先出现,然后是从祖父对象继承的 ACE,依此类推,直到对象树为止。
- 对于每个继承的 ACE 级别,拒绝访问的 ACE 放在允许访问的 ACE 之前。
如果此顺序以某种方式混淆,您将看到“权限排序错误”错误消息。
要重新排列权限的顺序,您可以使用以下函数:
function Repair-DirectoryPermissions {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
[ValidateScript({Test-Path $_ -PathType Container})]
[string]$Path
)
$acl = Get-Acl -Path $Path
# create a new empty ACL object
$newAcl = New-Object System.Security.AccessControl.DirectorySecurity
# copy the access rules from the existing ACL to the new one in the correct order
# first the explicit DENY rules
$acl.Access | Where-Object { !$_.IsInherited -and $_.AccessControlType -eq 'Deny' } | ForEach-Object {
$newAcl.AddAccessRule($_)
}
# next the explicit ALLOW rules
$acl.Access | Where-Object { !$_.IsInherited -and $_.AccessControlType -eq 'Allow' } | ForEach-Object {
$newAcl.AddAccessRule($_)
}
# finally the inherited rules
$acl.Access | Where-Object { $_.IsInherited } | ForEach-Object {
$newAcl.AddAccessRule($_)
}
# set the the reordered ACL to the directory object
Set-Acl -Path $Path -AclObject $newAcl
}
并像这样使用它:
Repair-DirectoryPermissions -Path 'D:\Blah'
执行此操作时,您可能会收到一个异常,告诉您您需要SeSecurityPrivilege
执行此操作的权限。
为此,请在脚本之上添加另一个函数:
function Enable-Privilege {
[CmdletBinding(ConfirmImpact = 'low', SupportsShouldProcess = $false)]
[OutputType('System.Boolean')]
Param(
[Parameter(Mandatory = $true, Position = 0)]
[ValidateSet(
"SeAssignPrimaryTokenPrivilege", "SeAuditPrivilege", "SeBackupPrivilege", "SeChangeNotifyPrivilege",
"SeCreateGlobalPrivilege", "SeCreatePagefilePrivilege", "SeCreatePermanentPrivilege",
"SeCreateSymbolicLinkPrivilege", "SeCreateTokenPrivilege", "SeDebugPrivilege", "SeEnableDelegationPrivilege",
"SeImpersonatePrivilege", "SeIncreaseBasePriorityPrivilege", "SeIncreaseQuotaPrivilege",
"SeIncreaseWorkingSetPrivilege", "SeLoadDriverPrivilege", "SeLockMemoryPrivilege",
"SeMachineAccountPrivilege", "SeManageVolumePrivilege", "SeProfileSingleProcessPrivilege",
"SeRelabelPrivilege", "SeRemoteShutdownPrivilege", "SeRestorePrivilege", "SeSecurityPrivilege",
"SeShutdownPrivilege", "SeSyncAgentPrivilege", "SeSystemEnvironmentPrivilege", "SeSystemProfilePrivilege",
"SeSystemtimePrivilege", "SeTakeOwnershipPrivilege", "SeTcbPrivilege", "SeTimeZonePrivilege",
"SeTrustedCredManAccessPrivilege", "SeUndockPrivilege", "SeUnsolicitedInputPrivilege")]
[String]$Privilege,
[Parameter(Position = 1)]
$ProcessId = $PID,
[switch]$Disable
)
begin {
Add-Type -TypeDefinition @'
using System;
using System.Runtime.InteropServices;
public class Privilege {
[DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall, ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen);
[DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
internal static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr phtok);
[DllImport("advapi32.dll", SetLastError = true)]
internal static extern bool LookupPrivilegeValue(string host, string name, ref long pluid);
[StructLayout(LayoutKind.Sequential, Pack = 1)]
internal struct TokPriv1Luid {
public int Count;
public long Luid;
public int Attr;
}
internal const int SE_PRIVILEGE_ENABLED = 0x00000002;
internal const int SE_PRIVILEGE_DISABLED = 0x00000000;
internal const int TOKEN_QUERY = 0x00000008;
internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
public static bool EnablePrivilege(long processHandle, string privilege, bool disable) {
bool retVal;
TokPriv1Luid tp;
IntPtr hproc = new IntPtr(processHandle);
IntPtr htok = IntPtr.Zero;
retVal = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
tp.Count = 1;
tp.Luid = 0;
if(disable) { tp.Attr = SE_PRIVILEGE_DISABLED; }
else { tp.Attr = SE_PRIVILEGE_ENABLED; }
retVal = LookupPrivilegeValue(null, privilege, ref tp.Luid);
retVal = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
return retVal;
}
}
'@
}
process {
try {
$proc = Get-Process -Id $ProcessId -ErrorAction Stop
$name = $proc.ProcessName
$handle = $proc.Handle
$action = if ($Disable) { 'Disabling' } else { 'Enabling' }
Write-Verbose ("{0} '{1}' for process {2}" -f $action, $Privilege, $name)
[Privilege]::EnablePrivilege($handle, $Privilege, [bool]$Disable)
}
catch {
throw
}
}
}
并调用这两个函数:
Enable-Privilege -Privilege SeSecurityPrivilege
Repair-DirectoryPermissions -Path 'D:\Blah'
推荐阅读
- google-cloud-platform - 带有 Firebase 身份验证的 ESPv2 的 JWT 验证失败
- c# - 如何点击第三方网站上的网站提交按钮
- google-cloud-platform - 使用云部署管理器解决部署数据流
- c# - 我无法在 C# 中使用 ASPOSE.PDF 通过 URL 创建 PDF 文件,我遇到了以下问题
- node.js - NodeJs 无法将所有行从 csv 保存到 Mongodb
- vue.js - 从 url 获取 {id} 的最佳解决方案?
- jquery - appendTo 基于标题和类型
- reactjs - 如何在 react-hls-player 中使用 hlsConfig
- python - 在 Python 错误中嵌入 Powershell 脚本
- postgresql - 当用户选择“全部”时动态增加用户选择