我正在尝试构建一个仪表板来检索我们所有服务器上的证书信息,但是我在Powershell对象处理方面苦苦挣扎。我相信这是对象在循环内外传递的方式。我的代码有3次迭代。
首先,将检索所有证书,但是每个对象上的FriendlyName均被清空:
$serverCert = $null
$servers=get-adcomputer -filter { ( OperatingSystem -like '*server*') -AND ( Name -notlike '*-DT0094' ) } | sort Name
foreach ( $server in $servers ) {
$ServerName=$server.Name
$ServerName="$ServerName.DOMAINSUFFIX"
$serverCert += Invoke-Command -ComputerName $ServerName -Scriptblock {
return $(Get-ChildItem Cert:\LocalMachine\My)
}
}
$serverCert | Select-Object PSComputerName, Thumbprint, FriendlyName, NotAfter, @{N="Template";E={($_.Extensions | ?{$_.oid.Friendlyname -match "Certificate Template Information"}).Format(0) -replace "(.+)?=(.+)\((.+)?", '$2'}}, @{N="IssuedBy";E={($_.IssuerName.Name -split ',*..=')[1]}}, @{N="Subject";E={($_.Subject -split ',*..=')[1]}} | Sort Thumbprint | Format-Table -Wrap
在此迭代中,扩展是通过以下方式实现的:
PS C:\WINDOWS> $serverCert[0] | Select-Object -Property Extensions
Extensions
----------
{System.Security.Cryptography.Oid, System.Security.Cryptography.Oid}
在第二个中,我通过将FriendlyName作为一个名为“ Description”的新属性显式传递来解决了这个问题……不幸的是,现在模板不显示:
$serverCert = $null
$servers=get-adcomputer -filter { ( OperatingSystem -like '*server*') -AND ( Name -notlike '*-DT0094' ) } | sort Name
foreach ( $server in $servers ) {
$ServerName=$server.Name
$ServerName="$ServerName.DOMAINSUFFIX"
$serverCert += Invoke-Command -ComputerName $ServerName -Scriptblock {
return $(Get-ChildItem Cert:\LocalMachine\My | Select-Object *, @{N="Description";E={$_.FriendlyName}})
}
}
$serverCert | Select-Object PSComputerName, Thumbprint, Description, NotAfter, @{N="Template";E={($_.Extensions | ?{$_.oid.Friendlyname -match "Certificate Template Information"}).Format(0) -replace "(.+)?=(.+)\((.+)?", '$2'}}, @{N="IssuedBy";E={($_.IssuerName.Name -split ',*..=')[1]}}, @{N="Subject";E={($_.Subject -split ',*..=')[1]}} | Sort Thumbprint | Format-Table -Wrap
在此迭代中,扩展是这样进行的,我无法显示模板名称:
PS C:\WINDOWS> $serverCert[0] | Select-Object -Property Extensions
Extensions
----------
{System.Security.Cryptography.X509Certificates.X509EnhancedKeyUsageExtension, System.Security.Cryptography.X509Certificates.X509KeyUsageExtension}
现在是第三个。这次,我尝试将模板信息作为“描述”之类的属性向前传递。问题是模板信息不清楚。而不是友好名称,将显示其他信息。
$serverCert = $null
$servers=get-adcomputer -filter { ( OperatingSystem -like '*server*') -AND ( Name -notlike '*-DT0094' ) } | sort Name
foreach ( $server in $servers ) {
$ServerName=$server.Name
$ServerName="$ServerName.DOMAINSUFFIX"
$serverCert += Invoke-Command -ComputerName $ServerName -Scriptblock {
return $(Get-ChildItem Cert:\LocalMachine\My | Select-Object *, @{N="Description";E={$_.FriendlyName}}, @{N="Template";E={($_.Extensions | ?{$_.oid.Friendlyname -match "Certificate Template Information"}).Format(0) -replace "(.+)?=(.+)\((.+)?", '$2'}})
}
}
$serverCert | Select-Object PSComputerName, Thumbprint, Description, NotAfter, Template, @{N="IssuedBy";E={($_.IssuerName.Name -split ',*..=')[1]}}, @{N="Subject";E={($_.Subject -split ',*..=')[1]}} | Sort Thumbprint | Format-Table -Wrap
某些证书的模板信息(我无法在模板,操作系统版本...任何内容上建立关联)看起来像这样:
模板== 1.3.6.1.4.1.311.21.8.16245382.12313948.10571683.3565079.1665071.100.15924968.15384388,主要版本号= 100,次要版本号= 4
我很困惑。我仍然对Powershell感到满意,但是我对对象操作的理解不够深刻,无法知道如何解决此问题。任何帮助表示赞赏!
答案 0 :(得分:1)
我认为在使用 -ComputerName 参数时,PowerShell在第一次迭代中未返回的原因与PowerShell反序列化数据的方式有关。
在第一次迭代中,尝试更改此行:
return $(Get-ChildItem Cert:\LocalMachine\My)
收件人:
return $(Get-ChildItem Cert:\LocalMachine\My | Select-Object *)
为说明问题,请运行以下三个命令,您希望它们都包含相同的对象属性。请注意,FriendlyName仅包含在前两个命令的输出中:
Invoke-Command -ScriptBlock { gci Cert:\LocalMachine\My } | Select-Object FriendlyName
Invoke-Command -ScriptBlock { gci Cert:\LocalMachine\My | Select-Object * } -ComputerName . | Select-Object FriendlyName
Invoke-Command -ScriptBlock { gci Cert:\LocalMachine\My } -ComputerName . | Select-Object FriendlyName
编辑:这就是我的做法:
Function Get-Cert-Info($ComputerName) {
Invoke-Command -Computer $ComputerName -ScriptBlock {
$certs = Get-ChildItem cert:\localmachine\my
foreach($cert in $certs) {
[pscustomobject]@{
ComputerName = $env:COMPUTERNAME
Thumbprint = $cert.Thumbprint
Description = $cert.FriendlyName
TemplateName = $(
$Template = $cert.Extensions | Where-Object { $_.oid.FriendlyName -match "Certificate Template Information" }
if($Template) {
($Template.Format(0) -split "\(")[0] -replace "Template=", ""
}
)
SAN=$(
try {
$cert.Extensions | Where-Object {$_.Oid.FriendlyName -eq "subject alternative name"} | ForEach {
$SANString = "{0}" -f $_.Format(0)
$SANS = $SANString -split ','
foreach($SAN in $SANS) {
($SAN -split "=")[1]
}
}
} catch {
"n/a"
}
)
IssuedBy=$(($cert.IssuerName.Name -split ',')[0] -replace 'CN=', '')
Subject=$(($cert.Subject -split ',')[0] -replace 'CN=', '')
NotAfter=$cert.NotAfter
}
}
}
}
$servers=get-adcomputer -filter { ( OperatingSystem -like '*server*') -AND ( Name -notlike '*-DT0094' ) } | sort Name
foreach ( $server in $servers ) {
Get-Cert-Info -ComputerName $server.Name
}
答案 1 :(得分:0)
虽然我找到了一种获取模板名称的方法,但是查找会失败,所以当我获得ID时,我做了类似于替换的操作:
# Get all certificates from all servers
clear-host
$serverCert = $null
ipconfig /flushdns
$servers=get-adcomputer -filter { OperatingSystem -like '*server*' } | sort Name
foreach ( $server in $servers ) {
$ServerName=$server.Name
$ServerName="$ServerName.DOMAINSUFFIX"
$serverCert += Invoke-Command -ComputerName $ServerName -Scriptblock {
return $(Get-ChildItem Cert:\LocalMachine\My | Select-Object *, @{N="Description";E={$_.FriendlyName}}, @{N="TemplateName";E={($_.Extensions | ?{$_.oid.Friendlyname -match "Certificate Template Information"}).Format(0) -replace "(.+)?=(.+)\((.+)?", '$2' -replace 'Template=', '' -replace '1.3.6.1.4.1.311.21.8.16245382.12313948.10571683.3565079.1665071.100.15924968.15384388.*', 'SCCM Client Certificate' -replace '1.3.6.1.4.1.311.21.8.16245382.12313948.10571683.3565079.1665071.100.9941395.14900143.*','IIS Web Servers' -replace '1.3.6.1.4.1.311.21.8.16245382.12313948.10571683.3565079.1665071.100.1979823.4984146.*','WSUS Web Server Certificate'}})
}
}
$serverCert | Select-Object PSComputerName, Thumbprint, Description, NotAfter, TemplateName, @{N="IssuedBy";E={($_.IssuerName.Name -split ',*..=')[1]}}, @{N="Subject";E={($_.Subject -split ',*..=')[1]}} | Sort NotAfter, PSComputerName | Format-Table -Wrap