-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathGet-CertificateHealth.ps1
344 lines (326 loc) · 17.9 KB
/
Get-CertificateHealth.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
<#
.Synopsis
Get certificates from the filesystem or certificate store and display their health
for expiration, pending expiration, and deprecated signature algorithms.
.DESCRIPTION
Get certificates from the filesystem or certificate store and display their health
for expiration, pending expiration, and deprecated signature algorithms.
The function outputs custom objects that include basic certificate properties as
well as the certificate's expiration date, how many days are left, and the name of
the signature algorithm used to generate the certificate.
Depending on the provided warning and critical algorithm parameters, a certificate
will be marked as OK, Warning, or Critical. By default the script considers sha1RSA
certificates to be warning (deprecated) since vendors are beginning to consider these
certificates to use weak encryption. The md5 signature algorithm has already been
designated as vulnerable and will be marked as critical. Microsoft already blocks
these certificates.
The certificate validity period is evaluated to determine if the certificate has
expired (Critical) or will be expiring soon. Use the WarningDays and CriticalDays
parameters to denote certificates with pending expiration.
The certificate key size is also an indicator of health. Key sizes less than
1024 bits are no longer supported, and now it is recommended to use at least 2048 bits.
Requires Get-CertificateFile function from module CertificateHealth to evaluate
certificate files from the filesystem.
.NOTES
Created by: Jason Wasser @wasserja
Modified: 9/28/2016 02:43:52 PM
Changelog:
Version 1.3.1
* Added an example that utilizes the ComputerName parameter
* Corrected verbiage for expired certificates in Verbose
Version 1.3
* Added support for remote computer check for cert:\ provider using PSRP.
Version 1.2
* Added key size health properties
Version 1.1
* Added PowerShell 2.0 compatibility.
Version 1.0
* Initial Release
.PARAMETER Path
Enter a path or paths containing certificates to be checked.
Checking of remote certificate files should be done through UNC path.
.PARAMETER ComputerName
Enter a name of a computer to check the certificate store provider via PSRP.
.PARAMETER WarningDays
Specify the amount of days before the certificate expiration should be in a
warning state.
.PARAMETER CriticalDays
Specify the amount of days before the certificate expiration should be in a
critical state.
.PARAMETER ExcludedThumbprint
Array of thumbprints of certificates that should be excluded from being checked.
This would be used if there is a certificate that you wish to ignore from health
checks.
.PARAMETER WarningAlgorithm
Array of algorithms that are deprecated.
.PARAMETER CriticalAlgorithm
Array of algorithms with known vulnerabilities.
.PARAMETER CritialKeySize
Certificates with key size less than this value will be considered critical.
.PARAMETER WarningKeySize
Certificates with key size less than this value and greater than the CriticalKeySize
will be considered warning.
.PARAMETER CertUtilPath
Path to the certutil.exe.
.PARAMETER CertificateFileType
Array of certificate file types that need to be checked.
.PARAMETER Recurse
Recurse through subdirectories of specified path(s).
.EXAMPLE
Get-CertificateHealth
FileName : Microsoft.PowerShell.Security\Certificate::LocalMachine\My\27AC9369FAF25207
BB2627CEFACCBE4EF9C319B8
Subject : CN=Go Daddy Secure Certificate Authority - G2,
OU=http://certs.godaddy.com/repository/, O="GoDaddy.com, Inc.",
L=Scottsdale, S=Arizona, C=US
SignatureAlgorithm : sha256RSA
NotBefore : 5/3/2011 3:00:00 AM
NotAfter : 5/3/2031 3:00:00 AM
Days : 5329
Thumbprint : 27AC9369FAF25207BB2627CEFACCBE4EF9C319B8
ValidityPeriodStatus : OK
ValidityPeriodStatusMessage : Certificate expires in 5329 days.
AlgorithmStatus : OK
AlgorithmStatusMessage : Certificate uses valid algorithm sha256RSA.
KeySize : 2048
KeySizeStatus : OK
KeySizeStatusMessage : Certificate key size 2048 is greater than or equal to 2048.
Gets all the certificates in the local machine personal certificate store (cert:\LocalMachine\My)
and shows their basic information and health.
.EXAMPLE
Get-CertificateHealth -Path C:\Website\Certificates
Gets all the certificates in the c:\Website\Certificates folder and shows their basic
information and health.
.EXAMPLE
Get-CertificateHealth -Path 'Cert:\LocalMachine\My','C:\SSL' -Recurse
Gets all the certificates in the local machine personal certificate store (cert:\LocalMachine\My)
and C:\SSL including subfolders and shows their basic information and health.
.EXAMPLE
Get-CertificateHealth -ComputerName MyServer
Gets all the certificates in MyServer's personal certificate store (Cert:\LocalMachine\My). This is accomplished using PSRemoting.
It show the basic information and certificate health
.LINK
https://gallery.technet.microsoft.com/scriptcenter/Certificate-Health-b646aeff
#>
#requires -Version 2.0
function Get-CertificateHealth
{
[CmdletBinding()]
Param
(
[Parameter(ValueFromPipelineByPropertyName=$true)]
[string[]]$Path = 'Cert:\LocalMachine\My',
[string]$ComputerName,
[int]$WarningDays = 60,
[int]$CriticalDays = 30,
[string[]]$ExcludedThumbprint,#=@('DF16240B462E80151BBCD7529D4C557A8CE1671C'),
[string[]]$WarningAlgorithm=('sha1RSA'),
[string[]]$CriticalAlgorithm=('md5RSA'),
[int]$CriticalKeySize=1024,
[int]$WarningKeySize=2048,
[string]$CertUtilPath = 'C:\Windows\System32\certutil.exe',
[string[]]$CertificateFileType = ('*.cer','*.crt','*.p7b'),
[switch]$Recurse = $false
)
Begin
{
}
Process
{
#region Certificate Check
foreach ($CertPath in $Path) {
# Gather certificates from the $CertPath
# If we are looking in the Certificate PowerShell Provider - Cert:\
if ($CertPath -like 'cert:\*') {
# Remote or local
# If computername was specified, try to use psremoting to get the certificates.
if ($ComputerName) {
try {
Write-Verbose "Getting certificates from $CertPath from $ComputerName"
$Certificates = Invoke-Command -ScriptBlock {Get-ChildItem -Path $args[0] -Recurse:([bool]$args[1].IsPresent) -Exclude $args[2]} -ComputerName $ComputerName -ArgumentList $CertPath,$Recurse,$ExcludedThumbprint -ErrorAction Stop
}
catch {
Write-Error "Unable to connect to $ComputerName"
return
}
}
# If computername was not specified, then get from local certificate store provider.
else {
Write-Verbose "Getting certificates from $CertPath"
$Certificates = Get-ChildItem -Path $CertPath -Recurse:([bool]$Recurse.IsPresent) -Exclude $ExcludedThumbprint
$ComputerName = $env:COMPUTERNAME
}
}
# Otherwise we need to use the certutil.exe to get certificate information.
else {
Write-Verbose "Getting certificates from $CertPath"
$Certificates = Get-CertificateFile -Path $CertPath -CertificateFileType $CertificateFileType -Recurse:([bool]$Recurse.IsPresent) | Where-Object -FilterScript {$_.Thumbprint -notcontains $ExcludedThumbprint}
}
if ($Certificates) {
#region Check individual certificate
foreach ($Certificate in $Certificates) {
# I first need to convert the properties so that I can use a similar process on either file or store certificates.
if ($Certificate.PSPath) {
if ($PSVersionTable.PSVersion.Major -lt 3) {
$CertificateProperties = @{
ComputerName = $ComputerName
FileName = $Certificate.PSPath
Subject = $Certificate.Subject
SignatureAlgorithm = $Certificate.SignatureAlgorithm.FriendlyName
NotBefore = $Certificate.NotBefore
NotAfter = $Certificate.NotAfter
Days = ($Certificate.NotAfter - (Get-Date)).Days
Thumbprint = $Certificate.Thumbprint
KeySize = $Certificate.PublicKey.Key.KeySize
}
}
else {
$CertificateProperties = [ordered]@{
ComputerName = $ComputerName
FileName = $Certificate.PSPath
Subject = $Certificate.Subject
SignatureAlgorithm = $Certificate.SignatureAlgorithm.FriendlyName
NotBefore = $Certificate.NotBefore
NotAfter = $Certificate.NotAfter
Days = ($Certificate.NotAfter - (Get-Date)).Days
Thumbprint = $Certificate.Thumbprint
KeySize = $Certificate.PublicKey.Key.KeySize
}
}
$Certificate = New-Object -TypeName PSObject -Property $CertificateProperties
}
elseif ($Certificate.FileName) {
# Nothing to do here yet.
}
else {
# Nothing to do here yet.
}
#region Check certificate expiration
# Check certificate is within $WarningDays
if ($Certificate.NotAfter -le (Get-Date).AddDays($WarningDays) -and $Certificate.NotAfter -gt (Get-Date).AddDays($CriticalDays)) {
Write-Verbose "Certificate is expiring within $WarningDays days."
$ValidityPeriodStatus = 'Warning'
$ValidityPeriodStatusMessage = "Certificate expiring in $($Certificate.Days) days."
}
# Check certificate is within $CriticalDays
elseif ($Certificate.NotAfter -le (Get-Date).AddDays($CriticalDays) -and $Certificate.NotAfter -gt (Get-Date)) {
Write-Verbose "Certificate is expiring within $CriticalDays days."
$ValidityPeriodStatus = 'Critical'
$ValidityPeriodStatusMessage = "Certificate expiring in $($Certificate.Days) days."
}
# Check certificate is expired
elseif ($Certificate.NotAfter -le (Get-Date)) {
Write-Verbose "Certificate is expired: $($Certificate.Days) days."
$ValidityPeriodStatus = 'Critical'
$ValidityPeriodStatusMessage = "Certificate expired: $($Certificate.Days) days."
}
# Certificate validity period is healthy.
else {
Write-Verbose "Certificate is within validity period."
$ValidityPeriodStatus = 'OK'
$ValidityPeriodStatusMessage = "Certificate expires in $($Certificate.Days) days."
}
#endregion
#region Check certificate algorithm
if ($CriticalAlgorithm -contains $Certificate.SignatureAlgorithm) {
Write-Verbose "Certificate uses critical algorithm."
$AlgorithmStatus = 'Critical'
$AlgorithmStatusMessage = "Certificate uses a vulnerable algorithm $($Certificate.SignatureAlgorithm)."
}
elseif ($WarningAlgorithm -contains $Certificate.SignatureAlgorithm) {
Write-Verbose "Certificate uses warning algorithm."
$AlgorithmStatus = 'Warning'
$AlgorithmStatusMessage = "Certificate uses the deprecated algorithm $($Certificate.SignatureAlgorithm)."
}
else {
Write-Verbose "Certificate uses acceptable algorithm."
$AlgorithmStatus = 'OK'
$AlgorithmStatusMessage = "Certificate uses valid algorithm $($Certificate.SignatureAlgorithm)."
}
#endregion
#region Check MinimumKeySize
Write-Verbose 'Checking minimum key length.'
if ($Certificate.KeySize -lt $CriticalKeySize) {
# Key Size is critical
Write-Verbose 'Certificate key length is critical.'
$KeySizeStatus = 'Critical'
$KeySizeStatusMessage = "Certificate key size $($Certificate.KeySize) is less than $CriticalKeySize."
}
elseif ($Certificate.KeySize -lt $WarningKeySize -and $Certificate.KeySize -ge $CriticalKeySize) {
# Key Size is warning
Write-Verbose 'Certificate key length is warning.'
$KeySizeStatus = 'Warning'
$KeySizeStatusMessage = "Certificate key size $($Certificate.KeySize) is less than $WarningKeySize."
}
elseif ($Certificate.KeySize -ge $WarningKeySize) {
# Key Size is OK
Write-Verbose 'Certificate key length is OK.'
$KeySizeStatus = 'OK'
$KeySizeStatusMessage = "Certificate key size $($Certificate.KeySize) is greater than or equal to $WarningKeySize."
}
else {
# Key Size is OK
Write-Verbose 'Certificate key length is Unknown.'
$KeySizeStatus = 'Unknown'
$KeySizeStatusMessage = "Certificate key size is unknown."
}
#endregion
Write-Verbose 'Adding additional properties to the certificate object.'
if ($PSVersionTable.PSVersion.Major -lt 3) {
$CertificateProperties = @{
ComputerName = $ComputerName
FileName = $Certificate.Filename
Subject = $Certificate.Subject
SignatureAlgorithm = $Certificate.SignatureAlgorithm
NotBefore = $Certificate.NotBefore
NotAfter = $Certificate.NotAfter
Days = $Certificate.Days
Thumbprint = $Certificate.Thumbprint
ValidityPeriodStatus = $ValidityPeriodStatus
ValidityPeriodStatusMessage = $ValidityPeriodStatusMessage
AlgorithmStatus = $AlgorithmStatus
AlgorithmStatusMessage = $AlgorithmStatusMessage
KeySize = $Certificate.KeySize
KeySizeStatus = $KeySizeStatus
KeySizeStatusMessage = $KeySizeStatusMessage
}
}
else {
$CertificateProperties = [ordered]@{
ComputerName = $ComputerName
FileName = $Certificate.Filename
Subject = $Certificate.Subject
SignatureAlgorithm = $Certificate.SignatureAlgorithm
NotBefore = $Certificate.NotBefore
NotAfter = $Certificate.NotAfter
Days = $Certificate.Days
Thumbprint = $Certificate.Thumbprint
ValidityPeriodStatus = $ValidityPeriodStatus
ValidityPeriodStatusMessage = $ValidityPeriodStatusMessage
AlgorithmStatus = $AlgorithmStatus
AlgorithmStatusMessage = $AlgorithmStatusMessage
KeySize = $Certificate.KeySize
KeySizeStatus = $KeySizeStatus
KeySizeStatusMessage = $KeySizeStatusMessage
}
}
$Certificate = New-Object -TypeName PSObject -Property $CertificateProperties
if ($PSVersionTable.PSVersion.Major -lt 3) {
$Certificate | Select-Object ComputerName,FileName,Subject,SignatureAlgorithm,NotBefore,NotAfter,Days,Thumbprint,ValidityPeriodStatus,ValidityPeriodStatusMessage,AlgorithmStatus,AlgorithmStatusMessage,KeySize,KeySizeStatus,KeySizeStatusMessage
}
else {
$Certificate
}
}
#endregion
}
else {
Write-Verbose "No Certificates found in $CertPath"
}
}
#endregion
}
End
{
}
}