Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Another quick and dirty PoC script to retreive a Let's Encrypt certificate and post it to Directadmin. Script receives token and uploads to FTP to verify domain ownership. Probably needs PowerShell 5.
#import the ACMEsharp module - https://github.com/ebekker/ACMESharp
#more info: https://github.com/ebekker/ACMESharp/wiki/Quick-Start
import-module .\ACMESharp\ACMESharp.psd1
#set global variables
$date = "$(get-date -format yyyy-MM-dd--HH-mm)"
$dnsname1 = "dns1-$date"
$dnsname2 = "dns2-$date"
#DirectAdmin and FTP credentials
$Username = "fancyusername"
$Password = "fancypassword"
$FTPuser = $Username
$FTPuserPass = $Password
$DAUser = $Username
$DAPass = $Password
$domainname = "mendelonline.be"
#DirectAdminServer
$DAServer = "https://daserver.domain.ext"
#test if vault is initialized
if((get-acmevault) -eq "")
{
Initialize-ACMEVault
$mailaddress = read-host "Enter mailaddress"
New-ACMERegistration -Contacts "mailto:$mailaddress" -accepttos
}
#create new identifier for certificate request
New-ACMEIdentifier -Dns "$domainname" -Alias $dnsname1
New-ACMEIdentifier -Dns "www.$domainname" -Alias $dnsname2
#create new challenge
$var = Complete-ACMEChallenge $dnsname1 -ChallengeType http-01 -Handler manual
$var2 = Complete-ACMEChallenge $dnsname2 -ChallengeType http-01 -Handler manual
#get the manual challenge and export the token to a file
$challenge = $var.challenges | ?{$_.type -eq "http-01"}
$filename = $challenge.challenge.token
[string]$varfilecontent = $challenge.challenge.FileContent
$varfilecontent | Out-File $filename -Encoding:ascii -nonewline
#do the same for the subject alternative name
$challenge2 = $var2.challenges | ?{$_.type -eq "http-01"}
$filename2 = $challenge2.challenge.token
[string]$varfilecontent2 = $challenge2.challenge.FileContent
$varfilecontent2 | Out-File $filename2 -Encoding:ascii -nonewline
#upload file to ftp
$destinationpath = "ftp://ftp.$domainname/domains/$domainname/public_html/.well-known/acme-challenge"
$RemoteFile = $destinationpath + "/" + "$filename"
$LocalFile = ".\$filename"
# Create FTP Rquest Object
$FTPRequest = [System.Net.FtpWebRequest]::Create("$RemoteFile")
$FTPRequest = [System.Net.FtpWebRequest]$FTPRequest
$FTPRequest.Method = [System.Net.WebRequestMethods+Ftp]::UploadFile
$FTPRequest.Credentials = new-object System.Net.NetworkCredential($FTPuser, $FTPuserPass)
$FTPRequest.UseBinary = $true
$FTPRequest.UsePassive = $true
# Read the File for Upload
$FileContent = gc -en byte $LocalFile
$FTPRequest.ContentLength = $FileContent.Length
# Get Stream Request by bytes
$Run = $FTPRequest.GetRequestStream()
$Run.Write($FileContent, 0, $FileContent.Length)
# Cleanup
$Run.Close()
$Run.Dispose()
#same for san
$RemoteFile2 = $destinationpath + "/" + "$filename2"
$LocalFile2 = ".\$filename2"
$FTPRequest2 = [System.Net.FtpWebRequest]::Create("$RemoteFile2")
$FTPRequest2 = [System.Net.FtpWebRequest]$FTPRequest2
$FTPRequest2.Method = [System.Net.WebRequestMethods+Ftp]::UploadFile
$FTPRequest2.Credentials = new-object System.Net.NetworkCredential($FTPuser, $FTPuserPass)
$FTPRequest2.UseBinary = $true
$FTPRequest2.UsePassive = $true
$FileContent2 = gc -en byte $LocalFile2
$FTPRequest2.ContentLength = $FileContent2.Length
$Run2 = $FTPRequest2.GetRequestStream()
$Run2.Write($FileContent2, 0, $FileContent2.Length)
# Cleanup
$Run2.Close()
$Run2.Dispose()
#submit the challenge
Submit-ACMEChallenge $dnsname1 -ChallengeType http-01
(Update-ACMEIdentifier $dnsname1 -ChallengeType http-01).Challenges | Where-Object {$_.Type -eq "http-01"}
Update-ACMEIdentifier $dnsname1
#submit for san
Submit-ACMEChallenge $dnsname2 -ChallengeType http-01
(Update-ACMEIdentifier $dnsname2 -ChallengeType http-01).Challenges | Where-Object {$_.Type -eq "http-01"}
Update-ACMEIdentifier $dnsname2
#confirm with Let's Encrypt and retreive certificate
$certname = "cert-$dnsname1"
New-ACMECertificate $dnsname1 -Generate -Alias $certname -AlternativeIdentifierRefs $dnsname1,$dnsname2
$certresponse = Submit-ACMECertificate $certname
#if serialnumber is ok, certificate is issued and imported in the local vault, otherwise wait here (sleep)
if($certresponse.serialnumber -ne "")
{
write-output "ok"
}
else
{
write-error -Exception notready
}
#export the cert to key and crt
Get-ACMECertificate $certname -ExportKeyPEM "$pwd\$certname.key"
Get-ACMECertificate $certname -ExportCertificatePEM "$pwd\$certname.crt"
#post to DirectAdmin
$url = "$daserver/CMD_SSL?domain=$domainname"
$loginurl = "$DAServer/CMD_LOGIN"
#create a new session
$var = invoke-webrequest -Uri $url -sessionvariable ws
$headervals = @{'Referer'='$DAServer/CMD_SSL?domain=$domainname';'Content-Type'='application/x-www-form-urlencoded'}
#login to DirectAdmin
$postdata = "referer=%2FCMD_SSL%3Fdomain%3D$domainname&username=$DAUser&password=$DAPass"
$vaaar = invoke-webrequest -Uri $loginurl -Method Post -Body $postdata -Headers $headervals -websession $ws
#load certificate
$certkey = [string]::join([environment]::newline, (get-content -path "$pwd\$certname.key"))
$certkey = [string]::join([environment]::newline, (get-content -path "$pwd\$certname.crt"))
[string]$certpostdata = $certkey + "`r`n" + $cert
#create postdata
$postdata = ""
$postdata += "domain=$domainname"
$postdata += "&action=save"
$postdata += "&country="
$postdata += "&province="
$postdata += "&city="
$postdata += "&company="
$postdata += "&division="
$postdata += "&name=www.$domainname"
$postdata += "&email="
$postdata += "&keysize=4096"
$postdata += "&encryption=sha256"
$postdata += "&type=paste"
$postdata += "&certificate="
#add cert to postdata
$urlencodedcert = [uri]::EscapeDataString($certpostdata)
$postdata += $urlencodedcert
$postdata += "&submit=Save"
#post postdata to DirectAdmin
$headervals = @{'Referer'='$DAServer/CMD_SSL?domain=$domainname';'Content-Type'='application/x-www-form-urlencoded'}
$urlcert = "$DAServer/CMD_SSL"
$postresponse = invoke-webrequest -Uri $urlcert -Method Post -Body $postdata -Headers $headervals -websession $ws
#parse response
$splitstring1 = [string]$postresponse.rawcontent.substring($postresponse.rawcontent.lastindexof("<table width=100% height=100% cellspacing=0 cellpadding=5>"),500)
$splitstring2 = $splitstring1.substring($splitstring1.indexof('<p align="center">')+18)
$splitstring3 = $splitstring2.substring(0,$splitstring2.indexof('</p>'))
Write-Output "Result: $splitstring3"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment