jhartlep / servercow-dns-api

custom DNS API script (host servercow) for acme.sh (https://github.com/Neilpang/acme.sh)
MIT License
2 stars 1 forks source link

Incompatible with wildcards #1

Open levinuss opened 6 years ago

levinuss commented 6 years ago

Hey, the script does not work for me anymore when requesting wildcards from LE. If I want to get a cert for example.org and *.example.org LE will use two separate challenges and also two different TXT record values for this. acme.sh will call the script two times, one time for the base domain and the second time, with the same name but a different content, for the wildcard (https://community.letsencrypt.org/t/base-domain-validation/59009). The servercow API will override the first record when the script tries to place the second (see DNSAPIv1 documentation). content has to be an array to transfer multiple records with the same name. The script would have to get a list of all records and copy the existing ones into the content array. In my python script for the API I solved it like this (get_record_list is self-explanatory..):

def add_record(domain, record_type, record_name, record_content, record_ttl,                                                                                                                                
               keep_record):                                                                                                                                                                                
    record_list = get_record_list(domain, 0, 0)                                                                                                                                                             
    existing_records_content = []                                                                                                                                                                           
    for record in record_list:                                                                                                                                                                              
        if record['name'] == record_name:                                                                                                                                                                   
            existing_records_content.append(record['content'])                                                                                                                                                                                                                                                                                     
    if (keep_record == 1):                                                                                                                                                                                  
        if (isinstance(record_content, list)):                                                                                                                                                              
            for content in record_content:                                                                                                                                                                  
                existing_records_content.append(content)                                                                                                                                                    
        else:                                                                                                                                                                                               
            existing_records_content.append(record_content)                                                                                                                                                 
        records_contents = existing_records_content
        .....

Maybe this is helpful. I'm not that experienced, esp with shell, that's why I didn't create a PR. My current workaround is to use the manual mode or to first request a separate cert for each domain I wan't in my final cert and then issue my final cert. The successful challenges will be cached for some time.

jhartlep commented 6 years ago

Hi, thanks. I haven´t used wildcards with LE yet. But I will try to fix this issue.

jhartlep commented 6 years ago

Hi @levinus I just analysed this issue. The Servercow API currently does not support adding two DNS entries with different values. I am in contact with servercow to get a solution for this. If the Servercow API supports this, I will update my skript.

levinuss commented 6 years ago

Afaik it does. See this document from the servercow knowledgebase. If you look at the pyhton snippet above, you can see that I just add all values to an array.

baswag commented 5 years ago

Any update on the issue?

anom-human commented 3 years ago

https://github.com/acmesh-official/acme.sh/pull/3449

The PR should close the issue.

Miyamoto72 commented 3 years ago

Somehow this again is an issue. Trying to issue a cert for '*.mydomain.com' and mydomain.com, but I always get the following error:

acme.sh --issue --dns dns_servercow --keylength 4096 -d '*.mydomain.com' -d mydomain.com -f --debug

[...]

[Mo 27. Sep 08:51:33 CEST 2021] Getting webroot for domain='.mydomain.com' [Mo 27. Sep 08:51:33 CEST 2021] _w='dns_servercow' [Mo 27. Sep 08:51:33 CEST 2021] _currentRoot='dns_servercow' [Mo 27. Sep 08:51:33 CEST 2021] entry='"type":"dns-01","status":"pending","url":"https://acme-v02.api.letsencrypt.org/acme/chall-v3/34735927400/Km8dEA","token":"CqAfsHgCvloTMi3tnhyed9clsbT_A6DDEKi2jNQleRc"' [Mo 27. Sep 08:51:33 CEST 2021] token='CqAfsHgCvloTMi3tnhyed9clsbT_A6DDEKi2jNQleRc' [Mo 27. Sep 08:51:33 CEST 2021] uri='https://acme-v02.api.letsencrypt.org/acme/chall-v3/34735927400/Km8dEA' [Mo 27. Sep 08:51:33 CEST 2021] keyauthorization='CqAfsHgCvloTMi3tnhyed9clsbT_A6DDEKi2jNQleRc.yvIO2X0CtpshXNFS0MKSABMjwoPMndKDdmTch_Y1bWU' [Mo 27. Sep 08:51:33 CEST 2021] dvlist='.mydomain.com#CqAfsHgCvloTMi3tnhyed9clsbT_A6DDEKi2jNQleRc.yvIO2X0CtpshXNFS0MKSABMjwoPMndKDdmTch_Y1bWU#https://acme-v02.api.letsencrypt.org/acme/chall-v3/34735927400/Km8dEA#dns-01#dns_servercow' [Mo 27. Sep 08:51:33 CEST 2021] d='mydomain.com' [Mo 27. Sep 08:51:33 CEST 2021] Getting webroot for domain='mydomain.com' [Mo 27. Sep 08:51:33 CEST 2021] _w='dns_servercow' [Mo 27. Sep 08:51:33 CEST 2021] _currentRoot='dns_servercow' [Mo 27. Sep 08:51:33 CEST 2021] entry [Mo 27. Sep 08:51:33 CEST 2021] Not a wildcard domain, lets check whether the validation is already valid. [Mo 27. Sep 08:51:33 CEST 2021] mydomain.com is already valid. [Mo 27. Sep 08:51:33 CEST 2021] keyauthorization='verified_ok' [Mo 27. Sep 08:51:33 CEST 2021] dvlist='mydomain.com#verified_ok#https://acme-v02.api.letsencrypt.org/acme/chall-v3/34735927400/Km8dEA#dns-01#dns_servercow' [Mo 27. Sep 08:51:33 CEST 2021] d [Mo 27. Sep 08:51:33 CEST 2021] vlist='.mydomain.com#CqAfsHgCvloTMi3tnhyed9clsbT_A6DDEKi2jNQleRc.yvIO2X0CtpshXNFS0MKSABMjwoPMndKDdmTch_Y1bWU#https://acme-v02.api.letsencrypt.org/acme/chall-v3/34735927400/Km8dEA#dns-01#dns_servercow,mydomain.com#verified_ok#https://acme-v02.api.letsencrypt.org/acme/chall-v3/34735927400/Km8dEA#dns-01#dns_servercow,' [Mo 27. Sep 08:51:33 CEST 2021] d='.mydomain.com' [Mo 27. Sep 08:51:33 CEST 2021] _d_alias [Mo 27. Sep 08:51:33 CEST 2021] txtdomain='_acme-challenge.mydomain.com' [Mo 27. Sep 08:51:33 CEST 2021] txt='s_E_Rff3TS0uJDkmvjQp6qaoFZrZEBj-KBNlAtEZ9AU' [Mo 27. Sep 08:51:33 CEST 2021] d_api='/home/acmeuser/.acme.sh/dnsapi/dns_servercow.sh' [Mo 27. Sep 08:51:33 CEST 2021] Found domain api file: /home/acmeuser/.acme.sh/dnsapi/dns_servercow.sh [Mo 27. Sep 08:51:33 CEST 2021] Adding txt value: s_E_Rff3TS0uJDkmvjQp6qaoFZrZEBj-KBNlAtEZ9AU for domain: _acme-challenge.mydomain.com [Mo 27. Sep 08:51:33 CEST 2021] Using servercow [Mo 27. Sep 08:51:33 CEST 2021] fulldomain='_acme-challenge.mydomain.com' [Mo 27. Sep 08:51:33 CEST 2021] txtvalue='s_E_Rff3TS0uJDkmvjQp6qaoFZrZEBj-KBNlAtEZ9AU' [Mo 27. Sep 08:51:33 CEST 2021] First detect the root zone [Mo 27. Sep 08:51:33 CEST 2021] _domain='mydomain.com' [Mo 27. Sep 08:51:33 CEST 2021] Retrying GET [Mo 27. Sep 08:51:33 CEST 2021] GET [Mo 27. Sep 08:51:33 CEST 2021] url='https://api.servercow.de/dns/v1/domains/mydomain.com' [Mo 27. Sep 08:51:33 CEST 2021] timeout= [Mo 27. Sep 08:51:33 CEST 2021] displayError='1' [Mo 27. Sep 08:51:33 CEST 2021] _CURL='curl --silent --dump-header /home/acmeuser/.acme.sh/http.header -L ' [Mo 27. Sep 08:51:37 CEST 2021] ret='0' [Mo 27. Sep 08:51:37 CEST 2021] _hcode='0' [Mo 27. Sep 08:51:37 CEST 2021] _sub_domain='_acme-challenge' [Mo 27. Sep 08:51:37 CEST 2021] _domain='mydomain.com' [Mo 27. Sep 08:51:37 CEST 2021] There is no txt record with the name yet. [Mo 27. Sep 08:51:37 CEST 2021] data='{"type":"TXT","name":"_acme-challenge.mydomain.com","content":"s_E_Rff3TS0uJDkmvjQp6qaoFZrZEBj-KBNlAtEZ9AU","ttl":20}' [Mo 27. Sep 08:51:37 CEST 2021] Retrying post [Mo 27. Sep 08:51:37 CEST 2021] POST [Mo 27. Sep 08:51:37 CEST 2021] _post_url='https://api.servercow.de/dns/v1/domains/mydomain.com' [Mo 27. Sep 08:51:37 CEST 2021] _CURL='curl --silent --dump-header /home/acmeuser/.acme.sh/http.header -L ' [Mo 27. Sep 08:51:44 CEST 2021] _ret='0' [Mo 27. Sep 08:51:44 CEST 2021] _hcode='0' [Mo 27. Sep 08:51:44 CEST 2021] add txt record error. [Mo 27. Sep 08:51:44 CEST 2021] Error add txt for domain:_acme-challenge.mydomain.com [Mo 27. Sep 08:51:44 CEST 2021] _on_issue_err [Mo 27. Sep 08:51:44 CEST 2021] Please check log file for more details: /home/acmeuser/.acme.sh/acme.sh.log [Mo 27. Sep 08:51:44 CEST 2021] url='https://acme-v02.api.letsencrypt.org/acme/chall-v3/34735927400/Km8dEA' [Mo 27. Sep 08:51:44 CEST 2021] payload='{}'

[...]

Using acme.sh v3.0.1 on Debian Buster with NGinx 1.21.3 (from nginx.org)

Setup worked before flawlessly (acme.sh 2.8.6 for long time), but now I wasn't able to get a wildcard cert - got only the mydomain.com cert when issueing it alone

Happy to help track this down - pls let me know if I can be of help.

anom-human commented 3 years ago

I'll have a look at it in the next few days and make some improvements. But I can't promise anything, I'm a bit busy right now.

Miyamoto72 commented 3 years ago

Some more infos: Apparenly I had a problem with the authentication at times - this is solved. Trying to issue a new combined cert with a defined keylength of 4096 bits throws an error:

[Do 30. Sep 19:32:04 CEST 2021] Using CA: https://acme-v02.api.letsencrypt.org/directory
[Do 30. Sep 19:32:04 CEST 2021] Creating domain key
[Do 30. Sep 19:32:04 CEST 2021] error ecc key name: mydomain.com
[Do 30. Sep 19:32:04 CEST 2021] Can not create domain key
[Do 30. Sep 19:32:04 CEST 2021] Create domain key error.

Apparently acme.sh now tries to create ECC keys, too, by default, and those have other keylengths. In my opinion this is an error in acme.sh, of course.

Trying to issue an RSA key by command line options should be possible, I'd say, but I didn't find a way. So I tried to issue a new combined cert from the backup of the old CSR:

[Do 30. Sep 19:39:19 CEST 2021] Copy csr to: /home/acmeuser/.acme.sh/*.mydomain.com/*.mydomain.com.csr
[Do 30. Sep 19:39:19 CEST 2021] Using CA: https://acme-v02.api.letsencrypt.org/directory
[Do 30. Sep 19:39:19 CEST 2021] Signing from existing CSR.
[Do 30. Sep 19:39:19 CEST 2021] Getting domain auth token for each domain
[Do 30. Sep 19:39:22 CEST 2021] Getting webroot for domain='*.mydomain.com'
[Do 30. Sep 19:39:23 CEST 2021] Error, can not get domain token entry *.mydomain.com for http-01
[Do 30. Sep 19:39:23 CEST 2021] The supported validation types are: dns-01 , but you specified: http-01

Here's the log:

[Do 30. Sep 19:53:44 CEST 2021] Running cmd: signcsr
[Do 30. Sep 19:53:44 CEST 2021] _csrsubj='*.mydomain.com'
[Do 30. Sep 19:53:44 CEST 2021] _csrsubj='*.mydomain.com'
[Do 30. Sep 19:53:44 CEST 2021] _dnsAltnames='DNS:*.mydomain.com,DNS:mydomain.com'
[Do 30. Sep 19:53:44 CEST 2021] AltNames contains subject
[Do 30. Sep 19:53:44 CEST 2021] _excapedAlgnames='DNS:#.mydomain.com,DNS:mydomain.com'
[Do 30. Sep 19:53:44 CEST 2021] _escapedSubject='#.mydomain.com'
[Do 30. Sep 19:53:44 CEST 2021] _dnsAltnames='DNS:mydomain.com'
[Do 30. Sep 19:53:44 CEST 2021] _csrdomainlist='mydomain.com'
[Do 30. Sep 19:53:44 CEST 2021] RSA CSR
[Do 30. Sep 19:53:44 CEST 2021] Using config home:/home/acmeuser/.acme.sh
[Do 30. Sep 19:53:44 CEST 2021] default_acme_server='https://acme-v02.api.letsencrypt.org/directory'
[Do 30. Sep 19:53:44 CEST 2021] ACME_DIRECTORY='https://acme-v02.api.letsencrypt.org/directory'
[Do 30. Sep 19:53:44 CEST 2021] DOMAIN_PATH='/home/acmeuser/.acme.sh/*.mydomain.com'
[Do 30. Sep 19:53:44 CEST 2021] Copy csr to: /home/acmeuser/.acme.sh/*.mydomain.com/*.mydomain.com.csr
[Do 30. Sep 19:53:44 CEST 2021] _main_domain='*.mydomain.com'
[Do 30. Sep 19:53:44 CEST 2021] _alt_domains='mydomain.com'
[Do 30. Sep 19:53:44 CEST 2021] Using config home:/home/acmeuser/.acme.sh
[Do 30. Sep 19:53:44 CEST 2021] ACME_DIRECTORY='https://acme-v02.api.letsencrypt.org/directory'
[Do 30. Sep 19:53:44 CEST 2021] Using ACME_DIRECTORY: https://acme-v02.api.letsencrypt.org/directory
[Do 30. Sep 19:53:44 CEST 2021] _init api for server: https://acme-v02.api.letsencrypt.org/directory
[Do 30. Sep 19:53:44 CEST 2021] Retrying GET
[Do 30. Sep 19:53:44 CEST 2021] GET
[Do 30. Sep 19:53:44 CEST 2021] url='https://acme-v02.api.letsencrypt.org/directory'
[Do 30. Sep 19:53:44 CEST 2021] timeout=
[Do 30. Sep 19:53:44 CEST 2021] displayError='1'
[Do 30. Sep 19:53:44 CEST 2021] _CURL='curl --silent --dump-header /home/acmeuser/.acme.sh/http.header  -L '
[Do 30. Sep 19:53:45 CEST 2021] ret='0'
[Do 30. Sep 19:53:45 CEST 2021] _hcode='0'
[Do 30. Sep 19:53:45 CEST 2021] ACME_KEY_CHANGE='https://acme-v02.api.letsencrypt.org/acme/key-change'
[Do 30. Sep 19:53:45 CEST 2021] ACME_NEW_AUTHZ
[Do 30. Sep 19:53:45 CEST 2021] ACME_NEW_ORDER='https://acme-v02.api.letsencrypt.org/acme/new-order'
[Do 30. Sep 19:53:45 CEST 2021] ACME_NEW_ACCOUNT='https://acme-v02.api.letsencrypt.org/acme/new-acct'
[Do 30. Sep 19:53:45 CEST 2021] ACME_REVOKE_CERT='https://acme-v02.api.letsencrypt.org/acme/revoke-cert'
[Do 30. Sep 19:53:45 CEST 2021] ACME_AGREEMENT='https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf'
[Do 30. Sep 19:53:45 CEST 2021] ACME_NEW_NONCE='https://acme-v02.api.letsencrypt.org/acme/new-nonce'
[Do 30. Sep 19:53:45 CEST 2021] Le_NextRenewTime
[Do 30. Sep 19:53:45 CEST 2021] Using CA: https://acme-v02.api.letsencrypt.org/directory
[Do 30. Sep 19:53:45 CEST 2021] _on_before_issue
[Do 30. Sep 19:53:45 CEST 2021] _chk_main_domain='*.mydomain.com'
[Do 30. Sep 19:53:45 CEST 2021] _chk_alt_domains='mydomain.com'
[Do 30. Sep 19:53:45 CEST 2021] Le_LocalAddress
[Do 30. Sep 19:53:45 CEST 2021] d='*.mydomain.com'
[Do 30. Sep 19:53:45 CEST 2021] Check for domain='*.mydomain.com'
[Do 30. Sep 19:53:45 CEST 2021] _currentRoot='/var/www/letsencrypt/'
[Do 30. Sep 19:53:45 CEST 2021] d='mydomain.com'
[Do 30. Sep 19:53:45 CEST 2021] Check for domain='mydomain.com'
[Do 30. Sep 19:53:45 CEST 2021] _currentRoot='dns_servercow'
[Do 30. Sep 19:53:45 CEST 2021] d
[Do 30. Sep 19:53:45 CEST 2021] _saved_account_key_hash is not changed, skip register account.
[Do 30. Sep 19:53:45 CEST 2021] Signing from existing CSR.
[Do 30. Sep 19:53:45 CEST 2021] Getting domain auth token for each domain
[Do 30. Sep 19:53:45 CEST 2021] d='mydomain.com'
[Do 30. Sep 19:53:45 CEST 2021] d
[Do 30. Sep 19:53:45 CEST 2021] url='https://acme-v02.api.letsencrypt.org/acme/new-order'
[Do 30. Sep 19:53:45 CEST 2021] payload='{"identifiers": [{"type":"dns","value":"*.mydomain.com"},{"type":"dns","value":"mydomain.com"}]}'
[Do 30. Sep 19:53:45 CEST 2021] RSA key
[Do 30. Sep 19:53:45 CEST 2021] Retrying post
[Do 30. Sep 19:53:45 CEST 2021] HEAD
[Do 30. Sep 19:53:45 CEST 2021] _post_url='https://acme-v02.api.letsencrypt.org/acme/new-nonce'
[Do 30. Sep 19:53:45 CEST 2021] _CURL='curl --silent --dump-header /home/acmeuser/.acme.sh/http.header  -L  -I  '
[Do 30. Sep 19:53:46 CEST 2021] _ret='0'
[Do 30. Sep 19:53:46 CEST 2021] _hcode='0'
[Do 30. Sep 19:53:46 CEST 2021] Retrying post
[Do 30. Sep 19:53:46 CEST 2021] POST
[Do 30. Sep 19:53:46 CEST 2021] _post_url='https://acme-v02.api.letsencrypt.org/acme/new-order'
[Do 30. Sep 19:53:46 CEST 2021] _CURL='curl --silent --dump-header /home/acmeuser/.acme.sh/http.header  -L '
[Do 30. Sep 19:53:47 CEST 2021] _ret='0'
[Do 30. Sep 19:53:47 CEST 2021] _hcode='0'
[Do 30. Sep 19:53:47 CEST 2021] code='201'
[Do 30. Sep 19:53:47 CEST 2021] Le_LinkOrder='https://acme-v02.api.letsencrypt.org/acme/order/219267140/28406525630'
[Do 30. Sep 19:53:47 CEST 2021] Le_OrderFinalize='https://acme-v02.api.letsencrypt.org/acme/finalize/219267140/28406525630'
[Do 30. Sep 19:53:47 CEST 2021] url='https://acme-v02.api.letsencrypt.org/acme/authz-v3/35793653770'
[Do 30. Sep 19:53:47 CEST 2021] payload
[Do 30. Sep 19:53:47 CEST 2021] Retrying post
[Do 30. Sep 19:53:47 CEST 2021] POST
[Do 30. Sep 19:53:47 CEST 2021] _post_url='https://acme-v02.api.letsencrypt.org/acme/authz-v3/35793653770'
[Do 30. Sep 19:53:47 CEST 2021] _CURL='curl --silent --dump-header /home/acmeuser/.acme.sh/http.header  -L '
[Do 30. Sep 19:53:47 CEST 2021] _ret='0'
[Do 30. Sep 19:53:47 CEST 2021] _hcode='0'
[Do 30. Sep 19:53:47 CEST 2021] code='200'
[Do 30. Sep 19:53:47 CEST 2021] url='https://acme-v02.api.letsencrypt.org/acme/authz-v3/35793653780'
[Do 30. Sep 19:53:47 CEST 2021] payload
[Do 30. Sep 19:53:48 CEST 2021] Retrying post
[Do 30. Sep 19:53:48 CEST 2021] POST
[Do 30. Sep 19:53:48 CEST 2021] _post_url='https://acme-v02.api.letsencrypt.org/acme/authz-v3/35793653780'
[Do 30. Sep 19:53:48 CEST 2021] _CURL='curl --silent --dump-header /home/acmeuser/.acme.sh/http.header  -L '
[Do 30. Sep 19:53:48 CEST 2021] _ret='0'
[Do 30. Sep 19:53:48 CEST 2021] _hcode='0'
[Do 30. Sep 19:53:48 CEST 2021] code='200'
[Do 30. Sep 19:53:48 CEST 2021] d='*.mydomain.com'
[Do 30. Sep 19:53:48 CEST 2021] Getting webroot for domain='*.mydomain.com'
[Do 30. Sep 19:53:48 CEST 2021] _w='/var/www/letsencrypt/'
[Do 30. Sep 19:53:48 CEST 2021] _currentRoot='/var/www/letsencrypt/'
[Do 30. Sep 19:53:48 CEST 2021] entry
[Do 30. Sep 19:53:48 CEST 2021] Error, can not get domain token entry *.mydomain.com for http-01
[Do 30. Sep 19:53:48 CEST 2021] The supported validation types are: dns-01 , but you specified: http-01
[Do 30. Sep 19:53:48 CEST 2021] pid
[Do 30. Sep 19:53:48 CEST 2021] No need to restore nginx, skip.
[Do 30. Sep 19:53:48 CEST 2021] _clearupdns
[Do 30. Sep 19:53:48 CEST 2021] dns_entries
[Do 30. Sep 19:53:48 CEST 2021] skip dns.
[Do 30. Sep 19:53:48 CEST 2021] _on_issue_err
Miyamoto72 commented 3 years ago

I'll have a look at it in the next few days and make some improvements. But I can't promise anything, I'm a bit busy right now.

Not trying to push - any advances with this?