locked
Certreq hangs when run remotely via Invoke-Command RRS feed

  • Question

  • Hi all,

    Hopefully someone can help with this as I'm banging my head against a wall at the moment.

    I've created a PowerShell script to automate the tasks from certificate creation to binding it to an IIS site.

    The script works perfectly against WS 2008 although seems to hang when run against WS 2012.

    The part which hangs is when I tried to run the certification request creation:

    cmd /c "certreq -new c:\$InfFile c:\$ReqFile" | Out-Null

    where $InfFile is the name of the certificate request info file and $ReqFile is the desired name of my request file.

    I have also tried removing 'cmd /c' and pipe to Null but this doesn't work either.

    I've had varying results but it seems to get stuck sometimes I see the output where it would almost be finished I.E:

    ---

    Active Directory Enrollment Policy

    {GUID}

    ldap:

    ---

    Although it never gets any further than this.

    When run locally on the server via powershell it completes successfully.

    My .inf file contents is:

    ---

    $InfFileContent = @"

    [NewRequest]

    Subject = "CN=$using:URL"

    [RequestAttributes]

    CertificateTemplate = "WebTest"

    ---

    I seemed to get it working once by adding the 'Silent = true' flag to the .inf file which blocks it from prompting for anything although this never worked again.

    If anyone can help with this it would be massively appreciated as I've run out of ideas.

    Happy to post more of the script if that helps troubleshooting but I'm hoping this is a known bug and that there is some workaround.

    Many thanks,

    David

    Wednesday, June 25, 2014 3:05 PM

Answers

  • I found a solution as so:

    $OriginalEAP = $ErrorActionPreference
    $ErrorActionPreference = "SilentlyContinue"
    
    $shush = certreq -q -new $CertificateINI $CertificateREQ
    
    $ErrorActionPreference = $OriginalEAP
    
    

    Using the -q switch fixed the hanging issue. The other code is essentially to suppress the error message I was receiving above. I can now successfully generate requests against remote servers (via a web interface no less).

    Hope this helps!

    • Proposed as answer by RobinMalik Friday, October 3, 2014 4:58 PM
    • Unproposed as answer by RobinMalik Friday, October 3, 2014 4:58 PM
    • Proposed as answer by RobinMalik Friday, October 3, 2014 5:01 PM
    • Marked as answer by Mike Laughlin Monday, August 22, 2016 4:37 PM
    Wednesday, September 17, 2014 2:15 PM

