ebekker / ACMESharp

An ACME client library and PowerShell client for the .NET platform (Let's Encrypt)
https://pkisharp.github.io/ACMESharp-docs/
1.21k stars 184 forks source link

Example script for cloudflare dns #303

Open gnordli opened 6 years ago

gnordli commented 6 years ago

Does anyone have an example script with cloudflare dns authorization and alternate names. It would be great to have this added to the documentation.
thanks!!

ebekker commented 6 years ago

@gnordli, are you familiar with the Cloudflare APIs?

gnordli commented 6 years ago

Hi @ebekker

I use the cloudflare dns with acme.sh on Linux, which is working fine. Just looking for a quick example script that is using the current code with alternate names. For whatever reason I couldn't get it working properly.
thanks!!

ebekker commented 6 years ago

Unfortunately, the Cloudflare Provider was contributed by @janpieterz so I'm not too familiar with it or the inner workings. Perhaps he may be able to provide some guidance.

janpieterz commented 6 years ago

Hi @gnordli , yeah, I do have some examples.

This is in pure powershell, so you might have to adjust it a bit. You provide the domain and alternative domains as before, depending on what your script is based off on (unfamiliar with the acme.sh variant). For each alternate domain you go and after retrieving the ACMEIdentifier (either through New- or Get-) and you execute something like:

if ( ! ($result.Challenges | Where-Object { $_.Type -eq 'dns-01' -and $_.SubmitDate }).Count )
        {
            # No?  Has the request been submitted?
            if ( ! ($result.Challenges | Where-Object { $_.Type -eq 'dns-01' -and $_.HandlerName -eq 'CloudFlare' }).Count )
            {
                Log "Issue challenge for $alias" -seq $seq
                $result = Complete-ACMEChallenge $alias -ChallengeType dns-01 -Handler CloudFlare -HandlerParameters @{DomainName=$cloudflareDomain;EmailAddress=$cloudflareEmail;AuthKey=$cloudflareKey}                                                

            }
        }
        else
        {
            Log "The identifier '$alias' has been already been submitted" -seq $seq
        }

Do note that $cloudFlareDomain is the cloudflare main domain, not the alternative domains. So for retrieving, for example, test.github.com you'd still enter github.com for that variable, as it's based on your CloudFlare structure.

I've then built in a delay after doing the Complete-ACMEChallenge for all domains, as DNS propagation and CloudFlare sometimes made it fail and I just wanted it to always work. I've set it to 5 minutes:

Log "Sleeping for 5 minutes to let DNS propogate" -seq $seq
Start-Sleep -s 300
Log "Resuming operation after 5 minute sleep" -seq $seq

After which you iterate over all domains, Submit-ACMEChallenge, and follow the rest of the usual flow.

At the end make sure to call the Complete-ACMEChallenge with -Cleanup correctly, as it cleans up these keys in CloudFlare (important if you have multiple scripts hitting the same CloudFlare domain):

$domains.GetEnumerator() | ForEach-Object {
        $alias = $_.Key;
        $result = Complete-ACMEChallenge $alias -CleanUp -ChallengeType dns-01 -Handler CloudFlare -HandlerParameters @{DomainName=$cloudflareDomain;EmailAddress=$cloudflareEmail;AuthKey=$cloudflareKey}                                                
        Log "Cleanup of $alias with result $result" -seq $seq
    }

Let me know if this helps any or you'd like to know some more, a sample of where it goes wrong vs what worked with no alternate names might help.

ebekker commented 6 years ago

Thank you, @janpieterz !