From bcf63b5d270a4535347e64e7f25f24970e474e6f Mon Sep 17 00:00:00 2001 From: Martin Arndt <5111490+Eagle3386@users.noreply.github.com> Date: Sun, 27 Feb 2022 14:17:34 +0100 Subject: [PATCH 01/13] Add ArtFiles.de DNS API plugin --- dnsapi/dns_artfiles.sh | 176 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 176 insertions(+) create mode 100644 dnsapi/dns_artfiles.sh diff --git a/dnsapi/dns_artfiles.sh b/dnsapi/dns_artfiles.sh new file mode 100644 index 00000000..c857060a --- /dev/null +++ b/dnsapi/dns_artfiles.sh @@ -0,0 +1,176 @@ +#!/usr/bin/env sh + +################################################################################ +# ACME.sh 3rd party DNS API plugin for ArtFiles.de +################################################################################ +# Author: Martin Arndt, https://troublezone.net/ +# Released: 2022-02-27 +# Issues: https://github.com/acmesh-official/acme.sh/issues/XXXX +################################################################################ +# Usage: +# 1. export AF_API_Username="api12345678" +# 2. export AF_API_Password="apiPassword" +# 3. acme.sh --issue -d example.com --dns dns_artfiles +################################################################################ + +########## API configuration ################################################### +AF_API_SUCCESS='status":"OK' +AF_URL_DCP='https://dcp.c.artfiles.de/api/' +AF_URL_DNS=${AF_URL_DCP}'dns/{*}_dns.html?domain=' +AF_URL_DOMAINS=${AF_URL_BASE}'domain/get_domains.html' + +########## Public functions #################################################### + +# Adds a new TXT record for given ACME challenge value & domain. +# Usage: dns_artfiles_add _acme-challenge.www.example.com "ACME challenge value" +dns_artfiles_add() { + domain="$1" + txtValue="$2" + _info 'Using ArtFiles.de DNS addition API' + _debug 'Domain' "$domain" + _debug 'txtValue' "$txtValue" + + AF_API_USERNAME="${AF_API_USERNAME:-$(_readaccountconf_mutable AF_API_USERNAME)}" + AF_API_PASSWORD="${AF_API_PASSWORD:-$(_readaccountconf_mutable AF_API_PASSWORD)}" + if [ -z "$AF_API_USERNAME" ] || [ -z "$AF_API_PASSWORD" ]; then + _err 'Missing ArtFiles.de username and/or password.' + _err 'Please ensure both are set via export command & try again.' + + return 1 + fi + + _saveaccountconf_mutable 'AF_API_USERNAME' "$AF_API_USERNAME" + _saveaccountconf_mutable 'AF_API_PASSWORD' "$AF_API_PASSWORD" + + _set_headers + _get_zone "$domain" + _dns 'GET' + if ! _contains "$response" 'TXT'; then + _err 'Retrieving TXT records failed.' + + return 1 + fi + + _clean_records + _dns 'SET' "$(printf -- '%s\n_acme-challenge "%s"' "$response" "$txtValue")" + if ! _contains "$response" "$AF_API_SUCCESS"; then + _err 'Adding ACME challenge value failed.' + + return 1 + fi +} + +# Removes the existing TXT record for given ACME challenge value & domain. +# Usage: dns_artfiles_rm _acme-challenge.www.example.com "ACME challenge value" +dns_artfiles_rm() { + domain="$1" + txtValue="$2" + _info 'Using ArtFiles.de DNS removal API' + _debug 'Domain' "$domain" + _debug 'txtValue' "$txtValue" + + _set_headers + _get_zone "$domain" + if ! _dns 'GET'; then + return 1 + fi + + if ! _contains "$response" "$txtValue"; then + _err 'Retrieved TXT records are missing given ACME challenge value.' + + return 1 + fi + + _clean_records + response="$(printf -- '%s' "$response" | sed '$d')" + _dns 'SET' "$response" + if ! _contains "$response" "$AF_API_SUCCESS"; then + _err 'Removing ACME challenge value failed.' + + return 1 + fi +} + +########## Private functions ################################################### + +# Cleans awful TXT records response of ArtFiles's API & pretty prints it. +# Usage: _clean_records +_clean_records() +{ + # Extract TXT part, strip trailing quote sign (ACME.sh API guidelines forbid + # usage of SED's GNU extensions, hence couldn't omit it via regex), strip '\' + # from '\"' & turn '\n' into real LF characters. + # Yup, awful API to use - but that's all we got to get this working, so... ;) + _debug2 'Raw ' "$response" + response="$(printf -- '%s' "$response" + \ | sed 's/^\(.*TXT":"\)\([^,}]*\)\(.*\)$/\2/;s/.$//;s/\\"/"/g;s/\\n/\n/g')" + _debug2 'Clean' "$response" +} + +# Executes an HTTP GET or POST request for getting or setting DNS records, +# containing given payload upon POST. +# Usage: _dns [GET | SET] [payload] +_dns() +{ + action="$1" + payload="$(printf -- '%s' "$2" | _url_encode)" + url="$(printf -- '%s%s' "$AF_URL_DNS" "$domain" + \ | sed 's/{\*}/'"$(printf -- '%s' "$action" | _lower_case)"'/')" + + if [ "$action" = 'SET' ]; then + _debug2 'Payload' "$payload" + response="$(_post '' "$url&TXT=$payload" '' 'POST' 'application/x-www-form-urlencoded')" + else + response="$(_get "$url" '' 10)" + fi + + if ! _contains "$response" "$AF_API_SUCCESS"; then + _err "DNS API error: $response" + + return 1 + fi + + _debug 'Response' "$response" + + return 0 +} + +# Gets the root domain zone for given domain. +# Usage: _get_zone _acme-challenge.www.example.com +_get_zone() +{ + _info 'Getting domain zone...' + _debug2 'Initial FQDN' "$1" + fqdn="$1" + fqdn="${fqdn#*.}" # Strip "_acme-challenge" right away + _debug2 'Reduced FQDN' "$fqdn" + + domains="$(_get "$AF_URL_DOMAINS" '' 10)" + while true; do + if _contains "$domains" "$fqdn"; then + domain="$fqdn" + _info "Found root domain zone: $domain" + break + else + fqdn="${fqdn#*.}" + _debug2 'FQDN' "$fqdn" + fi + done + + if [ "$domain" = "$fqdn" ]; then + return 0 + fi + + _err "Couldn't find root domain zone." + + return 1 +} + +# Adds the HTTP Authorization & Content-Type headers to a follow-up request. +# Usage: _set_headers +_set_headers() +{ + encoded="$(printf -- '%s:%s' "$AF_API_USERNAME" "$AF_API_PASSWORD" | _base64)" + export _H1="Authorization: Basic $encoded" + export _H2='Content-Type: application/json' +} From 72d02f442e2e8528afb04a0e55c88185bb99a7e9 Mon Sep 17 00:00:00 2001 From: Martin Arndt <5111490+Eagle3386@users.noreply.github.com> Date: Sun, 27 Feb 2022 14:35:21 +0100 Subject: [PATCH 02/13] Fix formatting according to Shellcheck --- dnsapi/dns_artfiles.sh | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/dnsapi/dns_artfiles.sh b/dnsapi/dns_artfiles.sh index c857060a..4598854d 100644 --- a/dnsapi/dns_artfiles.sh +++ b/dnsapi/dns_artfiles.sh @@ -95,8 +95,7 @@ dns_artfiles_rm() { # Cleans awful TXT records response of ArtFiles's API & pretty prints it. # Usage: _clean_records -_clean_records() -{ +_clean_records() { # Extract TXT part, strip trailing quote sign (ACME.sh API guidelines forbid # usage of SED's GNU extensions, hence couldn't omit it via regex), strip '\' # from '\"' & turn '\n' into real LF characters. @@ -110,8 +109,7 @@ _clean_records() # Executes an HTTP GET or POST request for getting or setting DNS records, # containing given payload upon POST. # Usage: _dns [GET | SET] [payload] -_dns() -{ +_dns() { action="$1" payload="$(printf -- '%s' "$2" | _url_encode)" url="$(printf -- '%s%s' "$AF_URL_DNS" "$domain" @@ -137,8 +135,7 @@ _dns() # Gets the root domain zone for given domain. # Usage: _get_zone _acme-challenge.www.example.com -_get_zone() -{ +_get_zone() { _info 'Getting domain zone...' _debug2 'Initial FQDN' "$1" fqdn="$1" @@ -168,8 +165,7 @@ _get_zone() # Adds the HTTP Authorization & Content-Type headers to a follow-up request. # Usage: _set_headers -_set_headers() -{ +_set_headers() { encoded="$(printf -- '%s:%s' "$AF_API_USERNAME" "$AF_API_PASSWORD" | _base64)" export _H1="Authorization: Basic $encoded" export _H2='Content-Type: application/json' From 0bea2e2b94e49f59e05c7507bcec548c50a4abac Mon Sep 17 00:00:00 2001 From: Martin Arndt <5111490+Eagle3386@users.noreply.github.com> Date: Sun, 27 Feb 2022 14:37:22 +0100 Subject: [PATCH 03/13] Fix formatting according to Shellcheck 2/2 --- dnsapi/dns_artfiles.sh | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/dnsapi/dns_artfiles.sh b/dnsapi/dns_artfiles.sh index 4598854d..f83ce64a 100644 --- a/dnsapi/dns_artfiles.sh +++ b/dnsapi/dns_artfiles.sh @@ -101,8 +101,9 @@ _clean_records() { # from '\"' & turn '\n' into real LF characters. # Yup, awful API to use - but that's all we got to get this working, so... ;) _debug2 'Raw ' "$response" - response="$(printf -- '%s' "$response" - \ | sed 's/^\(.*TXT":"\)\([^,}]*\)\(.*\)$/\2/;s/.$//;s/\\"/"/g;s/\\n/\n/g')" + response="$( + printf -- '%s' "$response" + \ | sed 's/^\(.*TXT":"\)\([^,}]*\)\(.*\)$/\2/;s/.$//;s/\\"/"/g;s/\\n/\n/g')" _debug2 'Clean' "$response" } @@ -112,8 +113,9 @@ _clean_records() { _dns() { action="$1" payload="$(printf -- '%s' "$2" | _url_encode)" - url="$(printf -- '%s%s' "$AF_URL_DNS" "$domain" - \ | sed 's/{\*}/'"$(printf -- '%s' "$action" | _lower_case)"'/')" + url="$( + printf -- '%s%s' "$AF_URL_DNS" "$domain" + \ | sed 's/{\*}/'"$(printf -- '%s' "$action" | _lower_case)"'/')" if [ "$action" = 'SET' ]; then _debug2 'Payload' "$payload" From fb457968ecae380bc17914f22d134bcfba93d304 Mon Sep 17 00:00:00 2001 From: Martin Arndt <5111490+Eagle3386@users.noreply.github.com> Date: Sun, 27 Feb 2022 14:38:24 +0100 Subject: [PATCH 04/13] Fix formatting according to Shellcheck 3/3 --- dnsapi/dns_artfiles.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_artfiles.sh b/dnsapi/dns_artfiles.sh index f83ce64a..9c1a4338 100644 --- a/dnsapi/dns_artfiles.sh +++ b/dnsapi/dns_artfiles.sh @@ -103,7 +103,8 @@ _clean_records() { _debug2 'Raw ' "$response" response="$( printf -- '%s' "$response" - \ | sed 's/^\(.*TXT":"\)\([^,}]*\)\(.*\)$/\2/;s/.$//;s/\\"/"/g;s/\\n/\n/g')" + \ | sed 's/^\(.*TXT":"\)\([^,}]*\)\(.*\)$/\2/;s/.$//;s/\\"/"/g;s/\\n/\n/g' + )" _debug2 'Clean' "$response" } @@ -115,7 +116,8 @@ _dns() { payload="$(printf -- '%s' "$2" | _url_encode)" url="$( printf -- '%s%s' "$AF_URL_DNS" "$domain" - \ | sed 's/{\*}/'"$(printf -- '%s' "$action" | _lower_case)"'/')" + \ | sed 's/{\*}/'"$(printf -- '%s' "$action" | _lower_case)"'/' + )" if [ "$action" = 'SET' ]; then _debug2 'Payload' "$payload" From ed56d52af309a4d90747169a321dbd3698a4b71a Mon Sep 17 00:00:00 2001 From: Martin Arndt <5111490+Eagle3386@users.noreply.github.com> Date: Sun, 27 Feb 2022 15:12:05 +0100 Subject: [PATCH 05/13] Changed GitHub issues URL --- dnsapi/dns_artfiles.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_artfiles.sh b/dnsapi/dns_artfiles.sh index 9c1a4338..8e0a6151 100644 --- a/dnsapi/dns_artfiles.sh +++ b/dnsapi/dns_artfiles.sh @@ -5,7 +5,7 @@ ################################################################################ # Author: Martin Arndt, https://troublezone.net/ # Released: 2022-02-27 -# Issues: https://github.com/acmesh-official/acme.sh/issues/XXXX +# Issues: https://github.com/Eagle3386/acme.sh/issues ################################################################################ # Usage: # 1. export AF_API_Username="api12345678" From 13c71829485aac03e1d0da98784ea50e983e73cd Mon Sep 17 00:00:00 2001 From: Martin Arndt <5111490+Eagle3386@users.noreply.github.com> Date: Sat, 18 Jun 2022 17:32:56 +0200 Subject: [PATCH 06/13] Fix usage docs in file's header comment --- dnsapi/dns_artfiles.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_artfiles.sh b/dnsapi/dns_artfiles.sh index 8e0a6151..2f8e158f 100644 --- a/dnsapi/dns_artfiles.sh +++ b/dnsapi/dns_artfiles.sh @@ -8,8 +8,8 @@ # Issues: https://github.com/Eagle3386/acme.sh/issues ################################################################################ # Usage: -# 1. export AF_API_Username="api12345678" -# 2. export AF_API_Password="apiPassword" +# 1. export AF_API_USERNAME="api12345678" +# 2. export AF_API_PASSWORD="apiPassword" # 3. acme.sh --issue -d example.com --dns dns_artfiles ################################################################################ From 63fca33b0459b1483c91c38a9ae3060bb6ef621a Mon Sep 17 00:00:00 2001 From: Martin Arndt <5111490+Eagle3386@users.noreply.github.com> Date: Mon, 29 May 2023 20:12:52 +0200 Subject: [PATCH 07/13] Fix retrieval of domain zone --- dnsapi/dns_artfiles.sh | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/dnsapi/dns_artfiles.sh b/dnsapi/dns_artfiles.sh index 2f8e158f..703c02ac 100644 --- a/dnsapi/dns_artfiles.sh +++ b/dnsapi/dns_artfiles.sh @@ -140,14 +140,13 @@ _dns() { # Gets the root domain zone for given domain. # Usage: _get_zone _acme-challenge.www.example.com _get_zone() { - _info 'Getting domain zone...' - _debug2 'Initial FQDN' "$1" fqdn="$1" - fqdn="${fqdn#*.}" # Strip "_acme-challenge" right away - _debug2 'Reduced FQDN' "$fqdn" + domains="$(_get "$AF_URL_DOMAINS" "" 10)" + _info 'Getting domain zone...' + _debug2 'FQDN' "$fqdn" + _debug2 'Domains' "$domains" - domains="$(_get "$AF_URL_DOMAINS" '' 10)" - while true; do + while _contains "$fqdn" "."; do if _contains "$domains" "$fqdn"; then domain="$fqdn" _info "Found root domain zone: $domain" @@ -162,7 +161,7 @@ _get_zone() { return 0 fi - _err "Couldn't find root domain zone." + _err 'Couldn\'t find root domain zone.' return 1 } From fb33ea2a0b6fc8ff260da123709b0872c6b91e79 Mon Sep 17 00:00:00 2001 From: Martin Arndt <5111490+Eagle3386@users.noreply.github.com> Date: Mon, 29 May 2023 20:21:16 +0200 Subject: [PATCH 08/13] Fix single quote escaping --- dnsapi/dns_artfiles.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_artfiles.sh b/dnsapi/dns_artfiles.sh index 703c02ac..ad547e3f 100644 --- a/dnsapi/dns_artfiles.sh +++ b/dnsapi/dns_artfiles.sh @@ -161,7 +161,7 @@ _get_zone() { return 0 fi - _err 'Couldn\'t find root domain zone.' + _err 'Couldn'\''t find root domain zone.' return 1 } From d108072bfbc057f895d29620a8ecd6752ebe47f6 Mon Sep 17 00:00:00 2001 From: Martin Arndt <5111490+Eagle3386@users.noreply.github.com> Date: Tue, 30 May 2023 09:24:17 +0200 Subject: [PATCH 09/13] Add ArtFiles.de DNS API plugin --- dnsapi/dns_artfiles.sh | 175 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 175 insertions(+) create mode 100644 dnsapi/dns_artfiles.sh diff --git a/dnsapi/dns_artfiles.sh b/dnsapi/dns_artfiles.sh new file mode 100644 index 00000000..ad547e3f --- /dev/null +++ b/dnsapi/dns_artfiles.sh @@ -0,0 +1,175 @@ +#!/usr/bin/env sh + +################################################################################ +# ACME.sh 3rd party DNS API plugin for ArtFiles.de +################################################################################ +# Author: Martin Arndt, https://troublezone.net/ +# Released: 2022-02-27 +# Issues: https://github.com/Eagle3386/acme.sh/issues +################################################################################ +# Usage: +# 1. export AF_API_USERNAME="api12345678" +# 2. export AF_API_PASSWORD="apiPassword" +# 3. acme.sh --issue -d example.com --dns dns_artfiles +################################################################################ + +########## API configuration ################################################### +AF_API_SUCCESS='status":"OK' +AF_URL_DCP='https://dcp.c.artfiles.de/api/' +AF_URL_DNS=${AF_URL_DCP}'dns/{*}_dns.html?domain=' +AF_URL_DOMAINS=${AF_URL_BASE}'domain/get_domains.html' + +########## Public functions #################################################### + +# Adds a new TXT record for given ACME challenge value & domain. +# Usage: dns_artfiles_add _acme-challenge.www.example.com "ACME challenge value" +dns_artfiles_add() { + domain="$1" + txtValue="$2" + _info 'Using ArtFiles.de DNS addition API' + _debug 'Domain' "$domain" + _debug 'txtValue' "$txtValue" + + AF_API_USERNAME="${AF_API_USERNAME:-$(_readaccountconf_mutable AF_API_USERNAME)}" + AF_API_PASSWORD="${AF_API_PASSWORD:-$(_readaccountconf_mutable AF_API_PASSWORD)}" + if [ -z "$AF_API_USERNAME" ] || [ -z "$AF_API_PASSWORD" ]; then + _err 'Missing ArtFiles.de username and/or password.' + _err 'Please ensure both are set via export command & try again.' + + return 1 + fi + + _saveaccountconf_mutable 'AF_API_USERNAME' "$AF_API_USERNAME" + _saveaccountconf_mutable 'AF_API_PASSWORD' "$AF_API_PASSWORD" + + _set_headers + _get_zone "$domain" + _dns 'GET' + if ! _contains "$response" 'TXT'; then + _err 'Retrieving TXT records failed.' + + return 1 + fi + + _clean_records + _dns 'SET' "$(printf -- '%s\n_acme-challenge "%s"' "$response" "$txtValue")" + if ! _contains "$response" "$AF_API_SUCCESS"; then + _err 'Adding ACME challenge value failed.' + + return 1 + fi +} + +# Removes the existing TXT record for given ACME challenge value & domain. +# Usage: dns_artfiles_rm _acme-challenge.www.example.com "ACME challenge value" +dns_artfiles_rm() { + domain="$1" + txtValue="$2" + _info 'Using ArtFiles.de DNS removal API' + _debug 'Domain' "$domain" + _debug 'txtValue' "$txtValue" + + _set_headers + _get_zone "$domain" + if ! _dns 'GET'; then + return 1 + fi + + if ! _contains "$response" "$txtValue"; then + _err 'Retrieved TXT records are missing given ACME challenge value.' + + return 1 + fi + + _clean_records + response="$(printf -- '%s' "$response" | sed '$d')" + _dns 'SET' "$response" + if ! _contains "$response" "$AF_API_SUCCESS"; then + _err 'Removing ACME challenge value failed.' + + return 1 + fi +} + +########## Private functions ################################################### + +# Cleans awful TXT records response of ArtFiles's API & pretty prints it. +# Usage: _clean_records +_clean_records() { + # Extract TXT part, strip trailing quote sign (ACME.sh API guidelines forbid + # usage of SED's GNU extensions, hence couldn't omit it via regex), strip '\' + # from '\"' & turn '\n' into real LF characters. + # Yup, awful API to use - but that's all we got to get this working, so... ;) + _debug2 'Raw ' "$response" + response="$( + printf -- '%s' "$response" + \ | sed 's/^\(.*TXT":"\)\([^,}]*\)\(.*\)$/\2/;s/.$//;s/\\"/"/g;s/\\n/\n/g' + )" + _debug2 'Clean' "$response" +} + +# Executes an HTTP GET or POST request for getting or setting DNS records, +# containing given payload upon POST. +# Usage: _dns [GET | SET] [payload] +_dns() { + action="$1" + payload="$(printf -- '%s' "$2" | _url_encode)" + url="$( + printf -- '%s%s' "$AF_URL_DNS" "$domain" + \ | sed 's/{\*}/'"$(printf -- '%s' "$action" | _lower_case)"'/' + )" + + if [ "$action" = 'SET' ]; then + _debug2 'Payload' "$payload" + response="$(_post '' "$url&TXT=$payload" '' 'POST' 'application/x-www-form-urlencoded')" + else + response="$(_get "$url" '' 10)" + fi + + if ! _contains "$response" "$AF_API_SUCCESS"; then + _err "DNS API error: $response" + + return 1 + fi + + _debug 'Response' "$response" + + return 0 +} + +# Gets the root domain zone for given domain. +# Usage: _get_zone _acme-challenge.www.example.com +_get_zone() { + fqdn="$1" + domains="$(_get "$AF_URL_DOMAINS" "" 10)" + _info 'Getting domain zone...' + _debug2 'FQDN' "$fqdn" + _debug2 'Domains' "$domains" + + while _contains "$fqdn" "."; do + if _contains "$domains" "$fqdn"; then + domain="$fqdn" + _info "Found root domain zone: $domain" + break + else + fqdn="${fqdn#*.}" + _debug2 'FQDN' "$fqdn" + fi + done + + if [ "$domain" = "$fqdn" ]; then + return 0 + fi + + _err 'Couldn'\''t find root domain zone.' + + return 1 +} + +# Adds the HTTP Authorization & Content-Type headers to a follow-up request. +# Usage: _set_headers +_set_headers() { + encoded="$(printf -- '%s:%s' "$AF_API_USERNAME" "$AF_API_PASSWORD" | _base64)" + export _H1="Authorization: Basic $encoded" + export _H2='Content-Type: application/json' +} From db8a2d0c653ba19df024c8289942166d7e5bb025 Mon Sep 17 00:00:00 2001 From: Martin Arndt <5111490+Eagle3386@users.noreply.github.com> Date: Wed, 5 Jul 2023 11:05:06 +0200 Subject: [PATCH 10/13] Fix & improve DNS API for ArtFiles.de --- dnsapi/dns_artfiles.sh | 80 ++++++++++++++++++++++++------------------ 1 file changed, 46 insertions(+), 34 deletions(-) diff --git a/dnsapi/dns_artfiles.sh b/dnsapi/dns_artfiles.sh index ad547e3f..6224c416 100644 --- a/dnsapi/dns_artfiles.sh +++ b/dnsapi/dns_artfiles.sh @@ -5,40 +5,34 @@ ################################################################################ # Author: Martin Arndt, https://troublezone.net/ # Released: 2022-02-27 -# Issues: https://github.com/Eagle3386/acme.sh/issues +# Issues: https://github.com/acmesh-official/acme.sh/issues/XXXX ################################################################################ # Usage: -# 1. export AF_API_USERNAME="api12345678" -# 2. export AF_API_PASSWORD="apiPassword" +# 1. export AF_API_USERNAME='api12345678' +# 2. export AF_API_PASSWORD='apiPassword' # 3. acme.sh --issue -d example.com --dns dns_artfiles ################################################################################ ########## API configuration ################################################### + AF_API_SUCCESS='status":"OK' AF_URL_DCP='https://dcp.c.artfiles.de/api/' AF_URL_DNS=${AF_URL_DCP}'dns/{*}_dns.html?domain=' -AF_URL_DOMAINS=${AF_URL_BASE}'domain/get_domains.html' +AF_URL_DOMAINS=${AF_URL_DCP}'domain/get_domains.html' ########## Public functions #################################################### # Adds a new TXT record for given ACME challenge value & domain. # Usage: dns_artfiles_add _acme-challenge.www.example.com "ACME challenge value" -dns_artfiles_add() { +dns_artfiles_add() +{ domain="$1" txtValue="$2" - _info 'Using ArtFiles.de DNS addition API' + _info 'Using ArtFiles.de DNS addition API…' _debug 'Domain' "$domain" _debug 'txtValue' "$txtValue" - AF_API_USERNAME="${AF_API_USERNAME:-$(_readaccountconf_mutable AF_API_USERNAME)}" - AF_API_PASSWORD="${AF_API_PASSWORD:-$(_readaccountconf_mutable AF_API_PASSWORD)}" - if [ -z "$AF_API_USERNAME" ] || [ -z "$AF_API_PASSWORD" ]; then - _err 'Missing ArtFiles.de username and/or password.' - _err 'Please ensure both are set via export command & try again.' - - return 1 - fi - + _set_credentials _saveaccountconf_mutable 'AF_API_USERNAME' "$AF_API_USERNAME" _saveaccountconf_mutable 'AF_API_PASSWORD' "$AF_API_PASSWORD" @@ -62,13 +56,15 @@ dns_artfiles_add() { # Removes the existing TXT record for given ACME challenge value & domain. # Usage: dns_artfiles_rm _acme-challenge.www.example.com "ACME challenge value" -dns_artfiles_rm() { +dns_artfiles_rm() +{ domain="$1" txtValue="$2" - _info 'Using ArtFiles.de DNS removal API' + _info 'Using ArtFiles.de DNS removal API…' _debug 'Domain' "$domain" _debug 'txtValue' "$txtValue" + _set_credentials _set_headers _get_zone "$domain" if ! _dns 'GET'; then @@ -95,29 +91,28 @@ dns_artfiles_rm() { # Cleans awful TXT records response of ArtFiles's API & pretty prints it. # Usage: _clean_records -_clean_records() { +_clean_records() +{ + _info 'Cleaning TXT records…' # Extract TXT part, strip trailing quote sign (ACME.sh API guidelines forbid # usage of SED's GNU extensions, hence couldn't omit it via regex), strip '\' # from '\"' & turn '\n' into real LF characters. - # Yup, awful API to use - but that's all we got to get this working, so... ;) + # Yup, awful API to use - but that's all we got to get this working, so… ;) _debug2 'Raw ' "$response" - response="$( - printf -- '%s' "$response" - \ | sed 's/^\(.*TXT":"\)\([^,}]*\)\(.*\)$/\2/;s/.$//;s/\\"/"/g;s/\\n/\n/g' - )" + + response="$(printf -- '%s' "$response" | sed 's/^.*TXT":"\([^}]*\).*$/\1/;s/,".*$//;s/.$//;s/\\"/"/g;s/\\n/\n/g')" _debug2 'Clean' "$response" } # Executes an HTTP GET or POST request for getting or setting DNS records, # containing given payload upon POST. # Usage: _dns [GET | SET] [payload] -_dns() { +_dns() +{ + _info 'Executing HTTP request…' action="$1" payload="$(printf -- '%s' "$2" | _url_encode)" - url="$( - printf -- '%s%s' "$AF_URL_DNS" "$domain" - \ | sed 's/{\*}/'"$(printf -- '%s' "$action" | _lower_case)"'/' - )" + url="$(printf -- '%s%s' "$AF_URL_DNS" "$domain" | sed 's/{\*}/'"$(printf -- '%s' "$action" | _lower_case)"'/')" if [ "$action" = 'SET' ]; then _debug2 'Payload' "$payload" @@ -139,10 +134,11 @@ _dns() { # Gets the root domain zone for given domain. # Usage: _get_zone _acme-challenge.www.example.com -_get_zone() { +_get_zone() +{ fqdn="$1" - domains="$(_get "$AF_URL_DOMAINS" "" 10)" - _info 'Getting domain zone...' + domains="$(_get "$AF_URL_DOMAINS" '' 10)" + _info 'Getting domain zone…' _debug2 'FQDN' "$fqdn" _debug2 'Domains' "$domains" @@ -166,10 +162,26 @@ _get_zone() { return 1 } +# Sets the credentials for accessing ArtFiles's API +# Usage: _set_credentials +_set_credentials() +{ + _info 'Setting credentials…' + AF_API_USERNAME="${AF_API_USERNAME:-$(_readaccountconf_mutable AF_API_USERNAME)}" + AF_API_PASSWORD="${AF_API_PASSWORD:-$(_readaccountconf_mutable AF_API_PASSWORD)}" + if [ -z "$AF_API_USERNAME" ] || [ -z "$AF_API_PASSWORD" ]; then + _err 'Missing ArtFiles.de username and/or password.' + _err 'Please ensure both are set via export command & try again.' + + return 1 + fi +} + # Adds the HTTP Authorization & Content-Type headers to a follow-up request. # Usage: _set_headers -_set_headers() { - encoded="$(printf -- '%s:%s' "$AF_API_USERNAME" "$AF_API_PASSWORD" | _base64)" - export _H1="Authorization: Basic $encoded" +_set_headers() +{ + _info 'Setting headers…' + export _H1="$(printf -- 'Authorization: Basic %s:%s' "$AF_API_USERNAME" "$AF_API_PASSWORD" | _base64)" export _H2='Content-Type: application/json' } From 2961a90e7ffb37ad498a8d841d00dbb2a08d251c Mon Sep 17 00:00:00 2001 From: Martin Arndt <5111490+Eagle3386@users.noreply.github.com> Date: Wed, 5 Jul 2023 11:14:49 +0200 Subject: [PATCH 11/13] Make ShellCheck & ShellFormat happy --- dnsapi/dns_artfiles.sh | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/dnsapi/dns_artfiles.sh b/dnsapi/dns_artfiles.sh index 6224c416..04cdf026 100644 --- a/dnsapi/dns_artfiles.sh +++ b/dnsapi/dns_artfiles.sh @@ -24,8 +24,7 @@ AF_URL_DOMAINS=${AF_URL_DCP}'domain/get_domains.html' # Adds a new TXT record for given ACME challenge value & domain. # Usage: dns_artfiles_add _acme-challenge.www.example.com "ACME challenge value" -dns_artfiles_add() -{ +dns_artfiles_add() { domain="$1" txtValue="$2" _info 'Using ArtFiles.de DNS addition API…' @@ -56,8 +55,7 @@ dns_artfiles_add() # Removes the existing TXT record for given ACME challenge value & domain. # Usage: dns_artfiles_rm _acme-challenge.www.example.com "ACME challenge value" -dns_artfiles_rm() -{ +dns_artfiles_rm() { domain="$1" txtValue="$2" _info 'Using ArtFiles.de DNS removal API…' @@ -91,15 +89,13 @@ dns_artfiles_rm() # Cleans awful TXT records response of ArtFiles's API & pretty prints it. # Usage: _clean_records -_clean_records() -{ +_clean_records() { _info 'Cleaning TXT records…' # Extract TXT part, strip trailing quote sign (ACME.sh API guidelines forbid # usage of SED's GNU extensions, hence couldn't omit it via regex), strip '\' # from '\"' & turn '\n' into real LF characters. # Yup, awful API to use - but that's all we got to get this working, so… ;) _debug2 'Raw ' "$response" - response="$(printf -- '%s' "$response" | sed 's/^.*TXT":"\([^}]*\).*$/\1/;s/,".*$//;s/.$//;s/\\"/"/g;s/\\n/\n/g')" _debug2 'Clean' "$response" } @@ -107,8 +103,7 @@ _clean_records() # Executes an HTTP GET or POST request for getting or setting DNS records, # containing given payload upon POST. # Usage: _dns [GET | SET] [payload] -_dns() -{ +_dns() { _info 'Executing HTTP request…' action="$1" payload="$(printf -- '%s' "$2" | _url_encode)" @@ -134,8 +129,7 @@ _dns() # Gets the root domain zone for given domain. # Usage: _get_zone _acme-challenge.www.example.com -_get_zone() -{ +_get_zone() { fqdn="$1" domains="$(_get "$AF_URL_DOMAINS" '' 10)" _info 'Getting domain zone…' @@ -164,8 +158,7 @@ _get_zone() # Sets the credentials for accessing ArtFiles's API # Usage: _set_credentials -_set_credentials() -{ +_set_credentials() { _info 'Setting credentials…' AF_API_USERNAME="${AF_API_USERNAME:-$(_readaccountconf_mutable AF_API_USERNAME)}" AF_API_PASSWORD="${AF_API_PASSWORD:-$(_readaccountconf_mutable AF_API_PASSWORD)}" @@ -179,9 +172,9 @@ _set_credentials() # Adds the HTTP Authorization & Content-Type headers to a follow-up request. # Usage: _set_headers -_set_headers() -{ +_set_headers() { _info 'Setting headers…' - export _H1="$(printf -- 'Authorization: Basic %s:%s' "$AF_API_USERNAME" "$AF_API_PASSWORD" | _base64)" + encoded="$(printf -- '%s:%s' "$AF_API_USERNAME" "$AF_API_PASSWORD" | _base64)" + export _H1="Authorization: Basic $encoded" export _H2='Content-Type: application/json' } From 8b3acb719eb6eee82ef40edff94ed2372ecdc1df Mon Sep 17 00:00:00 2001 From: Martin Arndt <5111490+Eagle3386@users.noreply.github.com> Date: Wed, 5 Jul 2023 13:04:08 +0200 Subject: [PATCH 12/13] Fix TXT record removal --- dnsapi/dns_artfiles.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_artfiles.sh b/dnsapi/dns_artfiles.sh index 04cdf026..faf8c2ae 100644 --- a/dnsapi/dns_artfiles.sh +++ b/dnsapi/dns_artfiles.sh @@ -76,7 +76,7 @@ dns_artfiles_rm() { fi _clean_records - response="$(printf -- '%s' "$response" | sed '$d')" + response="$(printf -- '%s' "$response" | sed '/_acme-challenge "'"$txtValue"'"/d')" _dns 'SET' "$response" if ! _contains "$response" "$AF_API_SUCCESS"; then _err 'Removing ACME challenge value failed.' From 80006f47300bd0559729a2800ae014475f7499ce Mon Sep 17 00:00:00 2001 From: Martin Arndt <5111490+Eagle3386@users.noreply.github.com> Date: Sat, 29 Jul 2023 10:26:59 +0200 Subject: [PATCH 13/13] Added bug report url --- dnsapi/dns_artfiles.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_artfiles.sh b/dnsapi/dns_artfiles.sh index faf8c2ae..a762837e 100644 --- a/dnsapi/dns_artfiles.sh +++ b/dnsapi/dns_artfiles.sh @@ -5,7 +5,7 @@ ################################################################################ # Author: Martin Arndt, https://troublezone.net/ # Released: 2022-02-27 -# Issues: https://github.com/acmesh-official/acme.sh/issues/XXXX +# Issues: https://github.com/acmesh-official/acme.sh/issues/4718 ################################################################################ # Usage: # 1. export AF_API_USERNAME='api12345678'