处理 AD 用户证书
Processing AD user certificates
我是 Powershell 的菜鸟,实际问题是我对如何搜索各种属性有点迷茫,很难找到符合我需要的示例。
话虽如此,我需要搜索 Active Directory 以查找即将过期的用户 S/MIME 证书,这些证书是由特定的证书颁发机构颁发的。
我已经拥有的:
$Mail = user@example.com
$allProfileCerts = Get-ADUser -Server example.com:3268 -Filter {EmailAddress -eq $Mail} -Properties Certificates | select Certificates
结果是:
Handle Issuer Subject
------ ------ -------
1625625266096 CN=<CA1> E=test.user@example.com, CN=Test User, OU=Normal, OU=Users, OU=EXAMPLE, ...
1625625265968 CN=<CA2> E=test.user@example.com, CN=Test User, O=Example Company, ...
1625625271728 CN=<CA1> CN=Test User, OU=Normal, OU=Users, OU=EXAMPLE, ...
我认为下一步可以是:
$allProfileCerts.Certificates | foreach {New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 $_}
结果提供了更多详细信息(已编辑以删除 PII):
EnhancedKeyUsageList : {Secure Email (1.3.6.1.5.5.7.3.4)}
DnsNameList : {Test User}
SendAsTrustedIssuer : False
EnrollmentPolicyEndPoint : Microsoft.CertificateServices.Commands.EnrollmentEndPointProperty
EnrollmentServerEndPoint : Microsoft.CertificateServices.Commands.EnrollmentEndPointProperty
PolicyId :
Archived : False
Extensions : {System.Security.Cryptography.Oid, System.Security.Cryptography.Oid, System.Security.Cryptography.Oid, System.Security.Cryptography.Oid...}
FriendlyName :
IssuerName : System.Security.Cryptography.X509Certificates.X500DistinguishedName
NotAfter : 29/05/2021 10:47:00
NotBefore : 11/12/2018 09:47:00
HasPrivateKey : False
PrivateKey :
PublicKey : System.Security.Cryptography.X509Certificates.PublicKey
RawData : {48, 130, 8, 51...}
SerialNumber : <snip>
SubjectName : System.Security.Cryptography.X509Certificates.X500DistinguishedName
SignatureAlgorithm : System.Security.Cryptography.Oid
Thumbprint : <snip>
Version : 3
Handle : 1625625266096
Issuer : <ISSUER1>
Subject : <subject>
EnhancedKeyUsageList : {Secure Email (1.3.6.1.5.5.7.3.4)}
DnsNameList : {Test User}
SendAsTrustedIssuer : False
EnrollmentPolicyEndPoint : Microsoft.CertificateServices.Commands.EnrollmentEndPointProperty
EnrollmentServerEndPoint : Microsoft.CertificateServices.Commands.EnrollmentEndPointProperty
PolicyId :
Archived : False
Extensions : {System.Security.Cryptography.Oid, System.Security.Cryptography.Oid, System.Security.Cryptography.Oid, System.Security.Cryptography.Oid...}
FriendlyName :
IssuerName : System.Security.Cryptography.X509Certificates.X500DistinguishedName
NotAfter : 30/08/2020 14:00:00
NotBefore : 30/08/2018 02:00:00
HasPrivateKey : False
PrivateKey :
PublicKey : System.Security.Cryptography.X509Certificates.PublicKey
RawData : {48, 130, 5, 127...}
SerialNumber : <snip>
SubjectName : System.Security.Cryptography.X509Certificates.X500DistinguishedName
SignatureAlgorithm : System.Security.Cryptography.Oid
Thumbprint : <snip>
Version : 3
Handle : 1625625265968
Issuer : <ISSUER2>
Subject : <subject>
EnhancedKeyUsageList : {Encrypting File System (1.3.6.1.4.1.311.10.3.4)}
DnsNameList : {Test User}
SendAsTrustedIssuer : False
EnrollmentPolicyEndPoint : Microsoft.CertificateServices.Commands.EnrollmentEndPointProperty
EnrollmentServerEndPoint : Microsoft.CertificateServices.Commands.EnrollmentEndPointProperty
PolicyId :
Archived : False
Extensions : {System.Security.Cryptography.Oid, System.Security.Cryptography.Oid, System.Security.Cryptography.Oid, System.Security.Cryptography.Oid...}
FriendlyName :
IssuerName : System.Security.Cryptography.X509Certificates.X500DistinguishedName
NotAfter : 09/04/2020 15:57:37
NotBefore : 22/10/2017 15:57:37
HasPrivateKey : False
PrivateKey :
PublicKey : System.Security.Cryptography.X509Certificates.PublicKey
RawData : {48, 130, 8, 4...}
SerialNumber : <snip>
SubjectName : System.Security.Cryptography.X509Certificates.X500DistinguishedName
SignatureAlgorithm : System.Security.Cryptography.Oid
Thumbprint : <snip>
Version : 3
Handle : 1625625271728
Issuer : <ISSUER1>
Subject : <subject>
我还认为我可以使用 Where-Object NotAfter...
轻松按日期过滤(如果我在这方面有误,请纠正我 :)),但出于对世界的热爱,我不知道如何过滤EnhancedKeyUsageList : {Secure Email (1.3.6.1.5.5.7.3.4)}
。我认为它是一个数组(任何给定的证书中可能有多个 EKU),但我如何按数组元素进行过滤?
奖金问题:如果我有:
$oneCert = $allProfileCerts.Certificates | foreach {New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 $_} | Where-Object SerialNumber -Match "<SN>"
然后如何访问 "NotAfter" 字段?我尝试了 $oneCert."NotAfter"
、$oneCert["NotAfter"]
、$oneCert | % NotAfter
、$oneCert | select -expandproperty "NotAfter"
- 都不起作用:/
编辑:有效代码,基于@tomalak 提议:
Get-ADUser -Server $Server -Filter {EmailAddress -eq $Mail} -Property Certificates |
ForEach-Object {
# ...we have "user" objects here
Write-Host $_
$_.Certificates |
foreach {New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 $_} |
Where-Object {
$_.EnhancedKeyUsageList.FriendlyName -eq "Secure Email"
}
} |
ForEach-Object {
# ...we have "certificate" objects here
Write-Host $_.Issuer
}
我会过滤 ObjectId
值:
$certificates |Where-Object {$_.EnhancedKeyUsageList.ObjectId -like '1.3.6.1.5.5.7.3.2'}
此示例依赖于 属性 EnhancedKeyUsageList
中的 OID 枚举,因此它仅适用于 PowerShell 4.0 或更高版本
一般来说,您可以使用 Where-Object
过滤管道,使用 -eq
过滤列表。在这种情况下,类似于:
$adUser.Certificates | Where-Object {
$_.EnhancedKeyUsageList.oid.Value -eq "1.3.6.1.5.5.7.3.4"
}
将为您提供在其 EKU 列表中具有 "1.3.6.1.5.5.7.3.4"
的所有用户证书。
请注意,当 Powershell(4.0 及更高版本)看到这样的表达式 $object.Property.ChildProperty.SomeData
时,它会获取 all Property
值,对于所有这些值,它都会获取所有 ChildProperty
值,并且对于所有它们,它获取所有SomeData
值。这节省了很多打字。在传统的命令式语言中,您需要嵌套循环,而在 Powershell 中,您根本不需要任何循环。
知道这一点,$_.EnhancedKeyUsageList.oid.Value -eq "1.3.6.1.5.5.7.3.4"
成为可能,因为 -eq
不是您传统的 "equality" 运算符:它获取值列表并将它们过滤掉,即:
1,2,3 -eq 3 # produces 3
1,3,3 -eq 3 # produces 3,3
你可以做到
Get-ADUser -Property Certificates | Where-Object {
$_.Certificates.EnhancedKeyUsageList.oid.Value -eq "1.3.6.1.5.5.7.3.4"
}
一次性获取所有具有匹配证书的AD用户。
由于您想过滤每个证书的两个属性,我会推荐一些变体
$minValid = (Get-Date).AddMonths(6)
Get-ADUser -Property Certificates -PipelineVariable user | ForEach-Object {
# ...we have "user" objects here
Write-Host $_
$_.Certificates | Where-Object {
$_.EnhancedKeyUsageList.oid.Value -eq "1.3.6.1.5.5.7.3.4" -and $_.NotAfter -lt $minValid
}
} | ForEach-Object {
# ...we have "certificate" objects here
Write-Host $_
}
我是 Powershell 的菜鸟,实际问题是我对如何搜索各种属性有点迷茫,很难找到符合我需要的示例。
话虽如此,我需要搜索 Active Directory 以查找即将过期的用户 S/MIME 证书,这些证书是由特定的证书颁发机构颁发的。
我已经拥有的:
$Mail = user@example.com
$allProfileCerts = Get-ADUser -Server example.com:3268 -Filter {EmailAddress -eq $Mail} -Properties Certificates | select Certificates
结果是:
Handle Issuer Subject
------ ------ -------
1625625266096 CN=<CA1> E=test.user@example.com, CN=Test User, OU=Normal, OU=Users, OU=EXAMPLE, ...
1625625265968 CN=<CA2> E=test.user@example.com, CN=Test User, O=Example Company, ...
1625625271728 CN=<CA1> CN=Test User, OU=Normal, OU=Users, OU=EXAMPLE, ...
我认为下一步可以是:
$allProfileCerts.Certificates | foreach {New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 $_}
结果提供了更多详细信息(已编辑以删除 PII):
EnhancedKeyUsageList : {Secure Email (1.3.6.1.5.5.7.3.4)}
DnsNameList : {Test User}
SendAsTrustedIssuer : False
EnrollmentPolicyEndPoint : Microsoft.CertificateServices.Commands.EnrollmentEndPointProperty
EnrollmentServerEndPoint : Microsoft.CertificateServices.Commands.EnrollmentEndPointProperty
PolicyId :
Archived : False
Extensions : {System.Security.Cryptography.Oid, System.Security.Cryptography.Oid, System.Security.Cryptography.Oid, System.Security.Cryptography.Oid...}
FriendlyName :
IssuerName : System.Security.Cryptography.X509Certificates.X500DistinguishedName
NotAfter : 29/05/2021 10:47:00
NotBefore : 11/12/2018 09:47:00
HasPrivateKey : False
PrivateKey :
PublicKey : System.Security.Cryptography.X509Certificates.PublicKey
RawData : {48, 130, 8, 51...}
SerialNumber : <snip>
SubjectName : System.Security.Cryptography.X509Certificates.X500DistinguishedName
SignatureAlgorithm : System.Security.Cryptography.Oid
Thumbprint : <snip>
Version : 3
Handle : 1625625266096
Issuer : <ISSUER1>
Subject : <subject>
EnhancedKeyUsageList : {Secure Email (1.3.6.1.5.5.7.3.4)}
DnsNameList : {Test User}
SendAsTrustedIssuer : False
EnrollmentPolicyEndPoint : Microsoft.CertificateServices.Commands.EnrollmentEndPointProperty
EnrollmentServerEndPoint : Microsoft.CertificateServices.Commands.EnrollmentEndPointProperty
PolicyId :
Archived : False
Extensions : {System.Security.Cryptography.Oid, System.Security.Cryptography.Oid, System.Security.Cryptography.Oid, System.Security.Cryptography.Oid...}
FriendlyName :
IssuerName : System.Security.Cryptography.X509Certificates.X500DistinguishedName
NotAfter : 30/08/2020 14:00:00
NotBefore : 30/08/2018 02:00:00
HasPrivateKey : False
PrivateKey :
PublicKey : System.Security.Cryptography.X509Certificates.PublicKey
RawData : {48, 130, 5, 127...}
SerialNumber : <snip>
SubjectName : System.Security.Cryptography.X509Certificates.X500DistinguishedName
SignatureAlgorithm : System.Security.Cryptography.Oid
Thumbprint : <snip>
Version : 3
Handle : 1625625265968
Issuer : <ISSUER2>
Subject : <subject>
EnhancedKeyUsageList : {Encrypting File System (1.3.6.1.4.1.311.10.3.4)}
DnsNameList : {Test User}
SendAsTrustedIssuer : False
EnrollmentPolicyEndPoint : Microsoft.CertificateServices.Commands.EnrollmentEndPointProperty
EnrollmentServerEndPoint : Microsoft.CertificateServices.Commands.EnrollmentEndPointProperty
PolicyId :
Archived : False
Extensions : {System.Security.Cryptography.Oid, System.Security.Cryptography.Oid, System.Security.Cryptography.Oid, System.Security.Cryptography.Oid...}
FriendlyName :
IssuerName : System.Security.Cryptography.X509Certificates.X500DistinguishedName
NotAfter : 09/04/2020 15:57:37
NotBefore : 22/10/2017 15:57:37
HasPrivateKey : False
PrivateKey :
PublicKey : System.Security.Cryptography.X509Certificates.PublicKey
RawData : {48, 130, 8, 4...}
SerialNumber : <snip>
SubjectName : System.Security.Cryptography.X509Certificates.X500DistinguishedName
SignatureAlgorithm : System.Security.Cryptography.Oid
Thumbprint : <snip>
Version : 3
Handle : 1625625271728
Issuer : <ISSUER1>
Subject : <subject>
我还认为我可以使用 Where-Object NotAfter...
轻松按日期过滤(如果我在这方面有误,请纠正我 :)),但出于对世界的热爱,我不知道如何过滤EnhancedKeyUsageList : {Secure Email (1.3.6.1.5.5.7.3.4)}
。我认为它是一个数组(任何给定的证书中可能有多个 EKU),但我如何按数组元素进行过滤?
奖金问题:如果我有:
$oneCert = $allProfileCerts.Certificates | foreach {New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 $_} | Where-Object SerialNumber -Match "<SN>"
然后如何访问 "NotAfter" 字段?我尝试了 $oneCert."NotAfter"
、$oneCert["NotAfter"]
、$oneCert | % NotAfter
、$oneCert | select -expandproperty "NotAfter"
- 都不起作用:/
编辑:有效代码,基于@tomalak 提议:
Get-ADUser -Server $Server -Filter {EmailAddress -eq $Mail} -Property Certificates |
ForEach-Object {
# ...we have "user" objects here
Write-Host $_
$_.Certificates |
foreach {New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 $_} |
Where-Object {
$_.EnhancedKeyUsageList.FriendlyName -eq "Secure Email"
}
} |
ForEach-Object {
# ...we have "certificate" objects here
Write-Host $_.Issuer
}
我会过滤 ObjectId
值:
$certificates |Where-Object {$_.EnhancedKeyUsageList.ObjectId -like '1.3.6.1.5.5.7.3.2'}
此示例依赖于 属性 EnhancedKeyUsageList
中的 OID 枚举,因此它仅适用于 PowerShell 4.0 或更高版本
一般来说,您可以使用 Where-Object
过滤管道,使用 -eq
过滤列表。在这种情况下,类似于:
$adUser.Certificates | Where-Object {
$_.EnhancedKeyUsageList.oid.Value -eq "1.3.6.1.5.5.7.3.4"
}
将为您提供在其 EKU 列表中具有 "1.3.6.1.5.5.7.3.4"
的所有用户证书。
请注意,当 Powershell(4.0 及更高版本)看到这样的表达式 $object.Property.ChildProperty.SomeData
时,它会获取 all Property
值,对于所有这些值,它都会获取所有 ChildProperty
值,并且对于所有它们,它获取所有SomeData
值。这节省了很多打字。在传统的命令式语言中,您需要嵌套循环,而在 Powershell 中,您根本不需要任何循环。
知道这一点,$_.EnhancedKeyUsageList.oid.Value -eq "1.3.6.1.5.5.7.3.4"
成为可能,因为 -eq
不是您传统的 "equality" 运算符:它获取值列表并将它们过滤掉,即:
1,2,3 -eq 3 # produces 3
1,3,3 -eq 3 # produces 3,3
你可以做到
Get-ADUser -Property Certificates | Where-Object {
$_.Certificates.EnhancedKeyUsageList.oid.Value -eq "1.3.6.1.5.5.7.3.4"
}
一次性获取所有具有匹配证书的AD用户。
由于您想过滤每个证书的两个属性,我会推荐一些变体
$minValid = (Get-Date).AddMonths(6)
Get-ADUser -Property Certificates -PipelineVariable user | ForEach-Object {
# ...we have "user" objects here
Write-Host $_
$_.Certificates | Where-Object {
$_.EnhancedKeyUsageList.oid.Value -eq "1.3.6.1.5.5.7.3.4" -and $_.NotAfter -lt $minValid
}
} | ForEach-Object {
# ...we have "certificate" objects here
Write-Host $_
}