我试图弄清楚为什么在powershell中调用Set-Acl
会导致错误。
该调用是用于设置AD OU的较大脚本的一部分。该脚本的基本步骤是:
除了调用SetACL之外,该脚本正常:
#Some initialization data. In reality, the exact values are generated using the script parameters.
$NewDataPath="\\server\share\folder\"
$NewGroupName="UserGroup_1234"
#The actual code from the original script
$Acl = Get-Acl $NewDataPath
$Ar = New-Object System.Security.AccessControl.FileSystemAccessRule($NewGroupName, "Modify", "ContainerInherit,ObjectInherit", "None", "Allow")
#exception happens on the following line
$Acl.SetAccessRule($Ar)
#whetever happens afterward works fine
Set-Acl -Path $NewDataPath $Acl
这引发了以下异常:
Exception calling "SetAccessRule" with "1" argument(s): "Some or all
identity references could not be translated."
+ $Acl.SetAccessRule <<<< ($Ar)
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
真正奇怪的是,如果我手动运行每一行,它就可以工作。我已经将代码移动到一个单独的函数,并在初始代码失败后(使用完全相同的参数)手动调用它。
甚至更奇怪:如果我移动了在我将数据复制到其中后更新权限的代码部分,它就可以工作。
就好像SetAccessRule方法调用(或者可能是FileSystemAccessRule对象)无法访问AD中的新数据,即使所有其他调用都正常工作,并且如果引入了轻微延迟,它也会恢复。
虽然我能够找到解决方法,但我真的很想了解这里发生的事情。
答案 0 :(得分:1)
在创建多个相互依赖的新AD对象时,这似乎是一种典型的类似竞争的条件。
我还没有确认这一点,但我怀疑当您将帐户名称作为字符串提供给FileSystemAccessRule
构造函数时,.NET会使用计算机上的LSA查找缓存将名称解析为安全标识符
由于您几乎在几百毫秒之前就在另一台计算机(DC)上创建了帐户,因此查找缓存无法转换名称。
您可以通过提供新帐户的安全标识符来轻松避免这种情况。
要获取SID,请在创建组时指定-PassThru
开关,这将返回新对象(包括它的SID):
$NewGroupInstance = New-ADGroup -Name $NewGroupName -PassThru # -Path and so forth
# ...
$Ar = New-Object System.Security.AccessControl.FileSystemAccessRule($NewGroupInstance.SID, "Modify", "ContainerInherit,ObjectInherit", "None", "Allow")