ACMESharp icon indicating copy to clipboard operation
ACMESharp copied to clipboard

Submit-ACMECertificate errors with exception 403 forbidden

Open dschuermans opened this issue 7 years ago • 0 comments

Hello,

When trying to create new certificates for my domain & subdomains, my script has suddenly stopped working with the following exception:

C:\Tools\LetsEncryptCertificates\GenerateCertificates.ps1 : ACMESharp.AcmeClient+AcmeWebException: Unexpected error ---
> System.Net.WebException: The remote server returned an error: (403) Forbidden.
   at System.Net.HttpWebRequest.GetResponse()
   at ACMESharp.AcmeClient.RequestHttpPost(Uri uri, Object message) in C:\projects\acmesharp\ACMESharp\ACMESharp\AcmeCl
ient.cs:line 700
   --- End of inner exception stack trace ---
   at ACMESharp.AcmeClient.RequestCertificate(String csrContent) in C:\projects\acmesharp\ACMESharp\ACMESharp\AcmeClien
t.cs:line 569
   at ACMESharp.POSH.SubmitCertificate.ProcessRecord() in C:\projects\acmesharp\ACMESharp\ACMESharp.POSH\SubmitCertific
ate.cs:line 155
At line:1 char:1

The script has worked the last time I used it (3 months ago) and I haven't made any changes to it in the meantime. I have attempted to update ACMESharp after the first errors, but it did not help. ACMESharp 8.1 Windows Server 2008 R2 with latest updates installed. OpenSSL 1.0.2h 3 May 2016

Full script:

