【问题标题】:Get CN value from ADUser DistinguishedName从 ADUser DistinguishedName 获取 CN 值
【发布时间】:2021-05-12 11:30:42
【问题描述】:

我有一个 PS 脚本可以检查 Active Directory 中的一些自定义用户属性。 其中一个属性是“Manager”。

 $data = Get-ADUser $user -Properties * |  Select-Object DisplayName, LockedOut, Enabled, LastLogonDate, PasswordExpired, EmailAddress, Company, Title, Manager, Office

 Write-Host "9." $user "manager is" $data.manager -ForegroundColor Green

当我运行脚本时,我得到了:

User's manager is CN=cool.boss,OU=Users,OU=SO,OU=PL,OU=RET,OU=HBG,DC=domain,DC=com

问题是文本"OU=SO,OU=PL,OU=RET,OU=HBG,DC=domain,DC=com" 对于某些用户会有所不同

如何修改输出并删除除"cool.boss" 之外的所有内容? 提前谢谢你

【问题讨论】:

    标签: powershell active-directory distinguishedname


    【解决方案1】:

    这应该是一种或多或少安全且仍然简单的解析方法:

    ($data.manager -split "," | ConvertFrom-StringData).CN
    

    【讨论】:

    • (对不起,我误读了这个问题 - 你的答案很准确)。 +1 一个优雅的解决方案,其唯一的限制是嵌入在值 (\,) 中的 转义 逗号可能不常见,无法正确处理。
    • 解析CN+1的非常灵巧的方法。
    • @mklement0 是的,这就是我所说的“或多或少”的意思;)感谢您的回答,这是一个很好的参考,以防有人需要一个功能齐全的解决方案。
    【解决方案2】:

    你可以使用.split()方法得到你想要的。

    $DN = "CN=cool.boss,OU=Users,OU=SO,OU=PL,OU=RET,OU=HBG,DC=domain,DC =com"
    $DN.Split(',').Split('=')[1]
    

    我的建议是把它扔到另一个Get-ADUser 以获得更整洁的输出显示名称(:

    【讨论】:

      【解决方案3】:

      使用 PowerShell 惯用的 regex 解决方案补充此处的有用答案:

      $dn = 'CN=cool.boss,OU=Users,OU=SO,OU=PL,OU=RET,OU=HBG,DC=domain,DC=com'
      
      ($dn -split '(?:^|,)CN=|,')[1] # -> 'cool.boss'
      
      $dn = 'CN=cool.boss,OU=Users,OU=SO,OU=PL,OU=RET,OU=HBG,DC=domain,DC=com'
      
      $dn -replace '(?:^|,)CN=([^,]+).*', '$1' # -> 'cool.boss'
      

      注意:

      • 上述解决方案不依赖于输入中名称-值对 (RDN) 的特定顺序(即,CN 条目不必是第一个),但他们只提取 first CN 条目的值,如果存在多个,并且他们确实假设(至少)一个存在。

      • 原则上,DNs (Distinguished Names)(以输入字符串为例)可以在构成 DN 的名称-值对的值中嵌入 , 字符,转义为\,(或者,以十六进制表示,\2C);例如,"CN=boss\, cool,OU=Users,..."

      • 一个真正强大的解决方案必须考虑到这一点,并且理想情况下还 unescape 结果值;在撰写本文时,现有的答案都没有这样做;见下文。


      稳健地解析 LDAP/AD DN (Distinguished Name)

      以下Split-DN函数

      • 正确处理转义、嵌入 , 字符,以及其他转义序列
      • 取消转义这些值,其中不仅包括删除语法\,还包括以\<hh> 形式转换转义序列,其中hh 是两位数的十六进制。表示字符代码点的数字,转换为它们所表示的实际字符(例如,\3C,转换为 < 字符)。
      • 输出一个有序的hashtable,其键是名称组件(例如,CNOU),名称的值出现多次次 - 例如OU -表示为一个数组

      调用示例:

      PS> Split-DN 'CN=I \3C3 Huckabees\, I do,OU=Users,OU=SO,OU=PL,OU=RET,OU=HBG,DC=domain,DC=com'
      
      Name                           Value
      ----                           -----
      CN                             I <3 Huckabees, I do
      OU                             {Users, SO, PL, RET…}
      DC                             {domain, com}
      

      请注意转义序列 \3C 是如何转换为 &lt; 的,它所代表的字符,以及 \, 如何被识别为 , 嵌入CN 值中。

      由于输入字符串包含多个OUDC名称-值对(所谓的RDN,相对专有名称),它们对应的哈希表条目变为值的数组(在仅显示截断的输出中用{ ... } 表示,, 分隔元素)。


      函数Split-DN的源代码:

      注意:为简洁起见,省略了错误处理和验证。

      function Split-DN {
      
        param(
          [Parameter(Mandatory)]
          [string] $DN
        )
      
        # Initialize the (ordered) output hashtable.
        $oht = [ordered] @{}
      
        # Split into name-value pairs, while correctly recognizing escaped, embedded
        # commas.
        $nameValuePairs = $DN -split '(?<=(?:^|[^\\])(?:\\\\)*),'
      
        $nameValuePairs.ForEach({
      
          # Split into name and value.
          # Note: Names aren't permitted to contain escaped chars.
          $name, $value = ($_ -split '=', 2).Trim()
      
          # Unescape the value, if necessary.
          if ($value -and $value.Contains('\')) {
            $value = [regex]::Replace($value, '(?i)\\(?:[0-9a-f]){2}|\\.', {
              $char = $args[0].ToString().Substring(1)
              if ($char.Length -eq 1) { # A \<literal-char> sequence.
                $char # Output the character itself, without the preceding "\"
              }
              else { # A \<hh> escape sequence, conver the hex. code point to a char.
                [char] [uint16]::Parse($char, 'AllowHexSpecifier') 
              }
            })
          }
          
          # Add an entry to the output hashtable. If one already exists for the name,
          # convert the existing value to an array, if necessary, and append the new value.
          if ($existingEntry = $oht[$name]) {
            $oht[$name] = ([array] $existingEntry) + $value
          }
          else {
            $oht[$name] = $value
          }
      
        })
      
        # Output the hashtable.
        $oht
      }
      

      【讨论】:

        【解决方案4】:

        您可以为此使用正则表达式:

        $s = "CN=cool.boss,OU=Users,OU=SO,OU=PL,OU=RET,OU=HBG,DC=domain,DC =com"
        
        $pattern = [regex]"CN=.*?OU"
        $r = $pattern.Replace($s, "CN=OU")
        $r
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-02-27
          • 1970-01-01
          • 1970-01-01
          • 2015-12-17
          • 2020-06-18
          • 1970-01-01
          相关资源
          最近更新 更多