【问题标题】:Identifying Certificate by "Certificate Template Name" in PowerShell在 PowerShell 中通过“证书模板名称”识别证书
【发布时间】:2017-09-05 18:34:28
【问题描述】:

我需要使用 PowerShell 脚本来选择“证书模板名称”作为“机器”的证书。在 certmgr.msc 中,它具有值为“计算机”的“证书模板”。在详细信息中,相同的“证书模板名称”为“机器”。

如何在 PowerShell 脚本中使用这些值?

到目前为止,我有:

get-childitem cert:\localmachine\my | where-object {$_.}

我几乎尝试了所有可以加载智能感知的方法,但找不到任何满足我需求的方法。

谢谢,

【问题讨论】:

  • 您在哪里看到该信息,例如在 certmgr.msc 中?你试过Get-ChildItem cert:\localmachine\my | Get-Member -Force 吗?
  • 我不知道你会如何在 PowerShell 中处理它,但 X509CertificateCollection2.Find(X509FindType.FindByTemplateName, templateNameString, false) 可以做你想做的事。
  • 证书本身不包含模板名称,仅包含模板的对象标识符。您可以从 Active Directory 中提取特定证书模板的 OID,然后根据适当的扩展名进行过滤
  • @sodawillow 证书模板,一旦我打开个人证书,就列在最右边。证书模板名称列在右键单击 > 打开 > 详细信息中。
  • @SauerTrout 如上所述,这不是证书本身的一部分。 certmgr GUI 从 AD 获取模板名称。

标签: powershell certificate


【解决方案1】:

这是一个无模块的解决方案:

$templateName = 'Super Cool *'
Get-ChildItem 'Cert:\LocalMachine\My' | Where-Object{ $_.Extensions | Where-Object{ ($_.Oid.FriendlyName -eq 'Certificate Template Information') -and ($_.Format(0) -match $templateName) }}

