From b0ca4435fdbee019ac72f8df0cb304e1de5deffc Mon Sep 17 00:00:00 2001 From: Ciaran Walsh Date: Wed, 21 Feb 2024 00:21:09 +0000 Subject: [PATCH 01/66] Fix for empty error objects in response breaking extraction of domain validation types Fix for empty error objects in the response which mess up the extraction of domain validation types due to the closing brace in the error object prematurely matching the end of the search pattern. This seems to be a recent change with ZeroSSL in particular where "error":{} is being included in responses. There could potentially be a related issue if there is a complex error object ever returned in the validation check response where an embedded sub-object could lead to an incomplete extraction of the error message, roughly around line 5040. Adapted from fix suggested here: https://github.com/acmesh-official/acme.sh/issues/4933#issuecomment-1870499018 --- acme.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index 38ccaade..34ac49e8 100755 --- a/acme.sh +++ b/acme.sh @@ -4722,7 +4722,8 @@ $_authorizations_map" _debug keyauthorization "$keyauthorization" fi - entry="$(echo "$response" | _egrep_o '[^\{]*"type":"'$vtype'"[^\}]*')" + # Fix for empty error objects in response which mess up the original code, adapted from fix suggested here: https://github.com/acmesh-official/acme.sh/issues/4933#issuecomment-1870499018 + entry="$(echo "$response" | sed s/'"error":{}'/'"error":null'/ | _egrep_o '[^\{]*"type":"'$vtype'"[^\}]*')" _debug entry "$entry" if [ -z "$keyauthorization" -a -z "$entry" ]; then @@ -6283,7 +6284,8 @@ _deactivate() { fi _debug "Trigger validation." vtype="$(_getIdType "$_d_domain")" - entry="$(echo "$response" | _egrep_o '[^\{]*"type":"'$vtype'"[^\}]*')" + # Fix for empty error objects in response which mess up the original code, adapted from fix suggested here: https://github.com/acmesh-official/acme.sh/issues/4933#issuecomment-1870499018 + entry="$(echo "$response" | sed s/'"error":{}'/'"error":null'/ | _egrep_o '[^\{]*"type":"'$vtype'"[^\}]*')" _debug entry "$entry" if [ -z "$entry" ]; then _err "Error, can not get domain token $d" From 2beb2f5659e968423f91c8db2d634d85177fff2a Mon Sep 17 00:00:00 2001 From: Manuel Sanchez Pinar Date: Thu, 4 Jul 2024 14:03:20 +0200 Subject: [PATCH 02/66] fix: rage4 - add error 400 and TXT cleanup The following error happens if the header is set to 'Content-Type: application/json': {"statusCode":400,"message":"One or more errors occurred!", "errors":{"serializerErrors":["The input does not contain any JSON tokens. Expected the input to start with a valid JSON token, when isFinalBlock is true. LineNumber: 0 | BytePositionInLine: 0."]}} Fix TXT removal --- dnsapi/dns_rage4.sh | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_rage4.sh b/dnsapi/dns_rage4.sh index ad312759..c27fbc5f 100755 --- a/dnsapi/dns_rage4.sh +++ b/dnsapi/dns_rage4.sh @@ -42,6 +42,14 @@ dns_rage4_add() { _debug _domain_id "$_domain_id" _rage4_rest "createrecord/?id=$_domain_id&name=$fulldomain&content=$unquotedtxtvalue&type=TXT&active=true&ttl=1" + + # Response after adding a TXT record should be something like this: + # {"status":true,"id":28160443,"error":null} + if ! _contains "$response" '"error":null' >/dev/null; then + _err "Error while adding TXT record: '$response'" + return 1 + fi + return 0 } @@ -63,7 +71,12 @@ dns_rage4_rm() { _debug "Getting txt records" _rage4_rest "getrecords/?id=${_domain_id}" - _record_id=$(echo "$response" | sed -rn 's/.*"id":([[:digit:]]+)[^\}]*'"$txtvalue"'.*/\1/p') + _record_id=$(echo "$response" | tr '{' '\n' | grep '"TXT"' | grep "\"$txtvalue" | sed -rn 's/.*"id":([[:digit:]]+),.*/\1/p') + if [ -z "$_record_id" ]; then + _err "error retrieving the record_id of the new TXT record in order to delete it, got: '$_record_id'." + return 1 + fi + _rage4_rest "deleterecord/?id=${_record_id}" return 0 } @@ -105,8 +118,7 @@ _rage4_rest() { token_trimmed=$(echo "$RAGE4_TOKEN" | tr -d '"') auth=$(printf '%s:%s' "$username_trimmed" "$token_trimmed" | _base64) - export _H1="Content-Type: application/json" - export _H2="Authorization: Basic $auth" + export _H1="Authorization: Basic $auth" response="$(_get "$RAGE4_Api$ep")" From 29342e036f5b3e821be3770686bdef022623ef61 Mon Sep 17 00:00:00 2001 From: kir Date: Tue, 11 Mar 2025 08:07:38 +0000 Subject: [PATCH 03/66] Update _get_root url in dnsapi/dns_fornex.sh --- dnsapi/dns_fornex.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_fornex.sh b/dnsapi/dns_fornex.sh index 91e5491b..dcaa2297 100644 --- a/dnsapi/dns_fornex.sh +++ b/dnsapi/dns_fornex.sh @@ -95,7 +95,7 @@ _get_root() { return 1 fi - if ! _rest GET "dns/domain/"; then + if ! _rest GET "dns/domain/?q=$h"; then return 1 fi From dd29f970a2462c5bd4a6dfd6b0b89b05b368cf7c Mon Sep 17 00:00:00 2001 From: techknowlogick Date: Tue, 25 Mar 2025 19:27:17 -0400 Subject: [PATCH 04/66] Use endpoint environment variable for managed identities if set Some environments in azure don't use the default metadata endpoint, and instead inject an env var that should be used. --- dnsapi/dns_azure.sh | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_azure.sh b/dnsapi/dns_azure.sh index 03feaf63..f9d84706 100644 --- a/dnsapi/dns_azure.sh +++ b/dnsapi/dns_azure.sh @@ -340,8 +340,17 @@ _azure_getaccess_token() { if [ "$managedIdentity" = true ]; then # https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/how-to-use-vm-token#get-a-token-using-http - export _H1="Metadata: true" - response="$(_get http://169.254.169.254/metadata/identity/oauth2/token\?api-version=2018-02-01\&resource=https://management.azure.com/)" + if [ -n "$IDENTITY_ENDPOINT" ]; then + # Some Azure environments may set IDENTITY_ENDPOINT (formerly MSI_ENDPOINT) to have an alternative metadata endpoint + url="$IDENTITY_ENDPOINT?api-version=2019-08-01&resource=https://management.azure.com/" + headers="X-IDENTITY-HEADER: $IDENTITY_HEADER" + else + url="http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/" + headers="Metadata: true" + fi + + export _H1="$headers" + response="$(_get "$url")" response="$(echo "$response" | _normalizeJson)" accesstoken=$(echo "$response" | _egrep_o "\"access_token\":\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \") expires_on=$(echo "$response" | _egrep_o "\"expires_on\":\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \") From 45b99821725ef3359497cfe3b7b34e31101a3052 Mon Sep 17 00:00:00 2001 From: Meo597 <197331664+Meo597@users.noreply.github.com> Date: Tue, 15 Apr 2025 14:30:18 +0800 Subject: [PATCH 05/66] Add Spaceship DNS API --- dnsapi/dns_spaceship.sh | 197 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 197 insertions(+) create mode 100644 dnsapi/dns_spaceship.sh diff --git a/dnsapi/dns_spaceship.sh b/dnsapi/dns_spaceship.sh new file mode 100644 index 00000000..f94d9027 --- /dev/null +++ b/dnsapi/dns_spaceship.sh @@ -0,0 +1,197 @@ +#!/usr/bin/env sh +# shellcheck disable=SC2034 +dns_spaceship_info='Spaceship.com +Site: Spaceship.com +Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_spaceship +Options: + SPACESHIP_API_KEY Spaceship API Key + SPACESHIP_API_SECRET Spaceship API Secret + SPACESHIP_ROOT_DOMAIN (Optional) Manually specify the root domain if auto-detection fails +Issues: github.com/acmesh-official/acme.sh/issues/6304 +Author: Meow +' + +# Spaceship API +# https://docs.spaceship.dev/ + +######## Public functions ##################### + +SPACESHIP_API_BASE="https://spaceship.dev/api/v1" + +# Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +# Used to add txt record +dns_spaceship_add() { + fulldomain="$1" + txtvalue="$2" + + _info "Adding TXT record for $fulldomain with value $txtvalue" + + # Initialize API credentials and headers + if ! _spaceship_init; then + return 1 + fi + + # Detect root zone + if ! _get_root "$fulldomain"; then + return 1 + fi + + # Extract subdomain part relative to root domain + subdomain=$(echo "$fulldomain" | sed "s/\.$_domain$//") + if [ "$subdomain" = "$fulldomain" ]; then + _err "Failed to extract subdomain from $fulldomain relative to root domain $_domain" + return 1 + fi + _debug "Extracted subdomain: $subdomain for root domain: $_domain" + + # Escape txtvalue to prevent JSON injection (e.g., quotes in txtvalue) + escaped_txtvalue=$(echo "$txtvalue" | sed 's/"/\\"/g') + + # Prepare payload and URL for adding TXT record + # Note: 'name' in payload uses subdomain (e.g., _acme-challenge.sub) as required by Spaceship API + payload="{\"force\": true, \"items\": [{\"type\": \"TXT\", \"name\": \"$subdomain\", \"value\": \"$escaped_txtvalue\", \"ttl\": 600}]}" + url="$SPACESHIP_API_BASE/dns/records/$_domain" + + # Send API request + if _spaceship_api_request "PUT" "$url" "$payload"; then + _info "Successfully added TXT record for $fulldomain" + return 0 + else + _err "Failed to add TXT record. If the domain $_domain is incorrect, set SPACESHIP_ROOT_DOMAIN to the correct root domain." + return 1 + fi +} + +# Usage: fulldomain txtvalue +# Used to remove the txt record after validation +dns_spaceship_rm() { + fulldomain="$1" + txtvalue="$2" + + _info "Removing TXT record for $fulldomain with value $txtvalue" + + # Initialize API credentials and headers + if ! _spaceship_init; then + return 1 + fi + + # Detect root zone + if ! _get_root "$fulldomain"; then + return 1 + fi + + # Extract subdomain part relative to root domain + subdomain=$(echo "$fulldomain" | sed "s/\.$_domain$//") + if [ "$subdomain" = "$fulldomain" ]; then + _err "Failed to extract subdomain from $fulldomain relative to root domain $_domain" + return 1 + fi + _debug "Extracted subdomain: $subdomain for root domain: $_domain" + + # Escape txtvalue to prevent JSON injection + escaped_txtvalue=$(echo "$txtvalue" | sed 's/"/\\"/g') + + # Prepare payload and URL for deleting TXT record + # Note: 'name' in payload uses subdomain (e.g., _acme-challenge.sub) as required by Spaceship API + payload="{\"type\": \"TXT\", \"name\": \"$subdomain\", \"value\": \"$escaped_txtvalue\"}" + url="$SPACESHIP_API_BASE/dns/records/$_domain" + + # Send API request + if _spaceship_api_request "DELETE" "$url" "$payload"; then + _info "Successfully deleted TXT record for $fulldomain" + return 0 + else + _err "Failed to delete TXT record. If the domain $_domain is incorrect, set SPACESHIP_ROOT_DOMAIN to the correct root domain." + return 1 + fi +} + +#################### Private functions below ################################## + +_spaceship_init() { + SPACESHIP_API_KEY="${SPACESHIP_API_KEY:-$(_readaccountconf_mutable SPACESHIP_API_KEY)}" + SPACESHIP_API_SECRET="${SPACESHIP_API_SECRET:-$(_readaccountconf_mutable SPACESHIP_API_SECRET)}" + + if [ -z "$SPACESHIP_API_KEY" ] || [ -z "$SPACESHIP_API_SECRET" ]; then + _err "Spaceship API credentials are not set. Please set SPACESHIP_API_KEY and SPACESHIP_API_SECRET." + _err "Ensure ~/.acme.sh directory has restricted permissions (chmod 700 ~/.acme.sh) to protect credentials." + return 1 + fi + + # Save credentials to account config for future renewals + _saveaccountconf_mutable SPACESHIP_API_KEY "$SPACESHIP_API_KEY" + _saveaccountconf_mutable SPACESHIP_API_SECRET "$SPACESHIP_API_SECRET" + + # Set common headers for API requests + export _H1="X-API-Key: $SPACESHIP_API_KEY" + export _H2="X-API-Secret: $SPACESHIP_API_SECRET" + export _H3="Content-Type: application/json" + return 0 +} + +_get_root() { + domain="$1" + + # Check if user manually specified root domain + SPACESHIP_ROOT_DOMAIN="${SPACESHIP_ROOT_DOMAIN:-$(_readaccountconf_mutable SPACESHIP_ROOT_DOMAIN)}" + if [ -n "$SPACESHIP_ROOT_DOMAIN" ]; then + _domain="$SPACESHIP_ROOT_DOMAIN" + _debug "Using manually specified or saved root domain: $_domain" + # Ensure it's saved (in case it was read from config but not saved previously) + _saveaccountconf_mutable SPACESHIP_ROOT_DOMAIN "$SPACESHIP_ROOT_DOMAIN" + return 0 + fi + + # Split domain into parts and try from back to front + _debug "Detecting root zone for $domain from back to front" + _parts=$(echo "$domain" | tr '.' '\n' | wc -l) + if [ "$_parts" -lt 2 ]; then + _err "Invalid domain format for $domain" + return 1 + fi + + # Start with the last 2 parts (e.g., example.com) and move forward + i=2 + max_attempts=$((_parts + 1)) + while [ $i -le $max_attempts ]; do + _cutdomain=$(echo "$domain" | rev | cut -d . -f 1-$i | rev) + if [ -z "$_cutdomain" ]; then + break + fi + + _debug "Checking if $_cutdomain is root zone" + if _spaceship_api_request "GET" "$SPACESHIP_API_BASE/dns/records/$_cutdomain?take=1&skip=0"; then + _domain="$_cutdomain" + _debug "Root zone found: $_domain" + # Save the detected root domain to configuration for future use + _saveaccountconf_mutable SPACESHIP_ROOT_DOMAIN "$_domain" + _info "Root domain $_domain saved to configuration for future use." + return 0 + fi + i=$((i + 1)) + done + + _err "Could not detect root zone for $domain after $max_attempts attempts. Please set SPACESHIP_ROOT_DOMAIN manually." + return 1 +} + +_spaceship_api_request() { + method="$1" + url="$2" + payload="$3" + + _debug "Sending $method request to $url with payload $payload" + if [ "$method" = "GET" ]; then + response="$(_get "$url")" + else + response="$(_post "$payload" "$url" "" "$method")" + fi + + if [ "$?" != "0" ]; then + _err "API request failed. Response: $response" + return 1 + fi + + _debug "API response: $response" + return 0 +} From 5e8b40faf65fe2d712698798a25aa209a1c0bdd9 Mon Sep 17 00:00:00 2001 From: Meo597 <197331664+Meo597@users.noreply.github.com> Date: Tue, 15 Apr 2025 15:10:51 +0800 Subject: [PATCH 06/66] Spaceship: fix rm --- dnsapi/dns_spaceship.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dnsapi/dns_spaceship.sh b/dnsapi/dns_spaceship.sh index f94d9027..53dece76 100644 --- a/dnsapi/dns_spaceship.sh +++ b/dnsapi/dns_spaceship.sh @@ -93,7 +93,7 @@ dns_spaceship_rm() { # Prepare payload and URL for deleting TXT record # Note: 'name' in payload uses subdomain (e.g., _acme-challenge.sub) as required by Spaceship API - payload="{\"type\": \"TXT\", \"name\": \"$subdomain\", \"value\": \"$escaped_txtvalue\"}" + payload="[{\"type\": \"TXT\", \"name\": \"$subdomain\", \"value\": \"$escaped_txtvalue\"}]" url="$SPACESHIP_API_BASE/dns/records/$_domain" # Send API request @@ -156,6 +156,7 @@ _get_root() { while [ $i -le $max_attempts ]; do _cutdomain=$(echo "$domain" | rev | cut -d . -f 1-$i | rev) if [ -z "$_cutdomain" ]; then + _debug "Reached end of domain parts." break fi From e55a54f3d4cfb92102f3a5036882a64100f563a0 Mon Sep 17 00:00:00 2001 From: Meo597 <197331664+Meo597@users.noreply.github.com> Date: Tue, 15 Apr 2025 20:30:43 +0800 Subject: [PATCH 07/66] Spaceship: fix get_root --- dnsapi/dns_spaceship.sh | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/dnsapi/dns_spaceship.sh b/dnsapi/dns_spaceship.sh index 53dece76..d70a9a81 100644 --- a/dnsapi/dns_spaceship.sh +++ b/dnsapi/dns_spaceship.sh @@ -132,47 +132,49 @@ _spaceship_init() { _get_root() { domain="$1" - # Check if user manually specified root domain + # Check manual override SPACESHIP_ROOT_DOMAIN="${SPACESHIP_ROOT_DOMAIN:-$(_readaccountconf_mutable SPACESHIP_ROOT_DOMAIN)}" if [ -n "$SPACESHIP_ROOT_DOMAIN" ]; then _domain="$SPACESHIP_ROOT_DOMAIN" _debug "Using manually specified or saved root domain: $_domain" - # Ensure it's saved (in case it was read from config but not saved previously) _saveaccountconf_mutable SPACESHIP_ROOT_DOMAIN "$SPACESHIP_ROOT_DOMAIN" return 0 fi - # Split domain into parts and try from back to front - _debug "Detecting root zone for $domain from back to front" - _parts=$(echo "$domain" | tr '.' '\n' | wc -l) - if [ "$_parts" -lt 2 ]; then - _err "Invalid domain format for $domain" - return 1 - fi + _debug "Detecting root zone for '$domain'" - # Start with the last 2 parts (e.g., example.com) and move forward i=2 - max_attempts=$((_parts + 1)) - while [ $i -le $max_attempts ]; do - _cutdomain=$(echo "$domain" | rev | cut -d . -f 1-$i | rev) + p=1 + while true; do + _cutdomain=$(printf "%s" "$domain" | cut -d . -f "$i"-100) + + _debug "Attempt i=$i: Checking if '$_cutdomain' is root zone (cut ret=$?)" + if [ -z "$_cutdomain" ]; then - _debug "Reached end of domain parts." + _debug "Cut resulted in empty string, root zone not found." break fi - _debug "Checking if $_cutdomain is root zone" + # Call the API to check if this _cutdomain is a manageable zone if _spaceship_api_request "GET" "$SPACESHIP_API_BASE/dns/records/$_cutdomain?take=1&skip=0"; then + # API call succeeded (HTTP 200 OK for GET /dns/records) _domain="$_cutdomain" - _debug "Root zone found: $_domain" - # Save the detected root domain to configuration for future use + _debug "Root zone found: '$_domain'" + + # Save the detected root domain _saveaccountconf_mutable SPACESHIP_ROOT_DOMAIN "$_domain" - _info "Root domain $_domain saved to configuration for future use." + _info "Root domain '$_domain' saved to configuration for future use." + return 0 fi + + _debug "API check failed for '$_cutdomain'. Continuing search." + + p=$i i=$((i + 1)) done - _err "Could not detect root zone for $domain after $max_attempts attempts. Please set SPACESHIP_ROOT_DOMAIN manually." + _err "Could not detect root zone for '$domain'. Please set SPACESHIP_ROOT_DOMAIN manually." return 1 } From 827315e059c1b8ceba9828a9cbaf062768eeec6d Mon Sep 17 00:00:00 2001 From: Meo597 <197331664+Meo597@users.noreply.github.com> Date: Tue, 15 Apr 2025 20:49:48 +0800 Subject: [PATCH 08/66] Spaceship: valid api response --- dnsapi/dns_spaceship.sh | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_spaceship.sh b/dnsapi/dns_spaceship.sh index d70a9a81..501131b8 100644 --- a/dnsapi/dns_spaceship.sh +++ b/dnsapi/dns_spaceship.sh @@ -195,6 +195,18 @@ _spaceship_api_request() { return 1 fi - _debug "API response: $response" - return 0 + _debug "API response body: $response" + + if [ "$method" = "GET" ]; then + if _contains "$(_head_n 1 <"$HTTP_HEADER")" '200'; then + return 0 + fi + else + if _contains "$(_head_n 1 <"$HTTP_HEADER")" '204'; then + return 0 + fi + fi + + _debug "API response header: $HTTP_HEADER" + return 1 } From e81635f23ded487329195b09ff10e1559c15db0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alin=20Tr=C4=83istaru?= Date: Fri, 18 Apr 2025 00:25:10 +0200 Subject: [PATCH 09/66] check curl vault http return code --- deploy/vault.sh | 98 ++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 84 insertions(+), 14 deletions(-) diff --git a/deploy/vault.sh b/deploy/vault.sh index 03a0de83..89994f4b 100644 --- a/deploy/vault.sh +++ b/deploy/vault.sh @@ -80,10 +80,15 @@ vault_deploy() { if [ -n "$VAULT_RENEW_TOKEN" ]; then URL="$VAULT_ADDR/v1/auth/token/renew-self" _info "Renew the Vault token to default TTL" - if ! _post "" "$URL" >/dev/null; then + _response=$(_post "" "$URL") + if [ "$?" != "0" ]; then _err "Failed to renew the Vault token" return 1 fi + if echo "$_response" | grep -q '"errors":\['; then + _err "Failed to renew the Vault token: $_response" + return 1 + fi fi URL="$VAULT_ADDR/v1/$VAULT_PREFIX/$_cdomain" @@ -91,29 +96,85 @@ vault_deploy() { if [ -n "$VAULT_FABIO_MODE" ]; then _info "Writing certificate and key to $URL in Fabio mode" if [ -n "$VAULT_KV_V2" ]; then - _post "{ \"data\": {\"cert\": \"$_cfullchain\", \"key\": \"$_ckey\"} }" "$URL" >/dev/null || return 1 + _response=$(_post "{ \"data\": {\"cert\": \"$_cfullchain\", \"key\": \"$_ckey\"} }" "$URL") + if [ "$?" != "0" ]; then return 1; fi + if echo "$_response" | grep -q '"errors":\['; then + _err "Vault error: $_response" + return 1 + fi else - _post "{\"cert\": \"$_cfullchain\", \"key\": \"$_ckey\"}" "$URL" >/dev/null || return 1 + _response=$(_post "{\"cert\": \"$_cfullchain\", \"key\": \"$_ckey\"}" "$URL") + if [ "$?" != "0" ]; then return 1; fi + if echo "$_response" | grep -q '"errors":\['; then + _err "Vault error: $_response" + return 1 + fi fi else if [ -n "$VAULT_KV_V2" ]; then _info "Writing certificate to $URL/cert.pem" - _post "{\"data\": {\"value\": \"$_ccert\"}}" "$URL/cert.pem" >/dev/null || return 1 + _response=$(_post "{\"data\": {\"value\": \"$_ccert\"}}" "$URL/cert.pem") + if [ "$?" != "0" ]; then return 1; fi + if echo "$_response" | grep -q '"errors":\['; then + _err "Vault error writing cert.pem: $_response" + return 1 + fi + _info "Writing key to $URL/cert.key" - _post "{\"data\": {\"value\": \"$_ckey\"}}" "$URL/cert.key" >/dev/null || return 1 + _response=$(_post "{\"data\": {\"value\": \"$_ckey\"}}" "$URL/cert.key") + if [ "$?" != "0" ]; then return 1; fi + if echo "$_response" | grep -q '"errors":\['; then + _err "Vault error writing cert.key: $_response" + return 1 + fi + _info "Writing CA certificate to $URL/ca.pem" - _post "{\"data\": {\"value\": \"$_cca\"}}" "$URL/ca.pem" >/dev/null || return 1 + _response=$(_post "{\"data\": {\"value\": \"$_cca\"}}" "$URL/ca.pem") + if [ "$?" != "0" ]; then return 1; fi + if echo "$_response" | grep -q '"errors":\['; then + _err "Vault error writing ca.pem: $_response" + return 1 + fi + _info "Writing full-chain certificate to $URL/fullchain.pem" - _post "{\"data\": {\"value\": \"$_cfullchain\"}}" "$URL/fullchain.pem" >/dev/null || return 1 + _response=$(_post "{\"data\": {\"value\": \"$_cfullchain\"}}" "$URL/fullchain.pem") + if [ "$?" != "0" ]; then return 1; fi + if echo "$_response" | grep -q '"errors":\['; then + _err "Vault error writing fullchain.pem: $_response" + return 1 + fi else _info "Writing certificate to $URL/cert.pem" - _post "{\"value\": \"$_ccert\"}" "$URL/cert.pem" >/dev/null || return 1 + _response=$(_post "{\"value\": \"$_ccert\"}" "$URL/cert.pem") + if [ "$?" != "0" ]; then return 1; fi + if echo "$_response" | grep -q '"errors":\['; then + _err "Vault error writing cert.pem: $_response" + return 1 + fi + _info "Writing key to $URL/cert.key" - _post "{\"value\": \"$_ckey\"}" "$URL/cert.key" >/dev/null || return 1 + _response=$(_post "{\"value\": \"$_ckey\"}" "$URL/cert.key") + if [ "$?" != "0" ]; then return 1; fi + if echo "$_response" | grep -q '"errors":\['; then + _err "Vault error writing cert.key: $_response" + return 1 + fi + _info "Writing CA certificate to $URL/ca.pem" - _post "{\"value\": \"$_cca\"}" "$URL/ca.pem" >/dev/null || return 1 + _response=$(_post "{\"value\": \"$_cca\"}" "$URL/ca.pem") + if [ "$?" != "0" ]; then return 1; fi + if echo "$_response" | grep -q '"errors":\['; then + _err "Vault error writing ca.pem: $_response" + return 1 + fi + _info "Writing full-chain certificate to $URL/fullchain.pem" - _post "{\"value\": \"$_cfullchain\"}" "$URL/fullchain.pem" >/dev/null || return 1 + _response=$(_post "{\"value\": \"$_cfullchain\"}" "$URL/fullchain.pem") + if [ "$?" != "0" ]; then return 1; fi + if echo "$_response" | grep -q '"errors":\['; then + _err "Vault error writing fullchain.pem: $_response" + return 1 + fi fi # To make it compatible with the wrong ca path `chain.pem` which was used in former versions @@ -121,11 +182,20 @@ vault_deploy() { _err "The CA certificate has moved from chain.pem to ca.pem, if you don't depend on chain.pem anymore, you can delete it to avoid this warning" _info "Updating CA certificate to $URL/chain.pem for backward compatibility" if [ -n "$VAULT_KV_V2" ]; then - _post "{\"data\": {\"value\": \"$_cca\"}}" "$URL/chain.pem" >/dev/null || return 1 + _response=$(_post "{\"data\": {\"value\": \"$_cca\"}}" "$URL/chain.pem") + if [ "$?" != "0" ]; then return 1; fi + if echo "$_response" | grep -q '"errors":\['; then + _err "Vault error writing chain.pem: $_response" + return 1 + fi else - _post "{\"value\": \"$_cca\"}" "$URL/chain.pem" >/dev/null || return 1 + _response=$(_post "{\"value\": \"$_cca\"}" "$URL/chain.pem") + if [ "$?" != "0" ]; then return 1; fi + if echo "$_response" | grep -q '"errors":\['; then + _err "Vault error writing chain.pem: $_response" + return 1 + fi fi fi fi - } From 2d365efe564362b1d29964a4acb0a7a89e846e27 Mon Sep 17 00:00:00 2001 From: rka Date: Fri, 18 Apr 2025 02:48:48 +0300 Subject: [PATCH 10/66] Add Edgecenter DNS API --- dnsapi/dns_edgecenter.sh | 163 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 dnsapi/dns_edgecenter.sh diff --git a/dnsapi/dns_edgecenter.sh b/dnsapi/dns_edgecenter.sh new file mode 100644 index 00000000..cdd150df --- /dev/null +++ b/dnsapi/dns_edgecenter.sh @@ -0,0 +1,163 @@ +#!/usr/bin/env sh +# shellcheck disable=SC2034 + +# EdgeCenter DNS API integration for acme.sh +# Author: Konstantin Ruchev +dns_edgecenter_info='edgecenter DNS API +Site: https://edgecenter.ru +Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_edgecenter +Options: + EDGECENTER_API_KEY auth APIKey' + +EDGECENTER_API="https://api.edgecenter.ru" +DOMAIN_TYPE= +DOMAIN_MASTER= + +######## Public functions ##################### + +#Usage: dns_edgecenter_add _acme-challenge.www.domain.com "TXT_RECORD_VALUE" +dns_edgecenter_add() { + fulldomain="$1" + txtvalue="$2" + + _info "Using EdgeCenter DNS API" + + if ! _dns_edgecenter_init_check; then + return 1 + fi + + _debug "Detecting root zone for $fulldomain" + if ! _get_root "$fulldomain"; then + return 1 + fi + + subdomain="${fulldomain%."$_zone"}" + subdomain=${subdomain%.} + + _debug "Zone: $_zone" + _debug "Subdomain: $subdomain" + _debug "TXT value: $txtvalue" + + payload='{"resource_records": [ { "content": ["'"$txtvalue"'"] } ], "ttl": 60 }' + _dns_edgecenter_http_api_call "post" "dns/v2/zones/$_zone/$subdomain.$_zone/txt" "$payload" + + if _contains "$response" '"error":"rrset is already exists"'; then + _debug "RRSet exists, merging values" + _dns_edgecenter_http_api_call "get" "dns/v2/zones/$_zone/$subdomain.$_zone/txt" + current="$response" + newlist="" + for v in $(echo "$current" | sed -n 's/.*"content":\["\([^"]*\)"\].*/\1/p'); do + newlist="$newlist {\"content\":[\"$v\"]}," + done + newlist="$newlist{\"content\":[\"$txtvalue\"]}" + putdata="{\"resource_records\":[${newlist}]} +" + _dns_edgecenter_http_api_call "put" "dns/v2/zones/$_zone/$subdomain.$_zone/txt" "$putdata" + _info "Updated existing RRSet with new TXT value." + return 0 + fi + + if _contains "$response" '"exception":'; then + _err "Record cannot be added." + return 1 + fi + + _info "TXT record added successfully." + return 0 +} + +#Usage: dns_edgecenter_rm _acme-challenge.www.domain.com "TXT_RECORD_VALUE" +dns_edgecenter_rm() { + fulldomain="$1" + txtvalue="$2" + + _info "Removing TXT record for $fulldomain" + + if ! _dns_edgecenter_init_check; then + return 1 + fi + + if ! _get_root "$fulldomain"; then + return 1 + fi + + subdomain="${fulldomain%."$_zone"}" + subdomain=${subdomain%.} + + _dns_edgecenter_http_api_call "delete" "dns/v2/zones/$_zone/$subdomain.$_zone/txt" + + if [ -z "$response" ]; then + _info "TXT record deleted successfully." + else + _info "TXT record may not have been deleted: $response" + fi + return 0 +} + +#################### Private functions below ################################## + +_dns_edgecenter_init_check() { + EDGECENTER_API_KEY="${EDGECENTER_API_KEY:-$(_readaccountconf_mutable EDGECENTER_API_KEY)}" + if [ -z "$EDGECENTER_API_KEY" ]; then + _err "EDGECENTER_API_KEY was not exported." + return 1 + fi + + _saveaccountconf_mutable EDGECENTER_API_KEY "$EDGECENTER_API_KEY" + export _H1="Authorization: APIKey $EDGECENTER_API_KEY" + + _dns_edgecenter_http_api_call "get" "dns/v2/clients/me/features" + if ! _contains "$response" '"id":'; then + _err "Invalid API key." + return 1 + fi + return 0 +} + +_get_root() { + domain="$1" + i=1 + while true; do + h=$(printf "%s" "$domain" | cut -d . -f "$i"-) + if [ -z "$h" ]; then + return 1 + fi + _dns_edgecenter_http_api_call "get" "dns/v2/zones/$h" + if ! _contains "$response" 'zone is not found'; then + _zone="$h" + return 0 + fi + i=$((i + 1)) + done + return 1 +} + +_dns_edgecenter_http_api_call() { + mtd="$1" + endpoint="$2" + data="$3" + + export _H1="Authorization: APIKey $EDGECENTER_API_KEY" + + case "$mtd" in + get) + response="$(_get "$EDGECENTER_API/$endpoint")" + ;; + post) + response="$(_post "$data" "$EDGECENTER_API/$endpoint")" + ;; + delete) + response="$(_post "" "$EDGECENTER_API/$endpoint" "" "DELETE")" + ;; + put) + response="$(_post "$data" "$EDGECENTER_API/$endpoint" "" "PUT")" + ;; + *) + _err "Unknown HTTP method $mtd" + return 1 + ;; + esac + + _debug "HTTP $mtd response: $response" + return 0 +} From 1ce8d3ae9bf03146bc6cf0142cce8e4f4898db8c Mon Sep 17 00:00:00 2001 From: neil Date: Wed, 23 Apr 2025 21:42:39 +0200 Subject: [PATCH 11/66] start 3.1.2 --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index dd21785d..4d75ab62 100755 --- a/acme.sh +++ b/acme.sh @@ -1,6 +1,6 @@ #!/usr/bin/env sh -VER=3.1.1 +VER=3.1.2 PROJECT_NAME="acme.sh" From 24a1b93842dda7ce74a83a6165e7a642c499df07 Mon Sep 17 00:00:00 2001 From: Joe Bauser Date: Sat, 2 Mar 2024 13:01:59 -0500 Subject: [PATCH 12/66] Add deploy/zyxel_gs1900.sh Add support for deploying to the Zyxel GS1900 line of switches as long as those switches are running at least firmware V2.80. Tested on a Zyxel GS1900-8 and GS1900-24E Resolves #5042 --- deploy/zyxel_gs1900.sh | 500 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 500 insertions(+) create mode 100644 deploy/zyxel_gs1900.sh diff --git a/deploy/zyxel_gs1900.sh b/deploy/zyxel_gs1900.sh new file mode 100644 index 00000000..443a5b05 --- /dev/null +++ b/deploy/zyxel_gs1900.sh @@ -0,0 +1,500 @@ +#!/usr/bin/env sh + +# Deploy certificates to Zyxel GS1900 series switches +# +# This script uses the https web administration interface in order +# to upload updated certificates to Zyxel GS1900 series switches. +# Only a few models have been tested but untested switches from the +# same model line may work as well. If you test and confirm a switch +# as working please submit a pull request updating this compatibility +# list! +# +# Known Issues: +# 1. This is a consumer grade switch and is a bit underpowered +# the longer the RSA key size the slower your switch web UI +# will be. RSA 2048 will work, RSA 4096 will work but you may +# experience performance problems. +# 2. You must use RSA certificates. The switch will reject EC-256 +# and EC-384 certificates in firmware 2.80 +# See: https://community.zyxel.com/en/discussion/21506/bug-cannot-import-ssl-cert-on-gs1900-8-and-gs1900-24e-firmware-v2-80/ +# +# Current GS1900 Switch Compatibility: +# GS1900-8 - Working as of firmware V2.80 +# GS1900-8HP - Untested +# GS1900-10HP - Untested +# GS1900-16 - Untested +# GS1900-24 - Untested +# GS1900-24E - Working as of firmware V2.80 +# GS1900-24EP - Untested +# GS1900-24HP - Untested +# GS1900-48 - Untested +# GS1900-48HP - Untested +# +# Prerequisite Setup Steps: +# 1. Install at least firmware V2.80 on your switch +# 2. Enable HTTPS web management on your switch +# +# Usage: +# 1. Ensure the switch has firmware V2.80 or later. +# 2. Ensure the switch has HTTPS management enabled. +# 3. Set the appropriate environment variables for your environment. +# +# DEPLOY_ZYXEL_SWITCH - The switch hostname. (Default: _cdomain) +# DEPLOY_ZYXEL_SWITCH_USER - The webadmin user. (Default: admin) +# DEPLOY_ZYXEL_SWITCH_PASSWORD - The webadmin password for the switch. +# DEPLOY_ZYXEL_SWITCH_REBOOT - If "1" reboot after update. (Default: "0") +# +# 4. Run the deployment plugin: +# acme.sh --deploy --deploy-hook zyxel_gs1900 -d example.com +# +# returns 0 means success, otherwise error. + +#domain keyfile certfile cafile fullchain +zyxel_gs1900_deploy() { + _zyxel_gs1900_minimum_firmware_version="v2.80" + + _cdomain="$1" + _ckey="$2" + _ccert="$3" + _cca="$4" + _cfullchain="$5" + + _debug _cdomain "$_cdomain" + _debug2 _ckey "$_ckey" + _debug _ccert "$_ccert" + _debug _cca "$_cca" + _debug _cfullchain "$_cfullchain" + + _getdeployconf DEPLOY_ZYXEL_SWITCH + _getdeployconf DEPLOY_ZYXEL_SWITCH_USER + _getdeployconf DEPLOY_ZYXEL_SWITCH_PASSWORD + _getdeployconf DEPLOY_ZYXEL_SWITCH_REBOOT + + if [ -z "$DEPLOY_ZYXEL_SWITCH" ]; then + DEPLOY_ZYXEL_SWITCH="$_cdomain" + fi + + if [ -z "$DEPLOY_ZYXEL_SWITCH_USER" ]; then + DEPLOY_ZYXEL_SWITCH_USER="admin" + fi + + if [ -z "$DEPLOY_ZYXEL_SWITCH_PASSWORD" ]; then + DEPLOY_ZYXEL_SWITCH_PASSWORD="1234" + fi + + if [ -z "$DEPLOY_ZYXEL_SWITCH_REBOOT" ]; then + DEPLOY_ZYXEL_SWITCH_REBOOT="0" + fi + + _savedeployconf DEPLOY_ZYXEL_SWITCH "$DEPLOY_ZYXEL_SWITCH" + _savedeployconf DEPLOY_ZYXEL_SWITCH_USER "$DEPLOY_ZYXEL_SWITCH_USER" + _savedeployconf DEPLOY_ZYXEL_SWITCH_PASSWORD "$DEPLOY_ZYXEL_SWITCH_PASSWORD" + _savedeployconf DEPLOY_ZYXEL_SWITCH_REBOOT "$DEPLOY_ZYXEL_SWITCH_REBOOT" + + _debug DEPLOY_ZYXEL_SWITCH "$DEPLOY_ZYXEL_SWITCH" + _debug DEPLOY_ZYXEL_SWITCH_USER "$DEPLOY_ZYXEL_SWITCH_USER" + _secure_debug DEPLOY_ZYXEL_SWITCH_PASSWORD "$DEPLOY_ZYXEL_SWITCH_PASSWORD" + _debug DEPLOY_ZYXEL_SWITCH_REBOOT "$DEPLOY_ZYXEL_SWITCH_REBOOT" + + _zyxel_switch_base_uri="https://${DEPLOY_ZYXEL_SWITCH}" + + _info "Beginning to deploy to a Zyxel GS1900 series switch at ${_zyxel_switch_base_uri}." + _zyxel_gs1900_deployment_precheck || return $? + + _zyxel_gs1900_should_update + if [ "$?" != "0" ]; then + _info "The switch already has our certificate installed. No update required." + return 0 + else + _info "The switch does not yet have our certificate installed." + fi + + _info "Logging into the switch web interface." + _zyxel_gs1900_login || return $? + + _info "Validating the switch is compatible with this deployment process." + _zyxel_gs1900_validate_device_compatibility || return $? + + _info "Uploading the certificate." + _zyxel_gs1900_upload_certificate || return $? + + if [ "$DEPLOY_ZYXEL_SWITCH_REBOOT" = "1" ]; then + _info "Rebooting the switch." + _zyxel_gs1900_trigger_reboot || return $? + fi + + return 0 +} + +_zyxel_gs1900_deployment_precheck() { + # Initialize the keylength if it isn't already + if [ -z "$Le_Keylength" ]; then + Le_Keylength="" + fi + + if _isEccKey "$Le_Keylength"; then + _info "Warning: Zyxel GS1900 switches are not currently known to work with ECC keys!" + _info "You can continue, but your switch may reject your key." + elif [ -n "$Le_Keylength" ] && [ "$Le_Keylength" -gt "2048" ]; then + _info "Warning: Your RSA key length is greater than 2048!" + _info "You can continue, but you may experience performance issues in the web administration interface." + fi + + # Check the server for some common failure modes prior to authentication and certificate upload in order to avoid + # sending a certificate when we may not want to. + test_login_response=$(_post "username=test&password=test&login=true;" "${_zyxel_switch_base_uri}/cgi-bin/dispatcher.cgi?cmd=0.html" '' "POST" "application/x-www-form-urlencoded" 2>&1) + test_login_page_exitcode="$?" + _debug3 "Test Login Response: ${test_login_response}" + if [ "$test_login_page_exitcode" -ne "0" ]; then + if { [ "${ACME_USE_WGET:-0}" = "0" ] && [ "$test_login_page_exitcode" = "60" ]; } || { [ "${ACME_USE_WGET:-0}" = "1" ] && [ "$test_login_page_exitcode" = "5" ]; }; then + _err "The SSL certificate at $_zyxel_switch_base_uri could not be validated." + _err "Please double check your hostname, port, and that you are actually connecting to your switch." + _err "If the problem persists then please ensure that the certificate is not self-signed, has not" + _err "expired, and matches the switch hostname. If you expect validation to fail then you can disable" + _err "certificate validation by running with --insecure." + return 1 + elif [ "${ACME_USE_WGET:-0}" = "0" ] && [ "$test_login_page_exitcode" = "56" ]; then + _debug3 "Intentionally ignore curl exit code 56 in our precheck" + else + _err "Failed to submit the initial login attempt to $_zyxel_switch_base_uri." + return 1 + fi + fi +} + +_zyxel_gs1900_login() { + # Login to the switch and set the appropriate auth cookie in _H1 + username_encoded=$(printf "%s" "$DEPLOY_ZYXEL_SWITCH_USER" | _url_encode) + password_encoded=$(_zyxel_gs1900_password_obfuscate "$DEPLOY_ZYXEL_SWITCH_PASSWORD" | _url_encode) + + login_response=$(_post "username=${username_encoded}&password=${password_encoded}&login=true;" "${_zyxel_switch_base_uri}/cgi-bin/dispatcher.cgi?cmd=0.html" '' "POST" "application/x-www-form-urlencoded" | tr -d '\n') + auth_response=$(_post "authId=${login_response}&login_chk=true" "${_zyxel_switch_base_uri}/cgi-bin/dispatcher.cgi?cmd=0.html" '' "POST" "application/x-www-form-urlencoded" | tr -d '\n') + if [ "$auth_response" != "OK" ]; then + _err "Login failed due to invalid credentials." + _err "Please double check the configured username and password and try again." + return 1 + fi + + sessionid=$(grep -i '^set-cookie:' "$HTTP_HEADER" | _egrep_o 'HTTPS_XSSID=[^;]*;' | tr -d ';') + _secure_debug2 "sessionid" "$sessionid" + + export _H1="Cookie: $sessionid" + _secure_debug2 "_H1" "$_H1" + + return 0 +} + +_zyxel_gs1900_validate_device_compatibility() { + # Check the switches model and firmware version and throw errors + # if this script isn't compatible. + device_info_html=$(_get "${_zyxel_switch_base_uri}/cgi-bin/dispatcher.cgi?cmd=12" | tr -d '\n') + + model_name=$(_zyxel_gs1900_get_model "$device_info_html") + _debug2 "model_name" "$model_name" + if [ -z "$model_name" ]; then + _err "Could not find the switch model name." + _err "Please re-run with --debug and report a bug." + return $? + fi + + if ! expr "$model_name" : "GS1900-" >/dev/null; then + _err "Switch is an unsupported model: $model_name" + return 1 + fi + + firmware_version=$(_zyxel_gs1900_get_firmware_version "$device_info_html") + _debug2 "firmware_version" "$firmware_version" + if [ -z "$firmware_version" ]; then + _err "Could not find the switch firmware version." + _err "Please re-run with --debug and report a bug." + return $? + fi + + _debug2 "_zyxel_gs1900_minimum_firmware_version" "$_zyxel_gs1900_minimum_firmware_version" + minimum_major_version=$(_zyxel_gs1900_parse_major_version "$_zyxel_gs1900_minimum_firmware_version") + _debug2 "minimum_major_version" "$minimum_major_version" + minimum_minor_version=$(_zyxel_gs1900_parse_minor_version "$_zyxel_gs1900_minimum_firmware_version") + _debug2 "minimum_minor_version" "$minimum_minor_version" + + _debug2 "firmware_version" "$firmware_version" + firmware_major_version=$(_zyxel_gs1900_parse_major_version "$firmware_version") + _debug2 "firmware_major_version" "$firmware_major_version" + firmware_minor_version=$(_zyxel_gs1900_parse_minor_version "$firmware_version") + _debug2 "firmware_minor_version" "$firmware_minor_version" + + _ret=0 + if [ "$firmware_major_version" -lt "$minimum_major_version" ]; then + _ret=1 + elif [ "$firmware_major_version" -eq "$minimum_major_version" ] && [ "$firmware_minor_version" -lt "$minimum_minor_version" ]; then + _ret=1 + fi + + if [ "$_ret" != "0" ]; then + _err "Unsupported firmware version $firmware_version. Please upgrade to at least version $_zyxel_gs1900_minimum_firmware_version." + fi + + return $? +} + +_zyxel_gs1900_should_update() { + # Get the remote certificate serial number + _remote_cert=$(${ACME_OPENSSL_BIN:-openssl} s_client -showcerts -connect "${DEPLOY_ZYXEL_SWITCH}:443" 2>/dev/null "${upload_post_request}" + + _info "Upload certificate to the switch" + + # Unfortunately we cannot rely upon the switch response across switch models + # to return a consistent body return - so we cannot inspect the result of this + # upload to determine success. + upload_response=$(_zyxel_upload_pkcs12 "${upload_post_request}" "${upload_post_boundary}" 2>&1) + _debug3 "Upload response: ${upload_response}" + rm "${upload_post_request}" + + # Pause for a few seconds to give the switch a chance to process the certificate + # For some reason I've found this to be necessary on my GS1900-24E + _debug2 "Waiting 4 seconds for the switch to process the newly uploaded certificate." + sleep "4" + + # Check to see whether or not our update was successful + _ret=0 + _zyxel_gs1900_should_update + if [ "$?" != "0" ]; then + _info "The certificate was updated successfully" + else + _ret=1 + _err "The certificate upload does not appear to have worked." + _err "The remote certificate does not match the certificate we tried to upload." + _err "Please re-run with --debug 2 and review for unexpected errors. If none can be found please submit a bug." + fi + + # ensure the temporary files are cleaned up + [ -f "${temp_pkcs12}" ] && rm -f "${temp_pkcs12}" + + return $_ret +} + +# make the certificate upload request using either +# --data binary with @ for file access in CURL +# or using --post-file for wget to ensure we upload +# the pkcs12 without getting tripped up on null bytes +# +# Usage _zyxel_upload_pkcs12 [body file name] [post boundary marker] +_zyxel_upload_pkcs12() { + bodyfilename="$1" + multipartformmarker="$2" + _post_url="${_zyxel_switch_base_uri}/cgi-bin/httpuploadcert.cgi" + httpmethod="POST" + _postContentType="multipart/form-data; boundary=${multipartformmarker}" + + if [ -z "$httpmethod" ]; then + httpmethod="POST" + fi + _debug $httpmethod + _debug "_post_url" "$_post_url" + _debug2 "bodyfilename" "$bodyfilename" + _debug2 "_postContentType" "$_postContentType" + + _inithttp + + if [ "$_ACME_CURL" ] && [ "${ACME_USE_WGET:-0}" = "0" ]; then + _CURL="$_ACME_CURL" + if [ "$HTTPS_INSECURE" ]; then + _CURL="$_CURL --insecure " + fi + if [ "$httpmethod" = "HEAD" ]; then + _CURL="$_CURL -I " + fi + _debug "_CURL" "$_CURL" + + response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data-binary "@${bodyfilename}" "$_post_url")" + + _ret="$?" + if [ "$_ret" != "0" ]; then + _err "Please refer to https://curl.haxx.se/libcurl/c/libcurl-errors.html for error code: $_ret" + if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then + _err "Here is the curl dump log:" + _err "$(cat "$_CURL_DUMP")" + fi + fi + elif [ "$_ACME_WGET" ]; then + _WGET="$_ACME_WGET" + if [ "$HTTPS_INSECURE" ]; then + _WGET="$_WGET --no-check-certificate " + fi + _debug "_WGET" "$_WGET" + + response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --post-file="${bodyfilename}" "$_post_url" 2>"$HTTP_HEADER")" + + _ret="$?" + if [ "$_ret" = "8" ]; then + _ret=0 + _debug "wget returned 8 as the server returned a 'Bad Request' response. Let's process the response later." + fi + if [ "$_ret" != "0" ]; then + _err "Please refer to https://www.gnu.org/software/wget/manual/html_node/Exit-Status.html for error code: $_ret" + fi + if _contains "$_WGET" " -d "; then + # Demultiplex wget debug output + cat "$HTTP_HEADER" >&2 + _sed_i '/^[^ ][^ ]/d; /^ *$/d' "$HTTP_HEADER" + fi + # remove leading whitespaces from header to match curl format + _sed_i 's/^ //g' "$HTTP_HEADER" + else + _ret="$?" + _err "Neither curl nor wget have been found, cannot make $httpmethod request." + fi + _debug "_ret" "$_ret" + printf "%s" "$response" + return $_ret +} + +_zyxel_gs1900_trigger_reboot() { + # Trigger a reboot via the management reboot page in the web ui + reboot_page_html=$(_get "${_zyxel_switch_base_uri}/cgi-bin/dispatcher.cgi?cmd=5888" | tr -d '\n') + reboot_xss_value=$(printf "%s" "$reboot_page_html" | _egrep_o 'name="XSSID"\s*value="[^"]+"' | sed 's/^.*="\([^"]\{1,\}\)"$/\1/g') + _secure_debug2 "reboot_xss_value" "$reboot_xss_value" + + reboot_response_html=$(_post "XSSID=${reboot_xss_value}&cmd=5889&sysSubmit=Reboot" "${_zyxel_switch_base_uri}/cgi-bin/dispatcher.cgi" '' "POST" "application/x-www-form-urlencoded") + reboot_message=$(printf "%s" "$reboot_response_html" | tr -d '\t\r\n\v\f' | _egrep_o "Rebooting now...") + + if [ -z "$reboot_message" ]; then + _err "Failed to trigger switch reboot!" + return 1 + fi + + return 0 +} + +# password +_zyxel_gs1900_password_obfuscate() { + # Return the password obfuscated via the same method used by the + # switch's web UI login process + echo "$1" | awk '{ + encoded = ""; + password = $1; + allowed = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + len = length($1); + pwi = length($1); + + for (i=1; i <= (321 - pwi); i++) + { + if (0 == i % 5 && pwi > 0) + { + encoded = (encoded)(substr(password, pwi--, 1)); + } + else if (i == 123) + { + if (len < 10) + { + encoded = (encoded)(0); + } + else + { + encoded = (encoded)(int(len / 10)); + } + } + else if (i == 289) + { + encoded = (encoded)(len % 10) + } + else + { + encoded = (encoded)(substr(allowed, int(rand() * length(allowed)), 1)) + } + } + printf("%s", encoded); + }' +} + +# html label +_zyxel_html_table_lookup() { + # Look up a value in the html representing the status page of the switch + # when provided with the html of the page and the label (i.e. "Model Name:") + html="$1" + label=$(printf "%s" "$2" | tr -d ' ') + lookup_result=$(printf "%s" "$html" | tr -d "\t\r\n\v\f" | sed 's//\n/g' | sed 's/]*>//g' | tr -d ' ' | grep -i "$label" | sed "s/$label<\/td>\([^<]\{1,\}\)<\/td><\/tr>/\1/i") + printf "%s" "$lookup_result" + return 0 +} + +# html +_zyxel_gs1900_get_model() { + html="$1" + model_name=$(_zyxel_html_table_lookup "$html" "Model Name:") + printf "%s" "$model_name" +} + +# html +_zyxel_gs1900_get_firmware_version() { + html="$1" + firmware_version=$(_zyxel_html_table_lookup "$html" "Firmware Version:" | _egrep_o "V[^.]+.[^(]+") + printf "%s" "$firmware_version" +} + +# version_number +_zyxel_gs1900_parse_major_version() { + printf "%s" "$1" | sed 's/^V\([0-9]\{1,\}\).\{1,\}$/\1/gi' +} + +# version_number +_zyxel_gs1900_parse_minor_version() { + printf "%s" "$1" | sed 's/^.\{1,\}\.\([0-9]\{1,\}\)$/\1/gi' +} From e1d447847f0e3da3e213ae1b1a6c154bc72a40f0 Mon Sep 17 00:00:00 2001 From: Meo597 <197331664+Meo597@users.noreply.github.com> Date: Fri, 25 Apr 2025 05:21:52 +0800 Subject: [PATCH 13/66] Spaceship: fix domain conf --- dnsapi/dns_spaceship.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_spaceship.sh b/dnsapi/dns_spaceship.sh index 501131b8..7e9fb167 100644 --- a/dnsapi/dns_spaceship.sh +++ b/dnsapi/dns_spaceship.sh @@ -133,11 +133,11 @@ _get_root() { domain="$1" # Check manual override - SPACESHIP_ROOT_DOMAIN="${SPACESHIP_ROOT_DOMAIN:-$(_readaccountconf_mutable SPACESHIP_ROOT_DOMAIN)}" + SPACESHIP_ROOT_DOMAIN="${SPACESHIP_ROOT_DOMAIN:-$(_readdomainconf SPACESHIP_ROOT_DOMAIN)}" if [ -n "$SPACESHIP_ROOT_DOMAIN" ]; then _domain="$SPACESHIP_ROOT_DOMAIN" _debug "Using manually specified or saved root domain: $_domain" - _saveaccountconf_mutable SPACESHIP_ROOT_DOMAIN "$SPACESHIP_ROOT_DOMAIN" + _savedomainconf SPACESHIP_ROOT_DOMAIN "$SPACESHIP_ROOT_DOMAIN" return 0 fi @@ -162,7 +162,7 @@ _get_root() { _debug "Root zone found: '$_domain'" # Save the detected root domain - _saveaccountconf_mutable SPACESHIP_ROOT_DOMAIN "$_domain" + _savedomainconf SPACESHIP_ROOT_DOMAIN "$_domain" _info "Root domain '$_domain' saved to configuration for future use." return 0 From d01aefd1eb17c53604604645798d77a9ace399d9 Mon Sep 17 00:00:00 2001 From: Meo597 <197331664+Meo597@users.noreply.github.com> Date: Fri, 25 Apr 2025 05:24:05 +0800 Subject: [PATCH 14/66] Spaceship: i starts from 1 --- dnsapi/dns_spaceship.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_spaceship.sh b/dnsapi/dns_spaceship.sh index 7e9fb167..cc3f066f 100644 --- a/dnsapi/dns_spaceship.sh +++ b/dnsapi/dns_spaceship.sh @@ -143,7 +143,7 @@ _get_root() { _debug "Detecting root zone for '$domain'" - i=2 + i=1 p=1 while true; do _cutdomain=$(printf "%s" "$domain" | cut -d . -f "$i"-100) From b5e3883891e31b5082f5f7520c6ac68fad441eeb Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 26 Apr 2025 16:47:20 +0200 Subject: [PATCH 15/66] update --- .github/workflows/pr_dns.yml | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr_dns.yml b/.github/workflows/pr_dns.yml index 58630e8b..25096c7e 100644 --- a/.github/workflows/pr_dns.yml +++ b/.github/workflows/pr_dns.yml @@ -20,12 +20,26 @@ jobs: owner: context.repo.owner, repo: context.repo.repo, body: `**Welcome** + READ ME !!!!! + + + Read me !!!!!! + + First thing: don't send PR to the master branch, please send to the dev branch instead. - Please make sure you've read our [DNS API Dev Guide](../wiki/DNS-API-Dev-Guide) and [DNS-API-Test](../wiki/DNS-API-Test). + + + Please read the [DNS API Dev Guide](../wiki/DNS-API-Dev-Guide) and [DNS-API-Test](../wiki/DNS-API-Test). + + Then reply on this message, otherwise, your code will not be reviewed or merged. + + Please also make sure to add/update the usage here: https://github.com/acmesh-official/acme.sh/wiki/dnsapi2 - We look forward to reviewing your Pull request shortly ✨ + + 注意: 必须通过了 [DNS-API-Test](../wiki/DNS-API-Test) 才会被 review. 无论是修改, 还是新加的 dns api, 都必须确保通过这个测试. + ` }) From 2928d843393e839b538307ff8e04a01ca7ae738a Mon Sep 17 00:00:00 2001 From: Meo597 <197331664+Meo597@users.noreply.github.com> Date: Mon, 28 Apr 2025 00:04:49 +0800 Subject: [PATCH 16/66] Spaceship: replace debug with debug2 for detailed output in complex debugging --- dnsapi/dns_spaceship.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_spaceship.sh b/dnsapi/dns_spaceship.sh index cc3f066f..c6db9928 100644 --- a/dnsapi/dns_spaceship.sh +++ b/dnsapi/dns_spaceship.sh @@ -183,7 +183,7 @@ _spaceship_api_request() { url="$2" payload="$3" - _debug "Sending $method request to $url with payload $payload" + _debug2 "Sending $method request to $url with payload $payload" if [ "$method" = "GET" ]; then response="$(_get "$url")" else @@ -195,7 +195,7 @@ _spaceship_api_request() { return 1 fi - _debug "API response body: $response" + _debug2 "API response body: $response" if [ "$method" = "GET" ]; then if _contains "$(_head_n 1 <"$HTTP_HEADER")" '200'; then @@ -207,6 +207,6 @@ _spaceship_api_request() { fi fi - _debug "API response header: $HTTP_HEADER" + _debug2 "API response header: $HTTP_HEADER" return 1 } From e2d09231225a2d9cbb33d64d5a49f08a6284c060 Mon Sep 17 00:00:00 2001 From: Meo597 <197331664+Meo597@users.noreply.github.com> Date: Mon, 28 Apr 2025 00:18:23 +0800 Subject: [PATCH 17/66] Spaceship: replace ~/.acme.sh with $LE_CONFIG_HOME for configurable paths --- dnsapi/dns_spaceship.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_spaceship.sh b/dnsapi/dns_spaceship.sh index c6db9928..264bdefc 100644 --- a/dnsapi/dns_spaceship.sh +++ b/dnsapi/dns_spaceship.sh @@ -114,7 +114,7 @@ _spaceship_init() { if [ -z "$SPACESHIP_API_KEY" ] || [ -z "$SPACESHIP_API_SECRET" ]; then _err "Spaceship API credentials are not set. Please set SPACESHIP_API_KEY and SPACESHIP_API_SECRET." - _err "Ensure ~/.acme.sh directory has restricted permissions (chmod 700 ~/.acme.sh) to protect credentials." + _err "Ensure \"$LE_CONFIG_HOME\" directory has restricted permissions (chmod 700 \"$LE_CONFIG_HOME\") to protect credentials." return 1 fi From 8b4d93cc14e3c1cf246840c5cd95409c10fd6836 Mon Sep 17 00:00:00 2001 From: Meo597 <197331664+Meo597@users.noreply.github.com> Date: Mon, 28 Apr 2025 00:32:46 +0800 Subject: [PATCH 18/66] Spaceship: fix doc --- dnsapi/dns_spaceship.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_spaceship.sh b/dnsapi/dns_spaceship.sh index 264bdefc..770e22cc 100644 --- a/dnsapi/dns_spaceship.sh +++ b/dnsapi/dns_spaceship.sh @@ -2,7 +2,7 @@ # shellcheck disable=SC2034 dns_spaceship_info='Spaceship.com Site: Spaceship.com -Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_spaceship +Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_spaceship Options: SPACESHIP_API_KEY Spaceship API Key SPACESHIP_API_SECRET Spaceship API Secret From eb00852a714b3dfa0c556e4fb3806ade46392a11 Mon Sep 17 00:00:00 2001 From: neil Date: Thu, 1 May 2025 13:28:20 +0200 Subject: [PATCH 19/66] remove ocsp for letsencrypt server --- acme.sh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/acme.sh b/acme.sh index 4d75ab62..e9eb6b94 100755 --- a/acme.sh +++ b/acme.sh @@ -5504,6 +5504,13 @@ renew() { if [ -z "$Le_Keylength" ]; then Le_Keylength=2048 fi + if [ "$CA_LETSENCRYPT_V2" = "$Le_API" ]; then + #letsencrypt doesn't support ocsp anymore + if [ "$Le_OCSP_Staple" ]; then + export Le_OCSP_Staple="" + _cleardomainconf Le_OCSP_Staple + fi + fi issue "$Le_Webroot" "$Le_Domain" "$Le_Alt" "$Le_Keylength" "$Le_RealCertPath" "$Le_RealKeyPath" "$Le_RealCACertPath" "$Le_ReloadCmd" "$Le_RealFullChainPath" "$Le_PreHook" "$Le_PostHook" "$Le_RenewHook" "$Le_LocalAddress" "$Le_ChallengeAlias" "$Le_Preferred_Chain" "$Le_Valid_From" "$Le_Valid_To" res="$?" if [ "$res" != "0" ]; then From 42aaf7c2a020c3aeb84031d31ff9006de6aef670 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josef=20Vyb=C3=ADhal?= Date: Sun, 12 Jan 2025 16:41:00 +0100 Subject: [PATCH 20/66] dns_active24: rewrite for supporting new v2 API --- dnsapi/dns_active24.sh | 160 ++++++++++++++++++++++++++++------------- 1 file changed, 109 insertions(+), 51 deletions(-) diff --git a/dnsapi/dns_active24.sh b/dnsapi/dns_active24.sh index c56dd363..0f24c53a 100755 --- a/dnsapi/dns_active24.sh +++ b/dnsapi/dns_active24.sh @@ -1,17 +1,17 @@ #!/usr/bin/env sh # shellcheck disable=SC2034 -dns_active24_info='Active24.com -Site: Active24.com +dns_active24_info='Active24.cz +Site: Active24.cz Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_active24 Options: - ACTIVE24_Token API Token + Active24_ApiKey API Key. Called "Identifier" in the Active24 Admin + Active24_ApiSecret API Secret. Called "Secret key" in the Active24 Admin Issues: github.com/acmesh-official/acme.sh/issues/2059 -Author: Milan Pála ' -ACTIVE24_Api="https://api.active24.com" - -######## Public functions ##################### +Active24_Api="https://rest.active24.cz" +# export Active24_ApiKey=ak48l3h7-ak5d-qn4t-p8gc-b6fs8c3l +# export Active24_ApiSecret=ajvkeo3y82ndsu2smvxy3o36496dcascksldncsq # Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" # Used to add txt record @@ -22,8 +22,8 @@ dns_active24_add() { _active24_init _info "Adding txt record" - if _active24_rest POST "dns/$_domain/txt/v1" "{\"name\":\"$_sub_domain\",\"text\":\"$txtvalue\",\"ttl\":0}"; then - if _contains "$response" "errors"; then + if _active24_rest POST "/v2/service/$_service_id/dns/record" "{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"content\":\"$txtvalue\",\"ttl\":300}"; then + if _contains "$response" "error"; then _err "Add txt record error." return 1 else @@ -31,6 +31,7 @@ dns_active24_add() { return 0 fi fi + _err "Add txt record error." return 1 } @@ -44,19 +45,25 @@ dns_active24_rm() { _active24_init _debug "Getting txt records" - _active24_rest GET "dns/$_domain/records/v1" + # The API needs to send data in body in order the filter to work + # TODO: web can also add content $txtvalue to filter and then get the id from response + _active24_rest GET "/v2/service/$_service_id/dns/record" "{\"page\":1,\"descending\":true,\"sortBy\":\"name\",\"rowsPerPage\":100,\"totalRecords\":0,\"filters\":{\"type\":[\"TXT\"],\"name\":\"${_sub_domain}\"}}" + #_active24_rest GET "/v2/service/$_service_id/dns/record?rowsPerPage=100" - if _contains "$response" "errors"; then + if _contains "$response" "error"; then _err "Error" return 1 fi - hash_ids=$(echo "$response" | _egrep_o "[^{]+${txtvalue}[^}]+" | _egrep_o "hashId\":\"[^\"]+" | cut -c10-) + # Note: it might never be more than one record actually, NEEDS more INVESTIGATION + record_ids=$(printf "%s" "$response" | _egrep_o "[^{]+${txtvalue}[^}]+" | _egrep_o '"id" *: *[^,]+' | cut -d ':' -f 2) + _debug2 record_ids "$record_ids" - for hash_id in $hash_ids; do - _debug "Removing hash_id" "$hash_id" - if _active24_rest DELETE "dns/$_domain/$hash_id/v1" ""; then - if _contains "$response" "errors"; then + for redord_id in $record_ids; do + _debug "Removing record_id" "$redord_id" + _debug "txtvalue" "$txtvalue" + if _active24_rest DELETE "/v2/service/$_service_id/dns/record/$redord_id" ""; then + if _contains "$response" "error"; then _err "Unable to remove txt record." return 1 else @@ -70,21 +77,15 @@ dns_active24_rm() { return 1 } -#################### Private functions below ################################## -#_acme-challenge.www.domain.com -#returns -# _sub_domain=_acme-challenge.www -# _domain=domain.com -# _domain_id=sdjkglgdfewsdfg _get_root() { domain=$1 + i=1 + p=1 - if ! _active24_rest GET "dns/domains/v1"; then + if ! _active24_rest GET "/v1/user/self/service"; then return 1 fi - i=1 - p=1 while true; do h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug "h" "$h" @@ -104,45 +105,102 @@ _get_root() { return 1 } -_active24_rest() { - m=$1 - ep="$2" - data="$3" - _debug "$ep" - - export _H1="Authorization: Bearer $ACTIVE24_Token" - - if [ "$m" != "GET" ]; then - _debug "data" "$data" - response="$(_post "$data" "$ACTIVE24_Api/$ep" "" "$m" "application/json")" - else - response="$(_get "$ACTIVE24_Api/$ep")" +_active24_init() { + Active24_ApiKey="${Active24_ApiKey:-$(_readaccountconf_mutable Active24_ApiKey)}" + Active24_ApiSecret="${Active24_ApiSecret:-$(_readaccountconf_mutable Active24_ApiSecret)}" + #Active24_ServiceId="${Active24_ServiceId:-$(_readaccountconf_mutable Active24_ServiceId)}" + + if [ -z "$Active24_ApiKey" ] || [ -z "$Active24_ApiSecret" ]; then + Active24_ApiKey="" + Active24_ApiSecret="" + _err "You don't specify Active24 api key and ApiSecret yet." + _err "Please create your key and try again." + return 1 fi - if [ "$?" != "0" ]; then - _err "error $ep" + #save the credentials to the account conf file. + _saveaccountconf_mutable Active24_ApiKey "$Active24_ApiKey" + _saveaccountconf_mutable Active24_ApiSecret "$Active24_ApiSecret" + + _debug "A24 API CHECK" + if ! _active24_rest GET "/v2/check"; then + _err "A24 API check failed with: $response" return 1 fi - _debug2 response "$response" - return 0 -} -_active24_init() { - ACTIVE24_Token="${ACTIVE24_Token:-$(_readaccountconf_mutable ACTIVE24_Token)}" - if [ -z "$ACTIVE24_Token" ]; then - ACTIVE24_Token="" - _err "You didn't specify a Active24 api token yet." - _err "Please create the token and try again." + if ! echo "$response" | tr -d " " | grep \"verified\":true >/dev/null; then + _err "A24 API check failed with: $response" return 1 fi - _saveaccountconf_mutable ACTIVE24_Token "$ACTIVE24_Token" - _debug "First detect the root zone" if ! _get_root "$fulldomain"; then _err "invalid domain" return 1 fi + _debug _sub_domain "$_sub_domain" _debug _domain "$_domain" + _active24_get_service_id "$_domain" + _debug _service_id "$_service_id" +} + +_active24_get_service_id() { + _d=$1 + if ! _active24_rest GET "/v1/user/self/zone/${_d}"; then + return 1 + else + response=$(echo "$response" | _json_decode) + _service_id=$(echo "$response" | _egrep_o '"id" *: *[^,]+' | cut -d ':' -f 2) + fi +} + +_active24_rest() { + m=$1 + ep_qs=$2 # with query string + # ep=$2 + ep=$(printf "%s" "$ep_qs" | cut -d '?' -f1) # no query string + data="$3" + + _debug "A24 $ep" + _debug "A24 $Active24_ApiKey" + _debug "A24 $Active24_ApiSecret" + + timestamp=$(_time) + datez=$(date -u +"%Y%m%dT%H%M%SZ") + canonicalRequest="${m} ${ep} ${timestamp}" + signature=$(printf "%s" "$canonicalRequest" | _hmac sha1 "$(printf "%s" "$Active24_ApiSecret" | _hex_dump | tr -d " ")" hex) + authorization64="$(printf "%s:%s" "$Active24_ApiKey" "$signature" | _base64)" + + export _H1="Date: ${datez}" + export _H2="Accept: application/json" + export _H3="Content-Type: application/json" + export _H4="Authorization: Basic ${authorization64}" + + _debug2 H1 "$_H1" + _debug2 H2 "$_H2" + _debug2 H3 "$_H3" + _debug2 H4 "$_H4" + + # _sleep 1 + + if [ "$m" != "GET" ]; then + _debug2 "${m} $Active24_Api${ep_qs}" + _debug "data" "$data" + response="$(_post "$data" "$Active24_Api${ep_qs}" "" "$m" "application/json")" + else + if [ -z "$data" ]; then + _debug2 "GET $Active24_Api${ep_qs}" + response="$(_get "$Active24_Api${ep_qs}")" + else + _debug2 "GET $Active24_Api${ep_qs} with data: ${data}" + response="$(_post "$data" "$Active24_Api${ep_qs}" "" "$m" "application/json")" + fi + fi + if [ "$?" != "0" ]; then + _err "error $ep" + return 1 + fi + _debug2 response "$response" + return 0 } From ca73e1f024992fdc1ec7a1fe4383a9d477526bdf Mon Sep 17 00:00:00 2001 From: emueller Date: Mon, 12 May 2025 10:28:35 +0200 Subject: [PATCH 21/66] added deploy/kemplm.sh for deploying certs on Kemp Loadmaster --- deploy/kemplm.sh | 103 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100755 deploy/kemplm.sh diff --git a/deploy/kemplm.sh b/deploy/kemplm.sh new file mode 100755 index 00000000..937cbbca --- /dev/null +++ b/deploy/kemplm.sh @@ -0,0 +1,103 @@ +#!/usr/bin/env sh + +#Here is a script to deploy cert to a Kemp Loadmaster. + +#returns 0 means success, otherwise error. + +#DEPLOY_KEMP_TOKEN="token" +#DEPLOY_KEMP_URL="https://kemplm.example.com" + +######## Public functions ##################### + +#domain keyfile certfile cafile fullchain +kemplm_deploy() { + _cdomain="$1" + _ckey="$2" + _ccert="$3" + _cca="$4" + _cfullchain="$5" + + _debug _cdomain "$_cdomain" + _debug _ckey "$_ckey" + _debug _ccert "$_ccert" + _debug _cca "$_cca" + _debug _cfullchain "$_cfullchain" + + if ! _exists jq; then + _err "jq not found" + fi + + # Rename wildcard certs, kemp accepts only alphanumeric names + _kemp_domain=$(echo "${_cdomain}" | sed 's/\*/wildcard/') + _debug _kemp_domain "$_kemp_domain" + + # Clear traces of incorrectly stored values + _clearaccountconf DEPLOY_KEMP_TOKEN + _clearaccountconf DEPLOY_KEMP_URL + + # Read config from saved values or env + _getdeployconf DEPLOY_KEMP_TOKEN + _getdeployconf DEPLOY_KEMP_URL + + _debug DEPLOY_KEMP_URL "$DEPLOY_KEMP_URL" + _secure_debug DEPLOY_KEMP_TOKEN "$DEPLOY_KEMP_TOKEN" + + if [ -z "$DEPLOY_KEMP_TOKEN" ]; then + _err "Kemp Loadmaster token is not found, please define DEPLOY_KEMP_TOKEN." + return 1 + fi + if [ -z "$DEPLOY_KEMP_URL" ]; then + _err "Kemp Loadmaster url is not found, please define DEPLOY_KEMP_URL." + return 1 + fi + + # Save current values + _savedeployconf DEPLOY_KEMP_TOKEN "$DEPLOY_KEMP_TOKEN" + _savedeployconf DEPLOY_KEMP_URL "$DEPLOY_KEMP_URL" + + # Do not check for a valid SSL certificate + export HTTPS_INSECURE=1 + + # Check if certificate is already installed + _info "Check if certificate is already present" + _post_request="{\"cmd\": \"listcert\", \"apikey\": \"${DEPLOY_KEMP_TOKEN}\"}" + _debug3 _post_request "${_post_request}" + _kemp_cert_count=$(_post "${_post_request}" "${DEPLOY_KEMP_URL}/accessv2" | jq -r '.cert[] | .name' | grep -c "${_kemp_domain}") + _debug2 _kemp_cert_count "${_kemp_cert_count}" + + _kemp_replace_cert=1 + if [ "${_kemp_cert_count}" -eq 0 ]; then + _kemp_replace_cert=0 + _info "Certificate does not exist on Kemp Loadmaster" + else + _info "Certificate already exists on Kemp Loadmaster" + fi + _debug _kemp_replace_cert "${_kemp_replace_cert}" + + # Upload new certificate to Kemp Loadmaster + _kemp_upload_cert=$(_mktemp) + cat "${_cfullchain}" "${_ckey}" | base64 -w 0 > "${_kemp_upload_cert}" + + _info "Uploading certificate to Kemp Loadmaster" + _post_request="{\"cmd\": \"addcert\", \"apikey\": \"${DEPLOY_KEMP_TOKEN}\", \"replace\": ${_kemp_replace_cert}, \"cert\": \"${_kemp_domain}\", \"data\": \"$(cat ${_kemp_upload_cert})\"}" + _debug3 _post_request "${_post_request}" + _kemp_post_result=$(_post "${_post_request}" "${DEPLOY_KEMP_URL}/accessv2") + _retval=$? + _debug2 _kemp_post_result "${_kemp_post_result}" + if [ "${_retval}" -eq 0 ]; then + _kemp_post_status=$(echo "${_kemp_post_result}" | jq -r '.status') + _kemp_post_message=$(echo "${_kemp_post_result}" | jq -r '.message') + if [ "${_kemp_post_status}" = "ok" ]; then + _info "Upload successful" + else + _err "Upload failed: ${_kemp_post_message}" + fi + else + _err "Upload failed" + _retval=1 + fi + + rm "${_kemp_upload_cert}" + + return $retval +} From 7543d5220cfa01f42041e8d95ecc952b81e92987 Mon Sep 17 00:00:00 2001 From: emueller Date: Mon, 12 May 2025 10:45:01 +0200 Subject: [PATCH 22/66] fixed kemplm.sh formatting --- deploy/kemplm.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/deploy/kemplm.sh b/deploy/kemplm.sh index 937cbbca..3f762d75 100755 --- a/deploy/kemplm.sh +++ b/deploy/kemplm.sh @@ -23,11 +23,11 @@ kemplm_deploy() { _debug _cca "$_cca" _debug _cfullchain "$_cfullchain" - if ! _exists jq; then - _err "jq not found" - fi + if ! _exists jq; then + _err "jq not found" + fi - # Rename wildcard certs, kemp accepts only alphanumeric names + # Rename wildcard certs, kemp accepts only alphanumeric names _kemp_domain=$(echo "${_cdomain}" | sed 's/\*/wildcard/') _debug _kemp_domain "$_kemp_domain" @@ -76,7 +76,7 @@ kemplm_deploy() { # Upload new certificate to Kemp Loadmaster _kemp_upload_cert=$(_mktemp) - cat "${_cfullchain}" "${_ckey}" | base64 -w 0 > "${_kemp_upload_cert}" + cat "${_cfullchain}" "${_ckey}" | base64 -w 0 >"${_kemp_upload_cert}" _info "Uploading certificate to Kemp Loadmaster" _post_request="{\"cmd\": \"addcert\", \"apikey\": \"${DEPLOY_KEMP_TOKEN}\", \"replace\": ${_kemp_replace_cert}, \"cert\": \"${_kemp_domain}\", \"data\": \"$(cat ${_kemp_upload_cert})\"}" From bf2e99efa69b76bc5e495a73cbcf97221dce40ff Mon Sep 17 00:00:00 2001 From: emueller Date: Mon, 12 May 2025 10:52:35 +0200 Subject: [PATCH 23/66] fixed quoting in kemplm.sh --- deploy/kemplm.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/deploy/kemplm.sh b/deploy/kemplm.sh index 3f762d75..fbe25cd8 100755 --- a/deploy/kemplm.sh +++ b/deploy/kemplm.sh @@ -79,7 +79,8 @@ kemplm_deploy() { cat "${_cfullchain}" "${_ckey}" | base64 -w 0 >"${_kemp_upload_cert}" _info "Uploading certificate to Kemp Loadmaster" - _post_request="{\"cmd\": \"addcert\", \"apikey\": \"${DEPLOY_KEMP_TOKEN}\", \"replace\": ${_kemp_replace_cert}, \"cert\": \"${_kemp_domain}\", \"data\": \"$(cat ${_kemp_upload_cert})\"}" + _post_data=$(cat "${_kemp_upload_cert}") + _post_request="{\"cmd\": \"addcert\", \"apikey\": \"${DEPLOY_KEMP_TOKEN}\", \"replace\": ${_kemp_replace_cert}, \"cert\": \"${_kemp_domain}\", \"data\": \"${_post_data}\"}" _debug3 _post_request "${_post_request}" _kemp_post_result=$(_post "${_post_request}" "${DEPLOY_KEMP_URL}/accessv2") _retval=$? @@ -99,5 +100,5 @@ kemplm_deploy() { rm "${_kemp_upload_cert}" - return $retval + return $_retval } From 184cb0b9a8ae73940514a7759173d678e8a7cbe8 Mon Sep 17 00:00:00 2001 From: Adrian Fedoreanu Date: Thu, 15 May 2025 16:01:24 +0200 Subject: [PATCH 24/66] dns_1984.hosting.sh: fix session cookie name --- dnsapi/dns_1984hosting.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_1984hosting.sh b/dnsapi/dns_1984hosting.sh index 906ea443..8d9676ac 100755 --- a/dnsapi/dns_1984hosting.sh +++ b/dnsapi/dns_1984hosting.sh @@ -128,7 +128,7 @@ _1984hosting_login() { _get "https://1984.hosting/accounts/login/" | grep "csrfmiddlewaretoken" csrftoken="$(grep -i '^set-cookie:' "$HTTP_HEADER" | _egrep_o 'csrftoken=[^;]*;' | tr -d ';')" - sessionid="$(grep -i '^set-cookie:' "$HTTP_HEADER" | _egrep_o 'sessionid=[^;]*;' | tr -d ';')" + sessionid="$(grep -i '^set-cookie:' "$HTTP_HEADER" | _egrep_o 'cookie1984nammnamm=[^;]*;' | tr -d ';')" if [ -z "$csrftoken" ] || [ -z "$sessionid" ]; then _err "One or more cookies are empty: '$csrftoken', '$sessionid'." @@ -145,7 +145,7 @@ _1984hosting_login() { _debug2 response "$response" if _contains "$response" '"loggedin": true'; then - One984HOSTING_SESSIONID_COOKIE="$(grep -i '^set-cookie:' "$HTTP_HEADER" | _egrep_o 'sessionid=[^;]*;' | tr -d ';')" + One984HOSTING_SESSIONID_COOKIE="$(grep -i '^set-cookie:' "$HTTP_HEADER" | _egrep_o 'cookie1984nammnamm=[^;]*;' | tr -d ';')" One984HOSTING_CSRFTOKEN_COOKIE="$(grep -i '^set-cookie:' "$HTTP_HEADER" | _egrep_o 'csrftoken=[^;]*;' | tr -d ';')" export One984HOSTING_SESSIONID_COOKIE export One984HOSTING_CSRFTOKEN_COOKIE From b82f6801cd24f647510355f1818da2b1368c56a9 Mon Sep 17 00:00:00 2001 From: ymol-spraaklab Date: Fri, 16 May 2025 15:40:36 +0200 Subject: [PATCH 25/66] Set DNS Record TTL to 60 instead of 300 sec --- dnsapi/dns_transip.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_transip.sh b/dnsapi/dns_transip.sh index 2abbe34d..b3c5ed70 100644 --- a/dnsapi/dns_transip.sh +++ b/dnsapi/dns_transip.sh @@ -24,7 +24,7 @@ dns_transip_add() { _debug txtvalue="$txtvalue" _transip_setup "$fulldomain" || return 1 _info "Creating TXT record." - if ! _transip_rest POST "domains/$_domain/dns" "{\"dnsEntry\":{\"name\":\"$_sub_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"expire\":300}}"; then + if ! _transip_rest POST "domains/$_domain/dns" "{\"dnsEntry\":{\"name\":\"$_sub_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"expire\":60}}"; then _err "Could not add TXT record." return 1 fi @@ -38,7 +38,7 @@ dns_transip_rm() { _debug txtvalue="$txtvalue" _transip_setup "$fulldomain" || return 1 _info "Removing TXT record." - if ! _transip_rest DELETE "domains/$_domain/dns" "{\"dnsEntry\":{\"name\":\"$_sub_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"expire\":300}}"; then + if ! _transip_rest DELETE "domains/$_domain/dns" "{\"dnsEntry\":{\"name\":\"$_sub_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"expire\":60}}"; then _err "Could not remove TXT record $_sub_domain for $domain" return 1 fi From 99a4cf9e07f20c906fbd4f021b4bb6bd76f5c5dd Mon Sep 17 00:00:00 2001 From: Attackwave <51136146+Attackwave@users.noreply.github.com> Date: Fri, 16 May 2025 22:44:25 +0200 Subject: [PATCH 26/66] Quickfix TrueNAS 25.04 --- deploy/truenas_ws.sh | 125 +++++++++++++++++++++++++++---------------- 1 file changed, 78 insertions(+), 47 deletions(-) diff --git a/deploy/truenas_ws.sh b/deploy/truenas_ws.sh index 940cde2e..bdc1b846 100644 --- a/deploy/truenas_ws.sh +++ b/deploy/truenas_ws.sh @@ -52,6 +52,39 @@ _ws_call() { return 0 } +# Upload certificate with webclient api +_ws_upload_cert() { + + /usr/bin/env python - < Date: Sat, 17 May 2025 21:28:26 +0200 Subject: [PATCH 27/66] fix pr --- .github/workflows/pr_dns.yml | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/.github/workflows/pr_dns.yml b/.github/workflows/pr_dns.yml index 25096c7e..50eb2adb 100644 --- a/.github/workflows/pr_dns.yml +++ b/.github/workflows/pr_dns.yml @@ -20,26 +20,14 @@ jobs: owner: context.repo.owner, repo: context.repo.repo, body: `**Welcome** - READ ME !!!!! - - - Read me !!!!!! - - - First thing: don't send PR to the master branch, please send to the dev branch instead. - - - Please read the [DNS API Dev Guide](../wiki/DNS-API-Dev-Guide) and [DNS-API-Test](../wiki/DNS-API-Test). - - - Then reply on this message, otherwise, your code will not be reviewed or merged. - - - Please also make sure to add/update the usage here: https://github.com/acmesh-official/acme.sh/wiki/dnsapi2 - - - 注意: 必须通过了 [DNS-API-Test](../wiki/DNS-API-Test) 才会被 review. 无论是修改, 还是新加的 dns api, 都必须确保通过这个测试. - + READ ME !!!!! + Read me !!!!!! + First thing: don't send PR to the master branch, please send to the dev branch instead. + Please read the [DNS API Dev Guide](../wiki/DNS-API-Dev-Guide). + You MUST pass the [DNS-API-Test](../wiki/DNS-API-Test). + Then reply on this message, otherwise, your code will not be reviewed or merged. + Please also make sure to add/update the usage here: https://github.com/acmesh-official/acme.sh/wiki/dnsapi2 + 注意: 必须通过了 [DNS-API-Test](../wiki/DNS-API-Test) 才会被 review. 无论是修改, 还是新加的 dns api, 都必须确保通过这个测试. ` }) From 4f5a70b80404288f8a5b591d541d964b591b5db9 Mon Sep 17 00:00:00 2001 From: Joe Bauser Date: Sat, 17 May 2025 21:25:39 -0400 Subject: [PATCH 28/66] Apply suggested fixes from shfmt diffs --- deploy/zyxel_gs1900.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/zyxel_gs1900.sh b/deploy/zyxel_gs1900.sh index 443a5b05..37cf6005 100644 --- a/deploy/zyxel_gs1900.sh +++ b/deploy/zyxel_gs1900.sh @@ -245,7 +245,7 @@ _zyxel_gs1900_should_update() { _debug2 "_remote_cert_serial" "$_remote_cert_serial" # Get our certificate serial number - _our_cert_serial=$(${ACME_OPENSSL_BIN:-openssl} x509 -noout -serial < "${_ccert}") + _our_cert_serial=$(${ACME_OPENSSL_BIN:-openssl} x509 -noout -serial <"${_ccert}") _debug2 "_our_cert_serial" "$_our_cert_serial" [ "${_remote_cert_serial}" != "${_our_cert_serial}" ] From e0da5f170304dc373a4a647d83fbe0a13a53ec7e Mon Sep 17 00:00:00 2001 From: OPPO9008 <41640509+OPPO9008@users.noreply.github.com> Date: Mon, 19 May 2025 09:49:21 +0800 Subject: [PATCH 29/66] Update dns_la.sh --- dnsapi/dns_la.sh | 109 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 83 insertions(+), 26 deletions(-) diff --git a/dnsapi/dns_la.sh b/dnsapi/dns_la.sh index f19333c4..97437897 100644 --- a/dnsapi/dns_la.sh +++ b/dnsapi/dns_la.sh @@ -1,14 +1,18 @@ #!/usr/bin/env sh -# shellcheck disable=SC2034 -dns_la_info='dns.la -Site: dns.la -Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_la -Options: - LA_Id API ID - LA_Key API key -Issues: github.com/acmesh-official/acme.sh/issues/4257 -' +# LA_Id="123" +# LA_Sk="456" +# LA_Token="" +# +#Site: dns.la +#Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_la +#Options: +#我的账户 API 密钥 中获取 APIID APISecret +# LA_Id APIID +# LA_Key APISecret +# LA_Token 用冒号连接 APIID APISecret 再base64生成 +#Issues: github.com/acmesh-official/acme.sh/issues/4257 +#' LA_Api="https://api.dns.la/api" ######## Public functions ##################### @@ -19,18 +23,23 @@ dns_la_add() { txtvalue=$2 LA_Id="${LA_Id:-$(_readaccountconf_mutable LA_Id)}" - LA_Key="${LA_Key:-$(_readaccountconf_mutable LA_Key)}" + LA_Sk="${LA_Sk:-$(_readaccountconf_mutable LA_Sk)}" + _log "LA_Id=$LA_Id" + _log "LA_Sk=$LA_Sk" - if [ -z "$LA_Id" ] || [ -z "$LA_Key" ]; then + if [ -z "$LA_Id" ] || [ -z "$LA_Sk" ]; then LA_Id="" - LA_Key="" + LA_Sk="" _err "You didn't specify a dnsla api id and key yet." return 1 fi #save the api key and email to the account conf file. _saveaccountconf_mutable LA_Id "$LA_Id" - _saveaccountconf_mutable LA_Key "$LA_Key" + _saveaccountconf_mutable LA_Sk "$LA_Sk" + + # generate dnsla token + _la_token _debug "First detect the root zone" if ! _get_root "$fulldomain"; then @@ -42,11 +51,13 @@ dns_la_add() { _debug _domain "$_domain" _info "Adding record" - if _la_rest "record.ashx?cmd=create&apiid=$LA_Id&apipass=$LA_Key&rtype=json&domainid=$_domain_id&host=$_sub_domain&recordtype=TXT&recorddata=$txtvalue&recordline="; then - if _contains "$response" '"resultid":'; then + + # record type is enum in new api, 16 for TXT + if _la_post "{\"domainId\":\"$_domain_id\",\"type\":16,\"host\":\"$_sub_domain\",\"data\":\"$txtvalue\",\"ttl\":600}" "record"; then + if _contains "$response" '"id":'; then _info "Added, OK" return 0 - elif _contains "$response" '"code":532'; then + elif _contains "$response" '"msg":"与已有记录冲突"'; then _info "Already exists, OK" return 0 else @@ -54,7 +65,7 @@ dns_la_add() { return 1 fi fi - _err "Add txt record error." + _err "Add txt record failed." return 1 } @@ -65,7 +76,9 @@ dns_la_rm() { txtvalue=$2 LA_Id="${LA_Id:-$(_readaccountconf_mutable LA_Id)}" - LA_Key="${LA_Key:-$(_readaccountconf_mutable LA_Key)}" + LA_Sk="${LA_Sk:-$(_readaccountconf_mutable LA_Sk)}" + + _la_token _debug "First detect the root zone" if ! _get_root "$fulldomain"; then @@ -77,27 +90,29 @@ dns_la_rm() { _debug _domain "$_domain" _debug "Getting txt records" - if ! _la_rest "record.ashx?cmd=listn&apiid=$LA_Id&apipass=$LA_Key&rtype=json&domainid=$_domain_id&domain=$_domain&host=$_sub_domain&recordtype=TXT&recorddata=$txtvalue"; then + # record type is enum in new api, 16 for TXT + if ! _la_get "recordList?pageIndex=1&pageSize=10&domainId=$_domain_id&host=$_sub_domain&type=16&data=$txtvalue"; then _err "Error" return 1 fi - if ! _contains "$response" '"recordid":'; then + if ! _contains "$response" '"id":'; then _info "Don't need to remove." return 0 fi - record_id=$(printf "%s" "$response" | grep '"recordid":' | cut -d : -f 2 | cut -d , -f 1 | tr -d '\r' | tr -d '\n') + record_id=$(printf "%s" "$response" | grep '"id":' | head -n1 | sed 's/.*"id": *"\([^"]*\)".*/\1/') _debug "record_id" "$record_id" if [ -z "$record_id" ]; then _err "Can not get record id to remove." return 1 fi - if ! _la_rest "record.ashx?cmd=remove&apiid=$LA_Id&apipass=$LA_Key&rtype=json&domainid=$_domain_id&domain=$_domain&recordid=$record_id"; then + # remove record in new api is RESTful + if ! _la_post "" "record?id=$record_id" "DELETE"; then _err "Delete record error." return 1 fi - _contains "$response" '"code":300' + _contains "$response" '"code":200' } @@ -119,12 +134,13 @@ _get_root() { return 1 fi - if ! _la_rest "domain.ashx?cmd=get&apiid=$LA_Id&apipass=$LA_Key&rtype=json&domain=$h"; then + if ! _la_get "domain?domain=$h"; then return 1 fi - if _contains "$response" '"domainid":'; then - _domain_id=$(printf "%s" "$response" | grep '"domainid":' | cut -d : -f 2 | cut -d , -f 1 | tr -d '\r' | tr -d '\n') + if _contains "$response" '"domain":'; then + _domain_id=$(echo "$response" | sed -n 's/.*"id":"\([^"]*\)".*/\1/p') + _log "_domain_id" "$_domain_id" if [ "$_domain_id" ]; then _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain="$h" @@ -143,6 +159,21 @@ _la_rest() { url="$LA_Api/$1" _debug "$url" + if ! response="$(_get "$url" "Authorization: Basic $LA_Token" | tr -d ' ' | tr "}" ",")"; then + _err "Error: $url" + return 1 + fi + + _debug2 response "$response" + return 0 +} + +_la_get() { + url="$LA_Api/$1" + _debug "$url" + + export _H1="Authorization: Basic $LA_Token" + if ! response="$(_get "$url" | tr -d ' ' | tr "}" ",")"; then _err "Error: $url" return 1 @@ -151,3 +182,29 @@ _la_rest() { _debug2 response "$response" return 0 } + +# Usage: _la_post body url [POST|PUT|DELETE] +_la_post() { + body=$1 + url="$LA_Api/$2" + http_method=$3 + _debug "$body" + _debug "$url" + + export _H1="Authorization: Basic $LA_Token" + + if ! response="$(_post "$body" "$url" "" "$http_method")"; then + _err "Error: $url" + return 1 + fi + + _debug2 response "$response" + return 0 +} + +_la_token() { + LA_Token=$(printf "%s:%s" "$LA_Id" "$LA_Sk" | base64 -w 0) + _debug "$LA_Token" + + return 0 +} From 9e7d1b9ce75373c4233790527054925f42da5d16 Mon Sep 17 00:00:00 2001 From: OPPO9008 <41640509+OPPO9008@users.noreply.github.com> Date: Mon, 19 May 2025 13:16:30 +0800 Subject: [PATCH 30/66] Update dns_la.sh --- dnsapi/dns_la.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_la.sh b/dnsapi/dns_la.sh index 97437897..ba8ebcac 100644 --- a/dnsapi/dns_la.sh +++ b/dnsapi/dns_la.sh @@ -203,7 +203,7 @@ _la_post() { } _la_token() { - LA_Token=$(printf "%s:%s" "$LA_Id" "$LA_Sk" | base64 -w 0) + LA_Token=$(printf "%s:%s" "$LA_Id" "$LA_Sk" | _base64) _debug "$LA_Token" return 0 From 55282851c4a890369bece6f3c5b8082f91f2d1ad Mon Sep 17 00:00:00 2001 From: emueller Date: Mon, 19 May 2025 09:18:29 +0200 Subject: [PATCH 31/66] implemented all suggestions --- deploy/kemplm.sh | 52 +++++++++++++++++++++--------------------------- 1 file changed, 23 insertions(+), 29 deletions(-) diff --git a/deploy/kemplm.sh b/deploy/kemplm.sh index fbe25cd8..e44e06dc 100755 --- a/deploy/kemplm.sh +++ b/deploy/kemplm.sh @@ -11,30 +11,27 @@ #domain keyfile certfile cafile fullchain kemplm_deploy() { - _cdomain="$1" - _ckey="$2" - _ccert="$3" - _cca="$4" - _cfullchain="$5" - - _debug _cdomain "$_cdomain" - _debug _ckey "$_ckey" - _debug _ccert "$_ccert" - _debug _cca "$_cca" - _debug _cfullchain "$_cfullchain" + _domain="$1" + _key_file="$2" + _cert_file="$3" + _ca_file="$4" + _fullchain_file="$5" + + _debug _domain "$_domain" + _debug _key_file "$_key_file" + _debug _cert_file "$_cert_file" + _debug _ca_file "$_ca_file" + _debug _fullchain_file "$_fullchain_file" if ! _exists jq; then _err "jq not found" + return 1 fi - # Rename wildcard certs, kemp accepts only alphanumeric names - _kemp_domain=$(echo "${_cdomain}" | sed 's/\*/wildcard/') + # Rename wildcard certs, kemp accepts only alphanumeric names so we delete '*.' from filename + _kemp_domain=$(echo "${_domain}" | sed 's/\*\.//') _debug _kemp_domain "$_kemp_domain" - # Clear traces of incorrectly stored values - _clearaccountconf DEPLOY_KEMP_TOKEN - _clearaccountconf DEPLOY_KEMP_URL - # Read config from saved values or env _getdeployconf DEPLOY_KEMP_TOKEN _getdeployconf DEPLOY_KEMP_URL @@ -47,7 +44,7 @@ kemplm_deploy() { return 1 fi if [ -z "$DEPLOY_KEMP_URL" ]; then - _err "Kemp Loadmaster url is not found, please define DEPLOY_KEMP_URL." + _err "Kemp Loadmaster URL is not found, please define DEPLOY_KEMP_URL." return 1 fi @@ -55,14 +52,11 @@ kemplm_deploy() { _savedeployconf DEPLOY_KEMP_TOKEN "$DEPLOY_KEMP_TOKEN" _savedeployconf DEPLOY_KEMP_URL "$DEPLOY_KEMP_URL" - # Do not check for a valid SSL certificate - export HTTPS_INSECURE=1 - # Check if certificate is already installed _info "Check if certificate is already present" - _post_request="{\"cmd\": \"listcert\", \"apikey\": \"${DEPLOY_KEMP_TOKEN}\"}" - _debug3 _post_request "${_post_request}" - _kemp_cert_count=$(_post "${_post_request}" "${DEPLOY_KEMP_URL}/accessv2" | jq -r '.cert[] | .name' | grep -c "${_kemp_domain}") + _list_request="{\"cmd\": \"listcert\", \"apikey\": \"${DEPLOY_KEMP_TOKEN}\"}" + _debug3 _list_request "${_list_request}" + _kemp_cert_count=$(HTTPS_INSECURE=1 _post "${_list_request}" "${DEPLOY_KEMP_URL}/accessv2" | jq -r '.cert[] | .name' | grep -c "${_kemp_domain}") _debug2 _kemp_cert_count "${_kemp_cert_count}" _kemp_replace_cert=1 @@ -76,13 +70,13 @@ kemplm_deploy() { # Upload new certificate to Kemp Loadmaster _kemp_upload_cert=$(_mktemp) - cat "${_cfullchain}" "${_ckey}" | base64 -w 0 >"${_kemp_upload_cert}" + cat "${_fullchain_file}" "${_key_file}" | base64 | tr -d '\n' >"${_kemp_upload_cert}" _info "Uploading certificate to Kemp Loadmaster" - _post_data=$(cat "${_kemp_upload_cert}") - _post_request="{\"cmd\": \"addcert\", \"apikey\": \"${DEPLOY_KEMP_TOKEN}\", \"replace\": ${_kemp_replace_cert}, \"cert\": \"${_kemp_domain}\", \"data\": \"${_post_data}\"}" - _debug3 _post_request "${_post_request}" - _kemp_post_result=$(_post "${_post_request}" "${DEPLOY_KEMP_URL}/accessv2") + _add_data=$(cat "${_kemp_upload_cert}") + _add_request="{\"cmd\": \"addcert\", \"apikey\": \"${DEPLOY_KEMP_TOKEN}\", \"replace\": ${_kemp_replace_cert}, \"cert\": \"${_kemp_domain}\", \"data\": \"${_add_data}\"}" + _debug3 _add_request "${_add_request}" + _kemp_post_result=$(HTTPS_INSECURE=1 _post "${_add_request}" "${DEPLOY_KEMP_URL}/accessv2") _retval=$? _debug2 _kemp_post_result "${_kemp_post_result}" if [ "${_retval}" -eq 0 ]; then From f132010acb927065cef8294b4a772afe6301490f Mon Sep 17 00:00:00 2001 From: Sergey Ponomarev Date: Mon, 19 May 2025 15:08:54 +0300 Subject: [PATCH 32/66] dns_edgecenter.sh: fix structural info --- dnsapi/dns_edgecenter.sh | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/dnsapi/dns_edgecenter.sh b/dnsapi/dns_edgecenter.sh index cdd150df..8f4ad171 100644 --- a/dnsapi/dns_edgecenter.sh +++ b/dnsapi/dns_edgecenter.sh @@ -1,13 +1,13 @@ #!/usr/bin/env sh # shellcheck disable=SC2034 - -# EdgeCenter DNS API integration for acme.sh -# Author: Konstantin Ruchev -dns_edgecenter_info='edgecenter DNS API -Site: https://edgecenter.ru -Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_edgecenter +dns_edgecenter_info='EdgeCenter.ru +Site: EdgeCenter.ru +Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_edgecenter Options: - EDGECENTER_API_KEY auth APIKey' + EDGECENTER_API_KEY API Key +Issues: github.com/acmesh-official/acme.sh/issues/6313 +Author: Konstantin Ruchev +' EDGECENTER_API="https://api.edgecenter.ru" DOMAIN_TYPE= From 133ae8555a7114bf314d5a81be27f5e7a808e807 Mon Sep 17 00:00:00 2001 From: Sergey Ponomarev Date: Mon, 19 May 2025 15:15:46 +0300 Subject: [PATCH 33/66] dns_freemyip.sh: fix strutural info --- dnsapi/dns_freemyip.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_freemyip.sh b/dnsapi/dns_freemyip.sh index 0bad3809..d598a657 100644 --- a/dnsapi/dns_freemyip.sh +++ b/dnsapi/dns_freemyip.sh @@ -1,11 +1,11 @@ #!/usr/bin/env sh # shellcheck disable=SC2034 dns_freemyip_info='FreeMyIP.com -Site: freemyip.com +Site: FreeMyIP.com Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_freemyip Options: FREEMYIP_Token API Token -Issues: github.com/acmesh-official/acme.sh/issues/{XXXX} +Issues: github.com/acmesh-official/acme.sh/issues/6247 Author: Recolic Keghart , @Giova96 ' From 500cfbc19c08feab8763fd141181a5820290747e Mon Sep 17 00:00:00 2001 From: OPPO9008 <41640509+OPPO9008@users.noreply.github.com> Date: Mon, 19 May 2025 21:29:33 +0800 Subject: [PATCH 34/66] Update dns_la.sh --- dnsapi/dns_la.sh | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/dnsapi/dns_la.sh b/dnsapi/dns_la.sh index ba8ebcac..7c3765cd 100644 --- a/dnsapi/dns_la.sh +++ b/dnsapi/dns_la.sh @@ -2,17 +2,16 @@ # LA_Id="123" # LA_Sk="456" -# LA_Token="" -# -#Site: dns.la -#Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_la -#Options: -#我的账户 API 密钥 中获取 APIID APISecret -# LA_Id APIID -# LA_Key APISecret -# LA_Token 用冒号连接 APIID APISecret 再base64生成 -#Issues: github.com/acmesh-official/acme.sh/issues/4257 -#' +# shellcheck disable=SC2034 +LA_Token='dns.la +Site: dns.la +Docs: https://www.dns.la/docs/ApiDoc +Options: + LA_Id APIID + LA_Key APISecret + LA_Token 用冒号连接 APIID APISecret 再base64生成 +Issues: github.com/acmesh-official/acme.sh/issues/4257 +' LA_Api="https://api.dns.la/api" ######## Public functions ##################### From cddf098f47cde203dee97335176ef04bc7f3cdcc Mon Sep 17 00:00:00 2001 From: OPPO9008 <41640509+OPPO9008@users.noreply.github.com> Date: Tue, 20 May 2025 20:28:59 +0800 Subject: [PATCH 35/66] Update dns_la.sh --- dnsapi/dns_la.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_la.sh b/dnsapi/dns_la.sh index 7c3765cd..651b74c0 100644 --- a/dnsapi/dns_la.sh +++ b/dnsapi/dns_la.sh @@ -5,10 +5,10 @@ # shellcheck disable=SC2034 LA_Token='dns.la Site: dns.la -Docs: https://www.dns.la/docs/ApiDoc +Docs: https://github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_la Options: LA_Id APIID - LA_Key APISecret + LA_Sk APISecret LA_Token 用冒号连接 APIID APISecret 再base64生成 Issues: github.com/acmesh-official/acme.sh/issues/4257 ' From c8f1e4119719a911087dc266090ca04eb7dd20c1 Mon Sep 17 00:00:00 2001 From: OPPO9008 <41640509+OPPO9008@users.noreply.github.com> Date: Tue, 20 May 2025 20:29:44 +0800 Subject: [PATCH 36/66] Update dns_la.sh --- dnsapi/dns_la.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_la.sh b/dnsapi/dns_la.sh index 651b74c0..c2934b54 100644 --- a/dnsapi/dns_la.sh +++ b/dnsapi/dns_la.sh @@ -5,7 +5,7 @@ # shellcheck disable=SC2034 LA_Token='dns.la Site: dns.la -Docs: https://github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_la +Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_la Options: LA_Id APIID LA_Sk APISecret From 8241b078ced81178796ab76fad5b80baed44040f Mon Sep 17 00:00:00 2001 From: YANGJINZE <91786638+KincaidYang@users.noreply.github.com> Date: Fri, 23 May 2025 17:54:56 +0800 Subject: [PATCH 37/66] docs (dns_tencent) : update documentation links --- dnsapi/dns_tencent.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_tencent.sh b/dnsapi/dns_tencent.sh index d82768b9..b148adc3 100644 --- a/dnsapi/dns_tencent.sh +++ b/dnsapi/dns_tencent.sh @@ -2,7 +2,7 @@ # shellcheck disable=SC2034 dns_tencent_info='Tencent.com Site: cloud.Tencent.com -Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_tencent +Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_tencent Options: Tencent_SecretId Secret ID Tencent_SecretKey Secret Key From 28687ad7c7ac849d3201f6c7d8add0065718b60e Mon Sep 17 00:00:00 2001 From: Marcel Schlegel Date: Sat, 31 May 2025 15:02:25 +0200 Subject: [PATCH 38/66] Issue 3968: Fix missing api password encoding. --- dnsapi/dns_cloudns.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_cloudns.sh b/dnsapi/dns_cloudns.sh index 8bb0e00d..23a219da 100755 --- a/dnsapi/dns_cloudns.sh +++ b/dnsapi/dns_cloudns.sh @@ -197,10 +197,11 @@ _dns_cloudns_http_api_call() { auth_user="auth-id=$CLOUDNS_AUTH_ID" fi + encoded_password=$(echo "$CLOUDNS_AUTH_PASSWORD" | tr -d "\n\r" | _url_encode) if [ -z "$2" ]; then - data="$auth_user&auth-password=$CLOUDNS_AUTH_PASSWORD" + data="$auth_user&auth-password=$encoded_password" else - data="$auth_user&auth-password=$CLOUDNS_AUTH_PASSWORD&$2" + data="$auth_user&auth-password=$encoded_password&$2" fi response="$(_get "$CLOUDNS_API/$method?$data")" From 19678db9333f901219befcbd388fc454aa6b7119 Mon Sep 17 00:00:00 2001 From: OPPO9008 <41640509+OPPO9008@users.noreply.github.com> Date: Fri, 6 Jun 2025 02:06:27 +0800 Subject: [PATCH 39/66] Update dns_la.sh --- dnsapi/dns_la.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_la.sh b/dnsapi/dns_la.sh index c2934b54..772f8845 100644 --- a/dnsapi/dns_la.sh +++ b/dnsapi/dns_la.sh @@ -3,7 +3,7 @@ # LA_Id="123" # LA_Sk="456" # shellcheck disable=SC2034 -LA_Token='dns.la +dns_la_info='dns.la Site: dns.la Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_la Options: From bff1064dbd205db86832c876151304b97bf9d78f Mon Sep 17 00:00:00 2001 From: Lambiek12 Date: Sun, 8 Jun 2025 15:39:10 +0200 Subject: [PATCH 40/66] Add new dnsapi support for OpenProvider.eu using new REST API --- dnsapi/dns_openprovider_rest.sh | 193 ++++++++++++++++++++++++++++++++ 1 file changed, 193 insertions(+) create mode 100644 dnsapi/dns_openprovider_rest.sh diff --git a/dnsapi/dns_openprovider_rest.sh b/dnsapi/dns_openprovider_rest.sh new file mode 100644 index 00000000..a6725fcc --- /dev/null +++ b/dnsapi/dns_openprovider_rest.sh @@ -0,0 +1,193 @@ +#!/usr/bin/env sh +# shellcheck disable=SC2034 +dns_openprovider_rest_info='OpenProvider (REST) +Domains: OpenProvider.com +Site: OpenProvider.eu +Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_openprovider_rest +Options: + OPENPROVIDER_REST_USERNAME Openprovider Account Username + OPENPROVIDER_REST_PASSWORD Openprovider Account Password +Issues: github.com/acmesh-official/acme.sh/issues/6122 +Author: Lambiek12 +' + +OPENPROVIDER_API_URL="https://api.openprovider.eu/v1beta" + +######## Public functions ##################### + +# Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +# Used to add txt record +dns_openprovider_rest_add() { + fulldomain=$1 + txtvalue=$2 + + _openprovider_prepare_credentials || return 1 + + _debug "Try fetch OpenProvider DNS zone details" + if ! _get_dns_zone "$fulldomain"; then + _err "DNS zone not found within configured OpenProvider account." + return 1 + fi + + if [ -n "$_domain_id" ]; then + addzonerecordrequestparameters="dns/zones/$_domain_name" + addzonerecordrequestbody="{\"id\":$_domain_id,\"name\":\"$_domain_name\",\"records\":{\"add\":[{\"name\":\"$_sub_domain\",\"ttl\":900,\"type\":\"TXT\",\"value\":\"$txtvalue\"}]}}" + + if _openprovider_rest PUT "$addzonerecordrequestparameters" "$addzonerecordrequestbody"; then + if _contains "$response" "\"success\":true"; then + return 0 + elif _contains "$response" "\"Duplicate record\""; then + _debug "Record already existed" + return 0 + else + _err "Adding TXT record failed due to errors." + return 1 + fi + fi + fi + + _err "Adding TXT record failed due to errors." + return 1 +} + +# Usage: rm _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +# Used to remove the txt record after validation +dns_openprovider_rest_rm() { + fulldomain=$1 + txtvalue=$2 + + _openprovider_prepare_credentials || return 1 + + _debug "Try fetch OpenProvider DNS zone details" + if ! _get_dns_zone "$fulldomain"; then + _err "DNS zone not found within configured OpenProvider account." + return 1 + fi + + if [ -n "$_domain_id" ]; then + removezonerecordrequestparameters="dns/zones/$_domain_name" + removezonerecordrequestbody="{\"id\":$_domain_id,\"name\":\"$_domain_name\",\"records\":{\"remove\":[{\"name\":\"$_sub_domain\",\"ttl\":900,\"type\":\"TXT\",\"value\":\"\\\"$txtvalue\\\"\"}]}}" + + if _openprovider_rest PUT "$removezonerecordrequestparameters" "$removezonerecordrequestbody"; then + if _contains "$response" "\"success\":true"; then + return 0 + else + _err "Removing TXT record failed due to errors." + return 1 + fi + fi + fi + + _err "Removing TXT record failed due to errors." + return 1 +} + +#################### OpenProvider API common functions #################### +_openprovider_prepare_credentials() { + OPENPROVIDER_REST_USERNAME="${OPENPROVIDER_REST_USERNAME:-$(_readaccountconf_mutable OPENPROVIDER_REST_USERNAME)}" + OPENPROVIDER_REST_PASSWORD="${OPENPROVIDER_REST_PASSWORD:-$(_readaccountconf_mutable OPENPROVIDER_REST_PASSWORD)}" + + if [ -z "$OPENPROVIDER_REST_USERNAME" ] || [ -z "$OPENPROVIDER_REST_PASSWORD" ]; then + OPENPROVIDER_REST_USERNAME="" + OPENPROVIDER_REST_PASSWORD="" + _err "You didn't specify the Openprovider username or password yet." + return 1 + fi + + #save the credentials to the account conf file. + _saveaccountconf_mutable OPENPROVIDER_REST_USERNAME "$OPENPROVIDER_REST_USERNAME" + _saveaccountconf_mutable OPENPROVIDER_REST_PASSWORD "$OPENPROVIDER_REST_PASSWORD" +} + +_openprovider_rest() { + httpmethod=$1 + queryparameters=$2 + requestbody=$3 + + _openprovider_rest_login + if [ -z "$openproviderauthtoken" ]; then + _err "Unable to fetch authentication token from Openprovider API." + return 1 + fi + + export _H1="Content-Type: application/json" + export _H2="Accept: application/json" + export _H3="Authorization: Bearer $openproviderauthtoken" + + _debug httpmethod "$httpmethod" + _debug requestfullurl "$OPENPROVIDER_API_URL/$queryparameters" + _debug queryparameters "$queryparameters" + + if [ "$httpmethod" != "GET" ]; then + _debug requestbody "$requestbody" + + response="$(_post "$requestbody" "$OPENPROVIDER_API_URL/$queryparameters" "" "$httpmethod")" + else + response="$(_get "$OPENPROVIDER_API_URL/$queryparameters")" + fi + + if [ "$?" != "0" ]; then + _err "No valid parameters supplied for Openprovider API: Error $queryparameters" + return 1 + fi + + _debug2 response "$response" + + return 0 +} + +_openprovider_rest_login() { + export _H1="Content-Type: application/json" + export _H2="Accept: application/json" + + loginrequesturl="$OPENPROVIDER_API_URL/auth/login" + loginrequestbody="{\"ip\":\"0.0.0.0\",\"password\":\"$OPENPROVIDER_REST_PASSWORD\",\"username\":\"$OPENPROVIDER_REST_USERNAME\"}" + loginresponse="$(_post "$loginrequestbody" "$loginrequesturl" "" "POST")" + + openproviderauthtoken="$(printf "%s\n" "$loginresponse" | _egrep_o '"token" *: *"[^"]*' | _head_n 1 | sed 's#^"token" *: *"##')" + _debug openproviderauthtoken "$openproviderauthtoken" + + export openproviderauthtoken +} + +#################### Private functions ################################## + +# Usage: _get_dns_zone _acme-challenge.www.domain.com +# Returns: +# _domain_id=123456789 +# _domain_name=domain.com +# _sub_domain=_acme-challenge.www +_get_dns_zone() { + domain=$1 + i=1 + p=1 + + while true; do + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) + if [ -z "$h" ]; then + # Empty value not allowed + return 1 + fi + + if ! _openprovider_rest GET "dns/zones/$h" ""; then + return 1 + fi + + if _contains "$response" "\"name\":\"$h\""; then + _domain_id="$(printf "%s\n" "$response" | _egrep_o '"id" *: *[^,]*' | _head_n 1 | sed 's#^"id" *: *##')" + _debug _domain_id "$_domain_id" + + _domain_name="$h" + _debug _domain_name "$_domain_name" + + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") + _debug _sub_domain "$_sub_domain" + return 0 + fi + + p=$i + i=$(_math "$i" + 1) + done + + return 1 +} From 06d3739a8dc9b235aadc0460d7ddcbb2e867a04e Mon Sep 17 00:00:00 2001 From: Lambiek12 Date: Sun, 8 Jun 2025 17:29:39 +0200 Subject: [PATCH 41/66] Cleanup duplicate debug log output based on DNS test run --- dnsapi/dns_openprovider_rest.sh | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/dnsapi/dns_openprovider_rest.sh b/dnsapi/dns_openprovider_rest.sh index a6725fcc..3b8d20d2 100644 --- a/dnsapi/dns_openprovider_rest.sh +++ b/dnsapi/dns_openprovider_rest.sh @@ -113,14 +113,8 @@ _openprovider_rest() { export _H1="Content-Type: application/json" export _H2="Accept: application/json" export _H3="Authorization: Bearer $openproviderauthtoken" - - _debug httpmethod "$httpmethod" - _debug requestfullurl "$OPENPROVIDER_API_URL/$queryparameters" - _debug queryparameters "$queryparameters" - + if [ "$httpmethod" != "GET" ]; then - _debug requestbody "$requestbody" - response="$(_post "$requestbody" "$OPENPROVIDER_API_URL/$queryparameters" "" "$httpmethod")" else response="$(_get "$OPENPROVIDER_API_URL/$queryparameters")" @@ -145,7 +139,6 @@ _openprovider_rest_login() { loginresponse="$(_post "$loginrequestbody" "$loginrequesturl" "" "POST")" openproviderauthtoken="$(printf "%s\n" "$loginresponse" | _egrep_o '"token" *: *"[^"]*' | _head_n 1 | sed 's#^"token" *: *"##')" - _debug openproviderauthtoken "$openproviderauthtoken" export openproviderauthtoken } From fcd358eb71e0c8ca49b11e2fbca133c9c5937844 Mon Sep 17 00:00:00 2001 From: Lambiek12 Date: Sun, 8 Jun 2025 17:35:09 +0200 Subject: [PATCH 42/66] Resolve spellcheck error --- dnsapi/dns_openprovider_rest.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_openprovider_rest.sh b/dnsapi/dns_openprovider_rest.sh index 3b8d20d2..210dc6fc 100644 --- a/dnsapi/dns_openprovider_rest.sh +++ b/dnsapi/dns_openprovider_rest.sh @@ -113,7 +113,7 @@ _openprovider_rest() { export _H1="Content-Type: application/json" export _H2="Accept: application/json" export _H3="Authorization: Bearer $openproviderauthtoken" - + if [ "$httpmethod" != "GET" ]; then response="$(_post "$requestbody" "$OPENPROVIDER_API_URL/$queryparameters" "" "$httpmethod")" else From f2b248243c1de3f1ddb740cab828f1eb580d744a Mon Sep 17 00:00:00 2001 From: Erwin Oegema Date: Tue, 10 Jun 2025 10:36:06 +0200 Subject: [PATCH 43/66] Configure 10 second timeout to ACME_DIRECTORY API call --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index e9eb6b94..b8630742 100755 --- a/acme.sh +++ b/acme.sh @@ -2761,7 +2761,7 @@ _initAPI() { _request_retry_times=0 while [ -z "$ACME_NEW_ACCOUNT" ] && [ "${_request_retry_times}" -lt "$MAX_API_RETRY_TIMES" ]; do _request_retry_times=$(_math "$_request_retry_times" + 1) - response=$(_get "$_api_server") + response=$(_get "$_api_server" "" 10) if [ "$?" != "0" ]; then _debug2 "response" "$response" _info "Cannot init API for: $_api_server." From 242085d6765e43ad08a6b1863ec586c789a3f483 Mon Sep 17 00:00:00 2001 From: laDanz Date: Tue, 17 Jun 2025 14:05:40 +0200 Subject: [PATCH 44/66] add support for AIX style netstat --- acme.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/acme.sh b/acme.sh index e9eb6b94..e8378754 100755 --- a/acme.sh +++ b/acme.sh @@ -1401,6 +1401,12 @@ _ss() { return 0 fi + if [ "$(uname)" = "AIX" ]; then + _debug "Using: AIX netstat" + netstat -an | grep "^tcp" | grep "LISTEN" | grep "\.$_port " + return 0 + fi + if _exists "netstat"; then _debug "Using: netstat" if netstat -help 2>&1 | grep "\-p proto" >/dev/null; then From 4a16aaacb6a47d60dee9da2cd4f20fb101f5a47b Mon Sep 17 00:00:00 2001 From: neil Date: Wed, 25 Jun 2025 21:27:08 +0200 Subject: [PATCH 45/66] add --- .github/workflows/wiki-monitor.yml | 32 ++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 .github/workflows/wiki-monitor.yml diff --git a/.github/workflows/wiki-monitor.yml b/.github/workflows/wiki-monitor.yml new file mode 100644 index 00000000..b86347cf --- /dev/null +++ b/.github/workflows/wiki-monitor.yml @@ -0,0 +1,32 @@ +name: Notify via Issue on Wiki Edit + +on: + gollum: + +jobs: + notify: + runs-on: ubuntu-latest + steps: + - name: Generate wiki change message + run: | + echo "Wiki page:" > wiki-change-msg.txt + echo "User: ${{ github.actor }}" >> wiki-change-msg.txt + echo "Time: $(date '+%Y-%m-%d %H:%M:%S')" >> wiki-change-msg.txt + echo "" >> wiki-change-msg.txt + for page in $(jq -r '.gollum.pages[].html_url' "$GITHUB_EVENT_PATH"); do + echo "Path: $page" >> wiki-change-msg.txt + done + + - name: Create issue to notify Neilpang + uses: peter-evans/create-issue-from-file@v5 + with: + title: "Wiki page" + content-filepath: ./wiki-change-msg.txt + assignees: Neilpang + env: + TZ: Asia/Shanghai + + + + + From b025e7f0f280b33bbca418fa53a6634f4adcdb4f Mon Sep 17 00:00:00 2001 From: neil Date: Wed, 25 Jun 2025 21:46:58 +0200 Subject: [PATCH 46/66] fix for wiki --- .github/workflows/wiki-monitor.yml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/wiki-monitor.yml b/.github/workflows/wiki-monitor.yml index b86347cf..1955043e 100644 --- a/.github/workflows/wiki-monitor.yml +++ b/.github/workflows/wiki-monitor.yml @@ -9,18 +9,17 @@ jobs: steps: - name: Generate wiki change message run: | - echo "Wiki page:" > wiki-change-msg.txt + sudo apt-get update && sudo apt-get install -y jq + echo "Wiki page edited" > wiki-change-msg.txt echo "User: ${{ github.actor }}" >> wiki-change-msg.txt echo "Time: $(date '+%Y-%m-%d %H:%M:%S')" >> wiki-change-msg.txt echo "" >> wiki-change-msg.txt - for page in $(jq -r '.gollum.pages[].html_url' "$GITHUB_EVENT_PATH"); do - echo "Path: $page" >> wiki-change-msg.txt - done + jq -r '.gollum.pages[] | "Page: \(.html_url) (action: \(.action))"' "$GITHUB_EVENT_PATH" >> wiki-change-msg.txt - name: Create issue to notify Neilpang uses: peter-evans/create-issue-from-file@v5 with: - title: "Wiki page" + title: "Wiki edited" content-filepath: ./wiki-change-msg.txt assignees: Neilpang env: From 89071f722642248e54df7f627ed40943c5b622c7 Mon Sep 17 00:00:00 2001 From: neil Date: Wed, 25 Jun 2025 21:51:55 +0200 Subject: [PATCH 47/66] minor --- .github/workflows/wiki-monitor.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/wiki-monitor.yml b/.github/workflows/wiki-monitor.yml index 1955043e..c9432841 100644 --- a/.github/workflows/wiki-monitor.yml +++ b/.github/workflows/wiki-monitor.yml @@ -14,7 +14,8 @@ jobs: echo "User: ${{ github.actor }}" >> wiki-change-msg.txt echo "Time: $(date '+%Y-%m-%d %H:%M:%S')" >> wiki-change-msg.txt echo "" >> wiki-change-msg.txt - jq -r '.gollum.pages[] | "Page: \(.html_url) (action: \(.action))"' "$GITHUB_EVENT_PATH" >> wiki-change-msg.txt + cat "$GITHUB_EVENT_PATH" + jq -r '.gollum.pages // [] | .[] | "Page: \(.html_url) (action: \(.action))"' "$GITHUB_EVENT_PATH" >> wiki-change-msg.txt - name: Create issue to notify Neilpang uses: peter-evans/create-issue-from-file@v5 From 6966b3810ddf13fc0874116dfb8060aa58177e97 Mon Sep 17 00:00:00 2001 From: neil Date: Wed, 25 Jun 2025 22:01:11 +0200 Subject: [PATCH 48/66] minor --- .github/workflows/wiki-monitor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/wiki-monitor.yml b/.github/workflows/wiki-monitor.yml index c9432841..c29d92c7 100644 --- a/.github/workflows/wiki-monitor.yml +++ b/.github/workflows/wiki-monitor.yml @@ -15,7 +15,7 @@ jobs: echo "Time: $(date '+%Y-%m-%d %H:%M:%S')" >> wiki-change-msg.txt echo "" >> wiki-change-msg.txt cat "$GITHUB_EVENT_PATH" - jq -r '.gollum.pages // [] | .[] | "Page: \(.html_url) (action: \(.action))"' "$GITHUB_EVENT_PATH" >> wiki-change-msg.txt + jq -r '.pages // [] | .[] | "Page: \(.html_url) (action: \(.action))"' "$GITHUB_EVENT_PATH" >> wiki-change-msg.txt - name: Create issue to notify Neilpang uses: peter-evans/create-issue-from-file@v5 From 424d33faa082e3f41789ee5ec2ee7e3e280fcdc4 Mon Sep 17 00:00:00 2001 From: neil Date: Wed, 25 Jun 2025 22:11:35 +0200 Subject: [PATCH 49/66] wiki --- .github/workflows/wiki-monitor.yml | 42 +++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/.github/workflows/wiki-monitor.yml b/.github/workflows/wiki-monitor.yml index c29d92c7..1e216f2e 100644 --- a/.github/workflows/wiki-monitor.yml +++ b/.github/workflows/wiki-monitor.yml @@ -7,15 +7,43 @@ jobs: notify: runs-on: ubuntu-latest steps: + - name: Checkout wiki repository + uses: actions/checkout@v4 + with: + repository: ${{ github.repository }}.wiki + path: wiki + - name: Generate wiki change message run: | - sudo apt-get update && sudo apt-get install -y jq - echo "Wiki page edited" > wiki-change-msg.txt - echo "User: ${{ github.actor }}" >> wiki-change-msg.txt - echo "Time: $(date '+%Y-%m-%d %H:%M:%S')" >> wiki-change-msg.txt - echo "" >> wiki-change-msg.txt - cat "$GITHUB_EVENT_PATH" - jq -r '.pages // [] | .[] | "Page: \(.html_url) (action: \(.action))"' "$GITHUB_EVENT_PATH" >> wiki-change-msg.txt + actor="${{ github.actor }}" + sender_url=$(jq -r '.sender.html_url' "$GITHUB_EVENT_PATH") + page_name=$(jq -r '.pages[0].page_name' "$GITHUB_EVENT_PATH") + page_sha=$(jq -r '.pages[0].sha' "$GITHUB_EVENT_PATH") + page_url=$(jq -r '.pages[0].html_url' "$GITHUB_EVENT_PATH") + page_action=$(jq -r '.pages[0].action' "$GITHUB_EVENT_PATH") + now="$(date '+%Y-%m-%d %H:%M:%S')" + + cd wiki + prev_sha=$(git rev-list $page_sha^ -- "$page_name.md" | head -n 1) + if [ -n "$prev_sha" ]; then + git diff $prev_sha $page_sha -- "$page_name.md" > ../wiki.diff || echo "(No diff found)" > ../wiki.diff + else + echo "(no diff)" > ../wiki.diff + fi + cd .. + { + echo "Wiki edited" + echo -n "User: " + echo "[$actor]($sender_url)" + echo "Time: $now" + echo "Page: [$page_name]($page_url) (Action: $page_action)" + echo "" + echo "----" + echo "### diff:" + echo '```diff' + cat wiki.diff + echo '```' + } > wiki-change-msg.txt - name: Create issue to notify Neilpang uses: peter-evans/create-issue-from-file@v5 From 74fdf649d3883f1fee6fdb0128f8f146ef9c9e83 Mon Sep 17 00:00:00 2001 From: neil Date: Wed, 25 Jun 2025 22:14:30 +0200 Subject: [PATCH 50/66] wiki --- .github/workflows/wiki-monitor.yml | 58 +++++++++++++++--------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/.github/workflows/wiki-monitor.yml b/.github/workflows/wiki-monitor.yml index 1e216f2e..89497580 100644 --- a/.github/workflows/wiki-monitor.yml +++ b/.github/workflows/wiki-monitor.yml @@ -15,35 +15,35 @@ jobs: - name: Generate wiki change message run: | - actor="${{ github.actor }}" - sender_url=$(jq -r '.sender.html_url' "$GITHUB_EVENT_PATH") - page_name=$(jq -r '.pages[0].page_name' "$GITHUB_EVENT_PATH") - page_sha=$(jq -r '.pages[0].sha' "$GITHUB_EVENT_PATH") - page_url=$(jq -r '.pages[0].html_url' "$GITHUB_EVENT_PATH") - page_action=$(jq -r '.pages[0].action' "$GITHUB_EVENT_PATH") - now="$(date '+%Y-%m-%d %H:%M:%S')" - - cd wiki - prev_sha=$(git rev-list $page_sha^ -- "$page_name.md" | head -n 1) - if [ -n "$prev_sha" ]; then - git diff $prev_sha $page_sha -- "$page_name.md" > ../wiki.diff || echo "(No diff found)" > ../wiki.diff - else - echo "(no diff)" > ../wiki.diff - fi - cd .. - { - echo "Wiki edited" - echo -n "User: " - echo "[$actor]($sender_url)" - echo "Time: $now" - echo "Page: [$page_name]($page_url) (Action: $page_action)" - echo "" - echo "----" - echo "### diff:" - echo '```diff' - cat wiki.diff - echo '```' - } > wiki-change-msg.txt + actor="${{ github.actor }}" + sender_url=$(jq -r '.sender.html_url' "$GITHUB_EVENT_PATH") + page_name=$(jq -r '.pages[0].page_name' "$GITHUB_EVENT_PATH") + page_sha=$(jq -r '.pages[0].sha' "$GITHUB_EVENT_PATH") + page_url=$(jq -r '.pages[0].html_url' "$GITHUB_EVENT_PATH") + page_action=$(jq -r '.pages[0].action' "$GITHUB_EVENT_PATH") + now="$(date '+%Y-%m-%d %H:%M:%S')" + + cd wiki + prev_sha=$(git rev-list $page_sha^ -- "$page_name.md" | head -n 1) + if [ -n "$prev_sha" ]; then + git diff $prev_sha $page_sha -- "$page_name.md" > ../wiki.diff || echo "(No diff found)" > ../wiki.diff + else + echo "(no diff)" > ../wiki.diff + fi + cd .. + { + echo "Wiki edited" + echo -n "User: " + echo "[$actor]($sender_url)" + echo "Time: $now" + echo "Page: [$page_name]($page_url) (Action: $page_action)" + echo "" + echo "----" + echo "### diff:" + echo '```diff' + cat wiki.diff + echo '```' + } > wiki-change-msg.txt - name: Create issue to notify Neilpang uses: peter-evans/create-issue-from-file@v5 From 2bea808251d3e0c65fab47dafba0fec636128a6a Mon Sep 17 00:00:00 2001 From: OPPO9008 <41640509+OPPO9008@users.noreply.github.com> Date: Wed, 2 Jul 2025 21:15:46 +0800 Subject: [PATCH 51/66] Update dns_la.sh --- dnsapi/dns_la.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_la.sh b/dnsapi/dns_la.sh index 772f8845..9cb6327e 100644 --- a/dnsapi/dns_la.sh +++ b/dnsapi/dns_la.sh @@ -100,7 +100,7 @@ dns_la_rm() { return 0 fi - record_id=$(printf "%s" "$response" | grep '"id":' | head -n1 | sed 's/.*"id": *"\([^"]*\)".*/\1/') + record_id=$(printf "%s" "$response" | grep '"id":' | _head_n 1 | sed 's/.*"id": *"\([^"]*\)".*/\1/') _debug "record_id" "$record_id" if [ -z "$record_id" ]; then _err "Can not get record id to remove." From 76b68f7ccb3063a0d065ab1009d70156d3f5d135 Mon Sep 17 00:00:00 2001 From: Sergey Ponomarev Date: Sun, 6 Jul 2025 01:34:21 +0300 Subject: [PATCH 52/66] dnsapi: dns_mydnsjp.sh fix author The @epgdatacapbon was renamed to @tkmsst Signed-off-by: Sergey Ponomarev --- dnsapi/dns_mydnsjp.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_mydnsjp.sh b/dnsapi/dns_mydnsjp.sh index 336c4889..4dfffaaa 100755 --- a/dnsapi/dns_mydnsjp.sh +++ b/dnsapi/dns_mydnsjp.sh @@ -6,7 +6,7 @@ Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_mydnsjp Options: MYDNSJP_MasterID Master ID MYDNSJP_Password Password -Author: epgdatacapbon +Author: @tkmsst ' ######## Public functions ##################### From 01ed3c332648104652c6b7af3ff4518ebe3a32f2 Mon Sep 17 00:00:00 2001 From: Sergey Ponomarev Date: Sun, 6 Jul 2025 01:36:40 +0300 Subject: [PATCH 53/66] dnsapi: dns_ddnss.sh remove RaidenII from authors He made the DuckDNS script that was used for this script but he can't support the script. Signed-off-by: Sergey Ponomarev --- dnsapi/dns_ddnss.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_ddnss.sh b/dnsapi/dns_ddnss.sh index 118b148b..a624a268 100644 --- a/dnsapi/dns_ddnss.sh +++ b/dnsapi/dns_ddnss.sh @@ -6,7 +6,7 @@ Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_ddnss Options: DDNSS_Token API Token Issues: github.com/acmesh-official/acme.sh/issues/2230 -Author: RaidenII, helbgd, mod242 +Author: helbgd, mod242 ' DDNSS_DNS_API="https://ddnss.de/upd.php" From c6819cbd6b40d95e1b0f03273ee6a598cd9794a6 Mon Sep 17 00:00:00 2001 From: Sergey Ponomarev Date: Sun, 6 Jul 2025 01:40:53 +0300 Subject: [PATCH 54/66] dnsapi: fix authors: use @ for GitHub profiles Signed-off-by: Sergey Ponomarev --- dnsapi/dns_bookmyname.sh | 2 +- dnsapi/dns_ddnss.sh | 2 +- dnsapi/dns_dnshome.sh | 2 +- dnsapi/dns_duckdns.sh | 2 +- dnsapi/dns_dyn.sh | 2 +- dnsapi/dns_dynv6.sh | 2 +- dnsapi/dns_easydns.sh | 2 +- dnsapi/dns_freedns.sh | 2 +- dnsapi/dns_joker.sh | 2 +- dnsapi/dns_mijnhost.sh | 2 +- dnsapi/dns_namecom.sh | 2 +- dnsapi/dns_namesilo.sh | 2 +- dnsapi/dns_pleskxml.sh | 2 +- dnsapi/dns_schlundtech.sh | 2 +- dnsapi/dns_spaceship.sh | 2 +- dnsapi/dns_tele3.sh | 2 +- dnsapi/dns_timeweb.sh | 2 +- dnsapi/dns_udr.sh | 2 +- dnsapi/dns_vscale.sh | 2 +- dnsapi/dns_websupport.sh | 2 +- dnsapi/dns_world4you.sh | 2 +- 21 files changed, 21 insertions(+), 21 deletions(-) diff --git a/dnsapi/dns_bookmyname.sh b/dnsapi/dns_bookmyname.sh index 668cf074..cf3f1e3e 100644 --- a/dnsapi/dns_bookmyname.sh +++ b/dnsapi/dns_bookmyname.sh @@ -7,7 +7,7 @@ Options: BOOKMYNAME_USERNAME Username BOOKMYNAME_PASSWORD Password Issues: github.com/acmesh-official/acme.sh/issues/3209 -Author: Neilpang +Author: @Neilpang ' ######## Public functions ##################### diff --git a/dnsapi/dns_ddnss.sh b/dnsapi/dns_ddnss.sh index a624a268..0ac353d4 100644 --- a/dnsapi/dns_ddnss.sh +++ b/dnsapi/dns_ddnss.sh @@ -6,7 +6,7 @@ Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_ddnss Options: DDNSS_Token API Token Issues: github.com/acmesh-official/acme.sh/issues/2230 -Author: helbgd, mod242 +Author: @helbgd, @mod242 ' DDNSS_DNS_API="https://ddnss.de/upd.php" diff --git a/dnsapi/dns_dnshome.sh b/dnsapi/dns_dnshome.sh index 59828796..6d583246 100755 --- a/dnsapi/dns_dnshome.sh +++ b/dnsapi/dns_dnshome.sh @@ -7,7 +7,7 @@ Options: DNSHOME_Subdomain Subdomain DNSHOME_SubdomainPassword Subdomain Password Issues: github.com/acmesh-official/acme.sh/issues/3819 -Author: dnsHome.de https://github.com/dnsHome-de +Author: @dnsHome-de ' # Usage: add subdomain.ddnsdomain.tld "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" diff --git a/dnsapi/dns_duckdns.sh b/dnsapi/dns_duckdns.sh index 71594873..33d401b0 100755 --- a/dnsapi/dns_duckdns.sh +++ b/dnsapi/dns_duckdns.sh @@ -5,7 +5,7 @@ Site: www.DuckDNS.org Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_duckdns Options: DuckDNS_Token API Token -Author: RaidenII +Author: @RaidenII ' DuckDNS_API="https://www.duckdns.org/update" diff --git a/dnsapi/dns_dyn.sh b/dnsapi/dns_dyn.sh index 94201923..9b1a97a2 100644 --- a/dnsapi/dns_dyn.sh +++ b/dnsapi/dns_dyn.sh @@ -8,7 +8,7 @@ Options: DYN_Customer Customer DYN_Username API Username DYN_Password Secret -Author: Gerd Naschenweng +Author: Gerd Naschenweng <@magicdude4eva> ' # Dyn Managed DNS API diff --git a/dnsapi/dns_dynv6.sh b/dnsapi/dns_dynv6.sh index 76af17f5..0c9491f8 100644 --- a/dnsapi/dns_dynv6.sh +++ b/dnsapi/dns_dynv6.sh @@ -8,7 +8,7 @@ Options: OptionsAlt: KEY Path to SSH private key file. E.g. "/root/.ssh/dynv6" Issues: github.com/acmesh-official/acme.sh/issues/2702 -Author: StefanAbl +Author: @StefanAbl ' dynv6_api="https://dynv6.com/api/v2" diff --git a/dnsapi/dns_easydns.sh b/dnsapi/dns_easydns.sh index 1c96ac8f..423def2b 100644 --- a/dnsapi/dns_easydns.sh +++ b/dnsapi/dns_easydns.sh @@ -7,7 +7,7 @@ Options: EASYDNS_Token API Token EASYDNS_Key API Key Issues: github.com/acmesh-official/acme.sh/issues/2647 -Author: Neilpang, wurzelpanzer +Author: @Neilpang, wurzelpanzer ' # API Documentation: https://sandbox.rest.easydns.net:3001/ diff --git a/dnsapi/dns_freedns.sh b/dnsapi/dns_freedns.sh index 114f30e0..13d9f68b 100755 --- a/dnsapi/dns_freedns.sh +++ b/dnsapi/dns_freedns.sh @@ -7,7 +7,7 @@ Options: FREEDNS_User Username FREEDNS_Password Password Issues: github.com/acmesh-official/acme.sh/issues/2305 -Author: David Kerr +Author: David Kerr <@dkerr64> ' ######## Public functions ##################### diff --git a/dnsapi/dns_joker.sh b/dnsapi/dns_joker.sh index 1fe33c67..401471be 100644 --- a/dnsapi/dns_joker.sh +++ b/dnsapi/dns_joker.sh @@ -7,7 +7,7 @@ Options: JOKER_USERNAME Username JOKER_PASSWORD Password Issues: github.com/acmesh-official/acme.sh/issues/2840 -Author: +Author: @aattww ' JOKER_API="https://svc.joker.com/nic/replace" diff --git a/dnsapi/dns_mijnhost.sh b/dnsapi/dns_mijnhost.sh index 9dafc702..52a81632 100644 --- a/dnsapi/dns_mijnhost.sh +++ b/dnsapi/dns_mijnhost.sh @@ -5,7 +5,7 @@ Domains: mijn.host Site: mijn.host Docs: https://mijn.host/api/doc/ Issues: https://github.com/acmesh-official/acme.sh/issues/6177 -Author: peterv99 +Author: @peterv99 Options: MIJNHOST_API_KEY API Key ' diff --git a/dnsapi/dns_namecom.sh b/dnsapi/dns_namecom.sh index 44549c9e..1062c849 100755 --- a/dnsapi/dns_namecom.sh +++ b/dnsapi/dns_namecom.sh @@ -6,7 +6,7 @@ Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_namecom Options: Namecom_Username Username Namecom_Token API Token -Author: RaidenII +Author: @RaidenII ' ######## Public functions ##################### diff --git a/dnsapi/dns_namesilo.sh b/dnsapi/dns_namesilo.sh index b31e32a1..5d47a59a 100755 --- a/dnsapi/dns_namesilo.sh +++ b/dnsapi/dns_namesilo.sh @@ -5,7 +5,7 @@ Site: NameSilo.com Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_namesilo Options: Namesilo_Key API Key -Author: meowthink +Author: @meowthink ' #Utilize API to finish dns-01 verifications. diff --git a/dnsapi/dns_pleskxml.sh b/dnsapi/dns_pleskxml.sh index 6b38abcb..465bcc60 100644 --- a/dnsapi/dns_pleskxml.sh +++ b/dnsapi/dns_pleskxml.sh @@ -8,7 +8,7 @@ Options: pleskxml_user Username pleskxml_pass Password Issues: github.com/acmesh-official/acme.sh/issues/2577 -Author: Stilez, +Author: @Stilez, @romanlum ' ## Plesk XML API described at: diff --git a/dnsapi/dns_schlundtech.sh b/dnsapi/dns_schlundtech.sh index 6d2930a2..21930110 100644 --- a/dnsapi/dns_schlundtech.sh +++ b/dnsapi/dns_schlundtech.sh @@ -7,7 +7,7 @@ Options: SCHLUNDTECH_USER Username SCHLUNDTECH_PASSWORD Password Issues: github.com/acmesh-official/acme.sh/issues/2246 -Author: +Author: @mod242 ' SCHLUNDTECH_API="https://gateway.schlundtech.de" diff --git a/dnsapi/dns_spaceship.sh b/dnsapi/dns_spaceship.sh index 770e22cc..5e92a4fe 100644 --- a/dnsapi/dns_spaceship.sh +++ b/dnsapi/dns_spaceship.sh @@ -8,7 +8,7 @@ Options: SPACESHIP_API_SECRET Spaceship API Secret SPACESHIP_ROOT_DOMAIN (Optional) Manually specify the root domain if auto-detection fails Issues: github.com/acmesh-official/acme.sh/issues/6304 -Author: Meow +Author: Meow <@Meo597> ' # Spaceship API diff --git a/dnsapi/dns_tele3.sh b/dnsapi/dns_tele3.sh index e5974951..3a3ccf8c 100644 --- a/dnsapi/dns_tele3.sh +++ b/dnsapi/dns_tele3.sh @@ -6,7 +6,7 @@ Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#tele3 Options: TELE3_Key API Key TELE3_Secret API Secret -Author: Roman Blizik +Author: Roman Blizik <@par-pa> ' TELE3_API="https://www.tele3.cz/acme/" diff --git a/dnsapi/dns_timeweb.sh b/dnsapi/dns_timeweb.sh index 544564ea..7040ac9a 100644 --- a/dnsapi/dns_timeweb.sh +++ b/dnsapi/dns_timeweb.sh @@ -6,7 +6,7 @@ Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_timeweb Options: TW_Token API JWT token. Get it from the control panel at https://timeweb.cloud/my/api-keys Issues: github.com/acmesh-official/acme.sh/issues/5140 -Author: Nikolay Pronchev +Author: Nikolay Pronchev <@nikolaypronchev> ' TW_Api="https://api.timeweb.cloud/api/v1" diff --git a/dnsapi/dns_udr.sh b/dnsapi/dns_udr.sh index f9772e10..656a0557 100644 --- a/dnsapi/dns_udr.sh +++ b/dnsapi/dns_udr.sh @@ -7,7 +7,7 @@ Options: UDR_USER Username UDR_PASS Password Issues: github.com/acmesh-official/acme.sh/issues/3923 -Author: Andreas Scherer +Author: Andreas Scherer <@andischerer> ' UDR_API="https://api.domainreselling.de/api/call.cgi" diff --git a/dnsapi/dns_vscale.sh b/dnsapi/dns_vscale.sh index c3915c69..faf3105d 100755 --- a/dnsapi/dns_vscale.sh +++ b/dnsapi/dns_vscale.sh @@ -5,7 +5,7 @@ Site: vscale.io Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_vscale Options: VSCALE_API_KEY API Key -Author: Alex Loban +Author: Alex Loban <@LAV45> ' VSCALE_API_URL="https://api.vscale.io/v1" diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index bfc4b23a..2374afc3 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -7,7 +7,7 @@ Options: WS_ApiKey API Key. Called "Identifier" in the WS Admin WS_ApiSecret API Secret. Called "Secret key" in the WS Admin Issues: github.com/acmesh-official/acme.sh/issues/3486 -Author: trgo.sk , akulumbeg +Author: trgo.sk <@trgosk>, @akulumbeg ' # Requirements: API Key and Secret from https://admin.websupport.sk/en/auth/apiKey diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index 46cdc4fe..dc295330 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -7,7 +7,7 @@ Options: WORLD4YOU_USERNAME Username WORLD4YOU_PASSWORD Password Issues: github.com/acmesh-official/acme.sh/issues/3269 -Author: Lorenz Stechauner +Author: Lorenz Stechauner <@NerLOR> ' WORLD4YOU_API="https://my.world4you.com/en" From daf183e2cc8b1e11ecb754fd8eddd56c1b954c12 Mon Sep 17 00:00:00 2001 From: Sergey Ponomarev Date: Sun, 6 Jul 2025 01:41:58 +0300 Subject: [PATCH 55/66] dnsapi: dns_vultr.sh remove empty author Signed-off-by: Sergey Ponomarev --- dnsapi/dns_vultr.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/dnsapi/dns_vultr.sh b/dnsapi/dns_vultr.sh index 61ec3f60..4002e5de 100644 --- a/dnsapi/dns_vultr.sh +++ b/dnsapi/dns_vultr.sh @@ -6,7 +6,6 @@ Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_vultr Options: VULTR_API_KEY API Key Issues: github.com/acmesh-official/acme.sh/issues/2374 -Author: ' VULTR_Api="https://api.vultr.com/v2" From 85ec6343ff2f4388bf4e5cae77d5481f5dfcb46d Mon Sep 17 00:00:00 2001 From: Sergey Ponomarev Date: Sun, 6 Jul 2025 01:42:39 +0300 Subject: [PATCH 56/66] dnsapi: dns_mijnhost.sh rearrange fields, use user docs instead of API docs Signed-off-by: Sergey Ponomarev --- dnsapi/dns_mijnhost.sh | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/dnsapi/dns_mijnhost.sh b/dnsapi/dns_mijnhost.sh index 52a81632..9f5e7710 100644 --- a/dnsapi/dns_mijnhost.sh +++ b/dnsapi/dns_mijnhost.sh @@ -1,16 +1,15 @@ #!/usr/bin/env sh # shellcheck disable=SC2034 dns_mijnhost_info='mijn.host -Domains: mijn.host Site: mijn.host -Docs: https://mijn.host/api/doc/ -Issues: https://github.com/acmesh-official/acme.sh/issues/6177 -Author: @peterv99 +Docs: https://github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_mijnhost Options: MIJNHOST_API_KEY API Key +Issues: github.com/acmesh-official/acme.sh/issues/6177 +Author: @peterv99 ' -######## Public functions ###################### Constants for your mijn-host API +######## Public functions ###################### MIJNHOST_API="https://mijn.host/api/v2" # Add TXT record for domain verification From 8113711b7aff45ac243492c1b3f49282727ac1b1 Mon Sep 17 00:00:00 2001 From: Sergey Ponomarev Date: Sun, 6 Jul 2025 01:43:16 +0300 Subject: [PATCH 57/66] dnsapi: fix Structured DNS Info Signed-off-by: Sergey Ponomarev --- dnsapi/dns_beget.sh | 2 +- dnsapi/dns_he_ddns.sh | 1 + dnsapi/dns_selectel.sh | 38 ++++++++++++++++---------------------- dnsapi/dns_spaceship.sh | 6 +++--- 4 files changed, 21 insertions(+), 26 deletions(-) diff --git a/dnsapi/dns_beget.sh b/dnsapi/dns_beget.sh index aa43caed..5f3b1eb1 100755 --- a/dnsapi/dns_beget.sh +++ b/dnsapi/dns_beget.sh @@ -7,7 +7,7 @@ Options: BEGET_User API user BEGET_Password API password Issues: github.com/acmesh-official/acme.sh/issues/6200 -Author: ARNik arnik@arnik.ru +Author: ARNik ' Beget_Api="https://api.beget.com/api" diff --git a/dnsapi/dns_he_ddns.sh b/dnsapi/dns_he_ddns.sh index cd7d1ec2..1fe9a7fd 100644 --- a/dnsapi/dns_he_ddns.sh +++ b/dnsapi/dns_he_ddns.sh @@ -5,6 +5,7 @@ Site: dns.he.net Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_he_ddns Options: HE_DDNS_KEY The DDNS key +Issues: https://github.com/acmesh-official/acme.sh/issues/5238 Author: Markku Leiniö ' diff --git a/dnsapi/dns_selectel.sh b/dnsapi/dns_selectel.sh index 434bc483..565f541b 100644 --- a/dnsapi/dns_selectel.sh +++ b/dnsapi/dns_selectel.sh @@ -1,27 +1,21 @@ #!/usr/bin/env sh # shellcheck disable=SC2034 - -# dns_selectel_info='Selectel.com -# Domains: Selectel.ru -# Site: Selectel.com -# Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_selectel -# Options: -# Variables that must be defined before running -# SL_Ver can take one of the values 'v1' or 'v2', default is 'v1' -# SL_Ver='v1', when using version API legacy (v1) -# SL_Ver='v2', when using version API actual (v2) -# when using API version v1, i.e. SL_Ver is 'v1' or not defined: -# SL_Key - API Key, required -# when using API version v2: -# SL_Ver - required as 'v2' -# SL_Login_ID - account ID, required -# SL_Project_Name - name project, required -# SL_Login_Name - service user name, required -# SL_Pswd - service user password, required -# SL_Expire - token lifetime in minutes (0-1440), default 1400 minutes -# -# Issues: github.com/acmesh-official/acme.sh/issues/5126 -# +dns_selectel_info='Selectel.com +Domains: Selectel.ru +Site: Selectel.com +Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_selectel +Options: For old API version v1 (deprecated) + SL_Ver API version. Use "v1". + SL_Key API Key +OptionsAlt: For the current API version v2 + SL_Ver API version. Use "v2". + SL_Login_ID Account ID + SL_Project_Name Project name + SL_Login_Name Service user name + SL_Pswd Service user password + SL_Expire Token lifetime. In minutes (0-1440). Default "1400" +Issues: github.com/acmesh-official/acme.sh/issues/5126 +' SL_Api="https://api.selectel.ru/domains" auth_uri="https://cloud.api.selcloud.ru/identity/v3/auth/tokens" diff --git a/dnsapi/dns_spaceship.sh b/dnsapi/dns_spaceship.sh index 5e92a4fe..8fff4037 100644 --- a/dnsapi/dns_spaceship.sh +++ b/dnsapi/dns_spaceship.sh @@ -4,9 +4,9 @@ dns_spaceship_info='Spaceship.com Site: Spaceship.com Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_spaceship Options: - SPACESHIP_API_KEY Spaceship API Key - SPACESHIP_API_SECRET Spaceship API Secret - SPACESHIP_ROOT_DOMAIN (Optional) Manually specify the root domain if auto-detection fails + SPACESHIP_API_KEY API Key + SPACESHIP_API_SECRET API Secret + SPACESHIP_ROOT_DOMAIN Root domain. Manually specify the root domain if auto-detection fails. Optional. Issues: github.com/acmesh-official/acme.sh/issues/6304 Author: Meow <@Meo597> ' From 0c98dc54fee5194e5240e9e71e6d13f105894cb8 Mon Sep 17 00:00:00 2001 From: David Beitey Date: Sun, 13 Jul 2025 11:18:10 +1000 Subject: [PATCH 58/66] Fix logged typo when running pre hook --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index d70e323b..252d0227 100755 --- a/acme.sh +++ b/acme.sh @@ -3513,7 +3513,7 @@ _on_before_issue() { _debug _chk_alt_domains "$_chk_alt_domains" #run pre hook if [ "$_chk_pre_hook" ]; then - _info "Runing pre hook:'$_chk_pre_hook'" + _info "Running pre hook:'$_chk_pre_hook'" if ! ( export Le_Domain="$_chk_main_domain" export Le_Alt="$_chk_alt_domains" From 40e58ed12d14319f5e355055b7a1c973519dedcb Mon Sep 17 00:00:00 2001 From: David Beitey Date: Sun, 13 Jul 2025 11:40:34 +1000 Subject: [PATCH 59/66] Run post hook when _on_before_issue errors --- acme.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/acme.sh b/acme.sh index d70e323b..8ce5bacc 100755 --- a/acme.sh +++ b/acme.sh @@ -4502,6 +4502,7 @@ issue() { if ! _on_before_issue "$_web_roots" "$_main_domain" "$_alt_domains" "$_pre_hook" "$_local_addr"; then _err "_on_before_issue." + _on_issue_err "$_post_hook" return 1 fi From 1f486fc9a524ead28d4b801f450b097eb3a58311 Mon Sep 17 00:00:00 2001 From: keryfan <35259207+keryfan@users.noreply.github.com> Date: Tue, 12 Aug 2025 11:12:09 +0300 Subject: [PATCH 60/66] Upload latest dev branch to master (#3) * Fix for empty error objects in response breaking extraction of domain validation types Fix for empty error objects in the response which mess up the extraction of domain validation types due to the closing brace in the error object prematurely matching the end of the search pattern. This seems to be a recent change with ZeroSSL in particular where "error":{} is being included in responses. There could potentially be a related issue if there is a complex error object ever returned in the validation check response where an embedded sub-object could lead to an incomplete extraction of the error message, roughly around line 5040. Adapted from fix suggested here: https://github.com/acmesh-official/acme.sh/issues/4933#issuecomment-1870499018 * Add new dnsapi support for OpenProvider.eu using new REST API * Cleanup duplicate debug log output based on DNS test run * Resolve spellcheck error * Configure 10 second timeout to ACME_DIRECTORY API call * add support for AIX style netstat * add * fix for wiki * minor * minor * wiki * wiki * dnsapi: dns_mydnsjp.sh fix author The @epgdatacapbon was renamed to @tkmsst Signed-off-by: Sergey Ponomarev * dnsapi: dns_ddnss.sh remove RaidenII from authors He made the DuckDNS script that was used for this script but he can't support the script. Signed-off-by: Sergey Ponomarev * dnsapi: fix authors: use @ for GitHub profiles Signed-off-by: Sergey Ponomarev * dnsapi: dns_vultr.sh remove empty author Signed-off-by: Sergey Ponomarev * dnsapi: dns_mijnhost.sh rearrange fields, use user docs instead of API docs Signed-off-by: Sergey Ponomarev * dnsapi: fix Structured DNS Info Signed-off-by: Sergey Ponomarev * Fix logged typo when running pre hook * Run post hook when _on_before_issue errors --------- Signed-off-by: Sergey Ponomarev Co-authored-by: Ciaran Walsh Co-authored-by: Lambiek12 Co-authored-by: Erwin Oegema Co-authored-by: laDanz Co-authored-by: neil Co-authored-by: neil Co-authored-by: Sergey Ponomarev Co-authored-by: David Beitey Co-authored-by: Jan-willem van Kampen --- .github/workflows/wiki-monitor.yml | 60 ++++++++++ acme.sh | 17 ++- dnsapi/dns_beget.sh | 2 +- dnsapi/dns_bookmyname.sh | 2 +- dnsapi/dns_ddnss.sh | 2 +- dnsapi/dns_dnshome.sh | 2 +- dnsapi/dns_duckdns.sh | 2 +- dnsapi/dns_dyn.sh | 2 +- dnsapi/dns_dynv6.sh | 2 +- dnsapi/dns_easydns.sh | 2 +- dnsapi/dns_freedns.sh | 2 +- dnsapi/dns_he_ddns.sh | 1 + dnsapi/dns_joker.sh | 2 +- dnsapi/dns_mijnhost.sh | 9 +- dnsapi/dns_mydnsjp.sh | 2 +- dnsapi/dns_namecom.sh | 2 +- dnsapi/dns_namesilo.sh | 2 +- dnsapi/dns_openprovider_rest.sh | 186 +++++++++++++++++++++++++++++ dnsapi/dns_pleskxml.sh | 2 +- dnsapi/dns_schlundtech.sh | 2 +- dnsapi/dns_selectel.sh | 38 +++--- dnsapi/dns_spaceship.sh | 8 +- dnsapi/dns_tele3.sh | 2 +- dnsapi/dns_timeweb.sh | 2 +- dnsapi/dns_udr.sh | 2 +- dnsapi/dns_vscale.sh | 2 +- dnsapi/dns_vultr.sh | 1 - dnsapi/dns_websupport.sh | 2 +- dnsapi/dns_world4you.sh | 2 +- 29 files changed, 305 insertions(+), 57 deletions(-) create mode 100644 .github/workflows/wiki-monitor.yml create mode 100644 dnsapi/dns_openprovider_rest.sh diff --git a/.github/workflows/wiki-monitor.yml b/.github/workflows/wiki-monitor.yml new file mode 100644 index 00000000..89497580 --- /dev/null +++ b/.github/workflows/wiki-monitor.yml @@ -0,0 +1,60 @@ +name: Notify via Issue on Wiki Edit + +on: + gollum: + +jobs: + notify: + runs-on: ubuntu-latest + steps: + - name: Checkout wiki repository + uses: actions/checkout@v4 + with: + repository: ${{ github.repository }}.wiki + path: wiki + + - name: Generate wiki change message + run: | + actor="${{ github.actor }}" + sender_url=$(jq -r '.sender.html_url' "$GITHUB_EVENT_PATH") + page_name=$(jq -r '.pages[0].page_name' "$GITHUB_EVENT_PATH") + page_sha=$(jq -r '.pages[0].sha' "$GITHUB_EVENT_PATH") + page_url=$(jq -r '.pages[0].html_url' "$GITHUB_EVENT_PATH") + page_action=$(jq -r '.pages[0].action' "$GITHUB_EVENT_PATH") + now="$(date '+%Y-%m-%d %H:%M:%S')" + + cd wiki + prev_sha=$(git rev-list $page_sha^ -- "$page_name.md" | head -n 1) + if [ -n "$prev_sha" ]; then + git diff $prev_sha $page_sha -- "$page_name.md" > ../wiki.diff || echo "(No diff found)" > ../wiki.diff + else + echo "(no diff)" > ../wiki.diff + fi + cd .. + { + echo "Wiki edited" + echo -n "User: " + echo "[$actor]($sender_url)" + echo "Time: $now" + echo "Page: [$page_name]($page_url) (Action: $page_action)" + echo "" + echo "----" + echo "### diff:" + echo '```diff' + cat wiki.diff + echo '```' + } > wiki-change-msg.txt + + - name: Create issue to notify Neilpang + uses: peter-evans/create-issue-from-file@v5 + with: + title: "Wiki edited" + content-filepath: ./wiki-change-msg.txt + assignees: Neilpang + env: + TZ: Asia/Shanghai + + + + + diff --git a/acme.sh b/acme.sh index e9eb6b94..d9ae208a 100755 --- a/acme.sh +++ b/acme.sh @@ -1401,6 +1401,12 @@ _ss() { return 0 fi + if [ "$(uname)" = "AIX" ]; then + _debug "Using: AIX netstat" + netstat -an | grep "^tcp" | grep "LISTEN" | grep "\.$_port " + return 0 + fi + if _exists "netstat"; then _debug "Using: netstat" if netstat -help 2>&1 | grep "\-p proto" >/dev/null; then @@ -2761,7 +2767,7 @@ _initAPI() { _request_retry_times=0 while [ -z "$ACME_NEW_ACCOUNT" ] && [ "${_request_retry_times}" -lt "$MAX_API_RETRY_TIMES" ]; do _request_retry_times=$(_math "$_request_retry_times" + 1) - response=$(_get "$_api_server") + response=$(_get "$_api_server" "" 10) if [ "$?" != "0" ]; then _debug2 "response" "$response" _info "Cannot init API for: $_api_server." @@ -3507,7 +3513,7 @@ _on_before_issue() { _debug _chk_alt_domains "$_chk_alt_domains" #run pre hook if [ "$_chk_pre_hook" ]; then - _info "Runing pre hook:'$_chk_pre_hook'" + _info "Running pre hook:'$_chk_pre_hook'" if ! ( export Le_Domain="$_chk_main_domain" export Le_Alt="$_chk_alt_domains" @@ -4496,6 +4502,7 @@ issue() { if ! _on_before_issue "$_web_roots" "$_main_domain" "$_alt_domains" "$_pre_hook" "$_local_addr"; then _err "_on_before_issue." + _on_issue_err "$_post_hook" return 1 fi @@ -4755,7 +4762,8 @@ $_authorizations_map" _debug keyauthorization "$keyauthorization" fi - entry="$(echo "$response" | _egrep_o '[^\{]*"type":"'$vtype'"[^\}]*')" + # Fix for empty error objects in response which mess up the original code, adapted from fix suggested here: https://github.com/acmesh-official/acme.sh/issues/4933#issuecomment-1870499018 + entry="$(echo "$response" | sed s/'"error":{}'/'"error":null'/ | _egrep_o '[^\{]*"type":"'$vtype'"[^\}]*')" _debug entry "$entry" if [ -z "$keyauthorization" -a -z "$entry" ]; then @@ -6344,7 +6352,8 @@ _deactivate() { fi _debug "Trigger validation." vtype="$(_getIdType "$_d_domain")" - entry="$(echo "$response" | _egrep_o '[^\{]*"type":"'$vtype'"[^\}]*')" + # Fix for empty error objects in response which mess up the original code, adapted from fix suggested here: https://github.com/acmesh-official/acme.sh/issues/4933#issuecomment-1870499018 + entry="$(echo "$response" | sed s/'"error":{}'/'"error":null'/ | _egrep_o '[^\{]*"type":"'$vtype'"[^\}]*')" _debug entry "$entry" if [ -z "$entry" ]; then _err "$d: Cannot get domain token" diff --git a/dnsapi/dns_beget.sh b/dnsapi/dns_beget.sh index aa43caed..5f3b1eb1 100755 --- a/dnsapi/dns_beget.sh +++ b/dnsapi/dns_beget.sh @@ -7,7 +7,7 @@ Options: BEGET_User API user BEGET_Password API password Issues: github.com/acmesh-official/acme.sh/issues/6200 -Author: ARNik arnik@arnik.ru +Author: ARNik ' Beget_Api="https://api.beget.com/api" diff --git a/dnsapi/dns_bookmyname.sh b/dnsapi/dns_bookmyname.sh index 668cf074..cf3f1e3e 100644 --- a/dnsapi/dns_bookmyname.sh +++ b/dnsapi/dns_bookmyname.sh @@ -7,7 +7,7 @@ Options: BOOKMYNAME_USERNAME Username BOOKMYNAME_PASSWORD Password Issues: github.com/acmesh-official/acme.sh/issues/3209 -Author: Neilpang +Author: @Neilpang ' ######## Public functions ##################### diff --git a/dnsapi/dns_ddnss.sh b/dnsapi/dns_ddnss.sh index 118b148b..0ac353d4 100644 --- a/dnsapi/dns_ddnss.sh +++ b/dnsapi/dns_ddnss.sh @@ -6,7 +6,7 @@ Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_ddnss Options: DDNSS_Token API Token Issues: github.com/acmesh-official/acme.sh/issues/2230 -Author: RaidenII, helbgd, mod242 +Author: @helbgd, @mod242 ' DDNSS_DNS_API="https://ddnss.de/upd.php" diff --git a/dnsapi/dns_dnshome.sh b/dnsapi/dns_dnshome.sh index 59828796..6d583246 100755 --- a/dnsapi/dns_dnshome.sh +++ b/dnsapi/dns_dnshome.sh @@ -7,7 +7,7 @@ Options: DNSHOME_Subdomain Subdomain DNSHOME_SubdomainPassword Subdomain Password Issues: github.com/acmesh-official/acme.sh/issues/3819 -Author: dnsHome.de https://github.com/dnsHome-de +Author: @dnsHome-de ' # Usage: add subdomain.ddnsdomain.tld "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" diff --git a/dnsapi/dns_duckdns.sh b/dnsapi/dns_duckdns.sh index 71594873..33d401b0 100755 --- a/dnsapi/dns_duckdns.sh +++ b/dnsapi/dns_duckdns.sh @@ -5,7 +5,7 @@ Site: www.DuckDNS.org Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_duckdns Options: DuckDNS_Token API Token -Author: RaidenII +Author: @RaidenII ' DuckDNS_API="https://www.duckdns.org/update" diff --git a/dnsapi/dns_dyn.sh b/dnsapi/dns_dyn.sh index 94201923..9b1a97a2 100644 --- a/dnsapi/dns_dyn.sh +++ b/dnsapi/dns_dyn.sh @@ -8,7 +8,7 @@ Options: DYN_Customer Customer DYN_Username API Username DYN_Password Secret -Author: Gerd Naschenweng +Author: Gerd Naschenweng <@magicdude4eva> ' # Dyn Managed DNS API diff --git a/dnsapi/dns_dynv6.sh b/dnsapi/dns_dynv6.sh index 76af17f5..0c9491f8 100644 --- a/dnsapi/dns_dynv6.sh +++ b/dnsapi/dns_dynv6.sh @@ -8,7 +8,7 @@ Options: OptionsAlt: KEY Path to SSH private key file. E.g. "/root/.ssh/dynv6" Issues: github.com/acmesh-official/acme.sh/issues/2702 -Author: StefanAbl +Author: @StefanAbl ' dynv6_api="https://dynv6.com/api/v2" diff --git a/dnsapi/dns_easydns.sh b/dnsapi/dns_easydns.sh index 1c96ac8f..423def2b 100644 --- a/dnsapi/dns_easydns.sh +++ b/dnsapi/dns_easydns.sh @@ -7,7 +7,7 @@ Options: EASYDNS_Token API Token EASYDNS_Key API Key Issues: github.com/acmesh-official/acme.sh/issues/2647 -Author: Neilpang, wurzelpanzer +Author: @Neilpang, wurzelpanzer ' # API Documentation: https://sandbox.rest.easydns.net:3001/ diff --git a/dnsapi/dns_freedns.sh b/dnsapi/dns_freedns.sh index 114f30e0..13d9f68b 100755 --- a/dnsapi/dns_freedns.sh +++ b/dnsapi/dns_freedns.sh @@ -7,7 +7,7 @@ Options: FREEDNS_User Username FREEDNS_Password Password Issues: github.com/acmesh-official/acme.sh/issues/2305 -Author: David Kerr +Author: David Kerr <@dkerr64> ' ######## Public functions ##################### diff --git a/dnsapi/dns_he_ddns.sh b/dnsapi/dns_he_ddns.sh index cd7d1ec2..1fe9a7fd 100644 --- a/dnsapi/dns_he_ddns.sh +++ b/dnsapi/dns_he_ddns.sh @@ -5,6 +5,7 @@ Site: dns.he.net Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_he_ddns Options: HE_DDNS_KEY The DDNS key +Issues: https://github.com/acmesh-official/acme.sh/issues/5238 Author: Markku Leiniö ' diff --git a/dnsapi/dns_joker.sh b/dnsapi/dns_joker.sh index 1fe33c67..401471be 100644 --- a/dnsapi/dns_joker.sh +++ b/dnsapi/dns_joker.sh @@ -7,7 +7,7 @@ Options: JOKER_USERNAME Username JOKER_PASSWORD Password Issues: github.com/acmesh-official/acme.sh/issues/2840 -Author: +Author: @aattww ' JOKER_API="https://svc.joker.com/nic/replace" diff --git a/dnsapi/dns_mijnhost.sh b/dnsapi/dns_mijnhost.sh index 9dafc702..9f5e7710 100644 --- a/dnsapi/dns_mijnhost.sh +++ b/dnsapi/dns_mijnhost.sh @@ -1,16 +1,15 @@ #!/usr/bin/env sh # shellcheck disable=SC2034 dns_mijnhost_info='mijn.host -Domains: mijn.host Site: mijn.host -Docs: https://mijn.host/api/doc/ -Issues: https://github.com/acmesh-official/acme.sh/issues/6177 -Author: peterv99 +Docs: https://github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_mijnhost Options: MIJNHOST_API_KEY API Key +Issues: github.com/acmesh-official/acme.sh/issues/6177 +Author: @peterv99 ' -######## Public functions ###################### Constants for your mijn-host API +######## Public functions ###################### MIJNHOST_API="https://mijn.host/api/v2" # Add TXT record for domain verification diff --git a/dnsapi/dns_mydnsjp.sh b/dnsapi/dns_mydnsjp.sh index 336c4889..4dfffaaa 100755 --- a/dnsapi/dns_mydnsjp.sh +++ b/dnsapi/dns_mydnsjp.sh @@ -6,7 +6,7 @@ Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_mydnsjp Options: MYDNSJP_MasterID Master ID MYDNSJP_Password Password -Author: epgdatacapbon +Author: @tkmsst ' ######## Public functions ##################### diff --git a/dnsapi/dns_namecom.sh b/dnsapi/dns_namecom.sh index 44549c9e..1062c849 100755 --- a/dnsapi/dns_namecom.sh +++ b/dnsapi/dns_namecom.sh @@ -6,7 +6,7 @@ Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_namecom Options: Namecom_Username Username Namecom_Token API Token -Author: RaidenII +Author: @RaidenII ' ######## Public functions ##################### diff --git a/dnsapi/dns_namesilo.sh b/dnsapi/dns_namesilo.sh index b31e32a1..5d47a59a 100755 --- a/dnsapi/dns_namesilo.sh +++ b/dnsapi/dns_namesilo.sh @@ -5,7 +5,7 @@ Site: NameSilo.com Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_namesilo Options: Namesilo_Key API Key -Author: meowthink +Author: @meowthink ' #Utilize API to finish dns-01 verifications. diff --git a/dnsapi/dns_openprovider_rest.sh b/dnsapi/dns_openprovider_rest.sh new file mode 100644 index 00000000..210dc6fc --- /dev/null +++ b/dnsapi/dns_openprovider_rest.sh @@ -0,0 +1,186 @@ +#!/usr/bin/env sh +# shellcheck disable=SC2034 +dns_openprovider_rest_info='OpenProvider (REST) +Domains: OpenProvider.com +Site: OpenProvider.eu +Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_openprovider_rest +Options: + OPENPROVIDER_REST_USERNAME Openprovider Account Username + OPENPROVIDER_REST_PASSWORD Openprovider Account Password +Issues: github.com/acmesh-official/acme.sh/issues/6122 +Author: Lambiek12 +' + +OPENPROVIDER_API_URL="https://api.openprovider.eu/v1beta" + +######## Public functions ##################### + +# Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +# Used to add txt record +dns_openprovider_rest_add() { + fulldomain=$1 + txtvalue=$2 + + _openprovider_prepare_credentials || return 1 + + _debug "Try fetch OpenProvider DNS zone details" + if ! _get_dns_zone "$fulldomain"; then + _err "DNS zone not found within configured OpenProvider account." + return 1 + fi + + if [ -n "$_domain_id" ]; then + addzonerecordrequestparameters="dns/zones/$_domain_name" + addzonerecordrequestbody="{\"id\":$_domain_id,\"name\":\"$_domain_name\",\"records\":{\"add\":[{\"name\":\"$_sub_domain\",\"ttl\":900,\"type\":\"TXT\",\"value\":\"$txtvalue\"}]}}" + + if _openprovider_rest PUT "$addzonerecordrequestparameters" "$addzonerecordrequestbody"; then + if _contains "$response" "\"success\":true"; then + return 0 + elif _contains "$response" "\"Duplicate record\""; then + _debug "Record already existed" + return 0 + else + _err "Adding TXT record failed due to errors." + return 1 + fi + fi + fi + + _err "Adding TXT record failed due to errors." + return 1 +} + +# Usage: rm _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +# Used to remove the txt record after validation +dns_openprovider_rest_rm() { + fulldomain=$1 + txtvalue=$2 + + _openprovider_prepare_credentials || return 1 + + _debug "Try fetch OpenProvider DNS zone details" + if ! _get_dns_zone "$fulldomain"; then + _err "DNS zone not found within configured OpenProvider account." + return 1 + fi + + if [ -n "$_domain_id" ]; then + removezonerecordrequestparameters="dns/zones/$_domain_name" + removezonerecordrequestbody="{\"id\":$_domain_id,\"name\":\"$_domain_name\",\"records\":{\"remove\":[{\"name\":\"$_sub_domain\",\"ttl\":900,\"type\":\"TXT\",\"value\":\"\\\"$txtvalue\\\"\"}]}}" + + if _openprovider_rest PUT "$removezonerecordrequestparameters" "$removezonerecordrequestbody"; then + if _contains "$response" "\"success\":true"; then + return 0 + else + _err "Removing TXT record failed due to errors." + return 1 + fi + fi + fi + + _err "Removing TXT record failed due to errors." + return 1 +} + +#################### OpenProvider API common functions #################### +_openprovider_prepare_credentials() { + OPENPROVIDER_REST_USERNAME="${OPENPROVIDER_REST_USERNAME:-$(_readaccountconf_mutable OPENPROVIDER_REST_USERNAME)}" + OPENPROVIDER_REST_PASSWORD="${OPENPROVIDER_REST_PASSWORD:-$(_readaccountconf_mutable OPENPROVIDER_REST_PASSWORD)}" + + if [ -z "$OPENPROVIDER_REST_USERNAME" ] || [ -z "$OPENPROVIDER_REST_PASSWORD" ]; then + OPENPROVIDER_REST_USERNAME="" + OPENPROVIDER_REST_PASSWORD="" + _err "You didn't specify the Openprovider username or password yet." + return 1 + fi + + #save the credentials to the account conf file. + _saveaccountconf_mutable OPENPROVIDER_REST_USERNAME "$OPENPROVIDER_REST_USERNAME" + _saveaccountconf_mutable OPENPROVIDER_REST_PASSWORD "$OPENPROVIDER_REST_PASSWORD" +} + +_openprovider_rest() { + httpmethod=$1 + queryparameters=$2 + requestbody=$3 + + _openprovider_rest_login + if [ -z "$openproviderauthtoken" ]; then + _err "Unable to fetch authentication token from Openprovider API." + return 1 + fi + + export _H1="Content-Type: application/json" + export _H2="Accept: application/json" + export _H3="Authorization: Bearer $openproviderauthtoken" + + if [ "$httpmethod" != "GET" ]; then + response="$(_post "$requestbody" "$OPENPROVIDER_API_URL/$queryparameters" "" "$httpmethod")" + else + response="$(_get "$OPENPROVIDER_API_URL/$queryparameters")" + fi + + if [ "$?" != "0" ]; then + _err "No valid parameters supplied for Openprovider API: Error $queryparameters" + return 1 + fi + + _debug2 response "$response" + + return 0 +} + +_openprovider_rest_login() { + export _H1="Content-Type: application/json" + export _H2="Accept: application/json" + + loginrequesturl="$OPENPROVIDER_API_URL/auth/login" + loginrequestbody="{\"ip\":\"0.0.0.0\",\"password\":\"$OPENPROVIDER_REST_PASSWORD\",\"username\":\"$OPENPROVIDER_REST_USERNAME\"}" + loginresponse="$(_post "$loginrequestbody" "$loginrequesturl" "" "POST")" + + openproviderauthtoken="$(printf "%s\n" "$loginresponse" | _egrep_o '"token" *: *"[^"]*' | _head_n 1 | sed 's#^"token" *: *"##')" + + export openproviderauthtoken +} + +#################### Private functions ################################## + +# Usage: _get_dns_zone _acme-challenge.www.domain.com +# Returns: +# _domain_id=123456789 +# _domain_name=domain.com +# _sub_domain=_acme-challenge.www +_get_dns_zone() { + domain=$1 + i=1 + p=1 + + while true; do + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) + if [ -z "$h" ]; then + # Empty value not allowed + return 1 + fi + + if ! _openprovider_rest GET "dns/zones/$h" ""; then + return 1 + fi + + if _contains "$response" "\"name\":\"$h\""; then + _domain_id="$(printf "%s\n" "$response" | _egrep_o '"id" *: *[^,]*' | _head_n 1 | sed 's#^"id" *: *##')" + _debug _domain_id "$_domain_id" + + _domain_name="$h" + _debug _domain_name "$_domain_name" + + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") + _debug _sub_domain "$_sub_domain" + return 0 + fi + + p=$i + i=$(_math "$i" + 1) + done + + return 1 +} diff --git a/dnsapi/dns_pleskxml.sh b/dnsapi/dns_pleskxml.sh index 6b38abcb..465bcc60 100644 --- a/dnsapi/dns_pleskxml.sh +++ b/dnsapi/dns_pleskxml.sh @@ -8,7 +8,7 @@ Options: pleskxml_user Username pleskxml_pass Password Issues: github.com/acmesh-official/acme.sh/issues/2577 -Author: Stilez, +Author: @Stilez, @romanlum ' ## Plesk XML API described at: diff --git a/dnsapi/dns_schlundtech.sh b/dnsapi/dns_schlundtech.sh index 6d2930a2..21930110 100644 --- a/dnsapi/dns_schlundtech.sh +++ b/dnsapi/dns_schlundtech.sh @@ -7,7 +7,7 @@ Options: SCHLUNDTECH_USER Username SCHLUNDTECH_PASSWORD Password Issues: github.com/acmesh-official/acme.sh/issues/2246 -Author: +Author: @mod242 ' SCHLUNDTECH_API="https://gateway.schlundtech.de" diff --git a/dnsapi/dns_selectel.sh b/dnsapi/dns_selectel.sh index 434bc483..565f541b 100644 --- a/dnsapi/dns_selectel.sh +++ b/dnsapi/dns_selectel.sh @@ -1,27 +1,21 @@ #!/usr/bin/env sh # shellcheck disable=SC2034 - -# dns_selectel_info='Selectel.com -# Domains: Selectel.ru -# Site: Selectel.com -# Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_selectel -# Options: -# Variables that must be defined before running -# SL_Ver can take one of the values 'v1' or 'v2', default is 'v1' -# SL_Ver='v1', when using version API legacy (v1) -# SL_Ver='v2', when using version API actual (v2) -# when using API version v1, i.e. SL_Ver is 'v1' or not defined: -# SL_Key - API Key, required -# when using API version v2: -# SL_Ver - required as 'v2' -# SL_Login_ID - account ID, required -# SL_Project_Name - name project, required -# SL_Login_Name - service user name, required -# SL_Pswd - service user password, required -# SL_Expire - token lifetime in minutes (0-1440), default 1400 minutes -# -# Issues: github.com/acmesh-official/acme.sh/issues/5126 -# +dns_selectel_info='Selectel.com +Domains: Selectel.ru +Site: Selectel.com +Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_selectel +Options: For old API version v1 (deprecated) + SL_Ver API version. Use "v1". + SL_Key API Key +OptionsAlt: For the current API version v2 + SL_Ver API version. Use "v2". + SL_Login_ID Account ID + SL_Project_Name Project name + SL_Login_Name Service user name + SL_Pswd Service user password + SL_Expire Token lifetime. In minutes (0-1440). Default "1400" +Issues: github.com/acmesh-official/acme.sh/issues/5126 +' SL_Api="https://api.selectel.ru/domains" auth_uri="https://cloud.api.selcloud.ru/identity/v3/auth/tokens" diff --git a/dnsapi/dns_spaceship.sh b/dnsapi/dns_spaceship.sh index 770e22cc..8fff4037 100644 --- a/dnsapi/dns_spaceship.sh +++ b/dnsapi/dns_spaceship.sh @@ -4,11 +4,11 @@ dns_spaceship_info='Spaceship.com Site: Spaceship.com Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_spaceship Options: - SPACESHIP_API_KEY Spaceship API Key - SPACESHIP_API_SECRET Spaceship API Secret - SPACESHIP_ROOT_DOMAIN (Optional) Manually specify the root domain if auto-detection fails + SPACESHIP_API_KEY API Key + SPACESHIP_API_SECRET API Secret + SPACESHIP_ROOT_DOMAIN Root domain. Manually specify the root domain if auto-detection fails. Optional. Issues: github.com/acmesh-official/acme.sh/issues/6304 -Author: Meow +Author: Meow <@Meo597> ' # Spaceship API diff --git a/dnsapi/dns_tele3.sh b/dnsapi/dns_tele3.sh index e5974951..3a3ccf8c 100644 --- a/dnsapi/dns_tele3.sh +++ b/dnsapi/dns_tele3.sh @@ -6,7 +6,7 @@ Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#tele3 Options: TELE3_Key API Key TELE3_Secret API Secret -Author: Roman Blizik +Author: Roman Blizik <@par-pa> ' TELE3_API="https://www.tele3.cz/acme/" diff --git a/dnsapi/dns_timeweb.sh b/dnsapi/dns_timeweb.sh index 544564ea..7040ac9a 100644 --- a/dnsapi/dns_timeweb.sh +++ b/dnsapi/dns_timeweb.sh @@ -6,7 +6,7 @@ Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_timeweb Options: TW_Token API JWT token. Get it from the control panel at https://timeweb.cloud/my/api-keys Issues: github.com/acmesh-official/acme.sh/issues/5140 -Author: Nikolay Pronchev +Author: Nikolay Pronchev <@nikolaypronchev> ' TW_Api="https://api.timeweb.cloud/api/v1" diff --git a/dnsapi/dns_udr.sh b/dnsapi/dns_udr.sh index f9772e10..656a0557 100644 --- a/dnsapi/dns_udr.sh +++ b/dnsapi/dns_udr.sh @@ -7,7 +7,7 @@ Options: UDR_USER Username UDR_PASS Password Issues: github.com/acmesh-official/acme.sh/issues/3923 -Author: Andreas Scherer +Author: Andreas Scherer <@andischerer> ' UDR_API="https://api.domainreselling.de/api/call.cgi" diff --git a/dnsapi/dns_vscale.sh b/dnsapi/dns_vscale.sh index c3915c69..faf3105d 100755 --- a/dnsapi/dns_vscale.sh +++ b/dnsapi/dns_vscale.sh @@ -5,7 +5,7 @@ Site: vscale.io Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_vscale Options: VSCALE_API_KEY API Key -Author: Alex Loban +Author: Alex Loban <@LAV45> ' VSCALE_API_URL="https://api.vscale.io/v1" diff --git a/dnsapi/dns_vultr.sh b/dnsapi/dns_vultr.sh index 61ec3f60..4002e5de 100644 --- a/dnsapi/dns_vultr.sh +++ b/dnsapi/dns_vultr.sh @@ -6,7 +6,6 @@ Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_vultr Options: VULTR_API_KEY API Key Issues: github.com/acmesh-official/acme.sh/issues/2374 -Author: ' VULTR_Api="https://api.vultr.com/v2" diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index bfc4b23a..2374afc3 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -7,7 +7,7 @@ Options: WS_ApiKey API Key. Called "Identifier" in the WS Admin WS_ApiSecret API Secret. Called "Secret key" in the WS Admin Issues: github.com/acmesh-official/acme.sh/issues/3486 -Author: trgo.sk , akulumbeg +Author: trgo.sk <@trgosk>, @akulumbeg ' # Requirements: API Key and Secret from https://admin.websupport.sk/en/auth/apiKey diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index 46cdc4fe..dc295330 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -7,7 +7,7 @@ Options: WORLD4YOU_USERNAME Username WORLD4YOU_PASSWORD Password Issues: github.com/acmesh-official/acme.sh/issues/3269 -Author: Lorenz Stechauner +Author: Lorenz Stechauner <@NerLOR> ' WORLD4YOU_API="https://my.world4you.com/en" From 1b5e66f9c2e4907408c05164010d7cd4422d6051 Mon Sep 17 00:00:00 2001 From: wout Date: Wed, 23 Jul 2025 10:12:32 +0200 Subject: [PATCH 61/66] Add sleep before each REST call to Constellix to prevent rate limit --- dnsapi/dns_constellix.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dnsapi/dns_constellix.sh b/dnsapi/dns_constellix.sh index 6a50e199..480541ed 100644 --- a/dnsapi/dns_constellix.sh +++ b/dnsapi/dns_constellix.sh @@ -156,6 +156,9 @@ _constellix_rest() { data="$3" _debug "$ep" + # Prevent rate limit + _sleep 2 + rdate=$(date +"%s")"000" hmac=$(printf "%s" "$rdate" | _hmac sha1 "$(printf "%s" "$CONSTELLIX_Secret" | _hex_dump | tr -d ' ')" | _base64) From ab22c8ca1cb89cda5e47d510de10e12ffabd39a0 Mon Sep 17 00:00:00 2001 From: wout Date: Tue, 12 Aug 2025 19:04:19 +0200 Subject: [PATCH 62/66] Convert domain to lower case, needed for Constellix REST API --- dnsapi/dns_constellix.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_constellix.sh b/dnsapi/dns_constellix.sh index 480541ed..7251f8b2 100644 --- a/dnsapi/dns_constellix.sh +++ b/dnsapi/dns_constellix.sh @@ -117,7 +117,7 @@ dns_constellix_rm() { #################### Private functions below ################################## _get_root() { - domain=$1 + domain=$(echo "$1" | _lower_case) i=2 p=1 _debug "Detecting root zone" From bcf0afb25ef9f159da397db73f1050c3b92f56d0 Mon Sep 17 00:00:00 2001 From: Tobias Grave Date: Fri, 15 Aug 2025 09:02:57 +0200 Subject: [PATCH 63/66] Variomedia API: Fix DNS deletion issues --- dnsapi/dns_variomedia.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_variomedia.sh b/dnsapi/dns_variomedia.sh index fa38bbb6..4620b854 100644 --- a/dnsapi/dns_variomedia.sh +++ b/dnsapi/dns_variomedia.sh @@ -74,7 +74,7 @@ dns_variomedia_rm() { return 1 fi - _record_id="$(echo "$response" | sed -E 's/,"tags":\[[^]]*\]//g' | cut -d '[' -f2 | cut -d']' -f1 | sed 's/},[ \t]*{/\},§\{/g' | tr § '\n' | grep "$_sub_domain" | grep -- "$txtvalue" | sed 's/^{//;s/}[,]?$//' | tr , '\n' | tr -d '\"' | grep ^id | cut -d : -f2 | tr -d ' ')" + _record_id="$(echo "$response" | sed -E 's/,"tags":\[[^]]*\]//g' | cut -d '[' -f3 | cut -d']' -f1 | sed 's/},[ \t]*{/\},§\{/g' | tr § '\n' | grep -i "$_sub_domain" | grep -- "$txtvalue" | sed 's/^{//;s/}[,]?$//' | tr , '\n' | tr -d '\"' | grep ^id | cut -d : -f2 | tr -d ' ')" _debug _record_id "$_record_id" if [ "$_record_id" ]; then _info "Successfully retrieved the record id for ACME challenge." From d366b7e4fc7799bcb1a43213e2566096e1c19a28 Mon Sep 17 00:00:00 2001 From: Jacobo de Vera Date: Mon, 1 Sep 2025 19:54:36 +0100 Subject: [PATCH 64/66] Fix diff in wiki notifications (use full clone) The checkout action fetches one single commit, so attempts to find previous states of a page result in error. Adding fetch-depth:0 to the configuration fetches all commits and makes finding the previous commit that changed a page possible in the github action. --- .github/workflows/wiki-monitor.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/wiki-monitor.yml b/.github/workflows/wiki-monitor.yml index 89497580..b0332775 100644 --- a/.github/workflows/wiki-monitor.yml +++ b/.github/workflows/wiki-monitor.yml @@ -12,6 +12,7 @@ jobs: with: repository: ${{ github.repository }}.wiki path: wiki + fetch-depth: 0 - name: Generate wiki change message run: | @@ -58,3 +59,4 @@ jobs: + From 04e254923939d0d600cd8b29dfe3b34ca7421052 Mon Sep 17 00:00:00 2001 From: Guillaume PELURE Date: Tue, 2 Sep 2025 21:13:38 +0200 Subject: [PATCH 65/66] socat rejects TCP-LISTEN on ipv6 only networks --- acme.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index d70e323b..5c4d6543 100755 --- a/acme.sh +++ b/acme.sh @@ -2538,15 +2538,17 @@ _startserver() { _NC="socat" if [ "$Le_Listen_V6" ]; then _NC="$_NC -6" + SOCAT_OPTIONS=TCP6-LISTEN else _NC="$_NC -4" + SOCAT_OPTIONS=TCP4-LISTEN fi if [ "$DEBUG" ] && [ "$DEBUG" -gt "1" ]; then _NC="$_NC -d -d -v" fi - SOCAT_OPTIONS=TCP-LISTEN:$Le_HTTPPort,crlf,reuseaddr,fork + SOCAT_OPTIONS=$SOCAT_OPTIONS:$Le_HTTPPort,crlf,reuseaddr,fork #Adding bind to local-address if [ "$ncaddr" ]; then From 39cb87dc4bf481460ddba4d2754f07d351da07e4 Mon Sep 17 00:00:00 2001 From: neil Date: Fri, 5 Sep 2025 22:08:55 +0200 Subject: [PATCH 66/66] fix for DragonflyBSD just move "date -u -j -f" before the linux branch. --- acme.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/acme.sh b/acme.sh index d9ae208a..bfd26bd6 100755 --- a/acme.sh +++ b/acme.sh @@ -1811,6 +1811,10 @@ _time() { # 2022-04-01 08:10:33 to 1648800633 #or 2022-04-01T08:10:33Z to 1648800633 _date2time() { + #Mac/BSD + if date -u -j -f "%Y-%m-%d %H:%M:%S" "$(echo "$1" | tr -d "Z" | tr "T" ' ')" +"%s" 2>/dev/null; then + return + fi #Linux if date -u -d "$(echo "$1" | tr -d "Z" | tr "T" ' ')" +"%s" 2>/dev/null; then return @@ -1820,10 +1824,6 @@ _date2time() { if gdate -u -d "$(echo "$1" | tr -d "Z" | tr "T" ' ')" +"%s" 2>/dev/null; then return fi - #Mac/BSD - if date -u -j -f "%Y-%m-%d %H:%M:%S" "$(echo "$1" | tr -d "Z" | tr "T" ' ')" +"%s" 2>/dev/null; then - return - fi #Omnios if python3 -c "import datetime; print(int(datetime.datetime.strptime(\"$1\", \"%Y-%m-%d %H:%M:%S\").replace(tzinfo=datetime.timezone.utc).timestamp()))" 2>/dev/null; then return