用于从 servicenow 更新 ldap 数据的 Powershell 脚本

标签 powershell ldap servicenow

我们正在运行 powershelll 脚本以从 Servicenow 更新 LDAP 属性。我们得到以下错误。

Access Request Console : LDAP Script Directory : C:\MID Server INT\agent\scripts\PowerShell
        Object DN : employeeNumber=L1009804,ou=people,ou=partenaires,dc=total,dc=com
        Exception : The running command stopped because the preference variable "ErrorActionPreference" or common parameter is set to Stop: At C:\MID Server INT\agent\scripts\PowerShell\LDAP\ldapFunctions.psm1:14 char:1
        + {
        + ~
        Missing closing '}' in statement block or type definition.

        At C:\MID Server INT\agent\scripts\PowerShell\LDAP\ldapFunctions.psm1:58 char:2
        + }
        + ~
        Unexpected token '}' in expression or statement.

        At C:\MID Server INT\agent\scripts\PowerShell\LDAP\ldapFunctions.psm1:60 char:1
        + }
        + ~
        Unexpected token '}' in expression or statement. .

下面是 Powershell 脚本,该脚本在提出请求时触发,并通过工作流触发。数据流入工作正常,但从 ServiceNow 传出到 LDAP 时遇到问题。脚本每次运行都会失败。

    <#
    .Synopsis
    Create a new LdapConnection

    .EXAMPLE
    New-LdapConnection -LDAPServer 127.0.0.1 -Login admin -Password password1
    Description
    -----------
    Create a new LdapConnection on 127.0.0.1 server with admin credential
    #>
    [void][System.Reflection.Assembly]::LoadWithPartialName("System.DirectoryServices.Protocols")

    function New-LdapConnection
    {
        [OutputType([System.DirectoryServices.Protocols.LDAPConnection])]
        Param
        (
            # Description d'aide LDAPServer
            [String] $LDAPServer,
            # Description d'aide LDAPServerPort
            [Int32]  $LDAPServerPort=389,
            # Description d'aide Login
            [String] $Login,
            # Description d'aide Password
            [String] $Password,
            # Description d'aide AuhtenticationType
            [String] $AuhtenticationType="Basic",
            # Description d'aide ProtocolVersion
            [int] $ProtocolVersion=3,
            # Description d'aide SecureSocketLayer
            [Boolean] $SecureSocketLayer=$true,
            # Description d'aide EncryptionType
            [int] $EncryptionType=0
        )


        Process
        {
            #$LDAPServer = $ldapURL
            $Credentials = New-Object System.Net.NetworkCredential($Login,$Password)
            $LDAPConnection = New-Object System.DirectoryServices.Protocols.LDAPConnection($LDAPServer,$Credentials,$AuhtenticationType)
            $LDAPConnection.SessionOptions.ProtocolVersion = $ProtocolVersion
            $LDAPConnection.SessionOptions.SecureSocketLayer =$SecureSocketLayer
            # don't check certificate (feature enabled again on 24/11/2016 as requested by customer)

            $LDAPConnection.SessionOptions.VerifyServerCertificate = {
                param(
                    [DirectoryServices.Protocols.LdapConnection]$Connection,
                    [Security.Cryptography.X509Certificates.X509Certificate2]$Certificate
                )      
                $Global:LdapCertificate = $Certificate    
                return $true
            }

            $LDAPConnection.Bind()
            return $LDAPConnection

        }

    }


    <#
    .Synopsis
    Find a Entry in LDAP
    .EXAMPLE
    Find-LdapEntry -LdapConnection $con -filter "(objectClass=person)" -rootDistinguishedName "DC=test,DC=lab"
    #>
    function Find-LdapEntry
    {
        [OutputType([System.DirectoryServices.Protocols.SearchResultEntry])]
        Param
        (
            # Ldap Connection
            [Parameter(Mandatory=$true)]
            [System.DirectoryServices.Protocols.LDAPConnection] $LdapConnection,

            # Ldap Filter
            [Parameter(Mandatory=$true)]
            [String] $filter,

            # Base DN
            [Parameter(Mandatory=$true)]
            [String] $rootDistinguishedName
        )

        Process
        {
            Write-Host "Begin Find Entry"

            $Filter = $filter
            $TimeOut = New-Object System.TimeSpan(1,0,0)
            $Request = New-Object System.DirectoryServices.Protocols.SearchRequest($rootDistinguishedName, $Filter, "Subtree", $null)
            $Response = $LdapConnection.SendRequest($Request,$TimeOut)

            if($Response.Entries.Count -gt 0){
                $Entry = $Response.Entries[0]
            }else{
                $Entry = $null
            }
            return $Entry 
        }

    }

    <#
    .Synopsis
    Add a Entry in LDAP
    .EXAMPLE
    New-LdapAddRequest -LdapConnection $con -Attrib $attrib -ObjectDN $obj_dn
    #>
    function New-LdapAddRequest
    {
        Param
        (
            # Ldap Connection
            [Parameter(Mandatory=$true)]
            [System.DirectoryServices.Protocols.LDAPConnection] $LdapConnection,

            # Attributes to Add 
            [Parameter(Mandatory=$true)]
            [System.Collections.Hashtable] $Attrib,

            # Object DN
            [Parameter(Mandatory=$true)]
            [String] $ObjectDN

        )

        Process
        {
            [string[]]$result = @()

            [string[]] $newObjClass = @()
            $newObjClass = $Attrib.Get_Item("defaultobjclass").split("^") | where {$_ -ne "^"}  
            Write-Host "Begin New-LdapAddRequest"

            $newEntry = (new-object "System.DirectoryServices.Protocols.AddRequest")
            $newEntry.DistinguishedName = $ObjectDN

            if($Attrib.Get_Item("objectclass") -ne $null -and $Attrib.Get_Item("objectclass") -ne ""){
                $objcl = $Attrib.Get_Item("objectclass")
                $objs = $objcl.split("^") | where {$_ -ne "^"}  

                foreach($i in $objs){
                    $newObjClass += $i
                }
            }
            Write-Host "Create new entry ", $ObjectDN, " with class ", $newObjClass
            $attrObjClass = New-Object System.DirectoryServices.Protocols.DirectoryAttribute("objectclass",$newObjClass)
            $newEntry.Attributes.Add($attrObjClass) 
            #add values of the attribute

            foreach ($line in $Attrib.GetEnumerator()) {
                $key = $($line.Name)
                $val = $($line.Value)
                if($key -ne "DN" -and $key -ne "objectclass" -and $key -ne "defaultobjclass"){
                    Write-Host "Key : ", $key ," ; Value : ", $val
                    if( $val.Contains("^") ){
                        [string[]] $tab = @()
                        $tab = $val.split("^") | where {$_ -ne "^"}
                        $attr = New-Object System.DirectoryServices.Protocols.DirectoryAttribute($key, $tab)                    
                    }else{
                        $attr = New-Object System.DirectoryServices.Protocols.DirectoryAttribute( $key, $val)
                    }

                    $newEntry.Attributes.Add($attr)
                }

            }

            $re = $LdapConnection.SendRequest($newEntry)

            #$result += "NewEntry_ResultCode: $($re.ResultCode)"
            if ($re.ResultCode -ne [System.directoryServices.Protocols.ResultCode]::Success){
                Write-Host "NewEntry_ErrorMessage: $($re.ResultCode.ErrorMessage)"
                throw "$($re.ResultCode.ErrorMessage)"
            }
            #return $result
        }
    }

    <#
    .Synopsis
    Update access for an object in LDAP
    .EXAMPLE
    New-LdapUpdateRequest -LdapConnection $connexion -Entry $Entry -AttribToUpd $hashAttrUpd -AttribToDlt $hashAttrDlt
    #>
    function New-LdapUpdateRequest
    {
        Param
        (
            # Ldap Connection
            [Parameter(Mandatory=$true)]
            [System.DirectoryServices.Protocols.LDAPConnection] $LdapConnection,

            # Entry Profile
            [Parameter(Mandatory=$true)]
            [System.DirectoryServices.Protocols.SearchResultEntry] $Entry,

            # Attributes to Modify 
            [System.Collections.Hashtable] $AttribToUpd,

            # Attributes to Delete 
            [System.Collections.Hashtable] $AttribToDlt

        )

        Process
        {

            if ($AttribToUpd -ne $null) {
                $reUpt = New-LdapModifyRequest -LdapConnection $LdapConnection -Entry $Entry -Attrib $AttribToUpd
            }

            if ($AttribToDlt -ne $null) {
                $reDlt = New-LdapDeleteRequest -LdapConnection $LdapConnection -Entry $Entry -AttribToDelete $AttribToDlt
            }

        }
    }

    <#
    .Synopsis
    Delete a Entry in LDAP
    .EXAMPLE
    New-LdapDeleteRequest -LdapConnection $con -Entry $Entry -AttribToDelete $attrib
    #>
    function New-LdapDeleteRequest
    {
    #   [OutputType([System.DirectoryServices.Protocols.DirectoryResponse])]
        Param
        (
            # Ldap Connection
            [Parameter(Mandatory=$true)]
            [System.DirectoryServices.Protocols.LDAPConnection] $LdapConnection,

            # Entry Profile
            [Parameter(Mandatory=$true)]
            [System.DirectoryServices.Protocols.SearchResultEntry] $Entry,

            # Attributes to delete
            [Parameter(Mandatory=$true)]
            [System.Collections.Hashtable] $AttribToDelete
        )

        Process
        {
            $r = (new-object "System.DirectoryServices.Protocols.ModifyRequest")
            $r.DistinguishedName = $Entry.DistinguishedName

            foreach($attrib in $AttribToDelete.GetEnumerator()){
                $key = $($attrib.Name)
                $val = $($attrib.Value)
                if($key -ne "objectclass" -and $Entry.Attributes[$key] -ne $null ){
                    if ($val -eq "" -or $val -eq $null){
                        Write-Host "Delete attribute : ", $key

                        $ope = New-Object "System.DirectoryServices.Protocols.DirectoryAttributeModification"
                        $ope.Name = $key
                        $ope.Operation = [System.DirectoryServices.Protocols.DirectoryAttributeOperation]::Delete

                        $r.Modifications.Add($ope)              
                    }

                }

            }

            $ObjClassVal = $AttribToDelete.Get_Item("objectClass")

            if($ObjClassVal -ne $null){     
                # process objectClass when provided
                [string[]] $DelObjClassValue = @()
                $DelObjClassValue = $ObjClassVal.split("^") | where {$_ -ne "^"}

                if(!$Entry.Attributes["objectclass"].GetValues([string]).Contains($DelObjClassValue[0])){
                    Write-Host "The entry does not have that objectClass"
                }else{
                    $tabObjClass = $Entry.Attributes["objectclass"].GetValues([string])
                    Write-Host "Object Class : ", $tabObjClass

                    [string[]] $newObjClass = @()

                    foreach($i in $tabObjClass){
                        $validValue = $true
                        foreach($j in $DelObjClassValue){
                            if($i -eq $j){
                                $validValue = $false
                            }
                        }
                        if($validValue -eq $true){
                            $newObjClass += $i
                        }   
                    }
                    Write-Host "New Object Class : ", $newObjClass
                }
                #prepare the request
                $objclass = New-Object "System.DirectoryServices.Protocols.DirectoryAttributeModification"
                $objclass.Name = "objectclass"
                $objclass.Operation = [System.DirectoryServices.Protocols.DirectoryAttributeOperation]::Replace
                $objclass.AddRange($newObjClass)

                $r.Modifications.Add($objclass)

            }
            #Actually process the request through the server
            $re = $LDAPConnection.SendRequest($r);
            if ($re.ResultCode -ne [System.directoryServices.Protocols.ResultCode]::Success){
                Write-Host "SendRequest ResultCode : $($re.ResultCode) ; ErrorMessage : $($re.ResultCode.ErrorMessage)"
                throw "$($re.ResultCode.ErrorMessage)"
            }           
        }
    }

    <#
    .Synopsis
    Create access for a Entry in LDAP
    .EXAMPLE
    New-LdapModifyRequest -LdapConnection $con -Entry $Entry -Attrib $attrib
    #>
    function New-LdapModifyRequest
    {
        Param
        (
            # Ldap Connection
            [Parameter(Mandatory=$true)]
            [System.DirectoryServices.Protocols.LDAPConnection] $LdapConnection,

            # Entry Profile
            [Parameter(Mandatory=$true)]
            [System.DirectoryServices.Protocols.SearchResultEntry] $Entry,

            # Attributes to Add 
            [Parameter(Mandatory=$true)]
            [System.Collections.Hashtable] $Attrib

        )

        Process
        {

            Write-Host "Begin Update LdapModifyRequest for", $Entry.DistinguishedName

            $r = (new-object "System.DirectoryServices.Protocols.ModifyRequest")

            $r.DistinguishedName = $Entry.DistinguishedName

            $obj = $Attrib.Get_Item("objectclass")
            if($obj -ne $null){
            # process objectClass when provided
                [string[]] $TabObjclass = @()
                $TabObjclass = $obj.split("^") | where {$_ -ne "^"}
                $getAccess = $false
                foreach($line in $TabObjclass){
                    if($Entry.Attributes["objectclass"].GetValues([string]).Contains($line)){
                        $getAccess = $true
                    }
                }

                if(!$getAccess){

                    Write-Host "Create Entry - set objectClass"
                    $newobjclass = New-Object "System.DirectoryServices.Protocols.DirectoryAttributeModification"
                    $newobjclass.Name = "objectClass"
                    $newobjclass.Operation = [System.DirectoryServices.Protocols.DirectoryAttributeOperation]::Add
                    #add values of the attribute
                    foreach($line in $TabObjclass){
                        $newobjclass.Add($line)
                    }
                    $r.Modifications.Add($newobjclass)

                }
            }
            Write-Host "Update Attributes"
            foreach ($line in $Attrib.GetEnumerator()) {
                $key = $($line.Name)
                $val = $($line.Value)
                if ($Entry.Attributes[$key] -or $val) {

                    if ($key -ne "objectclass" -and $key -ne "defaultobjclass") {
                        if ($Entry.Attributes[$key]){
                            Write-Host " Key : ", $key ," ; New Value : ", $val ," ; LDAP Value : ", $Entry.Attributes[$key].GetValues([string]) 
                        }else{
                            Write-Host " Key : ", $key ," ; New Value : ", $val ," ; LDAP Value : EMPTY "
                        }

                        $attr = New-Object "System.DirectoryServices.Protocols.DirectoryAttributeModification"
                        $attr.Name = $key

                        if($Entry.Attributes[$key]){
                            $attr.Operation = [System.DirectoryServices.Protocols.DirectoryAttributeOperation]::Replace
                        }else{
                            $attr.Operation = [System.DirectoryServices.Protocols.DirectoryAttributeOperation]::Add
                        }

                        if($val -Match "\^"){
                            [string[]] $tab = @()
                            $tab = $val.split("^") | where {$_ -ne "^"}
                            $attr.AddRange($tab)    
                        }else{
                            $attr.Add($val) 
                        }

                        $r.Modifications.Add($attr)     
                    }
                }
            }

            #Actually process the request through the server
            $re = $LdapConnection.SendRequest($r);
            if ($re.ResultCode -ne [System.directoryServices.Protocols.ResultCode]::Success){
                Write-Host "SendRequest ResultCode : $($re.ResultCode) ; ErrorMessage : $($re.ResultCode.ErrorMessage)"
                throw "$($re.ResultCode.ErrorMessage)"
            }

        }
    }

    <# AMO 18/08/2017 Nouvelle fonction pour la suppression de l'entrée
    .Synopsis
    Delete an object in LDAP
    .EXAMPLE
    New-LdapDeleteRecord -LdapConnection $connexion -Entry $Entry 
    #>
    function New-LdapDeleteRecord
    {
        Param 
        (
            # Ldap Connection
            [Parameter(Mandatory=$true)]
            [System.DirectoryServices.Protocols.LDAPConnection] $LdapConnection,

            # Entry Profile
            [Parameter(Mandatory=$true)]
            [System.DirectoryServices.Protocols.SearchResultEntry] $Entry

        )

        Process
        {
                   Write-Host "New-LdapDeleteRecord Begin"
            #AMO 18/08/2017 Suppression de l'entrée
            $r = (new-object "System.DirectoryServices.Protocols.DeleteRequest")
            $r.DistinguishedName = $Entry.DistinguishedName

            Write-Host "New-LdapDeleteRecord sendRequest"
            #Actually process the request through the server
            $re = $LdapConnection.SendRequest($r);
            if ($re.ResultCode -ne [System.directoryServices.Protocols.ResultCode]::Success){
                Write-Host "SendRequest ResultCode : $($re.ResultCode) ; ErrorMessage : $($re.ResultCode.ErrorMessage)"
                throw "$($re.ResultCode.ErrorMessage)"
            }
             Write-Host "New-LdapDeleteRecord End"
        }
    }

    <#
    .Synopsis
    Transform a Json to HashTable
    .EXAMPLE
    Format-JsonToHashtable -JsonString $jsonStr
    #>
    function Format-JsonToHashtable
    {
        [OutputType([System.Collections.Hashtable])]
        Param
        (
            # Entry Profile
            [Parameter(Mandatory=$true)]
            [String] $JsonString
        )

        Process
        {

            $jsonConv = $JsonString -replace "\\", ""
            $jsonObject = $jsonConv | ConvertFrom-Json

            foreach ($myPsObject in $jsonObject) {
                $hashAttrJson = @{}
                $myPsObject | Get-Member -MemberType *Property | % {
                    $hashAttrJson.($_.name) = $myPsObject.($_.name)
                }
            }

            return $hashAttrJson
        }

    }