All replies

  • Can you put the full code that you are using here? You shouldn't need cmd /c as you can call certreq directly in PowerShell. I am curious to see whether you are defining $InfFile and $ReqFile inside of the scriptblock on Invoke-Command or outside and using -ArgumentList to ensure that those variable both have a value.

    Boe Prox
    Blog | Twitter
    PoshWSUS | PoshPAIG | PoshChat | PoshEventUI
    PowerShell Deep Dives Book

    Wednesday, June 25, 2014 3:19 PM
  • Thanks for the reply Boe.

    Below is the code relating to this particular section. The whole code is some 1300 lines so I won't post it all.

    $URL = "EnterURL"
    
    # ************************
    # Start of Invoke-Command
    # ************************
    ForEach ($computer in $computerList)
    {
       Invoke-Command -ComputerName $computer -ScriptBlock {   
    
       # Request Certificate for server/s
    
       # Certificate request input info
       $InfFileContent = @"
       [NewRequest]
       Subject = "CN=$using:URL"
       [RequestAttributes]
       CertificateTemplate = "WebTest"
       Silent = true
    "@
    
       #Write-Host "Generating Certificate Request file..." -ForegroundColor Cyan
    
       # Variable for certificate request input file name
       $InfFile = "Cert_Req.inf"
    
       # Creates certificate request input file (.inf)
       New-Item c:\$InfFile -type "file" -value $InfFileContent
    
       # Variable for hashed certificate request file name
       $ReqFile = "Cert_Req.req"
    
       # Creates final (.req) certificate request file using input file
       cmd /c "certreq -new c:\$InfFile c:\$ReqFile" | Out-Null
    
        #certreq -new "c:\$InfFile" "c:\$ReqFile"
        #Write-Host "Done"
                
        # Submits certificate request to certificate authority
        cmd /c certreq -submit -config "CA\Utility" c:\Cert_Req.req c:\Certificate.cer
                
        #certreq -submit -config "CA\Utility" "c:\Cert_Req.req" "c:\Certificate.cer" -q
        #Write-Host "Done"
    
        # Clear certificate request files
        Remove-Item c:\Cert_Req.inf -ErrorAction SilentlyContinue | Out-Null
        Remove-Item c:\Cert_Req.req -ErrorAction SilentlyContinue | Out-Null
    
        # End of Certificate request
    
        # Define The Cert File To Import
         $CertFile = "c:\Certificate.cer"
    
        # Target The Cert That Needs To Be Imported
        $CertImport = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 $CertFile
    
        # Define The Scope And Certificate Store Within That Scope To Import The Certificate Into
        # Available Cert Store Scopes are "LocalMachine" or "CurrentUser"
        $CertStoreScope = "LocalMachine"
        $CertStoreName = "My"
        $CertStore = New-Object System.Security.Cryptography.X509Certificates.X509Store $CertStoreName, $CertStoreScope
    
        # Import The Targeted Certificate Into The Specified Cert Store Name Of The Specified Cert Store Scope
        $CertStore.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadWrite)
        $CertStore.Add($CertImport)
        $CertStore.Close()
    
        # Get the Thumbprint for the certificate
        $thumbprint = Get-ChildItem cert:\LocalMachine\My | where { $_.Subject -match "CN=testertest" } | select -exp Thumbprint -First 1
        # Use the Thumbprint to repair the certificate which ensures the private key is created and allows the certificate to appear in IIS
        certutil –repairstore my “$thumbprint”
    
        # End of Certificate import
    
       }
       # **********************
       # End of Invoke-Command
       # **********************
    
    } # End of ForEach ($computer in $computerList) 

    As you can see the only variable I'm using outside of the invoke is URL. The cert file variables are all defined inside and work correctly. The script completes successfully on WS2008.

    I wondered if it could be something to do with Group Policy or UAC but have ruled out UAC which is turned off for the W2012 server I was testing against.

    Unfortunately I'm in training all day today so I can test the Group Policy part but it seems it may be more than that.

    Really appreciate any light you can shed on this.

    Thanks,

    David

    Thursday, June 26, 2014 7:42 AM
  • I'm also having this problem. The function that I'm running calls certreq as so:

    certreq -new $CertificateINI $CertificateREQ

    The error I get to the screen is:

    NotSpecified: (:String) [], RemoteException
        + CategoryInfo          : NotSpecified: (:String) [], RemoteException
        + FullyQualifiedErrorId : NativeCommandError
        + PSComputerName        : server.domain.com

    CertReq: Request Created

    and then it hangs. There are two errors in $Error.

    $Error[1] shows:

    writeErrorStream      : True
    OriginInfo            : server.domain.com
    Exception             : System.Management.Automation.RemoteException: NotSpecified: (:String) [], RemoteException
    TargetObject          :
    CategoryInfo          : NotSpecified: (:String) [], RemoteException
    FullyQualifiedErrorId : NativeCommandError
    ErrorDetails          :
    InvocationInfo        :
    ScriptStackTrace      :
    PipelineIterationInfo : {}
    PSMessageDetails      :
    Did you manage to solve this?
    • Edited by RobinMalik Wednesday, September 17, 2014 1:27 PM formatting
    Wednesday, September 17, 2014 1:27 PM
  • I found a solution as so:

    $OriginalEAP = $ErrorActionPreference
    $ErrorActionPreference = "SilentlyContinue"
    
    $shush = certreq -q -new $CertificateINI $CertificateREQ
    
    $ErrorActionPreference = $OriginalEAP
    
    

    Using the -q switch fixed the hanging issue. The other code is essentially to suppress the error message I was receiving above. I can now successfully generate requests against remote servers (via a web interface no less).

    Hope this helps!

    • Proposed as answer by RobinMalik Friday, October 3, 2014 4:58 PM
    • Unproposed as answer by RobinMalik Friday, October 3, 2014 4:58 PM
    • Proposed as answer by RobinMalik Friday, October 3, 2014 5:01 PM
    • Marked as answer by Mike Laughlin Monday, August 22, 2016 4:37 PM
    Wednesday, September 17, 2014 2:15 PM
  • Thanks Robin,

    I knew it would be something so simple! The addition of "-q" worked on the certificate request.

    I removed the the pipe to Out-Null to see what error I was getting and found another (probably unrelated) error about not being able to authenticate which was resolved by restarting the certificate propogation service on the server.

    It seemed that I had a stale ldap handle as per the following article:

    http://support.microsoft.com/kb2578494

    Now I hit the same problem with my submit which also hands for no apparent reason. I tried adding the -q switch to that but it doesn't work in this instance.

    Any ideas?

    Thanks,

    David

    

    Thursday, September 18, 2014 1:51 PM
  • You're welcome. Have proposed my comment as answer.

    I'm not sure about the new issue. The KB article you linked to doesn't appear to exist. Care to update with a working link and I can take a look?

    Regards,

    Robin

    Friday, October 3, 2014 5:01 PM