From c236073832867dd1e2488d2744d867eea2765cc5 Mon Sep 17 00:00:00 2001 From: mxtuma <71069082+mxtuma@users.noreply.github.com> Date: Fri, 11 Sep 2020 10:09:30 +0200 Subject: [PATCH 01/10] New DNS API for WEDOS provider New DNS API implementation for acme.sh script use WEDOS's WAPI XML interface to manage domain TXT entries. Both add and remove methods works. The code were tested successfully and spellchecked too. It seems there is no issue at all. The script skeleton from cloudfare were used. --- dnsapi/dns_wedos.sh | 371 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 371 insertions(+) create mode 100644 dnsapi/dns_wedos.sh diff --git a/dnsapi/dns_wedos.sh b/dnsapi/dns_wedos.sh new file mode 100644 index 00000000..ec1598e1 --- /dev/null +++ b/dnsapi/dns_wedos.sh @@ -0,0 +1,371 @@ +#!/usr/bin/env sh + +# This script has been created at June 2020, based on knowledge base of wedos.com provider. +# It is intended to allow DNS-01 challenges for acme.sh using wedos's WAPI using XML. + +# Author Michal Tuma +# For issues send me an email + +WEDOS_WAPI_ENDPOINT="https://api.wedos.com/wapi/xml" +TESTING_STAGE= + +######## Public functions ##################### + +#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_wedos_add() { + fulldomain=$1 + txtvalue=$2 + + WEDOS_Username="${WEDOS_Username:-$(_readaccountconf_mutable WEDOS_Username)}" + WEDOS_Wapipass="${WEDOS_Wapipass:-$(_readaccountconf_mutable WEDOS_Wapipass)}" + WEDOS_Authtoken="${WEDOS_Authtoken:-$(_readaccountconf_mutable WEDOS_Authtoken)}" + + if [ "${WEDOS_Authtoken}" ]; then + _debug "WEDOS Authtoken was already saved, using saved one" + _saveaccountconf_mutable WEDOS_Authtoken "${WEDOS_Authtoken}" + else + if [ -z "${WEDOS_Username}" ] || [ -z "${WEDOS_Wapipass}" ]; then + WEDOS_Username="" + WEDOS_Wapipass="" + _err "You didn't specify a WEDOS's username and wapi key yet." + _err "Please type: export WEDOS_Username=" + _err "And: export WEDOS_Wapipass=" + _err "After you export those variables, run the script again, the values will be saved for future" + return 1 + fi + + #build WEDOS_Authtoken + _debug "WEDOS Authtoken were not saved yet, building" + WEDOS_Authtoken=$(printf '%s' "${WEDOS_Wapipass}" | sha1sum | head -c 40) + _debug "WEDOS_Authtoken step 1, WAPI PASS sha1 sum: '${WEDOS_Authtoken}'" + WEDOS_Authtoken="${WEDOS_Username}${WEDOS_Authtoken}" + _debug "WEDOS_Authtoken step 2, username concat with token without hours: '${WEDOS_Authtoken}'" + + #save details + + _saveaccountconf_mutable WEDOS_Username "${WEDOS_Username}" + _saveaccountconf_mutable WEDOS_Wapipass "${WEDOS_Wapipass}" + _saveaccountconf_mutable WEDOS_Authtoken "${WEDOS_Authtoken}" + fi + + if ! _get_root "${fulldomain}"; then + _err "WEDOS Account do not contain primary domain to fullfill add of ${fulldomain}!" + return 1 + fi + + _debug _sub_domain "${_sub_domain}" + _debug _domain "${_domain}" + + if _wapi_row_add "${_domain}" "${_sub_domain}" "${txtvalue}" "300"; then + _info "WEDOS WAPI: dns record added and dns changes were commited" + return 0 + else + _err "FAILED TO ADD DNS RECORD OR COMMIT DNS CHANGES" + return 1 + fi +} + +#fulldomain txtvalue +dns_wedos_rm() { + fulldomain=$1 + txtvalue=$2 + + WEDOS_Username="${WEDOS_Username:-$(_readaccountconf_mutable WEDOS_Username)}" + WEDOS_Wapipass="${WEDOS_Wapipass:-$(_readaccountconf_mutable WEDOS_Wapipass)}" + WEDOS_Authtoken="${WEDOS_Authtoken:-$(_readaccountconf_mutable WEDOS_Authtoken)}" + + if [ "${WEDOS_Authtoken}" ]; then + _debug "WEDOS Authtoken was already saved, using saved one" + _saveaccountconf_mutable WEDOS_Authtoken "${WEDOS_Authtoken}" + else + if [ -z "${WEDOS_Username}" ] || [ -z "${WEDOS_Wapipass}" ]; then + WEDOS_Username="" + WEDOS_Wapipass="" + _err "You didn't specify a WEDOS's username and wapi key yet." + _err "Please type: export WEDOS_Username=" + _err "And: export WEDOS_Wapipass=" + _err "After you export those variables, run the script again, the values will be saved for future" + return 1 + fi + + #build WEDOS_Authtoken + _debug "WEDOS Authtoken were not saved yet, building" + WEDOS_Authtoken=$(printf '%s' "${WEDOS_Wapipass}" | sha1sum | head -c 40) + _debug "WEDOS_Authtoken step 1, WAPI PASS sha1 sum: '${WEDOS_Authtoken}'" + WEDOS_Authtoken="${WEDOS_Username}${WEDOS_Authtoken}" + _debug "WEDOS_Authtoken step 2, username concat with token without hours: '${WEDOS_Authtoken}'" + + #save details + + _saveaccountconf_mutable WEDOS_Username "${WEDOS_Username}" + _saveaccountconf_mutable WEDOS_Wapipass "${WEDOS_Wapipass}" + _saveaccountconf_mutable WEDOS_Authtoken "${WEDOS_Authtoken}" + fi + + + if ! _get_root "${fulldomain}"; then + _err "WEDOS Account do not contain primary domain to fullfill add of ${fulldomain}!" + return 1 + fi + + _debug _sub_domain "${_sub_domain}" + _debug _domain "${_domain}" + + if _wapi_find_row "${_domain}" "${_sub_domain}" "${txtvalue}"; then + _info "WEDOS WAPI: dns record found with id '${_row_id}'" + + if _wapi_delete_row "${_domain}" "${_row_id}"; then + _info "WEDOS WAPI: dns row were deleted and changes commited!" + return 0 + fi + fi + + + _err "Requested dns row were not found or was imposible to delete it, do it manually" + _err "Delete: ${fulldomain}" + _err "Value: ${txtvalue}" + return 1 +} + +#################### Private functions below ################################## + +# Function _wapi_post(), only takes data, prepares auth token and provide result +# $1 - WAPI command string, like 'dns-domains-list' +# $2 - WAPI data for given command, is not required +# returns WAPI response if request were successfully delivered to WAPI endpoint +_wapi_post() { + command=$1 + data=$2 + + _debug "Command : ${command}" + _debug "Data : ${data}" + + if [ -z "${command}" ]; then + _err "No command were provided, implamantation error!" + return 1 + fi + + # Prepare authentification token + hour=$(date +%H) + token=$(printf '%s' "${WEDOS_Authtoken}${hour}" | sha1sum | head -c 40) + _debug "Authentification token is '${token}'" + + # Build xml request + + request="request=\ +\ + ${WEDOS_Username}\ + ${token}\ + ${command}" + + if [ -z "${data}" ]; then + echo "" 1>/dev/null + else + request="${request}${data}" + fi + + if [ -z "$TESTING_STAGE" ]; then + echo "" 1>/dev/null + else + request="${request}\ + 1" + fi + + request="${request}\ +" + + _debug "Request to WAPI is: ${request}" + + if ! response="$(_post "${request}" "$WEDOS_WAPI_ENDPOINT")"; then + _err "Error contacting WEDOS WAPI with command ${command}" + return 1 + fi + + _debug "Response : ${response}" + echo "${response}" | grep "1000" 1>/dev/null 2>/dev/null + + return "$?" +} + + +# _get_root() function, for provided full domain, like _acme_challenge.www.example.com verify if WEDOS contains a primary active domain and found what is subdomain +# $1 - full domain to verify, ie _acme_challenge.www.example.com +# build ${_domain} found at WEDOS, like example.com and ${_sub_domain} from provided full domain, like _acme_challenge.www +_get_root() { + domain=$1 + + if [ -z "${domain}" ]; then + _err "Function _get_root was called without argument, implementation error!" + return 1; + fi + + _debug "Get root for domain: ${domain}" + + _debug "Getting list of domains using WAPI ..." + + if ! _wapi_post "dns-domains-list"; then + _err "Error on WAPI request for list of domains, response : ${response}" + return 1 + else + _debug "DNS list were successfully retrieved, response : ${response}" + fi + + for xml_domain in $(echo "${response}" | tr -d '\012\015' | grep -o -E "( )*.*( )*primary( )*active" | grep -o -E ".*") + do + _debug "Active and primary XML DOMAIN found: ${xml_domain}" + end_of_name=$((${#xml_domain} - 7)) + xml_domain_name=$(echo "${xml_domain}" | cut -c 7-${end_of_name}) + _debug "Found primary active domain: ${xml_domain_name}" + regex=".*\\."$(echo "${xml_domain_name}" | sed 's/\./\\./g') + _debug "Regex for matching domain: '${regex}'" + + if ! echo "${domain}" | grep -E "${regex}" 1>/dev/null 2>/dev/null; then + _debug "found domain do not match required" + else + end_of_name=$((${#domain} - ${#xml_domain_name} - 1)) + _domain=${xml_domain_name} + _sub_domain=$(echo "${domain}" | cut -c -${end_of_name}) + _info "Domain '${_domain}' was found at WEDOS account as primary, and subdomain is '${_sub_domain}'!" + return 0 + fi + done + + return 1 +} + +# for provided domain, it commites all performed changes +_wapi_dns_commit() { + domain=$1 + + if [ -z "${domain}" ]; then + _err "Invalid request to commit dns changes, domain is empty, implementation error!" + return 1; + fi + + data=" \ + ${domain}\ + " + + if ! _wapi_post "dns-domain-commit" "${data}"; then + _err "Error on WAPI request to commit DNS changes, response : ${response}" + _err "PLEASE USE WEB ACCESS TO CHECK IF CHANGES ARE REQUIRED TO COMMIT OR ROLLBACKED IMMEDIATELLY!" + return 1 + else + _debug "DNS CHANGES COMMITED, response : ${response}" + _info "WEDOS DNS WAPI: Changes were commited to domain '${domain}'" + fi + + return 0 + +} + +# add one TXT dns row to a specified fomain +_wapi_row_add() { + domain=$1 + sub_domain=$2 + value=$3 + ttl=$4 + + if [ -z "${domain}" ] || [ -z "${sub_domain}" ] || [ -z "${value}" ] || [ -z "${ttl}" ]; then + _err "Invalid request to add record, domain: '${domain}', sub_domain: '${sub_domain}', value: '${value}' and ttl: '${ttl}', on of required input were not provided, implementation error!" + return 1; + fi + + # Prepare data for request to WAPI + data=" \ + ${domain}\ + ${sub_domain}\ + ${ttl}\ + TXT\ + ${value}\ + Created using WAPI from acme.sh\ + " + + _debug "Adding row using WAPI ..." + + if ! _wapi_post "dns-row-add" "${data}"; then + _err "Error on WAPI request to add new TXT row, response : ${response}" + return 1 + else + _debug "ROW ADDED, response : ${response}" + _info "WEDOS DNS WAPI: Row to domain '${domain}' with name '${sub_domain}' were successfully added with value '${value}' and ttl set to ${ttl}" + fi + + # Now we have to commit + _wapi_dns_commit "${domain}" + + return "$?" + +} + +_wapi_find_row() { + domain=$1 + sub_domain=$2 + value=$3 + + if [ -z "${domain}" ] || [ -z "${sub_domain}" ] || [ -z "${value}" ]; then + _err "Invalud request to finad a row, domain: '${domain}', sub_domain: '${sub_domain}' and value: '${value}', one of required input were not provided, implementation error!" + return 1 + fi + + data=" \ + ${domain}\ + " + + _debug "Searching rows using WAPI ..." + + if ! _wapi_post "dns-rows-list" "${data}"; then + _err "Error on WAPI request to list domain rows, response : ${response}" + return 1 + fi + + _debug "Domain rows found, response : ${response}" + + sub_domain_regex=$(echo "${sub_domain}" | sed "s/\./\\\\./g") + + _debug "Subdomain regex '${sub_domain_regex}'" + + for xml_row in $(echo "${response}" | tr -d '\012\015' | grep -o -E "( )*[0-9]*( )*${sub_domain_regex}( )*[0-9]*( )*TXT( )*${value}" | grep -o -e "[0-9]*") + do + _debug "Found row in DNS with ID : ${xml_row}" + _row_id=$(echo "${xml_row}" | grep -o -E "[0-9]*") + _info "WEDOS API: Found DNS row id ${_row_id} for domain ${domain}" + return 0 + done + + _info "WEDOS API: No TXT row found for domain '${domain}' with name '${sub_domain}' and value '${value}'" + + return 1 +} + +_wapi_delete_row() { + domain=$1 + row_id=$2 + + if [ -z "${domain}" ] || [ -z "${row_id}" ]; then + _err "Invalid request to delete domain dns row, domain: '${domain}' and row_id: '${row_id}', one of required input were not provided, implementation error!" + return 1 + fi + + data=" \ + ${domain} + ${row_id} +" + + _debug "Deleting dns row using WAPI ..." + + if ! _wapi_post "dns-row-delete" "${data}"; then + _err "Error on WAPI request to delete dns row, response: ${response}" + return 1 + fi + + _debug "DNS row were deleted, response: ${response}" + + _info "WEDOS API: Required dns domain row with row_id '${row_id}' were correctly deleted at domain '${domain}'" + + # Now we have to commit changes + _wapi_dns_commit "${domain}" + + return "$?" + +} From ecbc48466f1c53ed48d3016448de54f5deeb2478 Mon Sep 17 00:00:00 2001 From: mxtuma <71069082+mxtuma@users.noreply.github.com> Date: Fri, 11 Sep 2020 11:08:58 +0200 Subject: [PATCH 02/10] Formating of the script based of shfmt Previous version failed at acme.sh on shfmt. --- dnsapi/dns_wedos.sh | 49 ++++++++++++++++++++------------------------- 1 file changed, 22 insertions(+), 27 deletions(-) diff --git a/dnsapi/dns_wedos.sh b/dnsapi/dns_wedos.sh index ec1598e1..4ad8eaa1 100644 --- a/dnsapi/dns_wedos.sh +++ b/dnsapi/dns_wedos.sh @@ -42,7 +42,7 @@ dns_wedos_add() { _debug "WEDOS_Authtoken step 2, username concat with token without hours: '${WEDOS_Authtoken}'" #save details - + _saveaccountconf_mutable WEDOS_Username "${WEDOS_Username}" _saveaccountconf_mutable WEDOS_Wapipass "${WEDOS_Wapipass}" _saveaccountconf_mutable WEDOS_Authtoken "${WEDOS_Authtoken}" @@ -62,7 +62,7 @@ dns_wedos_add() { else _err "FAILED TO ADD DNS RECORD OR COMMIT DNS CHANGES" return 1 - fi + fi } #fulldomain txtvalue @@ -102,7 +102,6 @@ dns_wedos_rm() { _saveaccountconf_mutable WEDOS_Authtoken "${WEDOS_Authtoken}" fi - if ! _get_root "${fulldomain}"; then _err "WEDOS Account do not contain primary domain to fullfill add of ${fulldomain}!" return 1 @@ -113,14 +112,13 @@ dns_wedos_rm() { if _wapi_find_row "${_domain}" "${_sub_domain}" "${txtvalue}"; then _info "WEDOS WAPI: dns record found with id '${_row_id}'" - + if _wapi_delete_row "${_domain}" "${_row_id}"; then _info "WEDOS WAPI: dns row were deleted and changes commited!" return 0 - fi + fi fi - _err "Requested dns row were not found or was imposible to delete it, do it manually" _err "Delete: ${fulldomain}" _err "Value: ${txtvalue}" @@ -174,8 +172,8 @@ _wapi_post() { request="${request}\ " - _debug "Request to WAPI is: ${request}" - + _debug "Request to WAPI is: ${request}" + if ! response="$(_post "${request}" "$WEDOS_WAPI_ENDPOINT")"; then _err "Error contacting WEDOS WAPI with command ${command}" return 1 @@ -187,22 +185,21 @@ _wapi_post() { return "$?" } - # _get_root() function, for provided full domain, like _acme_challenge.www.example.com verify if WEDOS contains a primary active domain and found what is subdomain # $1 - full domain to verify, ie _acme_challenge.www.example.com -# build ${_domain} found at WEDOS, like example.com and ${_sub_domain} from provided full domain, like _acme_challenge.www +# build ${_domain} found at WEDOS, like example.com and ${_sub_domain} from provided full domain, like _acme_challenge.www _get_root() { domain=$1 if [ -z "${domain}" ]; then _err "Function _get_root was called without argument, implementation error!" - return 1; + return 1 fi _debug "Get root for domain: ${domain}" _debug "Getting list of domains using WAPI ..." - + if ! _wapi_post "dns-domains-list"; then _err "Error on WAPI request for list of domains, response : ${response}" return 1 @@ -210,25 +207,24 @@ _get_root() { _debug "DNS list were successfully retrieved, response : ${response}" fi - for xml_domain in $(echo "${response}" | tr -d '\012\015' | grep -o -E "( )*.*( )*primary( )*active" | grep -o -E ".*") - do + for xml_domain in $(echo "${response}" | tr -d '\012\015' | grep -o -E "( )*.*( )*primary( )*active" | grep -o -E ".*"); do _debug "Active and primary XML DOMAIN found: ${xml_domain}" end_of_name=$((${#xml_domain} - 7)) xml_domain_name=$(echo "${xml_domain}" | cut -c 7-${end_of_name}) - _debug "Found primary active domain: ${xml_domain_name}" + _debug "Found primary active domain: ${xml_domain_name}" regex=".*\\."$(echo "${xml_domain_name}" | sed 's/\./\\./g') _debug "Regex for matching domain: '${regex}'" - + if ! echo "${domain}" | grep -E "${regex}" 1>/dev/null 2>/dev/null; then _debug "found domain do not match required" - else + else end_of_name=$((${#domain} - ${#xml_domain_name} - 1)) _domain=${xml_domain_name} _sub_domain=$(echo "${domain}" | cut -c -${end_of_name}) _info "Domain '${_domain}' was found at WEDOS account as primary, and subdomain is '${_sub_domain}'!" return 0 fi - done + done return 1 } @@ -239,7 +235,7 @@ _wapi_dns_commit() { if [ -z "${domain}" ]; then _err "Invalid request to commit dns changes, domain is empty, implementation error!" - return 1; + return 1 fi data=" \ @@ -256,7 +252,7 @@ _wapi_dns_commit() { fi return 0 - + } # add one TXT dns row to a specified fomain @@ -268,7 +264,7 @@ _wapi_row_add() { if [ -z "${domain}" ] || [ -z "${sub_domain}" ] || [ -z "${value}" ] || [ -z "${ttl}" ]; then _err "Invalid request to add record, domain: '${domain}', sub_domain: '${sub_domain}', value: '${value}' and ttl: '${ttl}', on of required input were not provided, implementation error!" - return 1; + return 1 fi # Prepare data for request to WAPI @@ -280,7 +276,7 @@ _wapi_row_add() { ${value}\ Created using WAPI from acme.sh\ " - + _debug "Adding row using WAPI ..." if ! _wapi_post "dns-row-add" "${data}"; then @@ -324,19 +320,18 @@ _wapi_find_row() { sub_domain_regex=$(echo "${sub_domain}" | sed "s/\./\\\\./g") _debug "Subdomain regex '${sub_domain_regex}'" - - for xml_row in $(echo "${response}" | tr -d '\012\015' | grep -o -E "( )*[0-9]*( )*${sub_domain_regex}( )*[0-9]*( )*TXT( )*${value}" | grep -o -e "[0-9]*") - do + + for xml_row in $(echo "${response}" | tr -d '\012\015' | grep -o -E "( )*[0-9]*( )*${sub_domain_regex}( )*[0-9]*( )*TXT( )*${value}" | grep -o -e "[0-9]*"); do _debug "Found row in DNS with ID : ${xml_row}" _row_id=$(echo "${xml_row}" | grep -o -E "[0-9]*") _info "WEDOS API: Found DNS row id ${_row_id} for domain ${domain}" return 0 done - _info "WEDOS API: No TXT row found for domain '${domain}' with name '${sub_domain}' and value '${value}'" + _info "WEDOS API: No TXT row found for domain '${domain}' with name '${sub_domain}' and value '${value}'" return 1 -} +} _wapi_delete_row() { domain=$1 From 55f9c4d2cc6b5b3919fae18b6e394135aa9324b7 Mon Sep 17 00:00:00 2001 From: mxtuma <71069082+mxtuma@users.noreply.github.com> Date: Thu, 19 Nov 2020 15:55:28 +0100 Subject: [PATCH 03/10] Fix review issues All "reviewed functions" replaced with acme.sh functions. Added time zone for authentication token. Fix all XML list search with proper descriptions. --- dnsapi/dns_wedos.sh | 537 +++++++++++++++++++++++--------------------- 1 file changed, 281 insertions(+), 256 deletions(-) diff --git a/dnsapi/dns_wedos.sh b/dnsapi/dns_wedos.sh index 4ad8eaa1..0102bb3a 100644 --- a/dnsapi/dns_wedos.sh +++ b/dnsapi/dns_wedos.sh @@ -13,116 +13,116 @@ TESTING_STAGE= #Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_wedos_add() { - fulldomain=$1 - txtvalue=$2 - - WEDOS_Username="${WEDOS_Username:-$(_readaccountconf_mutable WEDOS_Username)}" - WEDOS_Wapipass="${WEDOS_Wapipass:-$(_readaccountconf_mutable WEDOS_Wapipass)}" - WEDOS_Authtoken="${WEDOS_Authtoken:-$(_readaccountconf_mutable WEDOS_Authtoken)}" - - if [ "${WEDOS_Authtoken}" ]; then - _debug "WEDOS Authtoken was already saved, using saved one" - _saveaccountconf_mutable WEDOS_Authtoken "${WEDOS_Authtoken}" - else - if [ -z "${WEDOS_Username}" ] || [ -z "${WEDOS_Wapipass}" ]; then - WEDOS_Username="" - WEDOS_Wapipass="" - _err "You didn't specify a WEDOS's username and wapi key yet." - _err "Please type: export WEDOS_Username=" - _err "And: export WEDOS_Wapipass=" - _err "After you export those variables, run the script again, the values will be saved for future" - return 1 - fi - - #build WEDOS_Authtoken - _debug "WEDOS Authtoken were not saved yet, building" - WEDOS_Authtoken=$(printf '%s' "${WEDOS_Wapipass}" | sha1sum | head -c 40) - _debug "WEDOS_Authtoken step 1, WAPI PASS sha1 sum: '${WEDOS_Authtoken}'" - WEDOS_Authtoken="${WEDOS_Username}${WEDOS_Authtoken}" - _debug "WEDOS_Authtoken step 2, username concat with token without hours: '${WEDOS_Authtoken}'" - - #save details - - _saveaccountconf_mutable WEDOS_Username "${WEDOS_Username}" - _saveaccountconf_mutable WEDOS_Wapipass "${WEDOS_Wapipass}" - _saveaccountconf_mutable WEDOS_Authtoken "${WEDOS_Authtoken}" - fi - - if ! _get_root "${fulldomain}"; then - _err "WEDOS Account do not contain primary domain to fullfill add of ${fulldomain}!" - return 1 - fi - - _debug _sub_domain "${_sub_domain}" - _debug _domain "${_domain}" - - if _wapi_row_add "${_domain}" "${_sub_domain}" "${txtvalue}" "300"; then - _info "WEDOS WAPI: dns record added and dns changes were commited" - return 0 - else - _err "FAILED TO ADD DNS RECORD OR COMMIT DNS CHANGES" - return 1 - fi + fulldomain=$1 + txtvalue=$2 + + WEDOS_Username="${WEDOS_Username:-$(_readaccountconf_mutable WEDOS_Username)}" + WEDOS_Wapipass="${WEDOS_Wapipass:-$(_readaccountconf_mutable WEDOS_Wapipass)}" + WEDOS_Authtoken="${WEDOS_Authtoken:-$(_readaccountconf_mutable WEDOS_Authtoken)}" + + if [ "${WEDOS_Authtoken}" ]; then + _debug "WEDOS Authtoken was already saved, using saved one" + _saveaccountconf_mutable WEDOS_Authtoken "${WEDOS_Authtoken}" + else + if [ -z "${WEDOS_Username}" ] || [ -z "${WEDOS_Wapipass}" ]; then + WEDOS_Username="" + WEDOS_Wapipass="" + _err "You didn't specify a WEDOS's username and wapi key yet." + _err "Please type: export WEDOS_Username=" + _err "And: export WEDOS_Wapipass=" + _err "After you export those variables, run the script again, the values will be saved for future" + return 1 + fi + + #build WEDOS_Authtoken + _debug "WEDOS Authtoken were not saved yet, building" + WEDOS_Authtoken=$(printf '%s' "${WEDOS_Wapipass}" | _digest "sha1" "true" | head -c 40) + _debug "WEDOS_Authtoken step 1, WAPI PASS sha1 sum: '${WEDOS_Authtoken}'" + WEDOS_Authtoken="${WEDOS_Username}${WEDOS_Authtoken}" + _debug "WEDOS_Authtoken step 2, username concat with token without hours: '${WEDOS_Authtoken}'" + + #save details + + _saveaccountconf_mutable WEDOS_Username "${WEDOS_Username}" + _saveaccountconf_mutable WEDOS_Wapipass "${WEDOS_Wapipass}" + _saveaccountconf_mutable WEDOS_Authtoken "${WEDOS_Authtoken}" + fi + + if ! _get_root "${fulldomain}"; then + _err "WEDOS Account do not contain primary domain to fullfill add of ${fulldomain}!" + return 1 + fi + + _debug _sub_domain "${_sub_domain}" + _debug _domain "${_domain}" + + if _wapi_row_add "${_domain}" "${_sub_domain}" "${txtvalue}" "300"; then + _info "WEDOS WAPI: dns record added and dns changes were commited" + return 0 + else + _err "FAILED TO ADD DNS RECORD OR COMMIT DNS CHANGES" + return 1 + fi } #fulldomain txtvalue dns_wedos_rm() { - fulldomain=$1 - txtvalue=$2 - - WEDOS_Username="${WEDOS_Username:-$(_readaccountconf_mutable WEDOS_Username)}" - WEDOS_Wapipass="${WEDOS_Wapipass:-$(_readaccountconf_mutable WEDOS_Wapipass)}" - WEDOS_Authtoken="${WEDOS_Authtoken:-$(_readaccountconf_mutable WEDOS_Authtoken)}" - - if [ "${WEDOS_Authtoken}" ]; then - _debug "WEDOS Authtoken was already saved, using saved one" - _saveaccountconf_mutable WEDOS_Authtoken "${WEDOS_Authtoken}" - else - if [ -z "${WEDOS_Username}" ] || [ -z "${WEDOS_Wapipass}" ]; then - WEDOS_Username="" - WEDOS_Wapipass="" - _err "You didn't specify a WEDOS's username and wapi key yet." - _err "Please type: export WEDOS_Username=" - _err "And: export WEDOS_Wapipass=" - _err "After you export those variables, run the script again, the values will be saved for future" - return 1 - fi - - #build WEDOS_Authtoken - _debug "WEDOS Authtoken were not saved yet, building" - WEDOS_Authtoken=$(printf '%s' "${WEDOS_Wapipass}" | sha1sum | head -c 40) - _debug "WEDOS_Authtoken step 1, WAPI PASS sha1 sum: '${WEDOS_Authtoken}'" - WEDOS_Authtoken="${WEDOS_Username}${WEDOS_Authtoken}" - _debug "WEDOS_Authtoken step 2, username concat with token without hours: '${WEDOS_Authtoken}'" - - #save details - - _saveaccountconf_mutable WEDOS_Username "${WEDOS_Username}" - _saveaccountconf_mutable WEDOS_Wapipass "${WEDOS_Wapipass}" - _saveaccountconf_mutable WEDOS_Authtoken "${WEDOS_Authtoken}" - fi - - if ! _get_root "${fulldomain}"; then - _err "WEDOS Account do not contain primary domain to fullfill add of ${fulldomain}!" - return 1 - fi - - _debug _sub_domain "${_sub_domain}" - _debug _domain "${_domain}" - - if _wapi_find_row "${_domain}" "${_sub_domain}" "${txtvalue}"; then - _info "WEDOS WAPI: dns record found with id '${_row_id}'" - - if _wapi_delete_row "${_domain}" "${_row_id}"; then - _info "WEDOS WAPI: dns row were deleted and changes commited!" - return 0 - fi - fi - - _err "Requested dns row were not found or was imposible to delete it, do it manually" - _err "Delete: ${fulldomain}" - _err "Value: ${txtvalue}" - return 1 + fulldomain=$1 + txtvalue=$2 + + WEDOS_Username="${WEDOS_Username:-$(_readaccountconf_mutable WEDOS_Username)}" + WEDOS_Wapipass="${WEDOS_Wapipass:-$(_readaccountconf_mutable WEDOS_Wapipass)}" + WEDOS_Authtoken="${WEDOS_Authtoken:-$(_readaccountconf_mutable WEDOS_Authtoken)}" + + if [ "${WEDOS_Authtoken}" ]; then + _debug "WEDOS Authtoken was already saved, using saved one" + _saveaccountconf_mutable WEDOS_Authtoken "${WEDOS_Authtoken}" + else + if [ -z "${WEDOS_Username}" ] || [ -z "${WEDOS_Wapipass}" ]; then + WEDOS_Username="" + WEDOS_Wapipass="" + _err "You didn't specify a WEDOS's username and wapi key yet." + _err "Please type: export WEDOS_Username=" + _err "And: export WEDOS_Wapipass=" + _err "After you export those variables, run the script again, the values will be saved for future" + return 1 + fi + + #build WEDOS_Authtoken + _debug "WEDOS Authtoken were not saved yet, building" + WEDOS_Authtoken=$(printf '%s' "${WEDOS_Wapipass}" | sha1sum | head -c 40) + _debug "WEDOS_Authtoken step 1, WAPI PASS sha1 sum: '${WEDOS_Authtoken}'" + WEDOS_Authtoken="${WEDOS_Username}${WEDOS_Authtoken}" + _debug "WEDOS_Authtoken step 2, username concat with token without hours: '${WEDOS_Authtoken}'" + + #save details + + _saveaccountconf_mutable WEDOS_Username "${WEDOS_Username}" + _saveaccountconf_mutable WEDOS_Wapipass "${WEDOS_Wapipass}" + _saveaccountconf_mutable WEDOS_Authtoken "${WEDOS_Authtoken}" + fi + + if ! _get_root "${fulldomain}"; then + _err "WEDOS Account do not contain primary domain to fullfill add of ${fulldomain}!" + return 1 + fi + + _debug _sub_domain "${_sub_domain}" + _debug _domain "${_domain}" + + if _wapi_find_row "${_domain}" "${_sub_domain}" "${txtvalue}"; then + _info "WEDOS WAPI: dns record found with id '${_row_id}'" + + if _wapi_delete_row "${_domain}" "${_row_id}"; then + _info "WEDOS WAPI: dns row were deleted and changes commited!" + return 0 + fi + fi + + _err "Requested dns row were not found or was imposible to delete it, do it manually" + _err "Delete: ${fulldomain}" + _err "Value: ${txtvalue}" + return 1 } #################### Private functions below ################################## @@ -132,143 +132,153 @@ dns_wedos_rm() { # $2 - WAPI data for given command, is not required # returns WAPI response if request were successfully delivered to WAPI endpoint _wapi_post() { - command=$1 - data=$2 + command=$1 + data=$2 - _debug "Command : ${command}" - _debug "Data : ${data}" + _debug "Command : ${command}" + _debug "Data : ${data}" - if [ -z "${command}" ]; then - _err "No command were provided, implamantation error!" - return 1 - fi + if [ -z "${command}" ]; then + _err "No command were provided, implamantation error!" + return 1 + fi - # Prepare authentification token - hour=$(date +%H) - token=$(printf '%s' "${WEDOS_Authtoken}${hour}" | sha1sum | head -c 40) - _debug "Authentification token is '${token}'" + # Prepare authentification token + hour=$(TZ='Europe/Prague' date +%H) + token=$(printf '%s' "${WEDOS_Authtoken}${hour}" | _digest "sha1" "true" | head -c 40) + _debug "Authentification token is '${token}'" - # Build xml request + # Build xml request - request="request=\ + request="request=\ \ ${WEDOS_Username}\ ${token}\ ${command}" - if [ -z "${data}" ]; then - echo "" 1>/dev/null - else - request="${request}${data}" - fi + if [ -z "${data}" ]; then + echo "" 1>/dev/null + else + request="${request}${data}" + fi - if [ -z "$TESTING_STAGE" ]; then - echo "" 1>/dev/null - else - request="${request}\ + if [ -z "$TESTING_STAGE" ]; then + echo "" 1>/dev/null + else + request="${request}\ 1" - fi + fi - request="${request}\ + request="${request}\ " - _debug "Request to WAPI is: ${request}" + _debug "Request to WAPI is: ${request}" - if ! response="$(_post "${request}" "$WEDOS_WAPI_ENDPOINT")"; then - _err "Error contacting WEDOS WAPI with command ${command}" - return 1 - fi + if ! response="$(_post "${request}" "$WEDOS_WAPI_ENDPOINT")"; then + _err "Error contacting WEDOS WAPI with command ${command}" + return 1 + fi - _debug "Response : ${response}" - echo "${response}" | grep "1000" 1>/dev/null 2>/dev/null + _debug "Response : ${response}" + _contains "${response}" "1000" - return "$?" + return "$?" } # _get_root() function, for provided full domain, like _acme_challenge.www.example.com verify if WEDOS contains a primary active domain and found what is subdomain # $1 - full domain to verify, ie _acme_challenge.www.example.com # build ${_domain} found at WEDOS, like example.com and ${_sub_domain} from provided full domain, like _acme_challenge.www _get_root() { - domain=$1 - - if [ -z "${domain}" ]; then - _err "Function _get_root was called without argument, implementation error!" - return 1 - fi - - _debug "Get root for domain: ${domain}" - - _debug "Getting list of domains using WAPI ..." - - if ! _wapi_post "dns-domains-list"; then - _err "Error on WAPI request for list of domains, response : ${response}" - return 1 - else - _debug "DNS list were successfully retrieved, response : ${response}" - fi - - for xml_domain in $(echo "${response}" | tr -d '\012\015' | grep -o -E "( )*.*( )*primary( )*active" | grep -o -E ".*"); do - _debug "Active and primary XML DOMAIN found: ${xml_domain}" - end_of_name=$((${#xml_domain} - 7)) - xml_domain_name=$(echo "${xml_domain}" | cut -c 7-${end_of_name}) - _debug "Found primary active domain: ${xml_domain_name}" - regex=".*\\."$(echo "${xml_domain_name}" | sed 's/\./\\./g') - _debug "Regex for matching domain: '${regex}'" - - if ! echo "${domain}" | grep -E "${regex}" 1>/dev/null 2>/dev/null; then - _debug "found domain do not match required" - else - end_of_name=$((${#domain} - ${#xml_domain_name} - 1)) - _domain=${xml_domain_name} - _sub_domain=$(echo "${domain}" | cut -c -${end_of_name}) - _info "Domain '${_domain}' was found at WEDOS account as primary, and subdomain is '${_sub_domain}'!" - return 0 - fi - done - - return 1 + domain=$1 + + if [ -z "${domain}" ]; then + _err "Function _get_root was called without argument, implementation error!" + return 1 + fi + + _debug "Get root for domain: ${domain}" + + _debug "Getting list of domains using WAPI ..." + + if ! _wapi_post "dns-domains-list"; then + _err "Error on WAPI request for list of domains, response : ${response}" + return 1 + else + _debug "DNS list were successfully retrieved, response : ${response}" + fi + + # In for each cycle, try parse the response to find primary active domains + # For cycle description: + # 1st tr -d '\011\012\015' = remove all newlines and tab characters - whole XML became single line + # 2nd sed "s/^.*[ ]*//g" = remove all the xml data from the beggining of the XML - XML now start with the content of element + # 3rd sed "s/<\/data>.*$//g" = remove all the data after the data xml element - XML now contains only the content of data xml element + # 4th sed "s/>[ ]*<\([^\/]\)/><\1/g" = remove all spaces between XML tag and XML start tag - XML now contains content of data xml element and is without spaces between end and start xml tags + # 5th sed "s///g" = remove all domain xml start tags - XML now contains only ......... (next xml domain) + # 6th sed "s/[ ]*<\/domain>/\n/g"= replace all "spaces" by new line - now we create multiple lines each should contain only ......... + # 7th sed -n "/\([a-zA-Z0-9_\-\.]\+\)<\/name>primary<\/type>active<\/status>/p" = remove all non primary or non active domains lines + # 8th sed "s/\([a-zA-Z0-9_\-\.]\+\)<\/name>primary<\/type>active<\/status>/\1/g" = substitute for domain names only + + for xml_domain in $(echo "${response}" | tr -d '\011\012\015' | sed "s/^.*[ ]*//g" | sed "s/<\/data>.*$//g" | sed "s/>[ ]*<\([^\/]\)/><\1/g" | sed "s///g" | sed "s/[ ]*<\/domain>/\n/g" | sed -n "/\([a-zA-Z0-9_\-\.]\+\)<\/name>primary<\/type>active<\/status>/p" | sed "s/\([a-zA-Z0-9_\-\.]\+\)<\/name>primary<\/type>active<\/status>/\1/g"); do + _debug "Found primary active domain: ${xml_domain}" + if _endswith "${domain}" "${xml_domain}"; then + length_difference=$(_math "${#domain} - ${#xml_domain}") + possible_subdomain=$(echo "${domain}" | cut -c -"${length_difference}") + if _endswith "${possible_subdomain}" "."; then + length_difference=$(_math "${length_difference} - 1") + _domain=${xml_domain} + _sub_domain=$(echo "${possible_subdomain}" | cut -c -"${length_difference}") + + _info "Domain '${_domain}' was found at WEDOS account as primary, and subdomain is '${_sub_domain}'!" + return 0 + fi + fi + _debug " ... found domain does not match required!" + done + + return 1 + } # for provided domain, it commites all performed changes _wapi_dns_commit() { - domain=$1 + domain=$1 - if [ -z "${domain}" ]; then - _err "Invalid request to commit dns changes, domain is empty, implementation error!" - return 1 - fi + if [ -z "${domain}" ]; then + _err "Invalid request to commit dns changes, domain is empty, implementation error!" + return 1 + fi - data=" \ + data=" \ ${domain}\ " - if ! _wapi_post "dns-domain-commit" "${data}"; then - _err "Error on WAPI request to commit DNS changes, response : ${response}" - _err "PLEASE USE WEB ACCESS TO CHECK IF CHANGES ARE REQUIRED TO COMMIT OR ROLLBACKED IMMEDIATELLY!" - return 1 - else - _debug "DNS CHANGES COMMITED, response : ${response}" - _info "WEDOS DNS WAPI: Changes were commited to domain '${domain}'" - fi + if ! _wapi_post "dns-domain-commit" "${data}"; then + _err "Error on WAPI request to commit DNS changes, response : ${response}" + _err "PLEASE USE WEB ACCESS TO CHECK IF CHANGES ARE REQUIRED TO COMMIT OR ROLLBACKED IMMEDIATELLY!" + return 1 + else + _debug "DNS CHANGES COMMITED, response : ${response}" + _info "WEDOS DNS WAPI: Changes were commited to domain '${domain}'" + fi - return 0 + return 0 } # add one TXT dns row to a specified fomain _wapi_row_add() { - domain=$1 - sub_domain=$2 - value=$3 - ttl=$4 - - if [ -z "${domain}" ] || [ -z "${sub_domain}" ] || [ -z "${value}" ] || [ -z "${ttl}" ]; then - _err "Invalid request to add record, domain: '${domain}', sub_domain: '${sub_domain}', value: '${value}' and ttl: '${ttl}', on of required input were not provided, implementation error!" - return 1 - fi - - # Prepare data for request to WAPI - data=" \ + domain=$1 + sub_domain=$2 + value=$3 + ttl=$4 + + if [ -z "${domain}" ] || [ -z "${sub_domain}" ] || [ -z "${value}" ] || [ -z "${ttl}" ]; then + _err "Invalid request to add record, domain: '${domain}', sub_domain: '${sub_domain}', value: '${value}' and ttl: '${ttl}', on of required input were not provided, implementation error!" + return 1 + fi + + # Prepare data for request to WAPI + data=" \ ${domain}\ ${sub_domain}\ ${ttl}\ @@ -277,90 +287,105 @@ _wapi_row_add() { Created using WAPI from acme.sh\ " - _debug "Adding row using WAPI ..." + _debug "Adding row using WAPI ..." - if ! _wapi_post "dns-row-add" "${data}"; then - _err "Error on WAPI request to add new TXT row, response : ${response}" - return 1 - else - _debug "ROW ADDED, response : ${response}" - _info "WEDOS DNS WAPI: Row to domain '${domain}' with name '${sub_domain}' were successfully added with value '${value}' and ttl set to ${ttl}" - fi + if ! _wapi_post "dns-row-add" "${data}"; then + _err "Error on WAPI request to add new TXT row, response : ${response}" + return 1 + else + _debug "ROW ADDED, response : ${response}" + _info "WEDOS DNS WAPI: Row to domain '${domain}' with name '${sub_domain}' were successfully added with value '${value}' and ttl set to ${ttl}" + fi - # Now we have to commit - _wapi_dns_commit "${domain}" + # Now we have to commit + _wapi_dns_commit "${domain}" - return "$?" + return "$?" } _wapi_find_row() { - domain=$1 - sub_domain=$2 - value=$3 + domain=$1 + sub_domain=$2 + value=$3 - if [ -z "${domain}" ] || [ -z "${sub_domain}" ] || [ -z "${value}" ]; then - _err "Invalud request to finad a row, domain: '${domain}', sub_domain: '${sub_domain}' and value: '${value}', one of required input were not provided, implementation error!" - return 1 - fi + if [ -z "${domain}" ] || [ -z "${sub_domain}" ] || [ -z "${value}" ]; then + _err "Invalud request to finad a row, domain: '${domain}', sub_domain: '${sub_domain}' and value: '${value}', one of required input were not provided, implementation error!" + return 1 + fi - data=" \ + data=" \ ${domain}\ " - _debug "Searching rows using WAPI ..." + _debug "Searching rows using WAPI ..." + + if ! _wapi_post "dns-rows-list" "${data}"; then + _err "Error on WAPI request to list domain rows, response : ${response}" + return 1 + fi + + _debug "Domain rows found, response : ${response}" - if ! _wapi_post "dns-rows-list" "${data}"; then - _err "Error on WAPI request to list domain rows, response : ${response}" - return 1 - fi + # Prepare sub domain regex which will be later used for search domain row + # from _acme_challenge.sub it should be _acme_challenge\.sub - _debug "Domain rows found, response : ${response}" + sub_domain_regex=$(echo "${sub_domain}" | sed "s/\./\\\\./g") - sub_domain_regex=$(echo "${sub_domain}" | sed "s/\./\\\\./g") + _debug "Subdomain regex '${sub_domain_regex}'" - _debug "Subdomain regex '${sub_domain_regex}'" + # In for each cycle loops over the domains rows, description: + # 1st tr -d '\011\012\015' = delete all newlines and tab characters - XML became a single line + # 2nd sed "s/^.*[ ]*//g" = remove all from the beggining to the start of the content of the data xml element - XML is without unusefull beginning + # 3rd sed "s/[ ]*<\/data>.*$//g" = remove the end of the xml starting with xml end tag data - XML contains only the content of data xml element and is trimmed + # 4th sed "s/>[ ]*<\([^\/]\)/><\1/g" = remove all spaces between XML tag and XML start tag - XML now contains content of data xml element and is without spaces between end and start xml tags + # 5th sed "s///g" = remove all row xml start tags - XML now contains rows xml element content and its end tag + # 6th sed "s/[ ]*<\/row>/\n/g" = replace all "spaces" by new line - now we create multiple lines each should contain only single row xml content + # 7th sed -n "/${sub_domain_regex}<\/name>.*TXT<\/rdtype>/p" = remove all non TXT and non name matching row lines - now we have only xml lines with TXT rows matching requested values + # 8th sed "s/^\([0-9]\+\)<\/ID>.*\(.*\)<\/rdata>.*$/\1-\2/" = replace the whole lines to ID-value pairs + # -- now there are only lines with ID-value but value might contain spaces (BAD FOR FOREACH LOOP) or special characters (BAD FOR REGEX MATCHING) + # 9th grep "${value}" = match only a line containg searched value + # 10th sed "s/^\([0-9]\+\).*$/\1/" = get only ID from the row - for xml_row in $(echo "${response}" | tr -d '\012\015' | grep -o -E "( )*[0-9]*( )*${sub_domain_regex}( )*[0-9]*( )*TXT( )*${value}" | grep -o -e "[0-9]*"); do - _debug "Found row in DNS with ID : ${xml_row}" - _row_id=$(echo "${xml_row}" | grep -o -E "[0-9]*") - _info "WEDOS API: Found DNS row id ${_row_id} for domain ${domain}" - return 0 - done + for xml_row in $(echo "${response}" | tr -d '\011\012\015' | sed "s/^.*[ ]*//g" | sed "s/[ ]*<\/data>.*$//g" | sed "s/>[ ]*<\([^\/]\)/><\1/g" | sed "s///g" | sed "s/[ ]*<\/row>/\n/g" | sed -n "/${sub_domain_regex}<\/name>.*TXT<\/rdtype>/p" | sed "s/^\([0-9]\+\)<\/ID>.*\(.*\)<\/rdata>.*$/\1-\2/" | grep "${value}" | sed "s/^\([0-9]\+\).*$/\1/"); do + _row_id="${xml_row}" + _info "WEDOS API: Found DNS row id ${_row_id} for domain ${domain}" + return 0 + done - _info "WEDOS API: No TXT row found for domain '${domain}' with name '${sub_domain}' and value '${value}'" + _info "WEDOS API: No TXT row found for domain '${domain}' with name '${sub_domain}' and value '${value}'" - return 1 + return 1 } _wapi_delete_row() { - domain=$1 - row_id=$2 + domain=$1 + row_id=$2 - if [ -z "${domain}" ] || [ -z "${row_id}" ]; then - _err "Invalid request to delete domain dns row, domain: '${domain}' and row_id: '${row_id}', one of required input were not provided, implementation error!" - return 1 - fi + if [ -z "${domain}" ] || [ -z "${row_id}" ]; then + _err "Invalid request to delete domain dns row, domain: '${domain}' and row_id: '${row_id}', one of required input were not provided, implementation error!" + return 1 + fi - data=" \ + data=" \ ${domain} ${row_id} " - _debug "Deleting dns row using WAPI ..." + _debug "Deleting dns row using WAPI ..." - if ! _wapi_post "dns-row-delete" "${data}"; then - _err "Error on WAPI request to delete dns row, response: ${response}" - return 1 - fi + if ! _wapi_post "dns-row-delete" "${data}"; then + _err "Error on WAPI request to delete dns row, response: ${response}" + return 1 + fi - _debug "DNS row were deleted, response: ${response}" + _debug "DNS row were deleted, response: ${response}" - _info "WEDOS API: Required dns domain row with row_id '${row_id}' were correctly deleted at domain '${domain}'" + _info "WEDOS API: Required dns domain row with row_id '${row_id}' were correctly deleted at domain '${domain}'" - # Now we have to commit changes - _wapi_dns_commit "${domain}" + # Now we have to commit changes + _wapi_dns_commit "${domain}" - return "$?" + return "$?" } From e344c43c684208215e16ed56d156e1a7270dfd9a Mon Sep 17 00:00:00 2001 From: mxtuma <71069082+mxtuma@users.noreply.github.com> Date: Thu, 19 Nov 2020 16:10:26 +0100 Subject: [PATCH 04/10] Fixing indent from tab to 2 spaces --- dnsapi/dns_wedos.sh | 556 ++++++++++++++++++++++---------------------- 1 file changed, 278 insertions(+), 278 deletions(-) diff --git a/dnsapi/dns_wedos.sh b/dnsapi/dns_wedos.sh index 0102bb3a..b4df1db9 100644 --- a/dnsapi/dns_wedos.sh +++ b/dnsapi/dns_wedos.sh @@ -13,116 +13,116 @@ TESTING_STAGE= #Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_wedos_add() { - fulldomain=$1 - txtvalue=$2 - - WEDOS_Username="${WEDOS_Username:-$(_readaccountconf_mutable WEDOS_Username)}" - WEDOS_Wapipass="${WEDOS_Wapipass:-$(_readaccountconf_mutable WEDOS_Wapipass)}" - WEDOS_Authtoken="${WEDOS_Authtoken:-$(_readaccountconf_mutable WEDOS_Authtoken)}" - - if [ "${WEDOS_Authtoken}" ]; then - _debug "WEDOS Authtoken was already saved, using saved one" - _saveaccountconf_mutable WEDOS_Authtoken "${WEDOS_Authtoken}" - else - if [ -z "${WEDOS_Username}" ] || [ -z "${WEDOS_Wapipass}" ]; then - WEDOS_Username="" - WEDOS_Wapipass="" - _err "You didn't specify a WEDOS's username and wapi key yet." - _err "Please type: export WEDOS_Username=" - _err "And: export WEDOS_Wapipass=" - _err "After you export those variables, run the script again, the values will be saved for future" - return 1 - fi - - #build WEDOS_Authtoken - _debug "WEDOS Authtoken were not saved yet, building" - WEDOS_Authtoken=$(printf '%s' "${WEDOS_Wapipass}" | _digest "sha1" "true" | head -c 40) - _debug "WEDOS_Authtoken step 1, WAPI PASS sha1 sum: '${WEDOS_Authtoken}'" - WEDOS_Authtoken="${WEDOS_Username}${WEDOS_Authtoken}" - _debug "WEDOS_Authtoken step 2, username concat with token without hours: '${WEDOS_Authtoken}'" - - #save details - - _saveaccountconf_mutable WEDOS_Username "${WEDOS_Username}" - _saveaccountconf_mutable WEDOS_Wapipass "${WEDOS_Wapipass}" - _saveaccountconf_mutable WEDOS_Authtoken "${WEDOS_Authtoken}" - fi - - if ! _get_root "${fulldomain}"; then - _err "WEDOS Account do not contain primary domain to fullfill add of ${fulldomain}!" - return 1 - fi - - _debug _sub_domain "${_sub_domain}" - _debug _domain "${_domain}" - - if _wapi_row_add "${_domain}" "${_sub_domain}" "${txtvalue}" "300"; then - _info "WEDOS WAPI: dns record added and dns changes were commited" - return 0 - else - _err "FAILED TO ADD DNS RECORD OR COMMIT DNS CHANGES" - return 1 - fi + fulldomain=$1 + txtvalue=$2 + + WEDOS_Username="${WEDOS_Username:-$(_readaccountconf_mutable WEDOS_Username)}" + WEDOS_Wapipass="${WEDOS_Wapipass:-$(_readaccountconf_mutable WEDOS_Wapipass)}" + WEDOS_Authtoken="${WEDOS_Authtoken:-$(_readaccountconf_mutable WEDOS_Authtoken)}" + + if [ "${WEDOS_Authtoken}" ]; then + _debug "WEDOS Authtoken was already saved, using saved one" + _saveaccountconf_mutable WEDOS_Authtoken "${WEDOS_Authtoken}" + else + if [ -z "${WEDOS_Username}" ] || [ -z "${WEDOS_Wapipass}" ]; then + WEDOS_Username="" + WEDOS_Wapipass="" + _err "You didn't specify a WEDOS's username and wapi key yet." + _err "Please type: export WEDOS_Username=" + _err "And: export WEDOS_Wapipass=" + _err "After you export those variables, run the script again, the values will be saved for future" + return 1 + fi + + #build WEDOS_Authtoken + _debug "WEDOS Authtoken were not saved yet, building" + WEDOS_Authtoken=$(printf '%s' "${WEDOS_Wapipass}" | _digest "sha1" "true" | head -c 40) + _debug "WEDOS_Authtoken step 1, WAPI PASS sha1 sum: '${WEDOS_Authtoken}'" + WEDOS_Authtoken="${WEDOS_Username}${WEDOS_Authtoken}" + _debug "WEDOS_Authtoken step 2, username concat with token without hours: '${WEDOS_Authtoken}'" + + #save details + + _saveaccountconf_mutable WEDOS_Username "${WEDOS_Username}" + _saveaccountconf_mutable WEDOS_Wapipass "${WEDOS_Wapipass}" + _saveaccountconf_mutable WEDOS_Authtoken "${WEDOS_Authtoken}" + fi + + if ! _get_root "${fulldomain}"; then + _err "WEDOS Account do not contain primary domain to fullfill add of ${fulldomain}!" + return 1 + fi + + _debug _sub_domain "${_sub_domain}" + _debug _domain "${_domain}" + + if _wapi_row_add "${_domain}" "${_sub_domain}" "${txtvalue}" "300"; then + _info "WEDOS WAPI: dns record added and dns changes were commited" + return 0 + else + _err "FAILED TO ADD DNS RECORD OR COMMIT DNS CHANGES" + return 1 + fi } #fulldomain txtvalue dns_wedos_rm() { - fulldomain=$1 - txtvalue=$2 - - WEDOS_Username="${WEDOS_Username:-$(_readaccountconf_mutable WEDOS_Username)}" - WEDOS_Wapipass="${WEDOS_Wapipass:-$(_readaccountconf_mutable WEDOS_Wapipass)}" - WEDOS_Authtoken="${WEDOS_Authtoken:-$(_readaccountconf_mutable WEDOS_Authtoken)}" - - if [ "${WEDOS_Authtoken}" ]; then - _debug "WEDOS Authtoken was already saved, using saved one" - _saveaccountconf_mutable WEDOS_Authtoken "${WEDOS_Authtoken}" - else - if [ -z "${WEDOS_Username}" ] || [ -z "${WEDOS_Wapipass}" ]; then - WEDOS_Username="" - WEDOS_Wapipass="" - _err "You didn't specify a WEDOS's username and wapi key yet." - _err "Please type: export WEDOS_Username=" - _err "And: export WEDOS_Wapipass=" - _err "After you export those variables, run the script again, the values will be saved for future" - return 1 - fi - - #build WEDOS_Authtoken - _debug "WEDOS Authtoken were not saved yet, building" - WEDOS_Authtoken=$(printf '%s' "${WEDOS_Wapipass}" | sha1sum | head -c 40) - _debug "WEDOS_Authtoken step 1, WAPI PASS sha1 sum: '${WEDOS_Authtoken}'" - WEDOS_Authtoken="${WEDOS_Username}${WEDOS_Authtoken}" - _debug "WEDOS_Authtoken step 2, username concat with token without hours: '${WEDOS_Authtoken}'" - - #save details - - _saveaccountconf_mutable WEDOS_Username "${WEDOS_Username}" - _saveaccountconf_mutable WEDOS_Wapipass "${WEDOS_Wapipass}" - _saveaccountconf_mutable WEDOS_Authtoken "${WEDOS_Authtoken}" - fi - - if ! _get_root "${fulldomain}"; then - _err "WEDOS Account do not contain primary domain to fullfill add of ${fulldomain}!" - return 1 - fi - - _debug _sub_domain "${_sub_domain}" - _debug _domain "${_domain}" - - if _wapi_find_row "${_domain}" "${_sub_domain}" "${txtvalue}"; then - _info "WEDOS WAPI: dns record found with id '${_row_id}'" - - if _wapi_delete_row "${_domain}" "${_row_id}"; then - _info "WEDOS WAPI: dns row were deleted and changes commited!" - return 0 - fi - fi - - _err "Requested dns row were not found or was imposible to delete it, do it manually" - _err "Delete: ${fulldomain}" - _err "Value: ${txtvalue}" - return 1 + fulldomain=$1 + txtvalue=$2 + + WEDOS_Username="${WEDOS_Username:-$(_readaccountconf_mutable WEDOS_Username)}" + WEDOS_Wapipass="${WEDOS_Wapipass:-$(_readaccountconf_mutable WEDOS_Wapipass)}" + WEDOS_Authtoken="${WEDOS_Authtoken:-$(_readaccountconf_mutable WEDOS_Authtoken)}" + + if [ "${WEDOS_Authtoken}" ]; then + _debug "WEDOS Authtoken was already saved, using saved one" + _saveaccountconf_mutable WEDOS_Authtoken "${WEDOS_Authtoken}" + else + if [ -z "${WEDOS_Username}" ] || [ -z "${WEDOS_Wapipass}" ]; then + WEDOS_Username="" + WEDOS_Wapipass="" + _err "You didn't specify a WEDOS's username and wapi key yet." + _err "Please type: export WEDOS_Username=" + _err "And: export WEDOS_Wapipass=" + _err "After you export those variables, run the script again, the values will be saved for future" + return 1 + fi + + #build WEDOS_Authtoken + _debug "WEDOS Authtoken were not saved yet, building" + WEDOS_Authtoken=$(printf '%s' "${WEDOS_Wapipass}" | sha1sum | head -c 40) + _debug "WEDOS_Authtoken step 1, WAPI PASS sha1 sum: '${WEDOS_Authtoken}'" + WEDOS_Authtoken="${WEDOS_Username}${WEDOS_Authtoken}" + _debug "WEDOS_Authtoken step 2, username concat with token without hours: '${WEDOS_Authtoken}'" + + #save details + + _saveaccountconf_mutable WEDOS_Username "${WEDOS_Username}" + _saveaccountconf_mutable WEDOS_Wapipass "${WEDOS_Wapipass}" + _saveaccountconf_mutable WEDOS_Authtoken "${WEDOS_Authtoken}" + fi + + if ! _get_root "${fulldomain}"; then + _err "WEDOS Account do not contain primary domain to fullfill add of ${fulldomain}!" + return 1 + fi + + _debug _sub_domain "${_sub_domain}" + _debug _domain "${_domain}" + + if _wapi_find_row "${_domain}" "${_sub_domain}" "${txtvalue}"; then + _info "WEDOS WAPI: dns record found with id '${_row_id}'" + + if _wapi_delete_row "${_domain}" "${_row_id}"; then + _info "WEDOS WAPI: dns row were deleted and changes commited!" + return 0 + fi + fi + + _err "Requested dns row were not found or was imposible to delete it, do it manually" + _err "Delete: ${fulldomain}" + _err "Value: ${txtvalue}" + return 1 } #################### Private functions below ################################## @@ -132,153 +132,153 @@ dns_wedos_rm() { # $2 - WAPI data for given command, is not required # returns WAPI response if request were successfully delivered to WAPI endpoint _wapi_post() { - command=$1 - data=$2 + command=$1 + data=$2 - _debug "Command : ${command}" - _debug "Data : ${data}" + _debug "Command : ${command}" + _debug "Data : ${data}" - if [ -z "${command}" ]; then - _err "No command were provided, implamantation error!" - return 1 - fi + if [ -z "${command}" ]; then + _err "No command were provided, implamantation error!" + return 1 + fi - # Prepare authentification token - hour=$(TZ='Europe/Prague' date +%H) - token=$(printf '%s' "${WEDOS_Authtoken}${hour}" | _digest "sha1" "true" | head -c 40) - _debug "Authentification token is '${token}'" + # Prepare authentification token + hour=$(TZ='Europe/Prague' date +%H) + token=$(printf '%s' "${WEDOS_Authtoken}${hour}" | _digest "sha1" "true" | head -c 40) + _debug "Authentification token is '${token}'" - # Build xml request + # Build xml request - request="request=\ + request="request=\ \ ${WEDOS_Username}\ ${token}\ ${command}" - if [ -z "${data}" ]; then - echo "" 1>/dev/null - else - request="${request}${data}" - fi + if [ -z "${data}" ]; then + echo "" 1>/dev/null + else + request="${request}${data}" + fi - if [ -z "$TESTING_STAGE" ]; then - echo "" 1>/dev/null - else - request="${request}\ + if [ -z "$TESTING_STAGE" ]; then + echo "" 1>/dev/null + else + request="${request}\ 1" - fi + fi - request="${request}\ + request="${request}\ " - _debug "Request to WAPI is: ${request}" + _debug "Request to WAPI is: ${request}" - if ! response="$(_post "${request}" "$WEDOS_WAPI_ENDPOINT")"; then - _err "Error contacting WEDOS WAPI with command ${command}" - return 1 - fi + if ! response="$(_post "${request}" "$WEDOS_WAPI_ENDPOINT")"; then + _err "Error contacting WEDOS WAPI with command ${command}" + return 1 + fi - _debug "Response : ${response}" - _contains "${response}" "1000" + _debug "Response : ${response}" + _contains "${response}" "1000" - return "$?" + return "$?" } # _get_root() function, for provided full domain, like _acme_challenge.www.example.com verify if WEDOS contains a primary active domain and found what is subdomain # $1 - full domain to verify, ie _acme_challenge.www.example.com # build ${_domain} found at WEDOS, like example.com and ${_sub_domain} from provided full domain, like _acme_challenge.www _get_root() { - domain=$1 - - if [ -z "${domain}" ]; then - _err "Function _get_root was called without argument, implementation error!" - return 1 - fi - - _debug "Get root for domain: ${domain}" - - _debug "Getting list of domains using WAPI ..." - - if ! _wapi_post "dns-domains-list"; then - _err "Error on WAPI request for list of domains, response : ${response}" - return 1 - else - _debug "DNS list were successfully retrieved, response : ${response}" - fi - - # In for each cycle, try parse the response to find primary active domains - # For cycle description: - # 1st tr -d '\011\012\015' = remove all newlines and tab characters - whole XML became single line - # 2nd sed "s/^.*[ ]*//g" = remove all the xml data from the beggining of the XML - XML now start with the content of element - # 3rd sed "s/<\/data>.*$//g" = remove all the data after the data xml element - XML now contains only the content of data xml element - # 4th sed "s/>[ ]*<\([^\/]\)/><\1/g" = remove all spaces between XML tag and XML start tag - XML now contains content of data xml element and is without spaces between end and start xml tags - # 5th sed "s///g" = remove all domain xml start tags - XML now contains only ......... (next xml domain) - # 6th sed "s/[ ]*<\/domain>/\n/g"= replace all "spaces" by new line - now we create multiple lines each should contain only ......... - # 7th sed -n "/\([a-zA-Z0-9_\-\.]\+\)<\/name>primary<\/type>active<\/status>/p" = remove all non primary or non active domains lines - # 8th sed "s/\([a-zA-Z0-9_\-\.]\+\)<\/name>primary<\/type>active<\/status>/\1/g" = substitute for domain names only - - for xml_domain in $(echo "${response}" | tr -d '\011\012\015' | sed "s/^.*[ ]*//g" | sed "s/<\/data>.*$//g" | sed "s/>[ ]*<\([^\/]\)/><\1/g" | sed "s///g" | sed "s/[ ]*<\/domain>/\n/g" | sed -n "/\([a-zA-Z0-9_\-\.]\+\)<\/name>primary<\/type>active<\/status>/p" | sed "s/\([a-zA-Z0-9_\-\.]\+\)<\/name>primary<\/type>active<\/status>/\1/g"); do - _debug "Found primary active domain: ${xml_domain}" - if _endswith "${domain}" "${xml_domain}"; then - length_difference=$(_math "${#domain} - ${#xml_domain}") - possible_subdomain=$(echo "${domain}" | cut -c -"${length_difference}") - if _endswith "${possible_subdomain}" "."; then - length_difference=$(_math "${length_difference} - 1") - _domain=${xml_domain} - _sub_domain=$(echo "${possible_subdomain}" | cut -c -"${length_difference}") - - _info "Domain '${_domain}' was found at WEDOS account as primary, and subdomain is '${_sub_domain}'!" - return 0 - fi - fi - _debug " ... found domain does not match required!" - done - - return 1 + domain=$1 + + if [ -z "${domain}" ]; then + _err "Function _get_root was called without argument, implementation error!" + return 1 + fi + + _debug "Get root for domain: ${domain}" + + _debug "Getting list of domains using WAPI ..." + + if ! _wapi_post "dns-domains-list"; then + _err "Error on WAPI request for list of domains, response : ${response}" + return 1 + else + _debug "DNS list were successfully retrieved, response : ${response}" + fi + + # In for each cycle, try parse the response to find primary active domains + # For cycle description: + # 1st tr -d '\011\012\015' = remove all newlines and tab characters - whole XML became single line + # 2nd sed "s/^.*[ ]*//g" = remove all the xml data from the beggining of the XML - XML now start with the content of element + # 3rd sed "s/<\/data>.*$//g" = remove all the data after the data xml element - XML now contains only the content of data xml element + # 4th sed "s/>[ ]*<\([^\/]\)/><\1/g" = remove all spaces between XML tag and XML start tag - XML now contains content of data xml element and is without spaces between end and start xml tags + # 5th sed "s///g" = remove all domain xml start tags - XML now contains only ......... (next xml domain) + # 6th sed "s/[ ]*<\/domain>/\n/g"= replace all "spaces" by new line - now we create multiple lines each should contain only ......... + # 7th sed -n "/\([a-zA-Z0-9_\-\.]\+\)<\/name>primary<\/type>active<\/status>/p" = remove all non primary or non active domains lines + # 8th sed "s/\([a-zA-Z0-9_\-\.]\+\)<\/name>primary<\/type>active<\/status>/\1/g" = substitute for domain names only + + for xml_domain in $(echo "${response}" | tr -d '\011\012\015' | sed "s/^.*[ ]*//g" | sed "s/<\/data>.*$//g" | sed "s/>[ ]*<\([^\/]\)/><\1/g" | sed "s///g" | sed "s/[ ]*<\/domain>/\n/g" | sed -n "/\([a-zA-Z0-9_\-\.]\+\)<\/name>primary<\/type>active<\/status>/p" | sed "s/\([a-zA-Z0-9_\-\.]\+\)<\/name>primary<\/type>active<\/status>/\1/g"); do + _debug "Found primary active domain: ${xml_domain}" + if _endswith "${domain}" "${xml_domain}"; then + length_difference=$(_math "${#domain} - ${#xml_domain}") + possible_subdomain=$(echo "${domain}" | cut -c -"${length_difference}") + if _endswith "${possible_subdomain}" "."; then + length_difference=$(_math "${length_difference} - 1") + _domain=${xml_domain} + _sub_domain=$(echo "${possible_subdomain}" | cut -c -"${length_difference}") + + _info "Domain '${_domain}' was found at WEDOS account as primary, and subdomain is '${_sub_domain}'!" + return 0 + fi + fi + _debug " ... found domain does not match required!" + done + + return 1 } # for provided domain, it commites all performed changes _wapi_dns_commit() { - domain=$1 + domain=$1 - if [ -z "${domain}" ]; then - _err "Invalid request to commit dns changes, domain is empty, implementation error!" - return 1 - fi + if [ -z "${domain}" ]; then + _err "Invalid request to commit dns changes, domain is empty, implementation error!" + return 1 + fi - data=" \ + data=" \ ${domain}\ " - if ! _wapi_post "dns-domain-commit" "${data}"; then - _err "Error on WAPI request to commit DNS changes, response : ${response}" - _err "PLEASE USE WEB ACCESS TO CHECK IF CHANGES ARE REQUIRED TO COMMIT OR ROLLBACKED IMMEDIATELLY!" - return 1 - else - _debug "DNS CHANGES COMMITED, response : ${response}" - _info "WEDOS DNS WAPI: Changes were commited to domain '${domain}'" - fi + if ! _wapi_post "dns-domain-commit" "${data}"; then + _err "Error on WAPI request to commit DNS changes, response : ${response}" + _err "PLEASE USE WEB ACCESS TO CHECK IF CHANGES ARE REQUIRED TO COMMIT OR ROLLBACKED IMMEDIATELLY!" + return 1 + else + _debug "DNS CHANGES COMMITED, response : ${response}" + _info "WEDOS DNS WAPI: Changes were commited to domain '${domain}'" + fi - return 0 + return 0 } # add one TXT dns row to a specified fomain _wapi_row_add() { - domain=$1 - sub_domain=$2 - value=$3 - ttl=$4 - - if [ -z "${domain}" ] || [ -z "${sub_domain}" ] || [ -z "${value}" ] || [ -z "${ttl}" ]; then - _err "Invalid request to add record, domain: '${domain}', sub_domain: '${sub_domain}', value: '${value}' and ttl: '${ttl}', on of required input were not provided, implementation error!" - return 1 - fi - - # Prepare data for request to WAPI - data=" \ + domain=$1 + sub_domain=$2 + value=$3 + ttl=$4 + + if [ -z "${domain}" ] || [ -z "${sub_domain}" ] || [ -z "${value}" ] || [ -z "${ttl}" ]; then + _err "Invalid request to add record, domain: '${domain}', sub_domain: '${sub_domain}', value: '${value}' and ttl: '${ttl}', on of required input were not provided, implementation error!" + return 1 + fi + + # Prepare data for request to WAPI + data=" \ ${domain}\ ${sub_domain}\ ${ttl}\ @@ -287,105 +287,105 @@ _wapi_row_add() { Created using WAPI from acme.sh\ " - _debug "Adding row using WAPI ..." + _debug "Adding row using WAPI ..." - if ! _wapi_post "dns-row-add" "${data}"; then - _err "Error on WAPI request to add new TXT row, response : ${response}" - return 1 - else - _debug "ROW ADDED, response : ${response}" - _info "WEDOS DNS WAPI: Row to domain '${domain}' with name '${sub_domain}' were successfully added with value '${value}' and ttl set to ${ttl}" - fi + if ! _wapi_post "dns-row-add" "${data}"; then + _err "Error on WAPI request to add new TXT row, response : ${response}" + return 1 + else + _debug "ROW ADDED, response : ${response}" + _info "WEDOS DNS WAPI: Row to domain '${domain}' with name '${sub_domain}' were successfully added with value '${value}' and ttl set to ${ttl}" + fi - # Now we have to commit - _wapi_dns_commit "${domain}" + # Now we have to commit + _wapi_dns_commit "${domain}" - return "$?" + return "$?" } _wapi_find_row() { - domain=$1 - sub_domain=$2 - value=$3 + domain=$1 + sub_domain=$2 + value=$3 - if [ -z "${domain}" ] || [ -z "${sub_domain}" ] || [ -z "${value}" ]; then - _err "Invalud request to finad a row, domain: '${domain}', sub_domain: '${sub_domain}' and value: '${value}', one of required input were not provided, implementation error!" - return 1 - fi + if [ -z "${domain}" ] || [ -z "${sub_domain}" ] || [ -z "${value}" ]; then + _err "Invalud request to finad a row, domain: '${domain}', sub_domain: '${sub_domain}' and value: '${value}', one of required input were not provided, implementation error!" + return 1 + fi - data=" \ + data=" \ ${domain}\ " - _debug "Searching rows using WAPI ..." + _debug "Searching rows using WAPI ..." - if ! _wapi_post "dns-rows-list" "${data}"; then - _err "Error on WAPI request to list domain rows, response : ${response}" - return 1 - fi + if ! _wapi_post "dns-rows-list" "${data}"; then + _err "Error on WAPI request to list domain rows, response : ${response}" + return 1 + fi - _debug "Domain rows found, response : ${response}" + _debug "Domain rows found, response : ${response}" - # Prepare sub domain regex which will be later used for search domain row - # from _acme_challenge.sub it should be _acme_challenge\.sub + # Prepare sub domain regex which will be later used for search domain row + # from _acme_challenge.sub it should be _acme_challenge\.sub - sub_domain_regex=$(echo "${sub_domain}" | sed "s/\./\\\\./g") + sub_domain_regex=$(echo "${sub_domain}" | sed "s/\./\\\\./g") - _debug "Subdomain regex '${sub_domain_regex}'" + _debug "Subdomain regex '${sub_domain_regex}'" - # In for each cycle loops over the domains rows, description: - # 1st tr -d '\011\012\015' = delete all newlines and tab characters - XML became a single line - # 2nd sed "s/^.*[ ]*//g" = remove all from the beggining to the start of the content of the data xml element - XML is without unusefull beginning - # 3rd sed "s/[ ]*<\/data>.*$//g" = remove the end of the xml starting with xml end tag data - XML contains only the content of data xml element and is trimmed - # 4th sed "s/>[ ]*<\([^\/]\)/><\1/g" = remove all spaces between XML tag and XML start tag - XML now contains content of data xml element and is without spaces between end and start xml tags - # 5th sed "s///g" = remove all row xml start tags - XML now contains rows xml element content and its end tag - # 6th sed "s/[ ]*<\/row>/\n/g" = replace all "spaces" by new line - now we create multiple lines each should contain only single row xml content - # 7th sed -n "/${sub_domain_regex}<\/name>.*TXT<\/rdtype>/p" = remove all non TXT and non name matching row lines - now we have only xml lines with TXT rows matching requested values - # 8th sed "s/^\([0-9]\+\)<\/ID>.*\(.*\)<\/rdata>.*$/\1-\2/" = replace the whole lines to ID-value pairs - # -- now there are only lines with ID-value but value might contain spaces (BAD FOR FOREACH LOOP) or special characters (BAD FOR REGEX MATCHING) - # 9th grep "${value}" = match only a line containg searched value - # 10th sed "s/^\([0-9]\+\).*$/\1/" = get only ID from the row + # In for each cycle loops over the domains rows, description: + # 1st tr -d '\011\012\015' = delete all newlines and tab characters - XML became a single line + # 2nd sed "s/^.*[ ]*//g" = remove all from the beggining to the start of the content of the data xml element - XML is without unusefull beginning + # 3rd sed "s/[ ]*<\/data>.*$//g" = remove the end of the xml starting with xml end tag data - XML contains only the content of data xml element and is trimmed + # 4th sed "s/>[ ]*<\([^\/]\)/><\1/g" = remove all spaces between XML tag and XML start tag - XML now contains content of data xml element and is without spaces between end and start xml tags + # 5th sed "s///g" = remove all row xml start tags - XML now contains rows xml element content and its end tag + # 6th sed "s/[ ]*<\/row>/\n/g" = replace all "spaces" by new line - now we create multiple lines each should contain only single row xml content + # 7th sed -n "/${sub_domain_regex}<\/name>.*TXT<\/rdtype>/p" = remove all non TXT and non name matching row lines - now we have only xml lines with TXT rows matching requested values + # 8th sed "s/^\([0-9]\+\)<\/ID>.*\(.*\)<\/rdata>.*$/\1-\2/" = replace the whole lines to ID-value pairs + # -- now there are only lines with ID-value but value might contain spaces (BAD FOR FOREACH LOOP) or special characters (BAD FOR REGEX MATCHING) + # 9th grep "${value}" = match only a line containg searched value + # 10th sed "s/^\([0-9]\+\).*$/\1/" = get only ID from the row - for xml_row in $(echo "${response}" | tr -d '\011\012\015' | sed "s/^.*[ ]*//g" | sed "s/[ ]*<\/data>.*$//g" | sed "s/>[ ]*<\([^\/]\)/><\1/g" | sed "s///g" | sed "s/[ ]*<\/row>/\n/g" | sed -n "/${sub_domain_regex}<\/name>.*TXT<\/rdtype>/p" | sed "s/^\([0-9]\+\)<\/ID>.*\(.*\)<\/rdata>.*$/\1-\2/" | grep "${value}" | sed "s/^\([0-9]\+\).*$/\1/"); do - _row_id="${xml_row}" - _info "WEDOS API: Found DNS row id ${_row_id} for domain ${domain}" - return 0 - done + for xml_row in $(echo "${response}" | tr -d '\011\012\015' | sed "s/^.*[ ]*//g" | sed "s/[ ]*<\/data>.*$//g" | sed "s/>[ ]*<\([^\/]\)/><\1/g" | sed "s///g" | sed "s/[ ]*<\/row>/\n/g" | sed -n "/${sub_domain_regex}<\/name>.*TXT<\/rdtype>/p" | sed "s/^\([0-9]\+\)<\/ID>.*\(.*\)<\/rdata>.*$/\1-\2/" | grep "${value}" | sed "s/^\([0-9]\+\).*$/\1/"); do + _row_id="${xml_row}" + _info "WEDOS API: Found DNS row id ${_row_id} for domain ${domain}" + return 0 + done - _info "WEDOS API: No TXT row found for domain '${domain}' with name '${sub_domain}' and value '${value}'" + _info "WEDOS API: No TXT row found for domain '${domain}' with name '${sub_domain}' and value '${value}'" - return 1 + return 1 } _wapi_delete_row() { - domain=$1 - row_id=$2 + domain=$1 + row_id=$2 - if [ -z "${domain}" ] || [ -z "${row_id}" ]; then - _err "Invalid request to delete domain dns row, domain: '${domain}' and row_id: '${row_id}', one of required input were not provided, implementation error!" - return 1 - fi + if [ -z "${domain}" ] || [ -z "${row_id}" ]; then + _err "Invalid request to delete domain dns row, domain: '${domain}' and row_id: '${row_id}', one of required input were not provided, implementation error!" + return 1 + fi - data=" \ + data=" \ ${domain} ${row_id} " - _debug "Deleting dns row using WAPI ..." + _debug "Deleting dns row using WAPI ..." - if ! _wapi_post "dns-row-delete" "${data}"; then - _err "Error on WAPI request to delete dns row, response: ${response}" - return 1 - fi + if ! _wapi_post "dns-row-delete" "${data}"; then + _err "Error on WAPI request to delete dns row, response: ${response}" + return 1 + fi - _debug "DNS row were deleted, response: ${response}" + _debug "DNS row were deleted, response: ${response}" - _info "WEDOS API: Required dns domain row with row_id '${row_id}' were correctly deleted at domain '${domain}'" + _info "WEDOS API: Required dns domain row with row_id '${row_id}' were correctly deleted at domain '${domain}'" - # Now we have to commit changes - _wapi_dns_commit "${domain}" + # Now we have to commit changes + _wapi_dns_commit "${domain}" - return "$?" + return "$?" } From 3ad668a429a7225ad5373d1c848cee5a10ac933a Mon Sep 17 00:00:00 2001 From: mxtuma Date: Fri, 20 Nov 2020 12:43:46 +0100 Subject: [PATCH 05/10] Added comments for future maintaining --- dnsapi/dns_wedos.sh | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/dnsapi/dns_wedos.sh b/dnsapi/dns_wedos.sh index b4df1db9..49974179 100644 --- a/dnsapi/dns_wedos.sh +++ b/dnsapi/dns_wedos.sh @@ -3,15 +3,25 @@ # This script has been created at June 2020, based on knowledge base of wedos.com provider. # It is intended to allow DNS-01 challenges for acme.sh using wedos's WAPI using XML. +# See WIKI page how to use it https://github.com/acmesh-official/acme.sh/wiki/dnsapi#117-use-wedos-dns-api + # Author Michal Tuma -# For issues send me an email +# For issues, please perform the action with --debug switch and report to https://github.com/acmesh-official/acme.sh/issues/3166 +# MAIN WAPI ENDPOINT WEDOS_WAPI_ENDPOINT="https://api.wedos.com/wapi/xml" +# WHEN SET TO ANYTHINK, THEN GENERATED XML WAPI REQUEST ADD TESTING SWITCH TESTING_STAGE= ######## Public functions ##################### -#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +# Main implemented function for acme.sh. +# Function manages provided user informations, parse requested domain and subdomain name and create new TXT row with provided value. +# WEDOS WAPI Requests usage: +# - dns-domains-list : to retrieve a list of valid managed domains and check input $fulldomain +# - dns-row-add : to add new TXT row to a $fulldomain with $txtvalue set +# - dns-domain-commit : to commit added dns row +# Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_wedos_add() { fulldomain=$1 txtvalue=$2 @@ -65,7 +75,14 @@ dns_wedos_add() { fi } -#fulldomain txtvalue +# Main implemented function for acme.sh +# This function verify provided domain if is managed by stored account, try to find TXT row for the domain and removes it if it is found. +# WEDOS WAPI Requests used: +# - dns-domains-list : to verify requested $fulldomain is managed and to parse what is subdomain from it +# - dns-rows-list : to verify if provided $txtvalue exists as TXT entry +# - dns-row-delete : to request deletion of TXT value +# - dns-domain-commit : to commit deletion +# Usage: rm _acme_challenge.www.domain.org "e89fhwie73869yhe993e27d4hi" dns_wedos_rm() { fulldomain=$1 txtvalue=$2 @@ -187,7 +204,7 @@ _wapi_post() { # _get_root() function, for provided full domain, like _acme_challenge.www.example.com verify if WEDOS contains a primary active domain and found what is subdomain # $1 - full domain to verify, ie _acme_challenge.www.example.com -# build ${_domain} found at WEDOS, like example.com and ${_sub_domain} from provided full domain, like _acme_challenge.www +# builds ${_domain} found at WEDOS, like example.com and ${_sub_domain} from provided full domain, like _acme_challenge.www _get_root() { domain=$1 From ab564a0393f061d461d73a295fa8d436e22b4317 Mon Sep 17 00:00:00 2001 From: mxtuma Date: Sun, 22 Nov 2020 19:09:57 +0100 Subject: [PATCH 06/10] Updated regarding failed Mac OS testing On Mac OS sed can't replace characters to new lines. I replaced to tabs in sed, with knowing there were no tab exists as I deleted them before, and then by tr I replaced all tabs by new lines, hopefully in a portable way. --- dnsapi/dns_wedos.sh | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/dnsapi/dns_wedos.sh b/dnsapi/dns_wedos.sh index 49974179..e7416b65 100644 --- a/dnsapi/dns_wedos.sh +++ b/dnsapi/dns_wedos.sh @@ -231,11 +231,12 @@ _get_root() { # 3rd sed "s/<\/data>.*$//g" = remove all the data after the data xml element - XML now contains only the content of data xml element # 4th sed "s/>[ ]*<\([^\/]\)/><\1/g" = remove all spaces between XML tag and XML start tag - XML now contains content of data xml element and is without spaces between end and start xml tags # 5th sed "s///g" = remove all domain xml start tags - XML now contains only ......... (next xml domain) - # 6th sed "s/[ ]*<\/domain>/\n/g"= replace all "spaces" by new line - now we create multiple lines each should contain only ......... - # 7th sed -n "/\([a-zA-Z0-9_\-\.]\+\)<\/name>primary<\/type>active<\/status>/p" = remove all non primary or non active domains lines - # 8th sed "s/\([a-zA-Z0-9_\-\.]\+\)<\/name>primary<\/type>active<\/status>/\1/g" = substitute for domain names only + # 6th sed "s/[ ]*<\/domain>/\t/g" = replace all "spaces" by tab - now we are preparing to create multiple lines + # 7th th '\011' '\n' = replace all tabs from previous sed (Mac OS change) - now we create multiple lines each should contain only ......... + # 8th sed -n "/\([a-zA-Z0-9_\-\.]\+\)<\/name>primary<\/type>active<\/status>/p" = remove all non primary or non active domains lines + # 9th sed "s/\([a-zA-Z0-9_\-\.]\+\)<\/name>primary<\/type>active<\/status>/\1/g" = substitute for domain names only - for xml_domain in $(echo "${response}" | tr -d '\011\012\015' | sed "s/^.*[ ]*//g" | sed "s/<\/data>.*$//g" | sed "s/>[ ]*<\([^\/]\)/><\1/g" | sed "s///g" | sed "s/[ ]*<\/domain>/\n/g" | sed -n "/\([a-zA-Z0-9_\-\.]\+\)<\/name>primary<\/type>active<\/status>/p" | sed "s/\([a-zA-Z0-9_\-\.]\+\)<\/name>primary<\/type>active<\/status>/\1/g"); do + for xml_domain in $(echo "${response}" | tr -d '\011\012\015' | sed "s/^.*[ ]*//g" | sed "s/<\/data>.*$//g" | sed "s/>[ ]*<\([^\/]\)/><\1/g" | sed "s///g" | sed "s/[ ]*<\/domain>/\t/g" | tr '\011' '\n' | sed -n "/\([a-zA-Z0-9_\-\.]\+\)<\/name>primary<\/type>active<\/status>/p" | sed "s/\([a-zA-Z0-9_\-\.]\+\)<\/name>primary<\/type>active<\/status>/\1/g"); do _debug "Found primary active domain: ${xml_domain}" if _endswith "${domain}" "${xml_domain}"; then length_difference=$(_math "${#domain} - ${#xml_domain}") @@ -357,14 +358,15 @@ _wapi_find_row() { # 3rd sed "s/[ ]*<\/data>.*$//g" = remove the end of the xml starting with xml end tag data - XML contains only the content of data xml element and is trimmed # 4th sed "s/>[ ]*<\([^\/]\)/><\1/g" = remove all spaces between XML tag and XML start tag - XML now contains content of data xml element and is without spaces between end and start xml tags # 5th sed "s///g" = remove all row xml start tags - XML now contains rows xml element content and its end tag - # 6th sed "s/[ ]*<\/row>/\n/g" = replace all "spaces" by new line - now we create multiple lines each should contain only single row xml content - # 7th sed -n "/${sub_domain_regex}<\/name>.*TXT<\/rdtype>/p" = remove all non TXT and non name matching row lines - now we have only xml lines with TXT rows matching requested values - # 8th sed "s/^\([0-9]\+\)<\/ID>.*\(.*\)<\/rdata>.*$/\1-\2/" = replace the whole lines to ID-value pairs + # 6th sed "s/[ ]*<\/row>/\t/g" = replace all "spaces" by tab - now we are preparing to create multiple lines + # 7th tr '\011' '\n' = replace all tabs with new lines (Mac OS X hint) - we create multiple lines each should contain only single row xml content + # 8th sed -n "/${sub_domain_regex}<\/name>.*TXT<\/rdtype>/p" = remove all non TXT and non name matching row lines - now we have only xml lines with TXT rows matching requested values + # 9th sed "s/^\([0-9]\+\)<\/ID>.*\(.*\)<\/rdata>.*$/\1-\2/" = replace the whole lines to ID-value pairs # -- now there are only lines with ID-value but value might contain spaces (BAD FOR FOREACH LOOP) or special characters (BAD FOR REGEX MATCHING) - # 9th grep "${value}" = match only a line containg searched value - # 10th sed "s/^\([0-9]\+\).*$/\1/" = get only ID from the row + # 10th grep "${value}" = match only a line containg searched value + # 11th sed "s/^\([0-9]\+\).*$/\1/" = get only ID from the row - for xml_row in $(echo "${response}" | tr -d '\011\012\015' | sed "s/^.*[ ]*//g" | sed "s/[ ]*<\/data>.*$//g" | sed "s/>[ ]*<\([^\/]\)/><\1/g" | sed "s///g" | sed "s/[ ]*<\/row>/\n/g" | sed -n "/${sub_domain_regex}<\/name>.*TXT<\/rdtype>/p" | sed "s/^\([0-9]\+\)<\/ID>.*\(.*\)<\/rdata>.*$/\1-\2/" | grep "${value}" | sed "s/^\([0-9]\+\).*$/\1/"); do + for xml_row in $(echo "${response}" | tr -d '\011\012\015' | sed "s/^.*[ ]*//g" | sed "s/[ ]*<\/data>.*$//g" | sed "s/>[ ]*<\([^\/]\)/><\1/g" | sed "s///g" | sed "s/[ ]*<\/row>/\t/g" | tr '\011' '\n' | sed -n "/${sub_domain_regex}<\/name>.*TXT<\/rdtype>/p" | sed "s/^\([0-9]\+\)<\/ID>.*\(.*\)<\/rdata>.*$/\1-\2/" | grep "${value}" | sed "s/^\([0-9]\+\).*$/\1/"); do _row_id="${xml_row}" _info "WEDOS API: Found DNS row id ${_row_id} for domain ${domain}" return 0 From 7edd13d102b0bb552e8095954b50b6af6dc17139 Mon Sep 17 00:00:00 2001 From: mxtuma Date: Tue, 24 Nov 2020 09:25:11 +0100 Subject: [PATCH 07/10] Update to pass Mac OS X tests. Mac OS X failed because sed regex uses GNU extension + as a repeater I had tested commited code with --posix prefix for sed to simulate Mac OS X implementation on linux Also Mac OS X can't replace to \n characters, this was resolved by replacing to \t and then translating to new lines using tr --- dnsapi/dns_wedos.sh | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/dnsapi/dns_wedos.sh b/dnsapi/dns_wedos.sh index e7416b65..8c71b607 100644 --- a/dnsapi/dns_wedos.sh +++ b/dnsapi/dns_wedos.sh @@ -225,6 +225,7 @@ _get_root() { fi # In for each cycle, try parse the response to find primary active domains + # - in order to success with MacOSX, always take care if all sed works with --posix when testing the all sed commmands # For cycle description: # 1st tr -d '\011\012\015' = remove all newlines and tab characters - whole XML became single line # 2nd sed "s/^.*[ ]*//g" = remove all the xml data from the beggining of the XML - XML now start with the content of element @@ -233,10 +234,10 @@ _get_root() { # 5th sed "s///g" = remove all domain xml start tags - XML now contains only ......... (next xml domain) # 6th sed "s/[ ]*<\/domain>/\t/g" = replace all "spaces" by tab - now we are preparing to create multiple lines # 7th th '\011' '\n' = replace all tabs from previous sed (Mac OS change) - now we create multiple lines each should contain only ......... - # 8th sed -n "/\([a-zA-Z0-9_\-\.]\+\)<\/name>primary<\/type>active<\/status>/p" = remove all non primary or non active domains lines - # 9th sed "s/\([a-zA-Z0-9_\-\.]\+\)<\/name>primary<\/type>active<\/status>/\1/g" = substitute for domain names only + # 8th sed -n "/\([a-zA-Z0-9_.-][a-zA-Z0-9_.-]*\)<\/name>primary<\/type>active<\/status>/p" = remove all non primary or non active domains lines + # 9th sed "s/\([a-zA-Z0-9_.-][a-zA-Z0-9_.-]*\)<\/name>primary<\/type>active<\/status>/\1/g" = substitute for domain names only - for xml_domain in $(echo "${response}" | tr -d '\011\012\015' | sed "s/^.*[ ]*//g" | sed "s/<\/data>.*$//g" | sed "s/>[ ]*<\([^\/]\)/><\1/g" | sed "s///g" | sed "s/[ ]*<\/domain>/\t/g" | tr '\011' '\n' | sed -n "/\([a-zA-Z0-9_\-\.]\+\)<\/name>primary<\/type>active<\/status>/p" | sed "s/\([a-zA-Z0-9_\-\.]\+\)<\/name>primary<\/type>active<\/status>/\1/g"); do + for xml_domain in $(echo "${response}" | tr -d '\011\012\015' | sed "s/^.*[ ]*//g" | sed "s/<\/data>.*$//g" | sed "s/>[ ]*<\([^\/]\)/><\1/g" | sed "s///g" | sed "s/[ ]*<\/domain>/\t/g" | tr '\011' '\n' | sed -n "/\([a-zA-Z0-9_.-][a-zA-Z0-9_.-]*\)<\/name>primary<\/type>active<\/status>/p" | sed "s/\([a-zA-Z0-9_.-][a-zA-Z0-9_.-]*\)<\/name>primary<\/type>active<\/status>/\1/g"); do _debug "Found primary active domain: ${xml_domain}" if _endswith "${domain}" "${xml_domain}"; then length_difference=$(_math "${#domain} - ${#xml_domain}") @@ -353,6 +354,7 @@ _wapi_find_row() { _debug "Subdomain regex '${sub_domain_regex}'" # In for each cycle loops over the domains rows, description: + # - when testing use sed --posix to test if compatible with MacOSX = avoid replacement to \n and using + as repeater one or more (instead use the same patern without repeater and then the same with *) # 1st tr -d '\011\012\015' = delete all newlines and tab characters - XML became a single line # 2nd sed "s/^.*[ ]*//g" = remove all from the beggining to the start of the content of the data xml element - XML is without unusefull beginning # 3rd sed "s/[ ]*<\/data>.*$//g" = remove the end of the xml starting with xml end tag data - XML contains only the content of data xml element and is trimmed @@ -361,12 +363,12 @@ _wapi_find_row() { # 6th sed "s/[ ]*<\/row>/\t/g" = replace all "spaces" by tab - now we are preparing to create multiple lines # 7th tr '\011' '\n' = replace all tabs with new lines (Mac OS X hint) - we create multiple lines each should contain only single row xml content # 8th sed -n "/${sub_domain_regex}<\/name>.*TXT<\/rdtype>/p" = remove all non TXT and non name matching row lines - now we have only xml lines with TXT rows matching requested values - # 9th sed "s/^\([0-9]\+\)<\/ID>.*\(.*\)<\/rdata>.*$/\1-\2/" = replace the whole lines to ID-value pairs + # 9th sed "s/^\([0-9][0-9]*\)<\/ID>.*\(.*\)<\/rdata>.*$/\1-\2/" = replace the whole lines to ID-value pairs # -- now there are only lines with ID-value but value might contain spaces (BAD FOR FOREACH LOOP) or special characters (BAD FOR REGEX MATCHING) # 10th grep "${value}" = match only a line containg searched value - # 11th sed "s/^\([0-9]\+\).*$/\1/" = get only ID from the row + # 11th sed "s/^\([0-9][0-9]*\).*$/\1/" = get only ID from the row - for xml_row in $(echo "${response}" | tr -d '\011\012\015' | sed "s/^.*[ ]*//g" | sed "s/[ ]*<\/data>.*$//g" | sed "s/>[ ]*<\([^\/]\)/><\1/g" | sed "s///g" | sed "s/[ ]*<\/row>/\t/g" | tr '\011' '\n' | sed -n "/${sub_domain_regex}<\/name>.*TXT<\/rdtype>/p" | sed "s/^\([0-9]\+\)<\/ID>.*\(.*\)<\/rdata>.*$/\1-\2/" | grep "${value}" | sed "s/^\([0-9]\+\).*$/\1/"); do + for xml_row in $(echo "${response}" | tr -d '\011\012\015' | sed "s/^.*[ ]*//g" | sed "s/[ ]*<\/data>.*$//g" | sed "s/>[ ]*<\([^\/]\)/><\1/g" | sed "s///g" | sed "s/[ ]*<\/row>/\t/g" | tr '\011' '\n' | sed -n "/${sub_domain_regex}<\/name>.*TXT<\/rdtype>/p" | sed "s/^\([0-9][0-9]*\)<\/ID>.*\(.*\)<\/rdata>.*$/\1-\2/" | grep "${value}" | sed "s/^\([0-9][0-9]*\).*$/\1/"); do _row_id="${xml_row}" _info "WEDOS API: Found DNS row id ${_row_id} for domain ${domain}" return 0 From 23e7b13c48650530bbac7b570e60f6ac3766d5ef Mon Sep 17 00:00:00 2001 From: mxtuma Date: Wed, 25 Nov 2020 10:28:11 +0100 Subject: [PATCH 08/10] Changes to sed newline replacement as Mac OS X test failed. --- dnsapi/dns_wedos.sh | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/dnsapi/dns_wedos.sh b/dnsapi/dns_wedos.sh index 8c71b607..e61083a7 100644 --- a/dnsapi/dns_wedos.sh +++ b/dnsapi/dns_wedos.sh @@ -12,6 +12,9 @@ WEDOS_WAPI_ENDPOINT="https://api.wedos.com/wapi/xml" # WHEN SET TO ANYTHINK, THEN GENERATED XML WAPI REQUEST ADD TESTING SWITCH TESTING_STAGE= +# NEW LINE +NEW_LINE='\ +' ######## Public functions ##################### @@ -232,12 +235,11 @@ _get_root() { # 3rd sed "s/<\/data>.*$//g" = remove all the data after the data xml element - XML now contains only the content of data xml element # 4th sed "s/>[ ]*<\([^\/]\)/><\1/g" = remove all spaces between XML tag and XML start tag - XML now contains content of data xml element and is without spaces between end and start xml tags # 5th sed "s///g" = remove all domain xml start tags - XML now contains only ......... (next xml domain) - # 6th sed "s/[ ]*<\/domain>/\t/g" = replace all "spaces" by tab - now we are preparing to create multiple lines - # 7th th '\011' '\n' = replace all tabs from previous sed (Mac OS change) - now we create multiple lines each should contain only ......... - # 8th sed -n "/\([a-zA-Z0-9_.-][a-zA-Z0-9_.-]*\)<\/name>primary<\/type>active<\/status>/p" = remove all non primary or non active domains lines - # 9th sed "s/\([a-zA-Z0-9_.-][a-zA-Z0-9_.-]*\)<\/name>primary<\/type>active<\/status>/\1/g" = substitute for domain names only + # 6th sed "s/[ ]*<\/domain>/${NEW_LINE}/g" = replace all "spaces" by tab - now we create multiple lines each should contain only ......... + # 7th sed -n "/\([a-zA-Z0-9_.-][a-zA-Z0-9_.-]*\)<\/name>primary<\/type>active<\/status>/p" = remove all non primary or non active domains lines + # 8th sed "s/\([a-zA-Z0-9_.-][a-zA-Z0-9_.-]*\)<\/name>primary<\/type>active<\/status>/\1/g" = substitute for domain names only - for xml_domain in $(echo "${response}" | tr -d '\011\012\015' | sed "s/^.*[ ]*//g" | sed "s/<\/data>.*$//g" | sed "s/>[ ]*<\([^\/]\)/><\1/g" | sed "s///g" | sed "s/[ ]*<\/domain>/\t/g" | tr '\011' '\n' | sed -n "/\([a-zA-Z0-9_.-][a-zA-Z0-9_.-]*\)<\/name>primary<\/type>active<\/status>/p" | sed "s/\([a-zA-Z0-9_.-][a-zA-Z0-9_.-]*\)<\/name>primary<\/type>active<\/status>/\1/g"); do + for xml_domain in $(echo "${response}" | tr -d '\011\012\015' | sed "s/^.*[ ]*//g" | sed "s/<\/data>.*$//g" | sed "s/>[ ]*<\([^\/]\)/><\1/g" | sed "s///g" | sed "s/[ ]*<\/domain>/${NEW_LINE}/g" | sed -n "/\([a-zA-Z0-9_.-][a-zA-Z0-9_.-]*\)<\/name>primary<\/type>active<\/status>/p" | sed "s/\([a-zA-Z0-9_.-][a-zA-Z0-9_.-]*\)<\/name>primary<\/type>active<\/status>/\1/g"); do _debug "Found primary active domain: ${xml_domain}" if _endswith "${domain}" "${xml_domain}"; then length_difference=$(_math "${#domain} - ${#xml_domain}") @@ -360,15 +362,14 @@ _wapi_find_row() { # 3rd sed "s/[ ]*<\/data>.*$//g" = remove the end of the xml starting with xml end tag data - XML contains only the content of data xml element and is trimmed # 4th sed "s/>[ ]*<\([^\/]\)/><\1/g" = remove all spaces between XML tag and XML start tag - XML now contains content of data xml element and is without spaces between end and start xml tags # 5th sed "s///g" = remove all row xml start tags - XML now contains rows xml element content and its end tag - # 6th sed "s/[ ]*<\/row>/\t/g" = replace all "spaces" by tab - now we are preparing to create multiple lines - # 7th tr '\011' '\n' = replace all tabs with new lines (Mac OS X hint) - we create multiple lines each should contain only single row xml content + # 6th sed "s/[ ]*<\/row>/${NEW_LINE}/g" = replace all "spaces" by tab - we create multiple lines each should contain only single row xml content # 8th sed -n "/${sub_domain_regex}<\/name>.*TXT<\/rdtype>/p" = remove all non TXT and non name matching row lines - now we have only xml lines with TXT rows matching requested values # 9th sed "s/^\([0-9][0-9]*\)<\/ID>.*\(.*\)<\/rdata>.*$/\1-\2/" = replace the whole lines to ID-value pairs # -- now there are only lines with ID-value but value might contain spaces (BAD FOR FOREACH LOOP) or special characters (BAD FOR REGEX MATCHING) # 10th grep "${value}" = match only a line containg searched value # 11th sed "s/^\([0-9][0-9]*\).*$/\1/" = get only ID from the row - for xml_row in $(echo "${response}" | tr -d '\011\012\015' | sed "s/^.*[ ]*//g" | sed "s/[ ]*<\/data>.*$//g" | sed "s/>[ ]*<\([^\/]\)/><\1/g" | sed "s///g" | sed "s/[ ]*<\/row>/\t/g" | tr '\011' '\n' | sed -n "/${sub_domain_regex}<\/name>.*TXT<\/rdtype>/p" | sed "s/^\([0-9][0-9]*\)<\/ID>.*\(.*\)<\/rdata>.*$/\1-\2/" | grep "${value}" | sed "s/^\([0-9][0-9]*\).*$/\1/"); do + for xml_row in $(echo "${response}" | tr -d '\011\012\015' | sed "s/^.*[ ]*//g" | sed "s/[ ]*<\/data>.*$//g" | sed "s/>[ ]*<\([^\/]\)/><\1/g" | sed "s///g" | sed "s/[ ]*<\/row>/${NEW_LINE}/g" | sed -n "/${sub_domain_regex}<\/name>.*TXT<\/rdtype>/p" | sed "s/^\([0-9][0-9]*\)<\/ID>.*\(.*\)<\/rdata>.*$/\1-\2/" | grep "${value}" | sed "s/^\([0-9][0-9]*\).*$/\1/"); do _row_id="${xml_row}" _info "WEDOS API: Found DNS row id ${_row_id} for domain ${domain}" return 0 From 82e525b4428e2fea8047a931c437db688b1f0fb8 Mon Sep 17 00:00:00 2001 From: mxtuma Date: Wed, 25 Nov 2020 13:38:31 +0100 Subject: [PATCH 09/10] spellcheck supress error for defining new line variable for Mac OS sed replacement --- dnsapi/dns_wedos.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/dnsapi/dns_wedos.sh b/dnsapi/dns_wedos.sh index e61083a7..e51e32ae 100644 --- a/dnsapi/dns_wedos.sh +++ b/dnsapi/dns_wedos.sh @@ -13,6 +13,7 @@ WEDOS_WAPI_ENDPOINT="https://api.wedos.com/wapi/xml" # WHEN SET TO ANYTHINK, THEN GENERATED XML WAPI REQUEST ADD TESTING SWITCH TESTING_STAGE= # NEW LINE +# shellcheck disable=SC1004 NEW_LINE='\ ' From e8acda94e127feb7af681af91588c080feccc0d2 Mon Sep 17 00:00:00 2001 From: mxtuma Date: Wed, 25 Nov 2020 18:16:15 +0100 Subject: [PATCH 10/10] Solaris changes, head -c replaced with printf --- dnsapi/dns_wedos.sh | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_wedos.sh b/dnsapi/dns_wedos.sh index e51e32ae..01762739 100644 --- a/dnsapi/dns_wedos.sh +++ b/dnsapi/dns_wedos.sh @@ -50,7 +50,8 @@ dns_wedos_add() { #build WEDOS_Authtoken _debug "WEDOS Authtoken were not saved yet, building" - WEDOS_Authtoken=$(printf '%s' "${WEDOS_Wapipass}" | _digest "sha1" "true" | head -c 40) + WEDOS_Authtoken=$(printf '%s' "${WEDOS_Wapipass}" | _digest "sha1" "true") + WEDOS_Authtoken=$(printf '%.40s' "${WEDOS_Authtoken}") _debug "WEDOS_Authtoken step 1, WAPI PASS sha1 sum: '${WEDOS_Authtoken}'" WEDOS_Authtoken="${WEDOS_Username}${WEDOS_Authtoken}" _debug "WEDOS_Authtoken step 2, username concat with token without hours: '${WEDOS_Authtoken}'" @@ -111,7 +112,8 @@ dns_wedos_rm() { #build WEDOS_Authtoken _debug "WEDOS Authtoken were not saved yet, building" - WEDOS_Authtoken=$(printf '%s' "${WEDOS_Wapipass}" | sha1sum | head -c 40) + WEDOS_Authtoken=$(printf '%s' "${WEDOS_Wapipass}" | _digest "sha1" "true") + WEDOS_Authtoken=$(printf '%.40s' "${WEDOS_Authtoken}") _debug "WEDOS_Authtoken step 1, WAPI PASS sha1 sum: '${WEDOS_Authtoken}'" WEDOS_Authtoken="${WEDOS_Username}${WEDOS_Authtoken}" _debug "WEDOS_Authtoken step 2, username concat with token without hours: '${WEDOS_Authtoken}'" @@ -166,7 +168,8 @@ _wapi_post() { # Prepare authentification token hour=$(TZ='Europe/Prague' date +%H) - token=$(printf '%s' "${WEDOS_Authtoken}${hour}" | _digest "sha1" "true" | head -c 40) + token=$(printf '%s' "${WEDOS_Authtoken}${hour}" | _digest "sha1" "true") + token=$(printf '%.40s' "${token}") _debug "Authentification token is '${token}'" # Build xml request