[CmdletBinding()]
param(
    [string]
    $OutputFolder = "$PSScriptRoot\Certificates",
	[Switch]
	$AsPfx
)
begin{
    
    Import-Module ACMESharp
    Import-Module .\GoDaddyApi.psm1

    $ACMEValidValue = "valid"
    $ACMEPendingValue = "pending"
    $ACMEInvalidValue = "invalid"

    #Load list of domains to generate certificates for
    $domains = Get-Content "domains.txt"

    Write-Verbose "Output folder: $OutputFolder"
}
process {
    foreach($Domain in $domains) {
        $tmp = Get-Date -Format o | foreach{$_ -replace ":", ""} | foreach{$_ -replace "-", ""} | foreach{$_ -replace "T", "" } | foreach{($_).Substring(0, 12) }
        $Alias = "$($Domain)_$($tmp)"
        Write-Verbose "Processing $Domain as alias $Alias "

        try {
            # Create a new identifier for the given $Domain
            New-ACMEIdentifier -Dns $Domain -Alias $Alias | Out-Null
        } catch [System.ArgumentException]  {
            Write-Error "Alias $($Alias) already exists for domain $Domain"
        } catch {
            Write-Error $_.Exception
            Break
        }

        try {
            # Tell Lets Encrypt that we will manually perform DNS validation by creating a TXT record
            Write-Verbose "Performing manual validation through DNS"
            $challenge = Complete-ACMEChallenge $Alias -ChallengeType dns-01 -Handler manual
           
            $RecordName = ($challenge.Challenges | Where-Object { $_.Type -eq "dns-01" }).Challenge.RecordName
            $RecordValue = ($challenge.Challenges | Where-Object { $_.Type -eq "dns-01" }).Challenge.RecordValue
    
            Write-Verbose "Creating a TXT record for host: $RecordName"
            Write-Verbose "With value: $RecordValue"

            $godaddyResult = Submit-GoDaddyApiRecordForDomain -Domain $domain -Alias $RecordName -Value $RecordValue -RecordType "TXT" -ApiKey "9Q3PBA4L5V6_PvDoBQUqS1e6hcRzJbTh8t" -ApiSecret "PvDsFxMMMErok72a7suBFe"
            Write-Verbose "Godaddy result: $godaddyResult"
            if($godaddyResult -gt 0){
                Write-Error "GoDaddy API call failed, skipping domain."
                Break
            }

        } catch {
            Write-Error $_.Exception
            Break 
        }

        try {
            Write-Verbose "Submitting ACME challenge for $Alias"
            # Tell lets encrypt to check the DNS record for the request txt record
            Submit-ACMEChallenge $Alias -ChallengeType dns-01 | Out-Null
        } catch {
            Write-Error "An error occurred while submitting the challenge, exiting...";
			Write-Error $_.Exception
            Break
        }

        $checkStatus = $True;
        $count = 1;
        $valid = $False;

        Write-Verbose "Checking the status of the ACME challenge for alias $Alias..."
        while($checkStatus){
            Start-Sleep -Seconds 10

            Write-Verbose "Try #$($count) - Checking status..."

            $status = ((Update-ACMEIdentifier $Alias -ChallengeType dns-01).Challenges | Where-Object {$_.Type -eq "dns-01"}).Status
        
            Write-Verbose ("Status is: " + $status)

            if($status.CompareTo($ACMEValidValue) -eq 0){
                $valid = $True
                $checkStatus = $False
            } elseif ($status.CompareTo($ACMEInvalidValue) -eq 0) {
                $valid = $False;
                $checkStatus = $False;
            }else{
                $count += 1;

                if($count -gt 10){
                    $checkStatus = $False;
                }
                else{
                    Write-Verbose "Waiting 10 seconds for next try..."
                }
            } 
        }

        Write-Verbose "Done checking status for $Alias, valid: $($valid)"

        Write-Verbose "Generating new certificate for domain $Domain with alias $Alias"

        try{
            New-ACMECertificate $Alias -Generate -Alias $Alias
        } catch {
            Write-Error "Failed to generate certificate for $Domain ($Alias)"
            Write-Error $_.Exception
            Break
        }
        
        try {
            Submit-ACMECertificate $Alias
        }catch {
            Write-Error "Failed to submit certificate for $Domain ($Alias)"
            Write-Error $_.Exception
            Break
        }
        

        $checkStatus = $True;
        $count = 1;
        $valid = $False;

        Write-Verbose "Checking certificate request status for $Alias"
        while($checkStatus){
            Start-Sleep -Seconds 10

            Write-Verbose "Try #$($count) - Checking status..."

            $status = (Update-ACMECertificate $Alias).SerialNumber
        
            Write-Verbose ("Serial number is: " + $status)

            if($status){
                $valid = $True
                $checkStatus = $False
            }else{
                $count += 1;

                if($count -gt 10){
                    $checkStatus = $False;
                }
                else{
                    Write-Verbose "Waiting 10 seconds for next try..."
                }
            } 
        }

        if($valid){
			if($AsPfx)
			{
                try{

				    Get-ACMECertificate $Alias -ExportPkcs12 "$($OutputFolder)\$($Alias).pfx" | Out-Null
				    Write-Verbose "Certificate has been exported to $($OutputFolder)\$($Alias).pfx"
                }catch {
                    Write-Error "Failed to export certificate as Pkcs12"
                    Write-Error $_.Exception
                }
			}
			else{
                try {
				    Get-ACMECertificate $Alias -ExportKeyPEM "$($OutputFolder)\$($Alias).key.pem" | Out-Null
				    Write-Verbose "Private key has been exported to $($OutputFolder)\$($Alias).key.pem"
				    Get-ACMECertificate $Alias -ExportCertificatePEM "$($OutputFolder)\$($Alias).cert.pem" | Out-Null
				    Write-Verbose "Certificate has been exported to $($OutputFolder)\$($Alias).cert.pem"
                } catch {
                    Write-Error "Failed to export certificate as PEM files"
                    Write-Error $_.Exception
                }
			}
        } else {
            Write-Error "Unable to generate certificate for domain $Domain"
        }
    }

}
end {
    Remove-Module GoDaddyApi
}

dschuermans avatar Nov 22 '17 08:11 dschuermans