ACMESharp
ACMESharp copied to clipboard
Submit-ACMECertificate errors with exception 403 forbidden
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
}