最佳答案

我相信错误在这里:

        $LDAPConnection.SessionOptions.VerifyServerCertificate = {
            param(
                [DirectoryServices.Protocols.LdapConnection]$Connection,
                [Security.Cryptography.X509Certificates.X509Certificate2]$Certificate
            )      
            $Global:LdapCertificate = $Certificate    
            return $true
        }

您正在创建 Script Block带参数。我认为问题在于您没有向脚本 block 提供任何参数,因此 PowerShell 正在查看后续命令来“填充”参数,这会导致错误。

如果您像这样实现,则必须传递 -ArgumentList 来“填充”参数。例如:

        $LDAPConnection.SessionOptions.VerifyServerCertificate = {
            param(
                [DirectoryServices.Protocols.LdapConnection]$Connection,
                [Security.Cryptography.X509Certificates.X509Certificate2]$Certificate
            )      
            $Global:LdapCertificate = $Certificate    
            return $true
        } -ArgumentList "Connection", "Certificate"

关于用于从 servicenow 更新 ldap 数据的 Powershell 脚本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60889803/

相关文章:

javascript - 我如何从 Javascript 调用 VBscript

c# - 服务仅在调试时工作

Powershell - 将文件夹的结构导出到 txt 或 xls,但只能导出 3 个文件夹的深度且没有文件

java - 创建名称为 'Test_flow' : Cannot create inner bean '(inner bean) 的 bean 时出错

single-sign-on - 是否可以让 Okta 在 ServiceNow 中复制 AD 组(及其成员)?

java - 使用安装的 java keystore 证书连接到 ldap

Powershell : Remote Exception and NativeCommandError 中的 Python 脚本

shell - 使用Power Shell获取具有页面布局的SharePoint页面列表

php - 如何将 LDAP 时间戳转换为 Unix 时间戳

java - LDAP 使用 UPN 在 Active Directory 中搜索用户