|
| 1 | +# PowerShell implementation of X509StatusHelper.GetStatus() logic |
| 2 | + |
| 3 | +function Get-VdcCertificateStatus { |
| 4 | + <# |
| 5 | + .SYNOPSIS |
| 6 | + Calculate the Status field for a certificate, similar to what's shown on the Certificate Summary tab. |
| 7 | +
|
| 8 | + .DESCRIPTION |
| 9 | + This function replicates the logic from X509StatusHelper.GetStatus() to determine the certificate status. |
| 10 | + It checks InError, Status attribute, workflow tickets, revocation status, disabled state, |
| 11 | + consumer errors, and certificate expiration. |
| 12 | +
|
| 13 | + The current use for this is from Get-VdcCertificate -IncludeStatus |
| 14 | +
|
| 15 | + .PARAMETER Certificate |
| 16 | + Output from certificates/{guid} api call |
| 17 | +
|
| 18 | + .PARAMETER VenafiSession |
| 19 | + Authentication for the function. |
| 20 | + The value defaults to the script session object $VenafiSession created by New-VenafiSession. |
| 21 | +
|
| 22 | + #> |
| 23 | + |
| 24 | + [CmdletBinding()] |
| 25 | + param( |
| 26 | + [Parameter(Mandatory, ValueFromPipeline)] |
| 27 | + [object]$Certificate, |
| 28 | + |
| 29 | + [Parameter()] |
| 30 | + [ValidateNotNullOrEmpty()] |
| 31 | + [psobject] $VenafiSession = (Get-VenafiSession) |
| 32 | + |
| 33 | + ) |
| 34 | + |
| 35 | + process { |
| 36 | + # Initialize status |
| 37 | + $statusSummary = 'Ok' # Ok, Warning, Error |
| 38 | + $statusText = '' |
| 39 | + |
| 40 | + $attribs = Get-VdcAttribute -Path $Certificate.DN -Attribute 'Disabled', 'Ticket DN' -VenafiSession $VenafiSession |
| 41 | + $certAttributes = @{ |
| 42 | + 'In Error' = $Certificate.ProcessingDetails.InError |
| 43 | + 'Status' = $Certificate.ProcessingDetails.Status |
| 44 | + 'Disabled' = $attribs.Disabled -eq 1 |
| 45 | + 'Ticket DN' = $attribs.'Ticket DN' |
| 46 | + } |
| 47 | + |
| 48 | + # Check InError attribute |
| 49 | + $inError = $certAttributes.'In Error' |
| 50 | + if ($inError) { |
| 51 | + $statusSummary = 'Error' |
| 52 | + } |
| 53 | + |
| 54 | + # Check Status attribute |
| 55 | + $statusAttr = $certAttributes.'Status' |
| 56 | + if ($statusAttr) { |
| 57 | + $statusText = $statusAttr |
| 58 | + if (-not $inError) { |
| 59 | + $statusSummary = 'Warning' |
| 60 | + } |
| 61 | + } |
| 62 | + else { |
| 63 | + if (-not $inError) { |
| 64 | + $statusText = 'OK' |
| 65 | + $statusSummary = 'Ok' |
| 66 | + } |
| 67 | + } |
| 68 | + |
| 69 | + # Check for pending workflow (Ticket DN) |
| 70 | + $ticketDN = $certAttributes.'Ticket DN' |
| 71 | + if ($ticketDN) { |
| 72 | + $statusSummary = 'Warning' |
| 73 | + $statusText = 'Pending workflow resolution' |
| 74 | + } |
| 75 | + |
| 76 | + $stage = $certAttributes.'Stage' |
| 77 | + # Check revocation status from CertificateDetails.RevocationStatus |
| 78 | + # Known values: Requested, Confirmed, Complete, DiscoveredRevoked, Failed, Pending |
| 79 | + if (-not $ticketDN -and -not $stage -and $Certificate.CertificateDetails.RevocationStatus) { |
| 80 | + |
| 81 | + $statusSummary = 'Warning' |
| 82 | + if ($Certificate.CertificateDetails.RevocationDate) { |
| 83 | + $revocationDate = ([DateTime]$Certificate.CertificateDetails.RevocationDate).ToLocalTime().ToString() |
| 84 | + } |
| 85 | + |
| 86 | + switch ($Certificate.CertificateDetails.RevocationStatus) { |
| 87 | + 'Complete' { |
| 88 | + $statusText = if ($statusText) { '{0}; External Revocation Reported By CA' -f $statusText } else { 'External Revocation Reported By CA' } |
| 89 | + if ($Certificate.CertificateDetails.RevocationDate) { |
| 90 | + $statusText += " On: $revocationDate" |
| 91 | + } |
| 92 | + } |
| 93 | + 'Confirmed' { |
| 94 | + if ($Certificate.CertificateDetails.RevocationDate) { |
| 95 | + $statusText = 'Revocation Submitted On {0} But Not Confirmed By CA' -f $revocationDate |
| 96 | + } |
| 97 | + else { |
| 98 | + $statusText = 'Revocation Submitted But Not Confirmed By CA' |
| 99 | + } |
| 100 | + } |
| 101 | + 'DiscoveredRevoked' { |
| 102 | + $statusText = if ($statusText) { '{0}; External Revocation Reported By CA' -f $statusText } else { 'External Revocation Reported By CA' } |
| 103 | + if ($Certificate.CertificateDetails.RevocationDate) { |
| 104 | + $statusText += " On: $revocationDate" |
| 105 | + } |
| 106 | + } |
| 107 | + 'Pending' { |
| 108 | + $statusText = if ($statusText) { '{0}; Revocation Pending' -f $statusText } else { 'Revocation Pending' } |
| 109 | + } |
| 110 | + 'Failed' { |
| 111 | + $statusSummary = 'Error' |
| 112 | + # to get the underlying error involves a bit more digging in SecretStore. TODO possibly. |
| 113 | + $statusText = if ($statusText) { '{0}; Revocation Failed' -f $statusText } else { 'Revocation Failed' } |
| 114 | + } |
| 115 | + } |
| 116 | + |
| 117 | + # check for user who initiated the revocation |
| 118 | + if ( $Certificate.CertificateDetails.RevocationInitiatedBy ) { |
| 119 | + $identity = Get-VdcIdentity -ID $Certificate.CertificateDetails.RevocationInitiatedBy |
| 120 | + $initBy = if ( $identity.FullName ) { |
| 121 | + $identity.FullName |
| 122 | + } |
| 123 | + elseif ($identity.Name ) { |
| 124 | + $identity.Name |
| 125 | + } |
| 126 | + else { |
| 127 | + $Certificate.CertificateDetails.RevocationInitiatedBy |
| 128 | + } |
| 129 | + |
| 130 | + $statusText += '; Initiated By {0}' -f $initBy |
| 131 | + } |
| 132 | + } |
| 133 | + |
| 134 | + # Check Disabled attribute |
| 135 | + if ($certAttributes.'Disabled') { |
| 136 | + if ($statusText) { |
| 137 | + $statusText += ' (Processing disabled)' |
| 138 | + } |
| 139 | + else { |
| 140 | + $statusText = 'Processing disabled' |
| 141 | + } |
| 142 | + $statusSummary = 'Warning' |
| 143 | + } |
| 144 | + |
| 145 | + # Check consumer (application) errors |
| 146 | + if ($statusSummary -eq 'Ok' -and $Certificate.Consumers) { |
| 147 | + $consumerErrors = 0 |
| 148 | + $consumerWarnings = 0 |
| 149 | + $consumerDisabled = 0 |
| 150 | + $consumerOk = 0 |
| 151 | + |
| 152 | + $allAttribs = $Certificate.Consumers | Get-VdcAttribute -Attribute @('In Error', 'Status', 'Disabled') -VenafiSession $VenafiSession |
| 153 | + foreach ($consumerAttrs in $allAttribs) { |
| 154 | + try { |
| 155 | + |
| 156 | + if ($consumerAttrs.'Disabled' -eq 1) { |
| 157 | + $consumerDisabled++ |
| 158 | + $statusSummary = 'Warning' |
| 159 | + continue |
| 160 | + } |
| 161 | + |
| 162 | + if ($consumerAttrs.'In Error' -eq 1) { |
| 163 | + $consumerErrors++ |
| 164 | + $statusSummary = 'Error' |
| 165 | + } |
| 166 | + elseif ($consumerAttrs.'Status') { |
| 167 | + $consumerWarnings++ |
| 168 | + $statusSummary = 'Warning' |
| 169 | + } |
| 170 | + else { |
| 171 | + $consumerOk++ |
| 172 | + } |
| 173 | + } |
| 174 | + catch { |
| 175 | + # Consumer may not be accessible |
| 176 | + Write-Verbose "Could not read consumer: $consumerPath" |
| 177 | + } |
| 178 | + } |
| 179 | + |
| 180 | + if ($statusSummary -ne 'Ok') { |
| 181 | + $statusText = "Certificate Ok; Application errors: $consumerErrors, caution: $consumerWarnings, disabled: $consumerDisabled, Ok: $consumerOk" |
| 182 | + } |
| 183 | + } |
| 184 | + |
| 185 | + # Check certificate expiration |
| 186 | + if ($statusSummary -eq 'Ok' -and $Certificate.CertificateDetails.ValidTo) { |
| 187 | + $validTo = [DateTime]$Certificate.CertificateDetails.ValidTo |
| 188 | + if ($validTo -lt (Get-Date)) { |
| 189 | + $statusSummary = 'Error' |
| 190 | + $statusText = 'Certificate expired' |
| 191 | + } |
| 192 | + } |
| 193 | + |
| 194 | + # Return results |
| 195 | + @{ |
| 196 | + Status = $statusSummary |
| 197 | + StatusText = $statusText |
| 198 | + } |
| 199 | + } |
| 200 | +} |
0 commit comments