You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Active Directory中拒绝域账户servicePrincipalName写入权限的代码报错求助

Active Directory中拒绝域账户servicePrincipalName写入权限的代码报错求助

我最近在尝试禁止某个域账户修改自己的servicePrincipalName属性时踩了坑,写的PowerShell代码一直报错,完全搞不懂System.DirectoryServices.ActiveDirectoryAccessRule的用法哪里出问题了,有没有大佬能帮忙分析下?

我写的代码如下:

Import-Module activedirectory

$Username = "test_user"

$SPNProperty = "servicePrincipalName"

# Get the security descriptor for the user object
$SD = (Get-ADUser -Identity $Username -Properties nTSecurityDescriptor).nTSecurityDescriptor

# Get the GUID of the servicePrincipalName attribute
$SPNSchemaObj = Get-ADObject -SearchBase ((Get-ADRootDSE).schemaNamingContext) -Filter { LDAPDisplayName -eq $SPNProperty } -Properties schemaIDGUID
$SPNSchemaID = $SPNSchemaObj.schemaIDGUI  # 这里有拼写错误

# Create a new access rule to deny the "Write Property" permission for the servicePrincipalName attribute
$AccessRule = (New-Object System.DirectoryServices.ActiveDirectoryAccessRule -ArgumentList $Username, "WriteProperty", "Deny",$SPNSchemaID)

# Add the new access rule to the security descriptor
$SD.DiscretionaryAcl.AddAccessRule($AccessRule)

# Set the modified security descriptor on the user object
Set-ADUser -Identity $Username -Replace @{nTSecurityDescriptor = $SD}

运行后弹出了两个错误:

New-Object : Cannot find an overload for "ActiveDirectoryAccessRule" and the argument count: "6".
At line:10 char:16

  • ... cessRule = (New-Object System.DirectoryServices.ActiveDirectoryAccess ...
  • ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
  • CategoryInfo : InvalidOperation: (:) [New-Object], MethodException
  • FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand

You cannot call a method on a null-valued expression.
At line:14 char:1

  • $SD.DiscretionaryAcl.AddAccessRule($AccessRule)
  • CategoryInfo : InvalidOperation: (:) [], RuntimeException
  • FullyQualifiedErrorId : InvokeMethodOnNull

问题分析与修正方案

我帮你梳理下代码里的两个关键问题:

  1. 属性拼写错误导致变量为Null
    代码里$SPNSchemaID = $SPNSchemaObj.schemaIDGUI这一行写错了属性名,正确的属性应该是schemaIDGUID(少写了一个D),这会导致$SPNSchemaID的值为Null,后续调用AddAccessRule时自然会抛出“无法对Null值表达式调用方法”的错误。

  2. ActiveDirectoryAccessRule构造函数参数错误
    你直接传入字符串类型的参数,但ActiveDirectoryAccessRule的构造函数需要的是特定类型的参数,而不是字符串:

    • $Username需要转换为IdentityReference类型(比如NTAccount对象)
    • "WriteProperty"应该用枚举值[System.DirectoryServices.ActiveDirectoryRights]::WriteProperty
    • "Deny"应该用枚举值[System.Security.AccessControl.AccessControlType]::Deny

修正后的代码

Import-Module activedirectory

$Username = "test_user"
$SPNProperty = "servicePrincipalName"

# 获取用户对象的安全描述符
$SD = (Get-ADUser -Identity $Username -Properties nTSecurityDescriptor).nTSecurityDescriptor

# 获取servicePrincipalName属性的schemaIDGUID
$SPNSchemaObj = Get-ADObject -SearchBase ((Get-ADRootDSE).schemaNamingContext) -Filter { LDAPDisplayName -eq $SPNProperty } -Properties schemaIDGUID
$SPNSchemaID = $SPNSchemaObj.schemaIDGUID  # 修正拼写错误

# 将用户名转换为IdentityReference对象
$identity = [System.Security.Principal.NTAccount]$Username
# 定义权限和访问控制类型
$adRights = [System.DirectoryServices.ActiveDirectoryRights]::WriteProperty
$accessType = [System.Security.AccessControl.AccessControlType]::Deny

# 创建正确的访问规则
$AccessRule = New-Object System.DirectoryServices.ActiveDirectoryAccessRule -ArgumentList $identity, $adRights, $accessType, $SPNSchemaID

# 添加访问规则到安全描述符
$SD.DiscretionaryAcl.AddAccessRule($AccessRule)

# 应用修改后的安全描述符
Set-ADUser -Identity $Username -Replace @{nTSecurityDescriptor = $SD}

另外还要注意,执行这段代码需要有足够的AD权限(比如修改用户权限的权限),否则可能会出现权限不足的错误。

备注:内容来源于stack exchange,提问作者Rauf Asadov

火山引擎 最新活动