【讨论】:

    【解决方案2】:

    除了已经发布的答案,让我分享一下对我有用的方法:

    # Example usage:
    #   ls 'Cert:\LocalMachine\My' | ForEach-Object { Get-CertificateTemplateName $_ }
    #
    function Get-CertificateTemplateName($certificate)
    {
        # The template name is stored in the Extension data. 
        # If available, the best is the extension named "Certificate Template Name", since it contains the exact name.
        $templateExt = $certificate.Extensions | Where-Object{ ( $_.Oid.FriendlyName -eq 'Certificate Template Name') } | Select-Object -First 1   
        if($templateExt) {
            return $templateExt.Format(1)
        }
        else {
            # Our fallback option is the "Certificate Template Information" extension, it contains the name as part of a string like:
            # "Template=Web Server v2(1.3.6.1.4.1.311.21.8.2499889.12054413.13650051.8431889.13164297.111.14326010.6783216)"
            $templateExt = $certificate.Extensions | Where-Object{ ( $_.Oid.FriendlyName -eq 'Certificate Template Information') } | Select-Object -First 1   
            if($templateExt) {
                $information = $templateExt.Format(1)
    
                # Extract just the template name in $Matches[1]
                if($information -match "^Template=(.+)\([0-9\.]+\)") {
                    return $Matches[1]
                } else {
                    # No regex match, just return the complete information then
                    return $information
                }
            } else {
                # No template name found
                return $null
            }
        }
    }
    

    【讨论】:

      【解决方案3】:

      这是一个原生 PowerShell 解决方案:

      感谢PowerShell Gallery

      <#
      .SYNOPSIS
       Outputs an object consisting of the template name (Template), an OID (OID), the minor version (MinorVersion), and the major version (MajorVersion).
      
      .DESCRIPTION
       Outputs an object consisting of the template name (Template), an OID (OID), the minor version (MinorVersion), and the major version (MajorVersion).
       This information is derived from the Certificate Extensions.
      
      .PARAMETER Certificate
       A X509Certificate2 object
      
      .EXAMPLE
       Get-ChildItem "Cert:\LocalMachine\My" | Get-CertificateTemplate
      
      .EXAMPLE
       Get-ChildItem "Cert:\LocalMachine\My" | Select-Object Name,Thumbprint,@{Name="Template";Expression={Get-CertificateTemplate $_}}
      
      .INPUTS
       Any X509Certificate2 object
      
      .OUTPUTS
       [PSCustomObject] @{Template=<template name; OID=<oid string>; MajorVersion=<major version num>; MinorVersion=<minor version num> }
      #>
      function Get-CertificateTemplate {
        [CmdletBinding(SupportsShouldProcess=$false)]
        [OutputType([string])]
        Param([Parameter(Mandatory=$true, ValueFromPipeline=$true)] [ValidateNotNull()] [Security.Cryptography.X509Certificates.X509Certificate2]$Certificate)
      
        Process {
          $regExPrimary=[System.Text.RegularExpressions.Regex]::new("Template=([\w\s\d\.]+)\(((?:\d+.)+)\), Major Version Number=(\d+), Minor Version Number=(\d+)",[System.Text.RegularExpressions.RegexOptions]::None)
          $regExSecondary=[System.Text.RegularExpressions.Regex]::new("Template=((?:\d+.)+), Major Version Number=(\d+), Minor Version Number=(\d+)",[System.Text.RegularExpressions.RegexOptions]::None)
      
          $temp = $Certificate.Extensions | Where-Object { $_.Oid.FriendlyName -eq "Certificate Template Name" }
          if ($temp -eq $null) {
            Write-Verbose "Did not find 'Certificate Template Name' extension"
            $temp=$Certificate.Extensions | Where-Object { $_.Oid.Value -eq "1.3.6.1.4.1.311.21.7" }
          }
          else { Write-Verbose "Found 'Certificate Template Name' extension" }
      
          $Matches=$regExPrimary.Matches($temp.Format($false))
          if ($Matches.Count -gt 0) {
            $object=@{Template=$Matches[0].Groups[1].Value; OID=$Matches[0].Groups[2].Value; 
                      MajorVersion=$Matches[0].Groups[3].Value; MinorVersion=$Matches[0].Groups[4].Value;
                      Thumbprint=$Certificate.Thumbprint }
          }
          else {
            $Matches=$regExSecondary.Matches($temp.Format($false))
            if ($Matches.Count -gt 0) {
              Write-Verbose "Found certificate without a valid Template Name"
              $object=@{Template=$Matches[0].Groups[1].Value; OID=$Matches[0].Groups[1].Value; 
                        MajorVersion=$Matches[0].Groups[2].Value; MinorVersion=$Matches[0].Groups[3].Value;
                        Thumbprint=$Certificate.Thumbprint }
      
            }
            else {
              Write-Verbose "Found root certificate"
              $object=@{Template="Root Certificate"; OID=""; MajorVersion=""; MinorVersion=""; Thumbprint=$Certificate.Thumbprint }
            }
          }
          return [PSCustomObject]$object
        }
      }
      

      【讨论】:

        【解决方案4】:

        试试这个 powershell 模块CertificatePS。里面有这个 cmdlet Get-CertificateTemplate 可以满足您的需要。我开发了它,我自己用它来区分机器和网络模板证书。

        这是一个使用示例,尽管还有其他可能性,例如将 PSNoteProperty 添加到每个返回对象中

        # With Select-Object
        Get-ChildItem "Cert:\LocalMachine\My" | Select-Object Name,Thumbprint,@{Name="Template";Expression={Get-CertificateTemplate $_}}
        
        # With Where-Object
        Get-ChildItem "Cert:\LocalMachine\My" | Where-Object {Get-CertificateTemplate $_ -eq "Template"}}
        

        查看有关此模块的更多示例here

        该模块并不完美,因此如果您有任何反馈或贡献,请通过github project 进行。

        【讨论】:

          【解决方案5】:

          $cert.Extension.format(0) 和 format(1) 将以人类可读的方式返回这些属性。

               # Retrieves CRL distribution point if present
              function Get-CRLDistPoint {
                  Param ($cert)
                          $extension = $cert.Extensions | where {$_.OID.FriendlyName -eq "CRL Distribution Points"}
                          if ($extension) {
                              $crlURL = $extension.Format(0)
                              # trim header
                              $crlURL = $crlURL -replace "^.*URL=", ""
                              }
                          $crlURL
              }
          
          Get-ChildItem Cert:\LocalMachine\my | %{ Get-CRLDistPoint}
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2012-05-12
            • 1970-01-01
            • 1970-01-01
            • 2017-07-20
            • 2011-08-19
            • 2022-06-10
            • 1970-01-01
            相关资源
            最近更新 更多