SetAccessRule 在脚本中失败,否则有效
SetAccessRule failing while in script, works otherwise
我想弄清楚为什么在 powershell 中调用 Set-Acl
失败。
该调用是用于设置 AD OU 的更大脚本的一部分。该脚本的基本步骤是:
- 创建一个新的 OU
- 向该 OU 添加一个组
- 在文件共享上创建文件夹。
- 将新创建的组的权限添加到新创建的文件夹。
- 将模板文件夹的内容复制到新文件夹。
- 创建一个 DFS 文件夹以指向新文件夹。
除了调用 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 中的新数据,即使所有其他调用工作正常并且如果引入轻微延迟,它就会恢复。
虽然我能够找到解决方法,但我真的很想了解这里发生了什么。
这似乎是创建多个相互依赖的新 AD 对象时典型的类竞争情况。
我还没有证实这一点,但我怀疑当您将帐户名称作为字符串提供给 FileSystemAccessRule
构造函数时,.NET 使用您计算机上的 LSA 查找缓存将名称解析为安全标识符。
由于您实际上只是在几百毫秒前在另一台机器 (DC) 上创建了帐户,因此查找缓存无法转换名称。
您可以通过提供新帐户的安全标识符轻松规避此问题。
要获取 SID,请在创建组时指定 -PassThru
开关,这将 return 新对象(包括它的 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")
我想弄清楚为什么在 powershell 中调用 Set-Acl
失败。
该调用是用于设置 AD OU 的更大脚本的一部分。该脚本的基本步骤是:
- 创建一个新的 OU
- 向该 OU 添加一个组
- 在文件共享上创建文件夹。
- 将新创建的组的权限添加到新创建的文件夹。
- 将模板文件夹的内容复制到新文件夹。
- 创建一个 DFS 文件夹以指向新文件夹。
除了调用 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 中的新数据,即使所有其他调用工作正常并且如果引入轻微延迟,它就会恢复。
虽然我能够找到解决方法,但我真的很想了解这里发生了什么。
这似乎是创建多个相互依赖的新 AD 对象时典型的类竞争情况。
我还没有证实这一点,但我怀疑当您将帐户名称作为字符串提供给 FileSystemAccessRule
构造函数时,.NET 使用您计算机上的 LSA 查找缓存将名称解析为安全标识符。
由于您实际上只是在几百毫秒前在另一台机器 (DC) 上创建了帐户,因此查找缓存无法转换名称。
您可以通过提供新帐户的安全标识符轻松规避此问题。
要获取 SID,请在创建组时指定 -PassThru
开关,这将 return 新对象(包括它的 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")