PSPKI module causes a problem when used in a scheduled task

Sep 26, 2013 at 1:50 PM
Hello Experts,

I have developed a PS Script which does the following:

First a CSR File is submitted to the CA (with the Function Submit-CertificateRequest. If this is successfull in a next Step the new Certificate is downloaded with the Get-IssuedRequest Function.

All things work fine when I call the script interactively in a PS Window, but when the same script is started as a scheduled task, than I always get the following runtime-Exception when calling Get-IssuedRequest:

System.Management.Automation.RuntimeException, error: Property 'CertificateTemplate' cannot be found on this object. Make sure that it exists

The detailed call is:
$requestFullResult = Get-IssuedRequest -CertificationAuthority $certAuth -RequestID $requestResult.RequestID -Property $CertAttrs

$requestResult is set by the prior call of Submit-CertificateRequest function

$CertAttrs has the value @('RequestID', 'RawCertificate', 'SerialNumber', 'NotBefore', 'NotAfter', 'CommonName', 'CertificateTemplate')

So I have absolutely no Idea what is going wrong here? The account which is used interactively / in the scheduled tasks has enough rights on the CA so this cannot be the problem.

the scheduled task is called via powershell -nologo -noprofile -file MyScript.ps1 (I also left away the parameter -noprofile but this leads to the same error)

Any ideas?

Many thanks in advance Andreas
Coordinator
Sep 26, 2013 at 2:51 PM
can you provide exact repro steps?

You don't need to query CA if request is successfully issued. The Submit-CertificateRequest checks CA response and puts certificate in the request result object. http://pkix2.sysadmins.lv/library/html/AllMembers_T_PKI_Enrollment_CertRequestStatus.htm
you see that there is Certificate property which will contain issued certificate if enrollment succeeded. But in any way I would like to check this issue with Task Scheduler.
Sep 27, 2013 at 6:02 AM
The scheduled task is defined as follows:

powershell -nologo -noprofile -file MyScript.ps1

MyScript.ps1 consists of following lines regarding certificate handling:

_try {

$requestResult = Submit-CertificateRequest -Path "$tmpFileName" -CertificationAuthority $certAuth -Attribute "CertificateTemplate:$CATemplateName,SAN:$SanStr"

if ($requestResult -and ($requestResult.Status -match 'issued')) {
$requestFullResult  =  Get-IssuedRequest -CertificationAuthority $certAuth -RequestID $requestResult.RequestID -Property $CertAttrs # Download the new certificate from the CA
$base64CertValue = $certHeader + $($requestFullResult.RawCertificate).Trim() + $certFooter # Note RawCertificate is already Base64 Encoded

# 5. Update Database
$row.Certificate = $base64CertValue # write the final certificate to the database
$row.CertificateIssuer = try { $requestResult.Certificate.Issuer } catch { 'unavailable' } # maintain other attributes
$row.CertificateSubject = try { $requestResult.Certificate.Subject } catch { 'unavailable' }
$row.CertificateSerialNumber = $requestFullResult.SerialNumber
$row.CertificateThumbprint = try { $requestResult.Certificate.Thumbprint } catch { 'unavailable' }
$row.CertificateTemplate = try { $requestFullResult.CertificateTemplate } catch { 'unavailable' }
$row.CertificateType = $certType
$row.CertificateExpiryDate = $requestFullResult.NotAfter
$row.CertificateCN = $requestFullResult.CommonName
$row.CARequestID = $requestResult.RequestID
$row.IsReadyToSend = 1
# mark the entry as the certificate is send-able
$row.ProcessingError = 0_
........
}
catch {
 .......
}
When run interactively in a powershell window, the call succeeds when run via a scheduled task then in the line where Get-IssuedRequest is called the exception happens

System.Management.Automation.RuntimeException, error: Property 'CertificateTemplate' cannot be found on this object. Make sure that it exists

I have no idea why and found so far no possibility to trace this behavior

Regards Andreas
Coordinator
Sep 27, 2013 at 7:39 AM
I believe that exception claims that CertificateTemplate property is not available in your own object which is stored in $row variable and not in PSPKI object. Also, your code isn't looking very good as it has too many redundant code. For example:
$row.CertificateIssuer = try { $requestResult.Certificate.Issuer } catch { 'unavailable' } 
here try/catch blocks are redundant. If the property is nonexistent (only when read it), PowerShell silently eats internal exception about non-existent property. This means that the code never reaches Catch block. Therefore you can simply replace the line:
$row.CertificateIssuer = $requestResult.Certificate.Issuer
Also, you can simplify your own object construction as follows:
 if ($requestResult -and ($requestResult.Status -eq 'issued')) {
    $requestFullResult  =  Get-IssuedRequest -CertificationAuthority $certAuth -RequestID $requestResult.RequestID -Property $CertAttrs # Download the new certificate from the CA
    $row = new-object myobject -property @{
        Certificate = [Convert]::ToBase64String($requestResult.Certificate.RawData) # write the final certificate to the database 
        CertificateIssuer = $requestResult.Certificate.Issuer # maintain other attributes 
        CertificateSubject = $requestResult.Certificate.Subject
        CertificateSerialNumber = $requestFullResult.SerialNumber
        CertificateThumbprint = $requestResult.Certificate.Thumbprint
        CertificateTemplate = $requestFullResult.CertificateTemplate
        CertificateType = $certType
        CertificateExpiryDate = $requestFullResult.NotAfter
        CertificateCN = $requestFullResult.CommonName
        CARequestID = $requestResult.RequestID
        IsReadyToSend = 1
        # mark the entry as the certificate is send-able 
        ProcessingError = 0_
        #........
    }
}
Sep 27, 2013 at 8:43 AM
The CertificateTemplate is available at the $row Objecvt (1 checked it multiple times; otherwise the script would have a problem when started interactively too, but it really had not).

The code-line after the assignment statement containing get-issuedrequest is never reached in task scheduler mode, as I do also a logging what happens with text-output to a file and the subsequent assignment statements $row..... are not reached. That is the mystical thing I cannot understand.

Any other ideas?

Thank you for reminding me that when a property at an object is not available, than no exception is thrown, except when the object is on the left side of the assignment.

Thank you for your investigations so far.