From 778ee02803098904be7dc5ec608665ad56060215 Mon Sep 17 00:00:00 2001 From: Frank Wall Date: Mon, 7 Nov 2022 23:43:37 +0100 Subject: [PATCH 001/198] update documentation for --cert-home Although the main use-case may be the --install command, this command also proves to be useful for the --signcsr and --issue commands. --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index d6d8e48c6c..9d6dfecc6e 100755 --- a/acme.sh +++ b/acme.sh @@ -6897,7 +6897,7 @@ Parameters: --accountconf Specifies a customized account config file. --home Specifies the home dir for $PROJECT_NAME. - --cert-home Specifies the home dir to save all the certs, only valid for '--install' command. + --cert-home Specifies the home dir to save all the certs. --config-home Specifies the home dir to save all the configurations. --useragent Specifies the user agent string. it will be saved for future use too. -m, --email Specifies the account email, only valid for the '--install' and '--update-account' command. From b0ca4435fdbee019ac72f8df0cb304e1de5deffc Mon Sep 17 00:00:00 2001 From: Ciaran Walsh Date: Wed, 21 Feb 2024 00:21:09 +0000 Subject: [PATCH 002/198] 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 38ccaadeda..34ac49e83e 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 517baa3235cb5f94ffa866884cd65fa1147c3d10 Mon Sep 17 00:00:00 2001 From: Vladimir Alexeev <9141778236@mai.ru> Date: Mon, 29 Apr 2024 22:54:31 +1000 Subject: [PATCH 003/198] test DNS for v2 (actual) --- dnsapi/dns_selectel.sh | 479 +++++++++++++++++++++++++++++++++++------ 1 file changed, 418 insertions(+), 61 deletions(-) diff --git a/dnsapi/dns_selectel.sh b/dnsapi/dns_selectel.sh index 1b09882dba..f5b6b1b937 100644 --- a/dnsapi/dns_selectel.sh +++ b/dnsapi/dns_selectel.sh @@ -1,10 +1,29 @@ #!/usr/bin/env sh +# переменные, которые должны быть определены перед запуском +# export SL_Ver="v1" - версия API: 'v2' (actual) или 'v1' (legacy). +# По-умолчанию: v2 +# Если SL_Ver="v1" +# export SL_Key="API_KEY" - Токен Selectel (API key) +# Посмотреть или создать можно в панели управления в правом верхнем углу откройте меню Профиль и настройки -> Ключи API. +# https://my.selectel.ru/profile/apikeys +# Если SL_Ver="v2" +# export SL_Expire=60 - время жизни token в минутах (0-1440). +# По-умолчанию: 1400 минут +# export SL_Login_ID= - номер аккаунта в панели управления; +# export SL_Project_Name= - имя проекта. +# export SL_Login_name= - имя сервисного пользователя. Посмотреть имя можно в панели управления: +# в правом верхнем углу откройте меню → Профиль и настройки → раздел Управление пользователями → вкладка Сервисные пользователи +# export SL_Pswd='pswd' - пароль сервисного пользователя, можно посмотреть при создании пользователя или изменить на новый. +# Все эти переменные будут сохранены ~/.acme.sh/account.conf и будут использоваться повторно при необходимости. # -#SL_Key="sdfsdfsdfljlbjkljlkjsdfoiwje" -# +# Авторизация описана в: +# https://developers.selectel.ru/docs/control-panel/authorization/ +# https://developers.selectel.com/docs/control-panel/authorization/ -SL_Api="https://api.selectel.ru/domains/v1" +SL_Api="https://api.selectel.ru/domains" +auth_uri="https://cloud.api.selcloud.ru/identity/v3/auth/tokens" +_sl_sep='#' ######## Public functions ##################### @@ -13,17 +32,16 @@ dns_selectel_add() { fulldomain=$1 txtvalue=$2 - SL_Key="${SL_Key:-$(_readaccountconf_mutable SL_Key)}" - - if [ -z "$SL_Key" ]; then - SL_Key="" - _err "You don't specify selectel.ru api key yet." - _err "Please create you key and try again." + #if ! _sl_init_vars; then + if ! _sl_init_vars; then return 1 fi - - #save the api key to the account conf file. - _saveaccountconf_mutable SL_Key "$SL_Key" + _debug2 SL_Ver "$SL_Ver" + _secure_debug3 SL_Key "$SL_Key" + _debug2 SL_Expire "$SL_Expire" + _debug2 SL_Login_Name "$SL_Login_Name" + _debug2 SL_Login_ID "$SL_Login_ID" + _debug2 SL_Project_Name "$SL_Project_Name" _debug "First detect the root zone" if ! _get_root "$fulldomain"; then @@ -35,11 +53,68 @@ dns_selectel_add() { _debug _domain "$_domain" _info "Adding record" - if _sl_rest POST "/$_domain_id/records/" "{\"type\": \"TXT\", \"ttl\": 60, \"name\": \"$fulldomain\", \"content\": \"$txtvalue\"}"; then - if _contains "$response" "$txtvalue" || _contains "$response" "record_already_exists"; then + if [ "$SL_Ver" = "v2" ]; then + _ext_srv1="/zones/" + _ext_srv2="/rrset/" + _text_tmp=$(echo "$txtvalue" | sed -En "s/[\"]*([^\"]*)/\1/p") + _debug txtvalue "$txtvalue" + _text_tmp='\"'$_text_tmp'\"' + _debug _text_tmp "$_text_tmp" + _data="{\"type\": \"TXT\", \"ttl\": 60, \"name\": \"${fulldomain}.\", \"records\": [{\"content\":\"$_text_tmp\"}]}" + elif [ "$SL_Ver" = "v1" ]; then + _ext_srv1="/" + _ext_srv2="/records/" + _data="{\"type\":\"TXT\",\"ttl\":60,\"name\":\"$fulldomain\",\"content\":\"$txtvalue\"}" + else + #not valid + _err "Error. Unsupported version API $SL_Ver" + return 1 + fi + _ext_uri="${_ext_srv1}$_domain_id${_ext_srv2}" + _debug3 _ext_uri "$_ext_uri" + _debug3 _data "$_data" + + if _sl_rest POST "$_ext_uri" "$_data"; then + if _contains "$response" "$txtvalue"; then _info "Added, OK" return 0 fi + if _contains "$response" "already_exists"; then + # запись TXT с $fulldomain уже существует + if [ "$SL_Ver" = "v2" ]; then + # надо добавить к существующей записи еще один content + # + # считать записи rrset + _debug "Getting txt records" + _sl_rest GET "${_ext_uri}" + # Если в данной записи, есть текстовое значение $txtvalue, + # то все хорошо, добавлять ничего не надо и результат успешный + if _contains "$response" "$txtvalue"; then + _info "Added, OK" + _info "Txt record ${fulldomain} со значением ${txtvalue} already exists" + return 0 + fi + # группа \1 - полная запись rrset; группа \2 - значение records:[{"content":"\"v1\""},{"content":"\"v2\""}",...], а именно {"content":"\"v1\""},{"content":"\"v2\""}",... + _record_seg="$(echo "$response" | sed -En "s/.*(\{\"id\"[^}]*${fulldomain}[^}]*records[^}]*\[(\{[^]]*\})\][^}]*}).*/\1/p")" + _record_array="$(echo "$response" | sed -En "s/.*(\{\"id\"[^}]*${fulldomain}[^}]*records[^}]*\[(\{[^]]*\})\][^}]*}).*/\2/p")" + # record id + _record_id="$(echo "$_record_seg" | tr "," "\n" | tr "}" "\n" | tr -d " " | grep "\"id\"" | cut -d : -f 2 | tr -d "\"")" + _tmp_str="${_record_array},{\"content\":\"${_text_tmp}\"}" + _data="{\"ttl\": 60, \"records\": [${_tmp_str}]}" + _debug3 _record_seg "$_record_seg" + _debug3 _record_array "$_record_array" + _debug3 _record_array "$_record_id" + _debug3 _data "$_data" + # вызов REST API PATCH + if _sl_rest PATCH "${_ext_uri}${_record_id}" "$_data"; then + _info "Added, OK" + return 0 + fi + elif [ "$SL_Ver" = "v1" ]; then + _info "Added, OK" + return 0 + fi + fi fi _err "Add txt record error." return 1 @@ -49,16 +124,17 @@ dns_selectel_add() { dns_selectel_rm() { fulldomain=$1 txtvalue=$2 - - SL_Key="${SL_Key:-$(_readaccountconf_mutable SL_Key)}" - - if [ -z "$SL_Key" ]; then - SL_Key="" - _err "You don't specify slectel api key yet." - _err "Please create you key and try again." + #SL_Key="${SL_Key:-$(_readaccountconf_mutable SL_Key)}" + if ! _sl_init_vars "nosave"; then return 1 fi - + _debug2 SL_Ver "$SL_Ver" + _secure_debug3 SL_Key "$SL_Key" + _debug2 SL_Expire "$SL_Expire" + _debug2 SL_Login_Name "$SL_Login_Name" + _debug2 SL_Login_ID "$SL_Login_ID" + _debug2 SL_Project_Name "$SL_Project_Name" + # _debug "First detect the root zone" if ! _get_root "$fulldomain"; then _err "invalid domain" @@ -67,32 +143,90 @@ dns_selectel_rm() { _debug _domain_id "$_domain_id" _debug _sub_domain "$_sub_domain" _debug _domain "$_domain" - + # + if [ "$SL_Ver" = "v2" ]; then + _ext_srv1="/zones/" + _ext_srv2="/rrset/" + elif [ "$SL_Ver" = "v1" ]; then + _ext_srv1="/" + _ext_srv2="/records/" + else + #not valid + _err "Error. Unsupported version API $SL_Ver" + return 1 + fi + # _debug "Getting txt records" - _sl_rest GET "/${_domain_id}/records/" - + _ext_uri="${_ext_srv1}$_domain_id${_ext_srv2}" + _debug3 _ext_uri "$_ext_uri" + _sl_rest GET "${_ext_uri}" + # if ! _contains "$response" "$txtvalue"; then _err "Txt record not found" return 1 fi - - _record_seg="$(echo "$response" | _egrep_o "[^{]*\"content\" *: *\"$txtvalue\"[^}]*}")" - _debug2 "_record_seg" "$_record_seg" + # + if [ "$SL_Ver" = "v2" ]; then + _record_seg="$(echo "$response" | sed -En "s/.*(\{\"id\"[^}]*records[^[]*(\[(\{[^]]*${txtvalue}[^]]*)\])[^}]*}).*/\1/gp")" + _record_arr="$(echo "$response" | sed -En "s/.*(\{\"id\"[^}]*records[^[]*(\[(\{[^]]*${txtvalue}[^]]*)\])[^}]*}).*/\3/p")" + #_record_id="$(echo "$_record_seg" | tr "," "\n" | tr "}" "\n" | tr -d " " | grep "\"id\"" | cut -d : -f 2)" + elif [ "$SL_Ver" = "v1" ]; then + _record_seg="$(echo "$response" | _egrep_o "[^{]*\"content\" *: *\"$txtvalue\"[^}]*}")" + # record id + #_record_id="$(echo "$_record_seg" | tr "," "\n" | tr "}" "\n" | tr -d " " | grep "\"id\"" | cut -d : -f 2)" + else + #not valid + _err "Error. Unsupported version API $SL_Ver" + return 1 + fi + _debug3 "_record_seg" "$_record_seg" if [ -z "$_record_seg" ]; then _err "can not find _record_seg" return 1 fi - - _record_id="$(echo "$_record_seg" | tr "," "\n" | tr "}" "\n" | tr -d " " | grep "\"id\"" | cut -d : -f 2)" - _debug2 "_record_id" "$_record_id" + # record id + _record_id="$(echo "$_record_seg" | tr "," "\n" | tr "}" "\n" | tr -d " " | grep "\"id\"" | cut -d : -f 2 | tr -d "\"")" if [ -z "$_record_id" ]; then _err "can not find _record_id" return 1 fi - - if ! _sl_rest DELETE "/$_domain_id/records/$_record_id"; then - _err "Delete record error." - return 1 + _debug3 "_record_id" "$_record_id" + # delete all record type TXT with text $txtvalue + if [ "$SL_Ver" = "v2" ]; then + # actual + #del_txt='it47Qq60vJuzQJXb9WEaapciTwtt1gb_14gm1ubwzrA'; + _new_arr="$(echo "$_record_seg" | sed -En "s/.*(\{\"id\"[^}]*records[^[]*(\[(\{[^]]*${txtvalue}[^]]*)\])[^}]*}).*/\3/gp" | sed -En "s/(\},\{)/}\n{/gp" | sed "/${txtvalue}/d" | sed ":a;N;s/\n/,/;ta")" + # uri record for DEL or PATCH + _del_uri="${_ext_uri}${_record_id}" + if [ -z "$_new_arr" ]; then + # удалить запись + if ! _sl_rest DELETE "${_del_uri}"; then + _err "Delete record error: ${_del_uri}." + else + info "Delete record success: ${_del_uri}." + fi + else + # обновить запись, удалив content + _data="{\"ttl\": 60, \"records\": [${_new_arr}]}" + _debug3 _data "$_data" + # вызов REST API PATCH + if _sl_rest PATCH "${_del_uri}" "$_data"; then + _info "Patched, OK: ${_del_uri}" + else + _err "Patched record error: ${_del_uri}." + fi + fi + else + # legacy + for _one_id in $_record_id; do + _del_uri="${_ext_uri}${_one_id}" + _debug2 _ext_uri "$_del_uri" + if ! _sl_rest DELETE "${_del_uri}"; then + _err "Delete record error: ${_del_uri}." + else + info "Delete record success: ${_del_uri}." + fi + done fi return 0 } @@ -105,51 +239,114 @@ dns_selectel_rm() { # _domain_id=sdjkglgdfewsdfg _get_root() { domain=$1 + # + if [ "$SL_Ver" = 'v1' ]; then + # version API 1 + if ! _sl_rest GET "/"; then + return 1 + fi + i=2 + p=1 + while true; do + #h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) + _debug h "$h" + if [ -z "$h" ]; then + #not valid + return 1 + fi - if ! _sl_rest GET "/"; then + if _contains "$response" "\"name\" *: *\"$h\","; then + #_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") + _domain=$h + _debug "Getting domain id for $h" + if ! _sl_rest GET "/$h"; then + _err "Error read records of all domains $SL_Ver" + return 1 + fi + _domain_id="$(echo "$response" | tr "," "\n" | tr "}" "\n" | tr -d " " | grep "\"id\":" | cut -d : -f 2)" + return 0 + fi + p=$i + i=$(_math "$i" + 1) + done + _err "Error read records of all domains $SL_Ver" return 1 - fi - - i=2 - p=1 - while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) - _debug h "$h" - if [ -z "$h" ]; then + elif [ "$SL_Ver" = "v2" ]; then + # version API 2 + _ext_uri='/zones/' + domain="${domain}." + _debug "domain:: " "$domain" + # read records of all domains + if ! _sl_rest GET "$_ext_uri"; then #not valid + _err "Error read records of all domains $SL_Ver" return 1 fi - - if _contains "$response" "\"name\" *: *\"$h\","; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) - _domain=$h - _debug "Getting domain id for $h" - if ! _sl_rest GET "/$h"; then + i=2 + p=1 + while true; do + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) + _debug h "$h" + if [ -z "$h" ]; then + #not valid + _err "The domain was not found among the registered ones" return 1 fi - _domain_id="$(echo "$response" | tr "," "\n" | tr "}" "\n" | tr -d " " | grep "\"id\":" | cut -d : -f 2)" - return 0 - fi - p=$i - i=$(_math "$i" + 1) - done - return 1 + + _domain_record=$(echo "$response" | sed -En "s/.*(\{[^}]*id[^}]*\"name\" *: *\"$h\"[^}]*}).*/\1/p") + _debug "_domain_record:: " "$_domain_record" + if [ -n "$_domain_record" ]; then + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") + _domain=$h + _debug "Getting domain id for $h" + #_domain_id="$(echo "$_domain_record" | tr "," "\n" | tr "}" "\n" | tr -d " " | grep "\"id\":" | cut -d : -f 2 | sed -En "s/\"([^\"]*)\"/\1\p")" + _domain_id=$(echo "$_domain_record" | sed -En "s/\{[^}]*\"id\" *: *\"([^\"]*)\"[^}]*\}/\1/p") + return 0 + fi + p=$i + i=$(_math "$i" + 1) + done + #not valid + _err "Error read records of all domains $SL_Ver" + return 1 + else + #not valid + _err "Error. Unsupported version API $SL_Ver" + return 1 + fi } +################################################################# +# use: method add_url body _sl_rest() { m=$1 ep="$2" data="$3" - _debug "$ep" - export _H1="X-Token: $SL_Key" + _token=$(_get_auth_token) + #_debug "$_token" + if [ -z "$_token" ]; then + _err "BAD key or token $ep" + return 1 + fi + if [ "$SL_Ver" = v2 ]; then + _h1_name="X-Auth-Token" + else + _h1_name='X-Token' + fi + export _H1="${_h1_name}: ${_token}" export _H2="Content-Type: application/json" + _debug3 "Full URI: " "$SL_Api/${SL_Ver}${ep}" + _debug3 "_H1:" "$_H1" + _debug3 "_H2:" "$_H2" if [ "$m" != "GET" ]; then _debug data "$data" - response="$(_post "$data" "$SL_Api/$ep" "" "$m")" + response="$(_post "$data" "$SL_Api/${SL_Ver}${ep}" "" "$m")" else - response="$(_get "$SL_Api/$ep")" + response="$(_get "$SL_Api/${SL_Ver}${ep}")" fi if [ "$?" != "0" ]; then @@ -159,3 +356,163 @@ _sl_rest() { _debug2 response "$response" return 0 } + +#################################################################3 +# use: +_get_auth_token() { + if [ "$SL_Ver" = 'v1' ]; then + # token for v1 + _debug "Token v1" + _token_keystone=$SL_Key + elif [ "$SL_Ver" = 'v2' ]; then + # token for v2. Get a token for calling the API + _debug "Keystone Token v2" + token_v2=$(_readaccountconf_mutable SL_Token_V2) + if [ -n "$token_v2" ]; then + # The structure with the token was considered. Let's check its validity + # field 1 - SL_Login_Name + # field 2 - token keystone + # field 3 - SL_Login_ID + # field 4 - SL_Project_Name + # field 5 - Receipt time + # separator - ';' + _login_name=$(_getfield "$token_v2" 1 "$_sl_sep") + _token_keystone=$(_getfield "$token_v2" 2 "$_sl_sep") + _project_name=$(_getfield "$token_v2" 4 "$_sl_sep") + _receipt_time=$(_getfield "$token_v2" 5 "$_sl_sep") + _login_id=$(_getfield "$token_v2" 3 "$_sl_sep") + _debug3 _login_name "$_login_name" + _debug3 _login_id "$_login_id" + _debug3 _project_name "$_project_name" + _debug3 _receipt_time "$(date -d @"$_receipt_time" -u)" + # check the validity of the token for the user and the project and its lifetime + #_dt_diff_minute=$(( ( $(EPOCHSECONDS)-$_receipt_time )/60 )) + _dt_diff_minute=$((($(date +%s) - _receipt_time) / 60)) + _debug3 _dt_diff_minute "$_dt_diff_minute" + [ "$_dt_diff_minute" -gt "$SL_Expire" ] && unset _token_keystone + if [ "$_project_name" != "$SL_Project_Name" ] || [ "$_login_name" != "$SL_Login_Name" ] || [ "$_login_id" != "$SL_Login_ID" ]; then + unset _token_keystone + fi + _debug "Get exists token" + fi + if [ -z "$_token_keystone" ]; then + # the previous token is incorrect or was not received, get a new one + _debug "Update (get new) token" + _data_auth="{\"auth\":{\"identity\":{\"methods\":[\"password\"],\"password\":{\"user\":{\"name\":\"${SL_Login_Name}\",\"domain\":{\"name\":\"${SL_Login_ID}\"},\"password\":\"${SL_Pswd}\"}}},\"scope\":{\"project\":{\"name\":\"${SL_Project_Name}\",\"domain\":{\"name\":\"${SL_Login_ID}\"}}}}}" + #_secure_debug2 "_data_auth" "$_data_auth" + export _H1="Content-Type: application/json" + # body url [needbase64] [POST|PUT|DELETE] [ContentType] + _result=$(_post "$_data_auth" "$auth_uri") + _token_keystone=$(grep 'x-subject-token' "$HTTP_HEADER" | sed -nE "s/[[:space:]]*x-subject-token:[[:space:]]*([[:print:]]*)(\r*)/\1/p") + #echo $_token_keystone > /root/123456.qwe + #_dt_curr=$EPOCHSECONDS + _dt_curr=$(date +%s) + SL_Token_V2="${SL_Login_Name}${_sl_sep}${_token_keystone}${_sl_sep}${SL_Login_ID}${_sl_sep}${SL_Project_Name}${_sl_sep}${_dt_curr}" + _saveaccountconf_mutable SL_Token_V2 "$SL_Token_V2" + fi + else + # token set empty for unsupported version API + _token_keystone="" + fi + printf -- "%s" "$_token_keystone" +} + +################################################################# +# use: [non_save] +_sl_init_vars() { + _non_save="${1}" + _debug2 _non_save "$_non_save" + + _debug "First init variables" + # version API + SL_Ver="${SL_Ver:-$(_readaccountconf_mutable SL_Ver)}" + if [ -z "$SL_Ver" ]; then + SL_Ver="v2" + fi + if ! [ "$SL_Ver" = "v1" ] && ! [ "$SL_Ver" = "v2" ]; then + _err "You don't specify selectel.ru API version." + _err "Please define specify API version." + fi + _debug2 SL_Ver "$SL_Ver" + + if [ "$SL_Ver" = "v1" ]; then + # token + SL_Key="${SL_Key:-$(_readaccountconf_mutable SL_Key)}" + + if [ -z "$SL_Key" ]; then + SL_Key="" + _err "You don't specify selectel.ru api key yet." + _err "Please create you key and try again." + return 1 + fi + #save the api key to the account conf file. + if [ -z "$_non_save" ]; then + _saveaccountconf_mutable SL_Key "$SL_Key" + fi + elif [ "$SL_Ver" = "v2" ]; then + # time expire token + SL_Expire="${SL_Expire:-$(_readaccountconf_mutable SL_Expire)}" + if [ -z "$SL_Expire" ]; then + SL_Expire=1400 # 23h 20 min + fi + if [ -z "$_non_save" ]; then + _saveaccountconf_mutable SL_Expire "$SL_Expire" + fi + # login service user + SL_Login_Name="${SL_Login_Name:-$(_readaccountconf_mutable SL_Login_Name)}" + if [ -z "$SL_Login_Name" ]; then + SL_Login_Name='' + _err "You did not specify the selectel.ru API service user name." + _err "Please provide a service user name and try again." + return 1 + fi + if [ -z "$_non_save" ]; then + _saveaccountconf_mutable SL_Login_Name "$SL_Login_Name" + fi + # user ID + SL_Login_ID="${SL_Login_ID:-$(_readaccountconf_mutable SL_Login_ID)}" + if [ -z "$SL_Login_ID" ]; then + SL_Login_ID='' + _err "You did not specify the selectel.ru API user ID." + _err "Please provide a user ID and try again." + return 1 + fi + if [ -z "$_non_save" ]; then + _saveaccountconf_mutable SL_Login_ID "$SL_Login_ID" + fi + # project name + SL_Project_Name="${SL_Project_Name:-$(_readaccountconf_mutable SL_Project_Name)}" + if [ -z "$SL_Project_Name" ]; then + SL_Project_Name='' + _err "You did not specify the project name." + _err "Please provide a project name and try again." + return 1 + fi + if [ -z "$_non_save" ]; then + _saveaccountconf_mutable SL_Project_Name "$SL_Project_Name" + fi + # service user password + SL_Pswd="${SL_Pswd:-$(_readaccountconf_mutable SL_Pswd)}" + #_secure_debug3 SL_Pswd "$SL_Pswd" + if [ -z "$SL_Pswd" ]; then + SL_Pswd='' + _err "You did not specify the service user password." + _err "Please provide a service user password and try again." + return 1 + fi + if [ -z "$_non_save" ]; then + _saveaccountconf_mutable SL_Pswd "$SL_Pswd" "12345678" + fi + else + SL_Ver="" + _err "You also specified the wrong version of the selectel.ru API." + _err "Please provide the correct API version and try again." + return 1 + fi + + if [ -z "$_non_save" ]; then + _saveaccountconf_mutable SL_Ver "$SL_Ver" + fi + + return 0 +} From 577920de863d7ee142cc86f925eca1d1526bf441 Mon Sep 17 00:00:00 2001 From: Vladimir Alexeev <9141778236@mai.ru> Date: Tue, 30 Apr 2024 08:36:36 +1000 Subject: [PATCH 004/198] test DNS for v2 (actual) 001 --- dnsapi/dns_selectel.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/dnsapi/dns_selectel.sh b/dnsapi/dns_selectel.sh index f5b6b1b937..99f031ddc3 100644 --- a/dnsapi/dns_selectel.sh +++ b/dnsapi/dns_selectel.sh @@ -513,6 +513,5 @@ _sl_init_vars() { if [ -z "$_non_save" ]; then _saveaccountconf_mutable SL_Ver "$SL_Ver" fi - return 0 } From 73fe47ba798d269f3082aa4ec5ca06c1f4f6fb1f Mon Sep 17 00:00:00 2001 From: Vladimir Alexeev <9141778236@mai.ru> Date: Tue, 30 Apr 2024 09:57:49 +1000 Subject: [PATCH 005/198] test DNS for v1 (legacy) 001 --- dnsapi/dns_selectel.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_selectel.sh b/dnsapi/dns_selectel.sh index 99f031ddc3..73210164ba 100644 --- a/dnsapi/dns_selectel.sh +++ b/dnsapi/dns_selectel.sh @@ -427,7 +427,7 @@ _sl_init_vars() { # version API SL_Ver="${SL_Ver:-$(_readaccountconf_mutable SL_Ver)}" if [ -z "$SL_Ver" ]; then - SL_Ver="v2" + SL_Ver="v1" fi if ! [ "$SL_Ver" = "v1" ] && ! [ "$SL_Ver" = "v2" ]; then _err "You don't specify selectel.ru API version." From b8949ba3dd82f1846eef195e75700c148a91f214 Mon Sep 17 00:00:00 2001 From: Vladimir Alexeev <9141778236@mai.ru> Date: Tue, 30 Apr 2024 10:01:50 +1000 Subject: [PATCH 006/198] test DNS for v1 (legacy) 002 --- dnsapi/dns_selectel.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/dnsapi/dns_selectel.sh b/dnsapi/dns_selectel.sh index 73210164ba..04c9a38876 100644 --- a/dnsapi/dns_selectel.sh +++ b/dnsapi/dns_selectel.sh @@ -513,5 +513,6 @@ _sl_init_vars() { if [ -z "$_non_save" ]; then _saveaccountconf_mutable SL_Ver "$SL_Ver" fi + return 0 } From ada7e12b5a85297c42f6169e65612ac0cd2eb709 Mon Sep 17 00:00:00 2001 From: Vladimir Alexeev <9141778236@mai.ru> Date: Tue, 30 Apr 2024 11:03:53 +1000 Subject: [PATCH 007/198] test DNS for v1 (legacy) 003 --- dnsapi/dns_selectel.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_selectel.sh b/dnsapi/dns_selectel.sh index 04c9a38876..f5b6b1b937 100644 --- a/dnsapi/dns_selectel.sh +++ b/dnsapi/dns_selectel.sh @@ -427,7 +427,7 @@ _sl_init_vars() { # version API SL_Ver="${SL_Ver:-$(_readaccountconf_mutable SL_Ver)}" if [ -z "$SL_Ver" ]; then - SL_Ver="v1" + SL_Ver="v2" fi if ! [ "$SL_Ver" = "v1" ] && ! [ "$SL_Ver" = "v2" ]; then _err "You don't specify selectel.ru API version." From 2e3c1ef4ac7f0d971f2afe4e18a9b07c5e0427ca Mon Sep 17 00:00:00 2001 From: Vladimir Alexeev <9141778236@mai.ru> Date: Tue, 30 Apr 2024 13:49:53 +1000 Subject: [PATCH 008/198] test DNS for v1 (legacy) 003 --- dnsapi/dns_selectel.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/dnsapi/dns_selectel.sh b/dnsapi/dns_selectel.sh index f5b6b1b937..99f031ddc3 100644 --- a/dnsapi/dns_selectel.sh +++ b/dnsapi/dns_selectel.sh @@ -513,6 +513,5 @@ _sl_init_vars() { if [ -z "$_non_save" ]; then _saveaccountconf_mutable SL_Ver "$SL_Ver" fi - return 0 } From 8bb29f53d131f4761752a979d03270d650a260f1 Mon Sep 17 00:00:00 2001 From: Vladimir Alexeev <9141778236@mai.ru> Date: Tue, 30 Apr 2024 16:15:45 +1000 Subject: [PATCH 009/198] test DNS for v1 (legacy) 003 --- dnsapi/dns_selectel.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_selectel.sh b/dnsapi/dns_selectel.sh index 99f031ddc3..73210164ba 100644 --- a/dnsapi/dns_selectel.sh +++ b/dnsapi/dns_selectel.sh @@ -427,7 +427,7 @@ _sl_init_vars() { # version API SL_Ver="${SL_Ver:-$(_readaccountconf_mutable SL_Ver)}" if [ -z "$SL_Ver" ]; then - SL_Ver="v2" + SL_Ver="v1" fi if ! [ "$SL_Ver" = "v1" ] && ! [ "$SL_Ver" = "v2" ]; then _err "You don't specify selectel.ru API version." From 7a1305c1bb3448ba6573101a0cd9854455b2084d Mon Sep 17 00:00:00 2001 From: Vladimir Alexeev <9141778236@mai.ru> Date: Sat, 4 May 2024 19:12:42 +1000 Subject: [PATCH 010/198] fix del record for v1, delete one entry at a time --- dnsapi/dns_selectel.sh | 58 +++++++++--------------------------------- 1 file changed, 12 insertions(+), 46 deletions(-) diff --git a/dnsapi/dns_selectel.sh b/dnsapi/dns_selectel.sh index 73210164ba..4806773d84 100644 --- a/dnsapi/dns_selectel.sh +++ b/dnsapi/dns_selectel.sh @@ -2,7 +2,7 @@ # переменные, которые должны быть определены перед запуском # export SL_Ver="v1" - версия API: 'v2' (actual) или 'v1' (legacy). -# По-умолчанию: v2 +# По-умолчанию: v1 # Если SL_Ver="v1" # export SL_Key="API_KEY" - Токен Selectel (API key) # Посмотреть или создать можно в панели управления в правом верхнем углу откройте меню Профиль и настройки -> Ключи API. @@ -32,7 +32,6 @@ dns_selectel_add() { fulldomain=$1 txtvalue=$2 - #if ! _sl_init_vars; then if ! _sl_init_vars; then return 1 fi @@ -66,7 +65,6 @@ dns_selectel_add() { _ext_srv2="/records/" _data="{\"type\":\"TXT\",\"ttl\":60,\"name\":\"$fulldomain\",\"content\":\"$txtvalue\"}" else - #not valid _err "Error. Unsupported version API $SL_Ver" return 1 fi @@ -83,29 +81,27 @@ dns_selectel_add() { # запись TXT с $fulldomain уже существует if [ "$SL_Ver" = "v2" ]; then # надо добавить к существующей записи еще один content - # # считать записи rrset _debug "Getting txt records" _sl_rest GET "${_ext_uri}" - # Если в данной записи, есть текстовое значение $txtvalue, - # то все хорошо, добавлять ничего не надо и результат успешный + # Уже есть значение $txtvalue, добавлять не надо if _contains "$response" "$txtvalue"; then _info "Added, OK" _info "Txt record ${fulldomain} со значением ${txtvalue} already exists" return 0 fi - # группа \1 - полная запись rrset; группа \2 - значение records:[{"content":"\"v1\""},{"content":"\"v2\""}",...], а именно {"content":"\"v1\""},{"content":"\"v2\""}",... + # группа \1 - полная запись rrset; группа \2 - значение атрибута records, а именно {"content":"\"value1\""},{"content":"\"value2\""}",... _record_seg="$(echo "$response" | sed -En "s/.*(\{\"id\"[^}]*${fulldomain}[^}]*records[^}]*\[(\{[^]]*\})\][^}]*}).*/\1/p")" _record_array="$(echo "$response" | sed -En "s/.*(\{\"id\"[^}]*${fulldomain}[^}]*records[^}]*\[(\{[^]]*\})\][^}]*}).*/\2/p")" # record id _record_id="$(echo "$_record_seg" | tr "," "\n" | tr "}" "\n" | tr -d " " | grep "\"id\"" | cut -d : -f 2 | tr -d "\"")" + # готовим _data _tmp_str="${_record_array},{\"content\":\"${_text_tmp}\"}" _data="{\"ttl\": 60, \"records\": [${_tmp_str}]}" _debug3 _record_seg "$_record_seg" _debug3 _record_array "$_record_array" _debug3 _record_array "$_record_id" - _debug3 _data "$_data" - # вызов REST API PATCH + _debug2 "New data for record" "$_data" if _sl_rest PATCH "${_ext_uri}${_record_id}" "$_data"; then _info "Added, OK" return 0 @@ -124,7 +120,7 @@ dns_selectel_add() { dns_selectel_rm() { fulldomain=$1 txtvalue=$2 - #SL_Key="${SL_Key:-$(_readaccountconf_mutable SL_Key)}" + if ! _sl_init_vars "nosave"; then return 1 fi @@ -151,7 +147,6 @@ dns_selectel_rm() { _ext_srv1="/" _ext_srv2="/records/" else - #not valid _err "Error. Unsupported version API $SL_Ver" return 1 fi @@ -169,13 +164,9 @@ dns_selectel_rm() { if [ "$SL_Ver" = "v2" ]; then _record_seg="$(echo "$response" | sed -En "s/.*(\{\"id\"[^}]*records[^[]*(\[(\{[^]]*${txtvalue}[^]]*)\])[^}]*}).*/\1/gp")" _record_arr="$(echo "$response" | sed -En "s/.*(\{\"id\"[^}]*records[^[]*(\[(\{[^]]*${txtvalue}[^]]*)\])[^}]*}).*/\3/p")" - #_record_id="$(echo "$_record_seg" | tr "," "\n" | tr "}" "\n" | tr -d " " | grep "\"id\"" | cut -d : -f 2)" elif [ "$SL_Ver" = "v1" ]; then _record_seg="$(echo "$response" | _egrep_o "[^{]*\"content\" *: *\"$txtvalue\"[^}]*}")" - # record id - #_record_id="$(echo "$_record_seg" | tr "," "\n" | tr "}" "\n" | tr -d " " | grep "\"id\"" | cut -d : -f 2)" else - #not valid _err "Error. Unsupported version API $SL_Ver" return 1 fi @@ -185,7 +176,7 @@ dns_selectel_rm() { return 1 fi # record id - _record_id="$(echo "$_record_seg" | tr "," "\n" | tr "}" "\n" | tr -d " " | grep "\"id\"" | cut -d : -f 2 | tr -d "\"")" + _record_id="$(echo "$_record_seg" | tr "," "\n" | tr "}" "\n" | tr -d " " | grep "\"id\"" | cut -d : -f 2 | tr -d "\"" | sed '1!d')" if [ -z "$_record_id" ]; then _err "can not find _record_id" return 1 @@ -194,7 +185,6 @@ dns_selectel_rm() { # delete all record type TXT with text $txtvalue if [ "$SL_Ver" = "v2" ]; then # actual - #del_txt='it47Qq60vJuzQJXb9WEaapciTwtt1gb_14gm1ubwzrA'; _new_arr="$(echo "$_record_seg" | sed -En "s/.*(\{\"id\"[^}]*records[^[]*(\[(\{[^]]*${txtvalue}[^]]*)\])[^}]*}).*/\3/gp" | sed -En "s/(\},\{)/}\n{/gp" | sed "/${txtvalue}/d" | sed ":a;N;s/\n/,/;ta")" # uri record for DEL or PATCH _del_uri="${_ext_uri}${_record_id}" @@ -232,14 +222,10 @@ dns_selectel_rm() { } #################### Private functions below ################################## -#_acme-challenge.www.domain.com -#returns -# _sub_domain=_acme-challenge.www -# _domain=domain.com -# _domain_id=sdjkglgdfewsdfg + _get_root() { domain=$1 - # + if [ "$SL_Ver" = 'v1' ]; then # version API 1 if ! _sl_rest GET "/"; then @@ -248,16 +234,12 @@ _get_root() { i=2 p=1 while true; do - #h=$(printf "%s" "$domain" | cut -d . -f $i-100) h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug h "$h" if [ -z "$h" ]; then - #not valid return 1 fi - if _contains "$response" "\"name\" *: *\"$h\","; then - #_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain=$h _debug "Getting domain id for $h" @@ -280,7 +262,6 @@ _get_root() { _debug "domain:: " "$domain" # read records of all domains if ! _sl_rest GET "$_ext_uri"; then - #not valid _err "Error read records of all domains $SL_Ver" return 1 fi @@ -290,29 +271,24 @@ _get_root() { h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) _debug h "$h" if [ -z "$h" ]; then - #not valid _err "The domain was not found among the registered ones" return 1 fi - _domain_record=$(echo "$response" | sed -En "s/.*(\{[^}]*id[^}]*\"name\" *: *\"$h\"[^}]*}).*/\1/p") _debug "_domain_record:: " "$_domain_record" if [ -n "$_domain_record" ]; then _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain=$h _debug "Getting domain id for $h" - #_domain_id="$(echo "$_domain_record" | tr "," "\n" | tr "}" "\n" | tr -d " " | grep "\"id\":" | cut -d : -f 2 | sed -En "s/\"([^\"]*)\"/\1\p")" _domain_id=$(echo "$_domain_record" | sed -En "s/\{[^}]*\"id\" *: *\"([^\"]*)\"[^}]*\}/\1/p") return 0 fi p=$i i=$(_math "$i" + 1) done - #not valid _err "Error read records of all domains $SL_Ver" return 1 else - #not valid _err "Error. Unsupported version API $SL_Ver" return 1 fi @@ -341,14 +317,12 @@ _sl_rest() { _debug3 "Full URI: " "$SL_Api/${SL_Ver}${ep}" _debug3 "_H1:" "$_H1" _debug3 "_H2:" "$_H2" - if [ "$m" != "GET" ]; then _debug data "$data" response="$(_post "$data" "$SL_Api/${SL_Ver}${ep}" "" "$m")" else response="$(_get "$SL_Api/${SL_Ver}${ep}")" fi - if [ "$?" != "0" ]; then _err "error $ep" return 1 @@ -357,8 +331,6 @@ _sl_rest() { return 0 } -#################################################################3 -# use: _get_auth_token() { if [ "$SL_Ver" = 'v1' ]; then # token for v1 @@ -375,7 +347,7 @@ _get_auth_token() { # field 3 - SL_Login_ID # field 4 - SL_Project_Name # field 5 - Receipt time - # separator - ';' + # separator - '$_sl_sep' _login_name=$(_getfield "$token_v2" 1 "$_sl_sep") _token_keystone=$(_getfield "$token_v2" 2 "$_sl_sep") _project_name=$(_getfield "$token_v2" 4 "$_sl_sep") @@ -386,7 +358,6 @@ _get_auth_token() { _debug3 _project_name "$_project_name" _debug3 _receipt_time "$(date -d @"$_receipt_time" -u)" # check the validity of the token for the user and the project and its lifetime - #_dt_diff_minute=$(( ( $(EPOCHSECONDS)-$_receipt_time )/60 )) _dt_diff_minute=$((($(date +%s) - _receipt_time) / 60)) _debug3 _dt_diff_minute "$_dt_diff_minute" [ "$_dt_diff_minute" -gt "$SL_Expire" ] && unset _token_keystone @@ -399,13 +370,9 @@ _get_auth_token() { # the previous token is incorrect or was not received, get a new one _debug "Update (get new) token" _data_auth="{\"auth\":{\"identity\":{\"methods\":[\"password\"],\"password\":{\"user\":{\"name\":\"${SL_Login_Name}\",\"domain\":{\"name\":\"${SL_Login_ID}\"},\"password\":\"${SL_Pswd}\"}}},\"scope\":{\"project\":{\"name\":\"${SL_Project_Name}\",\"domain\":{\"name\":\"${SL_Login_ID}\"}}}}}" - #_secure_debug2 "_data_auth" "$_data_auth" export _H1="Content-Type: application/json" - # body url [needbase64] [POST|PUT|DELETE] [ContentType] _result=$(_post "$_data_auth" "$auth_uri") _token_keystone=$(grep 'x-subject-token' "$HTTP_HEADER" | sed -nE "s/[[:space:]]*x-subject-token:[[:space:]]*([[:print:]]*)(\r*)/\1/p") - #echo $_token_keystone > /root/123456.qwe - #_dt_curr=$EPOCHSECONDS _dt_curr=$(date +%s) SL_Token_V2="${SL_Login_Name}${_sl_sep}${_token_keystone}${_sl_sep}${SL_Login_ID}${_sl_sep}${SL_Project_Name}${_sl_sep}${_dt_curr}" _saveaccountconf_mutable SL_Token_V2 "$SL_Token_V2" @@ -427,14 +394,13 @@ _sl_init_vars() { # version API SL_Ver="${SL_Ver:-$(_readaccountconf_mutable SL_Ver)}" if [ -z "$SL_Ver" ]; then - SL_Ver="v1" + SL_Ver="v2" fi if ! [ "$SL_Ver" = "v1" ] && ! [ "$SL_Ver" = "v2" ]; then _err "You don't specify selectel.ru API version." _err "Please define specify API version." fi _debug2 SL_Ver "$SL_Ver" - if [ "$SL_Ver" = "v1" ]; then # token SL_Key="${SL_Key:-$(_readaccountconf_mutable SL_Key)}" @@ -509,9 +475,9 @@ _sl_init_vars() { _err "Please provide the correct API version and try again." return 1 fi - if [ -z "$_non_save" ]; then _saveaccountconf_mutable SL_Ver "$SL_Ver" fi + return 0 } From 177d9b7cb0fce9baabbc5fa90aa86f8765e33c3b Mon Sep 17 00:00:00 2001 From: Vladimir Alexeev <9141778236@mai.ru> Date: Sat, 4 May 2024 20:38:42 +1000 Subject: [PATCH 011/198] set default SL_Ver to v1 --- dnsapi/dns_selectel.sh | 47 +++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/dnsapi/dns_selectel.sh b/dnsapi/dns_selectel.sh index 4806773d84..65729804f6 100644 --- a/dnsapi/dns_selectel.sh +++ b/dnsapi/dns_selectel.sh @@ -4,7 +4,7 @@ # export SL_Ver="v1" - версия API: 'v2' (actual) или 'v1' (legacy). # По-умолчанию: v1 # Если SL_Ver="v1" -# export SL_Key="API_KEY" - Токен Selectel (API key) +# export SL_Key="API_Key" - Токен Selectel (API key) # Посмотреть или создать можно в панели управления в правом верхнем углу откройте меню Профиль и настройки -> Ключи API. # https://my.selectel.ru/profile/apikeys # Если SL_Ver="v2" @@ -35,12 +35,11 @@ dns_selectel_add() { if ! _sl_init_vars; then return 1 fi - _debug2 SL_Ver "$SL_Ver" - _secure_debug3 SL_Key "$SL_Key" - _debug2 SL_Expire "$SL_Expire" - _debug2 SL_Login_Name "$SL_Login_Name" - _debug2 SL_Login_ID "$SL_Login_ID" - _debug2 SL_Project_Name "$SL_Project_Name" + _debug3 SL_Ver "$SL_Ver" + _debug3 SL_Expire "$SL_Expire" + _debug3 SL_Login_Name "$SL_Login_Name" + _debug3 SL_Login_ID "$SL_Login_ID" + _debug3 SL_Project_Name "$SL_Project_Name" _debug "First detect the root zone" if ! _get_root "$fulldomain"; then @@ -56,9 +55,7 @@ dns_selectel_add() { _ext_srv1="/zones/" _ext_srv2="/rrset/" _text_tmp=$(echo "$txtvalue" | sed -En "s/[\"]*([^\"]*)/\1/p") - _debug txtvalue "$txtvalue" _text_tmp='\"'$_text_tmp'\"' - _debug _text_tmp "$_text_tmp" _data="{\"type\": \"TXT\", \"ttl\": 60, \"name\": \"${fulldomain}.\", \"records\": [{\"content\":\"$_text_tmp\"}]}" elif [ "$SL_Ver" = "v1" ]; then _ext_srv1="/" @@ -69,8 +66,8 @@ dns_selectel_add() { return 1 fi _ext_uri="${_ext_srv1}$_domain_id${_ext_srv2}" - _debug3 _ext_uri "$_ext_uri" - _debug3 _data "$_data" + _debug _ext_uri "$_ext_uri" + _debug _data "$_data" if _sl_rest POST "$_ext_uri" "$_data"; then if _contains "$response" "$txtvalue"; then @@ -101,7 +98,7 @@ dns_selectel_add() { _debug3 _record_seg "$_record_seg" _debug3 _record_array "$_record_array" _debug3 _record_array "$_record_id" - _debug2 "New data for record" "$_data" + _debug "New data for record" "$_data" if _sl_rest PATCH "${_ext_uri}${_record_id}" "$_data"; then _info "Added, OK" return 0 @@ -124,12 +121,11 @@ dns_selectel_rm() { if ! _sl_init_vars "nosave"; then return 1 fi - _debug2 SL_Ver "$SL_Ver" - _secure_debug3 SL_Key "$SL_Key" - _debug2 SL_Expire "$SL_Expire" - _debug2 SL_Login_Name "$SL_Login_Name" - _debug2 SL_Login_ID "$SL_Login_ID" - _debug2 SL_Project_Name "$SL_Project_Name" + _debug3 SL_Ver "$SL_Ver" + _debug3 SL_Expire "$SL_Expire" + _debug3 SL_Login_Name "$SL_Login_Name" + _debug3 SL_Login_ID "$SL_Login_ID" + _debug3 SL_Project_Name "$SL_Project_Name" # _debug "First detect the root zone" if ! _get_root "$fulldomain"; then @@ -153,7 +149,7 @@ dns_selectel_rm() { # _debug "Getting txt records" _ext_uri="${_ext_srv1}$_domain_id${_ext_srv2}" - _debug3 _ext_uri "$_ext_uri" + _debug _ext_uri "$_ext_uri" _sl_rest GET "${_ext_uri}" # if ! _contains "$response" "$txtvalue"; then @@ -176,7 +172,11 @@ dns_selectel_rm() { return 1 fi # record id - _record_id="$(echo "$_record_seg" | tr "," "\n" | tr "}" "\n" | tr -d " " | grep "\"id\"" | cut -d : -f 2 | tr -d "\"" | sed '1!d')" + # следующие строки меняют алгоритм удаления записей со значением $txtvalue + # если использовать 1-ю строку, то за раз удаляются все такие записи + # если использовать 2-ю строку, то удаляется только первая запись из них + #_record_id="$(echo "$_record_seg" | tr "," "\n" | tr "}" "\n" | tr -d " " | grep "\"id\"" | cut -d : -f 2 | tr -d "\"")" # удалять все записи со значением $txtvalue + _record_id="$(echo "$_record_seg" | tr "," "\n" | tr "}" "\n" | tr -d " " | grep "\"id\"" | cut -d : -f 2 | tr -d "\"" | sed '1!d')" # удалять только первую запись со значением $txtvalue if [ -z "$_record_id" ]; then _err "can not find _record_id" return 1 @@ -188,6 +188,7 @@ dns_selectel_rm() { _new_arr="$(echo "$_record_seg" | sed -En "s/.*(\{\"id\"[^}]*records[^[]*(\[(\{[^]]*${txtvalue}[^]]*)\])[^}]*}).*/\3/gp" | sed -En "s/(\},\{)/}\n{/gp" | sed "/${txtvalue}/d" | sed ":a;N;s/\n/,/;ta")" # uri record for DEL or PATCH _del_uri="${_ext_uri}${_record_id}" + _debug _del_uri "$_del_uri" if [ -z "$_new_arr" ]; then # удалить запись if ! _sl_rest DELETE "${_del_uri}"; then @@ -210,7 +211,7 @@ dns_selectel_rm() { # legacy for _one_id in $_record_id; do _del_uri="${_ext_uri}${_one_id}" - _debug2 _ext_uri "$_del_uri" + _debug _del_uri "$_del_uri" if ! _sl_rest DELETE "${_del_uri}"; then _err "Delete record error: ${_del_uri}." else @@ -302,7 +303,6 @@ _sl_rest() { data="$3" _token=$(_get_auth_token) - #_debug "$_token" if [ -z "$_token" ]; then _err "BAD key or token $ep" return 1 @@ -394,7 +394,7 @@ _sl_init_vars() { # version API SL_Ver="${SL_Ver:-$(_readaccountconf_mutable SL_Ver)}" if [ -z "$SL_Ver" ]; then - SL_Ver="v2" + SL_Ver="v1" fi if ! [ "$SL_Ver" = "v1" ] && ! [ "$SL_Ver" = "v2" ]; then _err "You don't specify selectel.ru API version." @@ -459,7 +459,6 @@ _sl_init_vars() { fi # service user password SL_Pswd="${SL_Pswd:-$(_readaccountconf_mutable SL_Pswd)}" - #_secure_debug3 SL_Pswd "$SL_Pswd" if [ -z "$SL_Pswd" ]; then SL_Pswd='' _err "You did not specify the service user password." From d989617825ccc0b9a60b4f9f657148243d14b15b Mon Sep 17 00:00:00 2001 From: Vladimir Alexeev <9141778236@mai.ru> Date: Sat, 4 May 2024 20:42:38 +1000 Subject: [PATCH 012/198] set default SL_Ver to v1 --- dnsapi/dns_selectel.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_selectel.sh b/dnsapi/dns_selectel.sh index 65729804f6..9868cb1243 100644 --- a/dnsapi/dns_selectel.sh +++ b/dnsapi/dns_selectel.sh @@ -173,7 +173,7 @@ dns_selectel_rm() { fi # record id # следующие строки меняют алгоритм удаления записей со значением $txtvalue - # если использовать 1-ю строку, то за раз удаляются все такие записи + # если использовать 1-ю строку, то за раз удаляются все такие записи # если использовать 2-ю строку, то удаляется только первая запись из них #_record_id="$(echo "$_record_seg" | tr "," "\n" | tr "}" "\n" | tr -d " " | grep "\"id\"" | cut -d : -f 2 | tr -d "\"")" # удалять все записи со значением $txtvalue _record_id="$(echo "$_record_seg" | tr "," "\n" | tr "}" "\n" | tr -d " " | grep "\"id\"" | cut -d : -f 2 | tr -d "\"" | sed '1!d')" # удалять только первую запись со значением $txtvalue From a375e924b491e8245ee763305f59627eac996f80 Mon Sep 17 00:00:00 2001 From: Vladimir Alexeev <9141778236@mai.ru> Date: Sun, 5 May 2024 07:42:22 +1000 Subject: [PATCH 013/198] translation of comments into English --- dnsapi/dns_selectel.sh | 62 +++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/dnsapi/dns_selectel.sh b/dnsapi/dns_selectel.sh index 9868cb1243..d4ca13b274 100644 --- a/dnsapi/dns_selectel.sh +++ b/dnsapi/dns_selectel.sh @@ -1,23 +1,23 @@ #!/usr/bin/env sh -# переменные, которые должны быть определены перед запуском -# export SL_Ver="v1" - версия API: 'v2' (actual) или 'v1' (legacy). -# По-умолчанию: v1 -# Если SL_Ver="v1" -# export SL_Key="API_Key" - Токен Selectel (API key) -# Посмотреть или создать можно в панели управления в правом верхнем углу откройте меню Профиль и настройки -> Ключи API. +# Variables that must be defined before running +# export SL_Ver="v1" - version API: 'v2' (actual) or 'v1' (legacy). +# Default: v1 +# If SL_Ver="v1" +# export SL_Key="API_Key" - Token Selectel (API key) +# You can view or create in the control panel in the upper right corner, open the menu: "Profile and setting -> Keys API". # https://my.selectel.ru/profile/apikeys -# Если SL_Ver="v2" -# export SL_Expire=60 - время жизни token в минутах (0-1440). -# По-умолчанию: 1400 минут -# export SL_Login_ID= - номер аккаунта в панели управления; -# export SL_Project_Name= - имя проекта. -# export SL_Login_name= - имя сервисного пользователя. Посмотреть имя можно в панели управления: -# в правом верхнем углу откройте меню → Профиль и настройки → раздел Управление пользователями → вкладка Сервисные пользователи -# export SL_Pswd='pswd' - пароль сервисного пользователя, можно посмотреть при создании пользователя или изменить на новый. -# Все эти переменные будут сохранены ~/.acme.sh/account.conf и будут использоваться повторно при необходимости. +# If SL_Ver="v2" +# export SL_Expire=60 - token lifetime in minutes (0-1440). +# Default: 1400 minutes +# export SL_Login_ID= - account number in the control panel; +# export SL_Project_Name= - name project. +# export SL_Login_name= - service user name. You can view the name in the control panel: +# in the upper right corner open menu: "Profile and setting → User management → Service users +# export SL_Pswd='pswd' - service user password, can be viewed when creating a user or changed to a new one. +# All these variables will be saved in ~/.acme.sh/account.conf and will be reused as needed. # -# Авторизация описана в: +# Authorization is described in: # https://developers.selectel.ru/docs/control-panel/authorization/ # https://developers.selectel.com/docs/control-panel/authorization/ @@ -75,24 +75,24 @@ dns_selectel_add() { return 0 fi if _contains "$response" "already_exists"; then - # запись TXT с $fulldomain уже существует + # record TXT with $fulldomain already exists if [ "$SL_Ver" = "v2" ]; then - # надо добавить к существующей записи еще один content - # считать записи rrset + # It is necessary to add one more content to the comments + # read all records rrset _debug "Getting txt records" _sl_rest GET "${_ext_uri}" - # Уже есть значение $txtvalue, добавлять не надо + # There is already a $txtvalue value, no need to add it if _contains "$response" "$txtvalue"; then _info "Added, OK" - _info "Txt record ${fulldomain} со значением ${txtvalue} already exists" + _info "Txt record ${fulldomain} with value ${txtvalue} already exists" return 0 fi - # группа \1 - полная запись rrset; группа \2 - значение атрибута records, а именно {"content":"\"value1\""},{"content":"\"value2\""}",... + # group \1 - full record rrset; group \2 - records attribute value, exactly {"content":"\"value1\""},{"content":"\"value2\""}",... _record_seg="$(echo "$response" | sed -En "s/.*(\{\"id\"[^}]*${fulldomain}[^}]*records[^}]*\[(\{[^]]*\})\][^}]*}).*/\1/p")" _record_array="$(echo "$response" | sed -En "s/.*(\{\"id\"[^}]*${fulldomain}[^}]*records[^}]*\[(\{[^]]*\})\][^}]*}).*/\2/p")" # record id _record_id="$(echo "$_record_seg" | tr "," "\n" | tr "}" "\n" | tr -d " " | grep "\"id\"" | cut -d : -f 2 | tr -d "\"")" - # готовим _data + # preparing _data _tmp_str="${_record_array},{\"content\":\"${_text_tmp}\"}" _data="{\"ttl\": 60, \"records\": [${_tmp_str}]}" _debug3 _record_seg "$_record_seg" @@ -172,11 +172,11 @@ dns_selectel_rm() { return 1 fi # record id - # следующие строки меняют алгоритм удаления записей со значением $txtvalue - # если использовать 1-ю строку, то за раз удаляются все такие записи - # если использовать 2-ю строку, то удаляется только первая запись из них - #_record_id="$(echo "$_record_seg" | tr "," "\n" | tr "}" "\n" | tr -d " " | grep "\"id\"" | cut -d : -f 2 | tr -d "\"")" # удалять все записи со значением $txtvalue - _record_id="$(echo "$_record_seg" | tr "," "\n" | tr "}" "\n" | tr -d " " | grep "\"id\"" | cut -d : -f 2 | tr -d "\"" | sed '1!d')" # удалять только первую запись со значением $txtvalue + # the following lines change the algorithm for deleting records with the value $txtvalue + # if you use the 1st line, then all such records are deleted at once + # if you use the 2nd line, then only the first entry from them is deleted + #_record_id="$(echo "$_record_seg" | tr "," "\n" | tr "}" "\n" | tr -d " " | grep "\"id\"" | cut -d : -f 2 | tr -d "\"")" + _record_id="$(echo "$_record_seg" | tr "," "\n" | tr "}" "\n" | tr -d " " | grep "\"id\"" | cut -d : -f 2 | tr -d "\"" | sed '1!d')" if [ -z "$_record_id" ]; then _err "can not find _record_id" return 1 @@ -190,17 +190,17 @@ dns_selectel_rm() { _del_uri="${_ext_uri}${_record_id}" _debug _del_uri "$_del_uri" if [ -z "$_new_arr" ]; then - # удалить запись + # remove record if ! _sl_rest DELETE "${_del_uri}"; then _err "Delete record error: ${_del_uri}." else info "Delete record success: ${_del_uri}." fi else - # обновить запись, удалив content + # update a record by removing one element in content _data="{\"ttl\": 60, \"records\": [${_new_arr}]}" _debug3 _data "$_data" - # вызов REST API PATCH + # REST API PATCH call if _sl_rest PATCH "${_del_uri}" "$_data"; then _info "Patched, OK: ${_del_uri}" else From 2beb2f5659e968423f91c8db2d634d85177fff2a Mon Sep 17 00:00:00 2001 From: Manuel Sanchez Pinar Date: Thu, 4 Jul 2024 14:03:20 +0200 Subject: [PATCH 014/198] 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 ad3127598d..c27fbc5f82 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 51151293d7556dde713c197d0fdc83b97cbbe642 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BB=D0=B0=D0=B4=D0=B8=D0=BC=D0=B8=D1=80=20=D0=90?= =?UTF-8?q?=D0=BB=D0=B5=D0=BA=D1=81=D0=B5=D0=B5=D0=B2?= <73811032+vlad-kms@users.noreply.github.com> Date: Sat, 6 Jul 2024 21:01:25 +1000 Subject: [PATCH 015/198] Remove `date -d` on macOS --- dnsapi/dns_selectel.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_selectel.sh b/dnsapi/dns_selectel.sh index c8aa2db7d8..511ab7f546 100644 --- a/dnsapi/dns_selectel.sh +++ b/dnsapi/dns_selectel.sh @@ -356,7 +356,7 @@ _get_auth_token() { _debug3 _login_name "$_login_name" _debug3 _login_id "$_login_id" _debug3 _project_name "$_project_name" - _debug3 _receipt_time "$(date -d @"$_receipt_time" -u)" + # _debug3 _receipt_time "$(date -d @"$_receipt_time" -u)" # check the validity of the token for the user and the project and its lifetime _dt_diff_minute=$((($(date +%s) - _receipt_time) / 60)) _debug3 _dt_diff_minute "$_dt_diff_minute" From 5214a7c3ec32cdffc3ff3497c163bf235bd7eaed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markku=20Leini=C3=B6?= <25136274+markkuleinio@users.noreply.github.com> Date: Sun, 4 Aug 2024 18:19:21 +0300 Subject: [PATCH 016/198] Add dnsapi script for HE DDNS --- dnsapi/dns_he_ddns.sh | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 dnsapi/dns_he_ddns.sh diff --git a/dnsapi/dns_he_ddns.sh b/dnsapi/dns_he_ddns.sh new file mode 100644 index 0000000000..7338ab1804 --- /dev/null +++ b/dnsapi/dns_he_ddns.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env sh +dns_he_ddns_info='Hurricane Electric HE.net DDNS +Site: dns.he.net +Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_he_ddns +Options: + HE_DDNS_KEY The DDNS key for updating the TXT record +Author: Markku Leiniö +' + +HE_DDNS_URL="https://dyn.dns.he.net/nic/update" + +######## Public functions ##################### + +#Usage: dns_he_ddns_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_he_ddns_add() { + fulldomain=$1 + txtvalue=$2 + HE_DDNS_KEY="${HE_DDNS_KEY:-$(_readaccountconf_mutable HE_DDNS_KEY)}" + if [ -z "$HE_DDNS_KEY" ]; then + HE_DDNS_KEY="" + _err "You didn't specify a DDNS key for accessing the TXT record in HE API." + return 1 + fi + #Save the DDNS key to the account conf file. + _saveaccountconf_mutable HE_DDNS_KEY "$HE_DDNS_KEY" + + _info "Using Hurricane Electric DDNS API" + _debug fulldomain "$fulldomain" + _debug txtvalue "$txtvalue" + + response="$(_post "hostname=$fulldomain&password=$HE_DDNS_KEY&txt=$txtvalue" "$HE_DDNS_URL")" + _info "Response: $response" + _contains "$response" "good" && return 0 || return 1 +} + +#Usage: fulldomain txtvalue +#Remove the txt record after validation. +dns_he_ddns_rm() { + fulldomain=$1 + txtvalue=$2 + _debug fulldomain "$fulldomain" + _debug txtvalue "$txtvalue" +} From c96fcf319a8667115baaad335f8820b1fba93735 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markku=20Leini=C3=B6?= <25136274+markkuleinio@users.noreply.github.com> Date: Sun, 4 Aug 2024 18:25:20 +0300 Subject: [PATCH 017/198] Remove dns_he_ddns_rm(), not used --- dnsapi/dns_he_ddns.sh | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/dnsapi/dns_he_ddns.sh b/dnsapi/dns_he_ddns.sh index 7338ab1804..44e6783e4d 100644 --- a/dnsapi/dns_he_ddns.sh +++ b/dnsapi/dns_he_ddns.sh @@ -33,11 +33,5 @@ dns_he_ddns_add() { _contains "$response" "good" && return 0 || return 1 } -#Usage: fulldomain txtvalue -#Remove the txt record after validation. -dns_he_ddns_rm() { - fulldomain=$1 - txtvalue=$2 - _debug fulldomain "$fulldomain" - _debug txtvalue "$txtvalue" -} +# dns_he_ddns_rm() is not implemented because the API call always updates the +# contents of the existing record (that the API key gives access to). From abc76299c0c74faa265933f532c8d1ec59a27b77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markku=20Leini=C3=B6?= <25136274+markkuleinio@users.noreply.github.com> Date: Sun, 4 Aug 2024 18:58:59 +0300 Subject: [PATCH 018/198] Fix documentation link --- dnsapi/dns_he_ddns.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_he_ddns.sh b/dnsapi/dns_he_ddns.sh index 44e6783e4d..95ec290b1c 100644 --- a/dnsapi/dns_he_ddns.sh +++ b/dnsapi/dns_he_ddns.sh @@ -1,7 +1,7 @@ #!/usr/bin/env sh dns_he_ddns_info='Hurricane Electric HE.net DDNS Site: dns.he.net -Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_he_ddns +Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_he_ddns Options: HE_DDNS_KEY The DDNS key for updating the TXT record Author: Markku Leiniö From 833632eee3d8aa9b562297cf6a8c13fee9d81b09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markku=20Leini=C3=B6?= <25136274+markkuleinio@users.noreply.github.com> Date: Sun, 4 Aug 2024 19:15:11 +0300 Subject: [PATCH 019/198] Add shellcheck disable=SC2034 for the info variable --- dnsapi/dns_he_ddns.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/dnsapi/dns_he_ddns.sh b/dnsapi/dns_he_ddns.sh index 95ec290b1c..0893f93850 100644 --- a/dnsapi/dns_he_ddns.sh +++ b/dnsapi/dns_he_ddns.sh @@ -1,4 +1,5 @@ #!/usr/bin/env sh +# shellcheck disable=SC2034 dns_he_ddns_info='Hurricane Electric HE.net DDNS Site: dns.he.net Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_he_ddns From 413a91646c03b0cd4ab6dace1bdabe78d702a710 Mon Sep 17 00:00:00 2001 From: Attackwave <51136146+Attackwave@users.noreply.github.com> Date: Sat, 16 Nov 2024 19:15:39 +0100 Subject: [PATCH 020/198] Create truenas_ws.sh --- deploy/truenas_ws.sh | 317 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 317 insertions(+) create mode 100644 deploy/truenas_ws.sh diff --git a/deploy/truenas_ws.sh b/deploy/truenas_ws.sh new file mode 100644 index 0000000000..b5ba51ab7f --- /dev/null +++ b/deploy/truenas_ws.sh @@ -0,0 +1,317 @@ +#!/usr/bin/env bash + +# TrueNAS deploy script for SCALE/CORE using websocket +# It is recommend to use a wildcard certificate +# +# Websocket Documentation: https://www.truenas.com/docs/api/scale_websocket_api.html +# +# Tested with TrueNAS Scale - Electric Eel 24.10 +# Changes certificate in the following services: +# - Web UI +# - FTP +# - iX Apps +# +# The following environment variables must be set: +# ------------------------------------------------ +# +# # API KEY +# # Use the folowing URL to create a new API token: /ui/apikeys +# export DEPLOY_TRUENAS_APIKEY=" Date: Sun, 17 Nov 2024 20:58:06 +0100 Subject: [PATCH 021/198] Fix syntax for OpenBSD sh --- dnsapi/dns_netcup.sh | 6 +++--- notify/aws_ses.sh | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dnsapi/dns_netcup.sh b/dnsapi/dns_netcup.sh index 687b99bc52..8609adf6db 100644 --- a/dnsapi/dns_netcup.sh +++ b/dnsapi/dns_netcup.sh @@ -19,7 +19,7 @@ client="" dns_netcup_add() { _debug NC_Apikey "$NC_Apikey" - login + _login if [ "$NC_Apikey" = "" ] || [ "$NC_Apipw" = "" ] || [ "$NC_CID" = "" ]; then _err "No Credentials given" return 1 @@ -61,7 +61,7 @@ dns_netcup_add() { } dns_netcup_rm() { - login + _login fulldomain=$1 txtvalue=$2 @@ -125,7 +125,7 @@ dns_netcup_rm() { logout } -login() { +_login() { tmp=$(_post "{\"action\": \"login\", \"param\": {\"apikey\": \"$NC_Apikey\", \"apipassword\": \"$NC_Apipw\", \"customernumber\": \"$NC_CID\"}}" "$end" "" "POST") sid=$(echo "$tmp" | tr '{}' '\n' | grep apisessionid | cut -d '"' -f 4) _debug "$tmp" diff --git a/notify/aws_ses.sh b/notify/aws_ses.sh index 30db45adbe..07e0c48ccd 100644 --- a/notify/aws_ses.sh +++ b/notify/aws_ses.sh @@ -89,7 +89,7 @@ _use_metadata() { _normalizeJson | tr '{,}' '\n' | while read -r _line; do - _key="$(echo "${_line%%:*}" | tr -d '"')" + _key="$(echo "${_line%%:*}" | tr -d \")" _value="${_line#*:}" _debug3 "_key" "$_key" _secure_debug3 "_value" "$_value" From d7855e8fe58d7fcbd01cbd195e23f315bb5086e4 Mon Sep 17 00:00:00 2001 From: Attackwave <51136146+Attackwave@users.noreply.github.com> Date: Sun, 24 Nov 2024 14:59:51 +0100 Subject: [PATCH 022/198] Update truenas_ws.sh (shfmt and shellcheck) --- deploy/truenas_ws.sh | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/deploy/truenas_ws.sh b/deploy/truenas_ws.sh index b5ba51ab7f..4b3a5c727e 100644 --- a/deploy/truenas_ws.sh +++ b/deploy/truenas_ws.sh @@ -51,7 +51,7 @@ _ws_call() { _ws_response=$(midclt -K "$DEPLOY_TRUENAS_APIKEY" call "$1") fi _debug "_ws_response" "$_ws_response" - printf "%s" $_ws_response + printf "%s" "$_ws_response" return 0 } @@ -99,7 +99,7 @@ _ws_get_job_result() { then _ws_result="$(printf "%s" "$_ws_response" | jq '.[]."result"')" _debug "_ws_result" "$_ws_result" - printf "%s" $_ws_result + printf "%s" "$_ws_result" _ws_error="$(printf "%s" "$_ws_response" | jq '.[]."error"')" if [ "$_ws_error" != "null" ] then @@ -175,7 +175,7 @@ truenas_ws_deploy() { then _err "Error calling system.ready:" _err "$_ws_response" - exit $_ws_re + exit $_ws_ret fi if [ "$_ws_response" != "TRUE" ] @@ -196,7 +196,7 @@ truenas_ws_deploy() { _truenas_version=$(printf "%s" "$_ws_response" | jq -r '."version"' | cut -d '-' -f 3) _info "TrueNAS system: $_truenas_system" _info "TrueNAS version: $_truenas_version" - if [ "$_truenas_system" != "SCALE" ] && ["$_truenas_system" != "CORE" ] + if [ "$_truenas_system" != "SCALE" ] && [ "$_truenas_system" != "CORE" ] then _err "Cannot gather TrueNAS system. Nor CORE oder SCALE detected." exit 10 @@ -210,7 +210,6 @@ truenas_ws_deploy() { _ui_certificate_name=$(printf "%s" "$_ws_response" | jq -r '."ui_certificate"."name"') _info "Current WebUI certificate ID: $_ui_certificate_id" _info "Current WebUI certificate name: $_ui_certificate_name" - _info "WebUI redirect to https: $_ui_http_redirect" ########## Upload new certificate @@ -225,9 +224,10 @@ truenas_ws_deploy() { exit 3 fi _ws_result=$(_ws_get_job_result "$_ws_jobid") - if [ $? -gt 0 ] + _ws_ret=$? + if [ $_ws_ret -gt 0 ] then - exit $? + exit $_ws_ret fi _debug "_ws_result" "$_ws_result" _new_certid=$(printf "%s" "$_ws_result" | jq -r '."id"') @@ -251,11 +251,11 @@ truenas_ws_deploy() { then _info "Replace app certificates..." _ws_response=$(_ws_call "app.query") - for _app_name in $(printf "%s" $_ws_response | jq -r '.[]."name"') + for _app_name in $(printf "%s" "$_ws_response" | jq -r '.[]."name"') do _info "Checking app $_app_name..." _ws_response=$(_ws_call "app.config" "$_app_name") - if [ "$(printf "%s" $_ws_response | jq -r '."network" | has("certificate_id")')" = "true" ] + if [ "$(printf "%s" "$_ws_response" | jq -r '."network" | has("certificate_id")')" = "true" ] then _info "App has certificate option, setup new certificate..." _info "App will be redeployed after updating the certificate." @@ -267,9 +267,10 @@ truenas_ws_deploy() { exit 3 fi _ws_result=$(_ws_get_job_result "$_ws_jobid") - if [ $? -gt 0 ] + _ws_ret=$? + if [ $_ws_ret -gt 0 ] then - exit $? + exit $_ws_ret fi _debug "_ws_result" "$_ws_result" _info "App certificate replaced." @@ -305,10 +306,11 @@ truenas_ws_deploy() { _err "No JobID returned from websocket method." exit 3 fi - _ws_result=$(_ws_get_job_result $_ws_jobid) - if [ $? -gt 0 ] + _ws_result=$(_ws_get_job_result "$_ws_jobid") + _ws_ret=$? + if [ $_ws_ret -gt 0 ] then - exit $? + exit $_ws_ret fi From f2a311bb8194cff518978545da619c439b2f1621 Mon Sep 17 00:00:00 2001 From: Attackwave <51136146+Attackwave@users.noreply.github.com> Date: Mon, 25 Nov 2024 14:44:52 +0100 Subject: [PATCH 023/198] Update truenas_ws.sh (added return instead exit) --- deploy/truenas_ws.sh | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/deploy/truenas_ws.sh b/deploy/truenas_ws.sh index 4b3a5c727e..952cfc42b5 100644 --- a/deploy/truenas_ws.sh +++ b/deploy/truenas_ws.sh @@ -161,7 +161,7 @@ truenas_ws_deploy() { if [ -z "$DEPLOY_TRUENAS_APIKEY" ] then _err "TrueNAS API key not found, please set the DEPLOY_TRUENAS_APIKEY environment variable." - exit 1 + return 1 fi _secure_debug2 DEPLOY_TRUENAS_APIKEY "$DEPLOY_TRUENAS_APIKEY" _info "Environment variables: OK" @@ -175,7 +175,7 @@ truenas_ws_deploy() { then _err "Error calling system.ready:" _err "$_ws_response" - exit $_ws_ret + return $_ws_ret fi if [ "$_ws_response" != "TRUE" ] @@ -183,7 +183,7 @@ truenas_ws_deploy() { _err "TrueNAS is not ready." _err "Please check environment variables DEPLOY_TRUENAS_APIKEY, DEPLOY_TRUENAS_HOSTNAME and DEPLOY_TRUENAS_PROTOCOL." _err "Verify API key." - exit 2 + return 2 fi _savedeployconf DEPLOY_TRUENAS_APIKEY "$DEPLOY_TRUENAS_APIKEY" _info "TrueNAS health: OK" @@ -199,7 +199,7 @@ truenas_ws_deploy() { if [ "$_truenas_system" != "SCALE" ] && [ "$_truenas_system" != "CORE" ] then _err "Cannot gather TrueNAS system. Nor CORE oder SCALE detected." - exit 10 + return 10 fi ########## Gather current certificate @@ -221,13 +221,13 @@ truenas_ws_deploy() { if ! _ws_check_jobid "$_ws_jobid" then _err "No JobID returned from websocket method." - exit 3 + return 3 fi _ws_result=$(_ws_get_job_result "$_ws_jobid") _ws_ret=$? if [ $_ws_ret -gt 0 ] then - exit $_ws_ret + return $_ws_ret fi _debug "_ws_result" "$_ws_result" _new_certid=$(printf "%s" "$_ws_result" | jq -r '."id"') @@ -242,7 +242,7 @@ truenas_ws_deploy() { then _err "Cannot set FTP certificate." _debug "_ws_response" "$_ws_response" - exit 4 + return 4 fi ########## ix Apps (SCALE only) @@ -264,13 +264,13 @@ truenas_ws_deploy() { if ! _ws_check_jobid "$_ws_jobid" then _err "No JobID returned from websocket method." - exit 3 + return 3 fi _ws_result=$(_ws_get_job_result "$_ws_jobid") _ws_ret=$? if [ $_ws_ret -gt 0 ] then - exit $_ws_ret + return $_ws_ret fi _debug "_ws_result" "$_ws_result" _info "App certificate replaced." @@ -288,7 +288,7 @@ truenas_ws_deploy() { if [ "$_changed_certid" != "$_new_certid" ] then _err "WebUI certificate change error.." - exit 5 + return 5 else _info "WebUI certificate replaced." fi @@ -304,13 +304,13 @@ truenas_ws_deploy() { if ! _ws_check_jobid "$_ws_jobid" then _err "No JobID returned from websocket method." - exit 3 + return 3 fi _ws_result=$(_ws_get_job_result "$_ws_jobid") _ws_ret=$? if [ $_ws_ret -gt 0 ] then - exit $_ws_ret + return $_ws_ret fi From 91103751736161e43e1806bc485e591661f4591a Mon Sep 17 00:00:00 2001 From: Attackwave <51136146+Attackwave@users.noreply.github.com> Date: Mon, 25 Nov 2024 20:50:40 +0100 Subject: [PATCH 024/198] Update truenas_ws.sh (fixed shfmt) --- deploy/truenas_ws.sh | 98 ++++++++++++++++---------------------------- 1 file changed, 36 insertions(+), 62 deletions(-) diff --git a/deploy/truenas_ws.sh b/deploy/truenas_ws.sh index 952cfc42b5..3ee983a3cc 100644 --- a/deploy/truenas_ws.sh +++ b/deploy/truenas_ws.sh @@ -38,16 +38,13 @@ _ws_call() { _debug "_ws_call arg1" "$1" _debug "_ws_call arg2" "$2" _debug "_ws_call arg3" "$3" - if [ $# -eq 3 ] - then + if [ $# -eq 3 ]; then _ws_response=$(midclt -K "$DEPLOY_TRUENAS_APIKEY" call "$1" "$2" "$3") fi - if [ $# -eq 2 ] - then + if [ $# -eq 2 ]; then _ws_response=$(midclt -K "$DEPLOY_TRUENAS_APIKEY" call "$1" "$2") fi - if [ $# -eq 1 ] - then + if [ $# -eq 1 ]; then _ws_response=$(midclt -K "$DEPLOY_TRUENAS_APIKEY" call "$1") fi _debug "_ws_response" "$_ws_response" @@ -69,14 +66,13 @@ _ws_call() { # 1: false _ws_check_jobid() { case "$1" in - [0-9]*) - return 0 - ;; + [0-9]*) + return 0 + ;; esac return 1 } - # Wait for job to finish and return result as JSON # Usage: # _ws_result=$(_ws_get_job_result "$_ws_jobid") @@ -91,18 +87,15 @@ _ws_check_jobid() { # Returns: # n/a _ws_get_job_result() { - while true - do + while true; do sleep 2 _ws_response=$(_ws_call "core.get_jobs" "[[\"id\", \"=\", $1]]") - if [ "$(printf "%s" "$_ws_response" | jq -r '.[]."state"')" != "RUNNING" ] - then + if [ "$(printf "%s" "$_ws_response" | jq -r '.[]."state"')" != "RUNNING" ]; then _ws_result="$(printf "%s" "$_ws_response" | jq '.[]."result"')" _debug "_ws_result" "$_ws_result" printf "%s" "$_ws_result" _ws_error="$(printf "%s" "$_ws_response" | jq '.[]."error"')" - if [ "$_ws_error" != "null" ] - then + if [ "$_ws_error" != "null" ]; then _err "Job $1 failed:" _err "$_ws_error" return 7 @@ -113,9 +106,6 @@ _ws_get_job_result() { return 0 } - - - ######################## ### Public functions ### ######################## @@ -153,33 +143,30 @@ truenas_ws_deploy() { _debug _file_ca "$_file_ca" _debug _file_fullchain "$_file_fullchain" -########## Environment check + ########## Environment check _info "Checking environment variables..." _getdeployconf DEPLOY_TRUENAS_APIKEY # Check API Key - if [ -z "$DEPLOY_TRUENAS_APIKEY" ] - then + if [ -z "$DEPLOY_TRUENAS_APIKEY" ]; then _err "TrueNAS API key not found, please set the DEPLOY_TRUENAS_APIKEY environment variable." return 1 fi _secure_debug2 DEPLOY_TRUENAS_APIKEY "$DEPLOY_TRUENAS_APIKEY" _info "Environment variables: OK" -########## Health check + ########## Health check _info "Checking TrueNAS health..." _ws_response=$(_ws_call "system.ready" | tr '[:lower:]' '[:upper:]') _ws_ret=$? - if [ $_ws_ret -gt 0 ] - then + if [ $_ws_ret -gt 0 ]; then _err "Error calling system.ready:" _err "$_ws_response" return $_ws_ret fi - if [ "$_ws_response" != "TRUE" ] - then + if [ "$_ws_response" != "TRUE" ]; then _err "TrueNAS is not ready." _err "Please check environment variables DEPLOY_TRUENAS_APIKEY, DEPLOY_TRUENAS_HOSTNAME and DEPLOY_TRUENAS_PROTOCOL." _err "Verify API key." @@ -188,7 +175,7 @@ truenas_ws_deploy() { _savedeployconf DEPLOY_TRUENAS_APIKEY "$DEPLOY_TRUENAS_APIKEY" _info "TrueNAS health: OK" -########## System info + ########## System info _info "Gather system info..." _ws_response=$(_ws_call "system.info") @@ -196,82 +183,73 @@ truenas_ws_deploy() { _truenas_version=$(printf "%s" "$_ws_response" | jq -r '."version"' | cut -d '-' -f 3) _info "TrueNAS system: $_truenas_system" _info "TrueNAS version: $_truenas_version" - if [ "$_truenas_system" != "SCALE" ] && [ "$_truenas_system" != "CORE" ] - then + if [ "$_truenas_system" != "SCALE" ] && [ "$_truenas_system" != "CORE" ]; then _err "Cannot gather TrueNAS system. Nor CORE oder SCALE detected." return 10 fi -########## Gather current certificate + ########## Gather current certificate _info "Gather current WebUI certificate..." _ws_response="$(_ws_call "system.general.config")" _ui_certificate_id=$(printf "%s" "$_ws_response" | jq -r '."ui_certificate"."id"') - _ui_certificate_name=$(printf "%s" "$_ws_response" | jq -r '."ui_certificate"."name"') + _ui_certificate_name=$(printf "%s" "$_ws_response" | jq -r '."ui_certificate"."name"') _info "Current WebUI certificate ID: $_ui_certificate_id" _info "Current WebUI certificate name: $_ui_certificate_name" -########## Upload new certificate + ########## Upload new certificate _info "Upload new certificate..." _certname="acme_$(_utc_date | tr -d '\-\:' | tr ' ' '_')" _debug _certname "$_certname" _ws_jobid=$(_ws_call "certificate.create" "{\"name\": \"${_certname}\", \"create_type\": \"CERTIFICATE_CREATE_IMPORTED\", \"certificate\": \"$(_json_encode <"$_file_fullchain")\", \"privatekey\": \"$(_json_encode <"$_file_key")\", \"passphrase\": \"\"}") _debug "_ws_jobid" "$_ws_jobid" - if ! _ws_check_jobid "$_ws_jobid" - then + if ! _ws_check_jobid "$_ws_jobid"; then _err "No JobID returned from websocket method." return 3 fi _ws_result=$(_ws_get_job_result "$_ws_jobid") _ws_ret=$? - if [ $_ws_ret -gt 0 ] - then + if [ $_ws_ret -gt 0 ]; then return $_ws_ret fi _debug "_ws_result" "$_ws_result" _new_certid=$(printf "%s" "$_ws_result" | jq -r '."id"') _info "New certificate ID: $_new_certid" -########## FTP + ########## FTP _info "Replace FTP certificate..." _ws_response=$(_ws_call "ftp.update" "{\"ssltls_certificate\": $_new_certid}") _ftp_certid=$(printf "%s" "$_ws_response" | jq -r '."ssltls_certificate"') - if [ "$_ftp_certid" != "$_new_certid" ] - then + if [ "$_ftp_certid" != "$_new_certid" ]; then _err "Cannot set FTP certificate." _debug "_ws_response" "$_ws_response" return 4 fi -########## ix Apps (SCALE only) + ########## ix Apps (SCALE only) - if [ "$_truenas_system" = "SCALE" ] - then + if [ "$_truenas_system" = "SCALE" ]; then _info "Replace app certificates..." _ws_response=$(_ws_call "app.query") - for _app_name in $(printf "%s" "$_ws_response" | jq -r '.[]."name"') - do + for _app_name in $(printf "%s" "$_ws_response" | jq -r '.[]."name"'); do _info "Checking app $_app_name..." _ws_response=$(_ws_call "app.config" "$_app_name") - if [ "$(printf "%s" "$_ws_response" | jq -r '."network" | has("certificate_id")')" = "true" ] - then + if [ "$(printf "%s" "$_ws_response" | jq -r '."network" | has("certificate_id")')" = "true" ]; then _info "App has certificate option, setup new certificate..." _info "App will be redeployed after updating the certificate." _ws_jobid=$(_ws_call "app.update" "$_app_name" "{\"values\": {\"network\": {\"certificate_id\": $_new_certid}}}") _debug "_ws_jobid" "$_ws_jobid" - if ! _ws_check_jobid "$_ws_jobid" - then + if ! _ws_check_jobid "$_ws_jobid"; then _err "No JobID returned from websocket method." return 3 fi _ws_result=$(_ws_get_job_result "$_ws_jobid") _ws_ret=$? - if [ $_ws_ret -gt 0 ] - then - return $_ws_ret - fi + if [ $_ws_ret -gt 0 ]; then + return $_ws_ret + fi _debug "_ws_result" "$_ws_result" _info "App certificate replaced." else @@ -280,13 +258,12 @@ truenas_ws_deploy() { done fi -########## WebUI + ########## WebUI _info "Replace WebUI certificate..." _ws_response=$(_ws_call "system.general.update" "{\"ui_certificate\": $_new_certid}") _changed_certid=$(printf "%s" "$_ws_response" | jq -r '."ui_certificate"."id"') - if [ "$_changed_certid" != "$_new_certid" ] - then + if [ "$_changed_certid" != "$_new_certid" ]; then _err "WebUI certificate change error.." return 5 else @@ -297,23 +274,20 @@ truenas_ws_deploy() { _info "Waiting for UI restart..." sleep 6 -########## Certificates + ########## Certificates _info "Deleting old certificate..." _ws_jobid=$(_ws_call "certificate.delete" "$_ui_certificate_id") - if ! _ws_check_jobid "$_ws_jobid" - then + if ! _ws_check_jobid "$_ws_jobid"; then _err "No JobID returned from websocket method." return 3 fi _ws_result=$(_ws_get_job_result "$_ws_jobid") _ws_ret=$? - if [ $_ws_ret -gt 0 ] - then + if [ $_ws_ret -gt 0 ]; then return $_ws_ret fi - _info "Have a nice day...bye!" } From 44240339d9856568d418d41f89556495cb651be2 Mon Sep 17 00:00:00 2001 From: Attackwave <51136146+Attackwave@users.noreply.github.com> Date: Mon, 25 Nov 2024 21:13:43 +0100 Subject: [PATCH 025/198] Update truenas_ws.sh (Interpreter changed from bash to sh) --- deploy/truenas_ws.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/truenas_ws.sh b/deploy/truenas_ws.sh index 3ee983a3cc..7292987bec 100644 --- a/deploy/truenas_ws.sh +++ b/deploy/truenas_ws.sh @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/usr/bin/env sh # TrueNAS deploy script for SCALE/CORE using websocket # It is recommend to use a wildcard certificate From ebaf4c9c01bd590003bc91dec4ca05e88c091cb7 Mon Sep 17 00:00:00 2001 From: Attackwave <51136146+Attackwave@users.noreply.github.com> Date: Mon, 25 Nov 2024 21:23:59 +0100 Subject: [PATCH 026/198] Update truenas_ws.sh (Output new certificate name) --- deploy/truenas_ws.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/deploy/truenas_ws.sh b/deploy/truenas_ws.sh index 7292987bec..940cde2e20 100644 --- a/deploy/truenas_ws.sh +++ b/deploy/truenas_ws.sh @@ -201,6 +201,7 @@ truenas_ws_deploy() { _info "Upload new certificate..." _certname="acme_$(_utc_date | tr -d '\-\:' | tr ' ' '_')" + _info "New WebUI certificate name: $_certname" _debug _certname "$_certname" _ws_jobid=$(_ws_call "certificate.create" "{\"name\": \"${_certname}\", \"create_type\": \"CERTIFICATE_CREATE_IMPORTED\", \"certificate\": \"$(_json_encode <"$_file_fullchain")\", \"privatekey\": \"$(_json_encode <"$_file_key")\", \"passphrase\": \"\"}") _debug "_ws_jobid" "$_ws_jobid" From f3b2ab5e604f49cf437e293f921812cdb46adc07 Mon Sep 17 00:00:00 2001 From: 3VAbdAVE Date: Sat, 30 Nov 2024 10:32:24 -0500 Subject: [PATCH 027/198] Fix gen1 cloudkey's symlinked keystore --- deploy/unifi.sh | 73 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 49 insertions(+), 24 deletions(-) diff --git a/deploy/unifi.sh b/deploy/unifi.sh index 4d8c058e44..706b24e8bc 100644 --- a/deploy/unifi.sh +++ b/deploy/unifi.sh @@ -30,7 +30,9 @@ # Keystore password (built into Unifi Controller, not a user-set password): #DEPLOY_UNIFI_KEYPASS="aircontrolenterprise" # Command to restart Unifi Controller: -#DEPLOY_UNIFI_RELOAD="service unifi restart" +# DEPLOY_UNIFI_RELOAD="systemctl restart unifi" +# System Properties file location for controller +#DEPLOY_UNIFI_SYSTEM_PROPERTIES="/usr/lib/unifi/data/system.properties" # # Settings for Unifi Cloud Key Gen1 (nginx admin pages): # Directory where cloudkey.crt and cloudkey.key live: @@ -43,7 +45,7 @@ # Directory where unifi-core.crt and unifi-core.key live: #DEPLOY_UNIFI_CORE_CONFIG="/data/unifi-core/config/" # Command to restart unifi-core: -#DEPLOY_UNIFI_RELOAD="systemctl restart unifi-core" +# DEPLOY_UNIFI_OS_RELOAD="systemctl restart unifi-core" # # At least one of DEPLOY_UNIFI_KEYSTORE, DEPLOY_UNIFI_CLOUDKEY_CERTDIR, # or DEPLOY_UNIFI_CORE_CONFIG must exist to receive the deployed certs. @@ -69,12 +71,16 @@ unifi_deploy() { _getdeployconf DEPLOY_UNIFI_CLOUDKEY_CERTDIR _getdeployconf DEPLOY_UNIFI_CORE_CONFIG _getdeployconf DEPLOY_UNIFI_RELOAD + _getdeployconf DEPLOY_UNIFI_SYSTEM_PROPERTIES + _getdeployconf DEPLOY_UNIFI_OS_RELOAD _debug2 DEPLOY_UNIFI_KEYSTORE "$DEPLOY_UNIFI_KEYSTORE" _debug2 DEPLOY_UNIFI_KEYPASS "$DEPLOY_UNIFI_KEYPASS" _debug2 DEPLOY_UNIFI_CLOUDKEY_CERTDIR "$DEPLOY_UNIFI_CLOUDKEY_CERTDIR" _debug2 DEPLOY_UNIFI_CORE_CONFIG "$DEPLOY_UNIFI_CORE_CONFIG" _debug2 DEPLOY_UNIFI_RELOAD "$DEPLOY_UNIFI_RELOAD" + _debug2 DEPLOY_UNIFI_OS_RELOAD "$DEPLOY_UNIFI_OS_RELOAD" + _debug2 DEPLOY_UNIFI_SYSTEM_PROPERTIES "$DEPLOY_UNIFI_SYSTEM_PROPERTIES" # Space-separated list of environments detected and installed: _services_updated="" @@ -136,32 +142,38 @@ unifi_deploy() { fi # Update unifi service for certificate cipher compatibility + _unifi_system_properties="${DEPLOY_UNIFI_SYSTEM_PROPERTIES:-/usr/lib/unifi/data/system.properties}" if ${ACME_OPENSSL_BIN:-openssl} pkcs12 \ -in "$_import_pkcs12" \ -password pass:aircontrolenterprise \ -nokeys | ${ACME_OPENSSL_BIN:-openssl} x509 -text \ -noout | grep -i "signature" | grep -iq ecdsa >/dev/null 2>&1; then - cp -f /usr/lib/unifi/data/system.properties /usr/lib/unifi/data/system.properties_original + cp -f "${_unifi_system_properties}" "${_unifi_system_properties}_original" _info "Updating system configuration for cipher compatibility." - _info "Saved original system config to /usr/lib/unifi/data/system.properties_original" - sed -i '/unifi\.https\.ciphers/d' /usr/lib/unifi/data/system.properties - echo "unifi.https.ciphers=ECDHE-ECDSA-AES256-GCM-SHA384,ECDHE-RSA-AES128-GCM-SHA256" >>/usr/lib/unifi/data/system.properties - sed -i '/unifi\.https\.sslEnabledProtocols/d' /usr/lib/unifi/data/system.properties - echo "unifi.https.sslEnabledProtocols=TLSv1.3,TLSv1.2" >>/usr/lib/unifi/data/system.properties + _info "Saved original system config to ${_unifi_system_properties}_original" + sed -i '/unifi\.https\.ciphers/d' "${_unifi_system_properties}" + echo "unifi.https.ciphers=ECDHE-ECDSA-AES256-GCM-SHA384,ECDHE-RSA-AES128-GCM-SHA256" >>"${_unifi_system_properties}" + sed -i '/unifi\.https\.sslEnabledProtocols/d' "${_unifi_system_properties}" + echo "unifi.https.sslEnabledProtocols=TLSv1.3,TLSv1.2" >>"${_unifi_system_properties}" _info "System configuration updated." + else + _info "New certificate does not require ecdsa ciphers, not updating system properties." fi rm "$_import_pkcs12" # Restarting unifi-core will bring up unifi, doing it out of order results in # a certificate error, and breaks wifiman. - # Restart if we aren't doing unifi-core, otherwise stop for later restart. - if systemctl -q is-active unifi; then - if [ ! -f "${DEPLOY_UNIFI_CORE_CONFIG:-/data/unifi-core/config}/unifi-core.key" ]; then - _reload_cmd="${_reload_cmd:+$_reload_cmd && }systemctl restart unifi" - else - _reload_cmd="${_reload_cmd:+$_reload_cmd && }systemctl stop unifi" - fi + # Restart if we aren't doing Unifi OS (e.g. unifi-core service), otherwise stop for later restart. + _unifi_reload="${DEPLOY_UNIFI_RELOAD:-systemctl restart unifi}" + if [ ! -f "${DEPLOY_UNIFI_CORE_CONFIG:-/data/unifi-core/config}/unifi-core.key" ]; then + _reload_cmd="${_reload_cmd:+$_reload_cmd && }$_unifi_reload" + else + _info "Stopping Unifi Controller for later restart." + _unifi_stop=$(echo "${_unifi_reload}" | sed -e 's/restart/stop/') + $_unifi_stop + _reload_cmd="${_reload_cmd:+$_reload_cmd && }$_unifi_reload" + _info "Unifi Controller stopped." fi _services_updated="${_services_updated} unifi" _info "Install Unifi Controller certificate success!" @@ -181,13 +193,24 @@ unifi_deploy() { return 1 fi # Cloud Key expects to load the keystore from /etc/ssl/private/unifi.keystore.jks. - # Normally /usr/lib/unifi/data/keystore is a symlink there (so the keystore was - # updated above), but if not, we don't know how to handle this installation: - if ! cmp -s "$_unifi_keystore" "${_cloudkey_certdir}/unifi.keystore.jks"; then - _err "Unsupported Cloud Key configuration: keystore not found at '${_cloudkey_certdir}/unifi.keystore.jks'" - return 1 + # It appears that unifi won't start if this is a symlink, so we'll copy it instead. + + # if ! cmp -s "$_unifi_keystore" "${_cloudkey_certdir}/unifi.keystore.jks"; then + # _err "Unsupported Cloud Key configuration: keystore not found at '${_cloudkey_certdir}/unifi.keystore.jks'" + # return 1 + # fi + + _info "Updating ${_cloudkey_certdir}/unifi.keystore.jks" + if [ -e "${_cloudkey_certdir}/unifi.keystore.jks" ]; then + if [ -L "${_cloudkey_certdir}/unifi.keystore.jks" ]; then + rm -f "${_cloudkey_certdir}/unifi.keystore.jks" + else + mv "${_cloudkey_certdir}/unifi.keystore.jks" "${_cloudkey_certdir}/unifi.keystore.jks_original" + fi fi + cp "_unifi_keystore" "${_cloudkey_certdir}/unifi.keystore.jks" + cat "$_cfullchain" >"${_cloudkey_certdir}/cloudkey.crt" cat "$_ckey" >"${_cloudkey_certdir}/cloudkey.key" (cd "$_cloudkey_certdir" && tar -cf cert.tar cloudkey.crt cloudkey.key unifi.keystore.jks) @@ -215,14 +238,14 @@ unifi_deploy() { # Save the existing certs in case something goes wrong. cp -f "${_unifi_core_config}"/unifi-core.crt "${_unifi_core_config}"/unifi-core_original.crt cp -f "${_unifi_core_config}"/unifi-core.key "${_unifi_core_config}"/unifi-core_original.key - _info "Previous certificate and key saved to ${_unifi_core_config}/unifi-core_original.crt/key." + _info "Previous certificate and key saved to ${_unifi_core_config}/unifi-core_original.crt.key." cat "$_cfullchain" >"${_unifi_core_config}/unifi-core.crt" cat "$_ckey" >"${_unifi_core_config}/unifi-core.key" - if systemctl -q is-active unifi-core; then - _reload_cmd="${_reload_cmd:+$_reload_cmd && }systemctl restart unifi-core" - fi + _unifi_os_reload="${DEPLOY_UNIFI_OS_RELOAD:-systemctl restart unifi-core}" + _reload_cmd="${_reload_cmd:+$_reload_cmd && }$_unifi_os_reload" + _info "Install UnifiOS certificate success!" _services_updated="${_services_updated} unifi-core" elif [ "$DEPLOY_UNIFI_CORE_CONFIG" ]; then @@ -261,6 +284,8 @@ unifi_deploy() { _savedeployconf DEPLOY_UNIFI_CLOUDKEY_CERTDIR "$DEPLOY_UNIFI_CLOUDKEY_CERTDIR" _savedeployconf DEPLOY_UNIFI_CORE_CONFIG "$DEPLOY_UNIFI_CORE_CONFIG" _savedeployconf DEPLOY_UNIFI_RELOAD "$DEPLOY_UNIFI_RELOAD" + _savedeployconf DEPLOY_UNIFI_OS_RELOAD "$DEPLOY_UNIFI_OS_RELOAD" + _savedeployconf DEPLOY_UNIFI_SYSTEM_PROPERTIES "$DEPLOY_UNIFI_SYSTEM_PROPERTIES" return 0 } From 22dfedf6ae447404616102b14c01bdf9ddb70caf Mon Sep 17 00:00:00 2001 From: Kevin Locke Date: Mon, 13 Feb 2017 14:09:25 -0700 Subject: [PATCH 028/198] Avoid permissions errors for chown .well-known When acme.sh is run as a non-root user different from the owner of the webroot directory it is unable to change the owner of the files in .well-known to that user, causing permissions errors. Avoid this by making the files world-readable. These files should pose no disclosure risk since they are sent in cleartext during the HTTP Identifier Validation Challenge[1] and may already be exposed by directory enumeration, depending on server settings. AFAIK they should be safe to expose as world-readable in all cases. 1. https://ietf-wg-acme.github.io/acme/#rfc.section.7.2 Fixes Neilpang/acme.sh#32 Signed-off-by: Kevin Locke --- acme.sh | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/acme.sh b/acme.sh index 9842e3f17a..3e1c85bd48 100755 --- a/acme.sh +++ b/acme.sh @@ -5002,9 +5002,11 @@ $_authorizations_map" _debug "Writing token: $token to $wellknown_path/$token" - mkdir -p "$wellknown_path" - - if ! printf "%s" "$keyauthorization" >"$wellknown_path/$token"; then + # Ensure .well-known is visible to web server user/group + # https://github.com/Neilpang/acme.sh/pull/32 + if ! (umask ugo+rx && + mkdir -p "$wellknown_path" && + printf "%s" "$keyauthorization" >"$wellknown_path/$token"); then _err "$d: Cannot write token to file: $wellknown_path/$token" _clearupwebbroot "$_currentRoot" "$removelevel" "$token" _clearup From 03e9c612b9138a8174aaf8a3a9c81b7866fdbccf Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 20 Dec 2024 10:34:51 +0100 Subject: [PATCH 029/198] Correct file ownership according to keystore directory --- deploy/unifi.sh | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/deploy/unifi.sh b/deploy/unifi.sh index 4d8c058e44..9ee7114c31 100644 --- a/deploy/unifi.sh +++ b/deploy/unifi.sh @@ -135,6 +135,15 @@ unifi_deploy() { cp -f "$_import_pkcs12" "$_unifi_keystore" fi + # correct file ownership according to the directory, the keystore is placed in + _unifi_keystore_dir=$(dirname "${_unifi_keystore}") + _unifi_keystore_dir_owner=$(ls -ld "${_unifi_keystore_dir}" | awk '{print $3}') + _unifi_keystore_owner=$(ls -l "${_unifi_keystore}" | awk '{print $3}') + if ! [ "${_unifi_keystore_owner}" = "${_unifi_keystore_dir_owner}" ] ; then + _debug "Changing keystore owner to ${_unifi_keystore_dir_owner}" + chown $_unifi_keystore_dir_owner "${_unifi_keystore}" >/dev/null 2>&1 # fail quietly if we're not running as root + fi + # Update unifi service for certificate cipher compatibility if ${ACME_OPENSSL_BIN:-openssl} pkcs12 \ -in "$_import_pkcs12" \ From 0e1d90dd0c6eb8ce2c57a9e71ba79b41283b4b07 Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 20 Dec 2024 10:36:45 +0100 Subject: [PATCH 030/198] Properly guess system.properties location --- deploy/unifi.sh | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/deploy/unifi.sh b/deploy/unifi.sh index 9ee7114c31..9ae54f2baf 100644 --- a/deploy/unifi.sh +++ b/deploy/unifi.sh @@ -150,14 +150,21 @@ unifi_deploy() { -password pass:aircontrolenterprise \ -nokeys | ${ACME_OPENSSL_BIN:-openssl} x509 -text \ -noout | grep -i "signature" | grep -iq ecdsa >/dev/null 2>&1; then - cp -f /usr/lib/unifi/data/system.properties /usr/lib/unifi/data/system.properties_original - _info "Updating system configuration for cipher compatibility." - _info "Saved original system config to /usr/lib/unifi/data/system.properties_original" - sed -i '/unifi\.https\.ciphers/d' /usr/lib/unifi/data/system.properties - echo "unifi.https.ciphers=ECDHE-ECDSA-AES256-GCM-SHA384,ECDHE-RSA-AES128-GCM-SHA256" >>/usr/lib/unifi/data/system.properties - sed -i '/unifi\.https\.sslEnabledProtocols/d' /usr/lib/unifi/data/system.properties - echo "unifi.https.sslEnabledProtocols=TLSv1.3,TLSv1.2" >>/usr/lib/unifi/data/system.properties - _info "System configuration updated." + if [ -f "$(dirname ${DEPLOY_UNIFI_KEYSTORE})/system.properties" ] ; then + _unifi_system_properties="$(dirname ${DEPLOY_UNIFI_KEYSTORE})/system.properties" + else + _unifi_system_properties="/usr/lib/unifi/data/system.properties" + fi + if [ -f "${_unifi_system_properties}" ] ; then + cp -f "${_unifi_system_properties}" "${_unifi_system_properties}"_original + _info "Updating system configuration for cipher compatibility." + _info "Saved original system config to ${_unifi_system_properties}_original" + sed -i '/unifi\.https\.ciphers/d' "${_unifi_system_properties}" + echo "unifi.https.ciphers=ECDHE-ECDSA-AES256-GCM-SHA384,ECDHE-RSA-AES128-GCM-SHA256" >>"${_unifi_system_properties}" + sed -i '/unifi\.https\.sslEnabledProtocols/d' "${_unifi_system_properties}" + echo "unifi.https.sslEnabledProtocols=TLSv1.3,TLSv1.2" >>"${_unifi_system_properties}" + _info "System configuration updated." + fi fi rm "$_import_pkcs12" From d75077c6f905c30caf983e076cf66b640d260967 Mon Sep 17 00:00:00 2001 From: neil Date: Sun, 22 Dec 2024 13:36:43 +0100 Subject: [PATCH 031/198] fix format --- deploy/unifi.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/deploy/unifi.sh b/deploy/unifi.sh index 9ae54f2baf..237840991b 100644 --- a/deploy/unifi.sh +++ b/deploy/unifi.sh @@ -139,7 +139,7 @@ unifi_deploy() { _unifi_keystore_dir=$(dirname "${_unifi_keystore}") _unifi_keystore_dir_owner=$(ls -ld "${_unifi_keystore_dir}" | awk '{print $3}') _unifi_keystore_owner=$(ls -l "${_unifi_keystore}" | awk '{print $3}') - if ! [ "${_unifi_keystore_owner}" = "${_unifi_keystore_dir_owner}" ] ; then + if ! [ "${_unifi_keystore_owner}" = "${_unifi_keystore_dir_owner}" ]; then _debug "Changing keystore owner to ${_unifi_keystore_dir_owner}" chown $_unifi_keystore_dir_owner "${_unifi_keystore}" >/dev/null 2>&1 # fail quietly if we're not running as root fi @@ -150,12 +150,12 @@ unifi_deploy() { -password pass:aircontrolenterprise \ -nokeys | ${ACME_OPENSSL_BIN:-openssl} x509 -text \ -noout | grep -i "signature" | grep -iq ecdsa >/dev/null 2>&1; then - if [ -f "$(dirname ${DEPLOY_UNIFI_KEYSTORE})/system.properties" ] ; then + if [ -f "$(dirname ${DEPLOY_UNIFI_KEYSTORE})/system.properties" ]; then _unifi_system_properties="$(dirname ${DEPLOY_UNIFI_KEYSTORE})/system.properties" else _unifi_system_properties="/usr/lib/unifi/data/system.properties" fi - if [ -f "${_unifi_system_properties}" ] ; then + if [ -f "${_unifi_system_properties}" ]; then cp -f "${_unifi_system_properties}" "${_unifi_system_properties}"_original _info "Updating system configuration for cipher compatibility." _info "Saved original system config to ${_unifi_system_properties}_original" From a9f97e1fe2a914acb7bfa2fd04c9829b2e40957a Mon Sep 17 00:00:00 2001 From: neil Date: Sun, 22 Dec 2024 14:17:33 +0100 Subject: [PATCH 032/198] fix format --- deploy/unifi.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/deploy/unifi.sh b/deploy/unifi.sh index 237840991b..a50b06ffd0 100644 --- a/deploy/unifi.sh +++ b/deploy/unifi.sh @@ -141,7 +141,7 @@ unifi_deploy() { _unifi_keystore_owner=$(ls -l "${_unifi_keystore}" | awk '{print $3}') if ! [ "${_unifi_keystore_owner}" = "${_unifi_keystore_dir_owner}" ]; then _debug "Changing keystore owner to ${_unifi_keystore_dir_owner}" - chown $_unifi_keystore_dir_owner "${_unifi_keystore}" >/dev/null 2>&1 # fail quietly if we're not running as root + chown "$_unifi_keystore_dir_owner" "${_unifi_keystore}" >/dev/null 2>&1 # fail quietly if we're not running as root fi # Update unifi service for certificate cipher compatibility @@ -150,8 +150,8 @@ unifi_deploy() { -password pass:aircontrolenterprise \ -nokeys | ${ACME_OPENSSL_BIN:-openssl} x509 -text \ -noout | grep -i "signature" | grep -iq ecdsa >/dev/null 2>&1; then - if [ -f "$(dirname ${DEPLOY_UNIFI_KEYSTORE})/system.properties" ]; then - _unifi_system_properties="$(dirname ${DEPLOY_UNIFI_KEYSTORE})/system.properties" + if [ -f "$(dirname "${DEPLOY_UNIFI_KEYSTORE}")/system.properties" ]; then + _unifi_system_properties="$(dirname "${DEPLOY_UNIFI_KEYSTORE}")/system.properties" else _unifi_system_properties="/usr/lib/unifi/data/system.properties" fi From 02da1700e0ff5bff4bb8f72e60f5e4394f13e8b9 Mon Sep 17 00:00:00 2001 From: neil Date: Sun, 22 Dec 2024 14:19:58 +0100 Subject: [PATCH 033/198] fix format --- deploy/unifi.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deploy/unifi.sh b/deploy/unifi.sh index a50b06ffd0..1c9dfb4459 100644 --- a/deploy/unifi.sh +++ b/deploy/unifi.sh @@ -137,8 +137,8 @@ unifi_deploy() { # correct file ownership according to the directory, the keystore is placed in _unifi_keystore_dir=$(dirname "${_unifi_keystore}") - _unifi_keystore_dir_owner=$(ls -ld "${_unifi_keystore_dir}" | awk '{print $3}') - _unifi_keystore_owner=$(ls -l "${_unifi_keystore}" | awk '{print $3}') + _unifi_keystore_dir_owner=$(find "${_unifi_keystore_dir}" -maxdepth 0 -printf '%u\n') + _unifi_keystore_owner=$(find "${_unifi_keystore}" -maxdepth 0 -printf '%u\n') if ! [ "${_unifi_keystore_owner}" = "${_unifi_keystore_dir_owner}" ]; then _debug "Changing keystore owner to ${_unifi_keystore_dir_owner}" chown "$_unifi_keystore_dir_owner" "${_unifi_keystore}" >/dev/null 2>&1 # fail quietly if we're not running as root From e42ad9be242dadc565ab7d93fc96b63519101563 Mon Sep 17 00:00:00 2001 From: Vladimir Alexeev <9141778236@mail.ru> Date: Mon, 23 Dec 2024 14:50:28 +1000 Subject: [PATCH 034/198] fix don't use debug3, use debug2 add # shellcheck disable=SC2034 --- dnsapi/dns_selectel.sh | 49 +++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/dnsapi/dns_selectel.sh b/dnsapi/dns_selectel.sh index 511ab7f546..7782fa4462 100644 --- a/dnsapi/dns_selectel.sh +++ b/dnsapi/dns_selectel.sh @@ -1,4 +1,5 @@ #!/usr/bin/env sh +# shellcheck disable=SC2034 # Variables that must be defined before running # export SL_Ver="v1" - version API: 'v2' (actual) or 'v1' (legacy). @@ -35,11 +36,11 @@ dns_selectel_add() { if ! _sl_init_vars; then return 1 fi - _debug3 SL_Ver "$SL_Ver" - _debug3 SL_Expire "$SL_Expire" - _debug3 SL_Login_Name "$SL_Login_Name" - _debug3 SL_Login_ID "$SL_Login_ID" - _debug3 SL_Project_Name "$SL_Project_Name" + _debug2 SL_Ver "$SL_Ver" + _debug2 SL_Expire "$SL_Expire" + _debug2 SL_Login_Name "$SL_Login_Name" + _debug2 SL_Login_ID "$SL_Login_ID" + _debug2 SL_Project_Name "$SL_Project_Name" _debug "First detect the root zone" if ! _get_root "$fulldomain"; then @@ -95,9 +96,9 @@ dns_selectel_add() { # preparing _data _tmp_str="${_record_array},{\"content\":\"${_text_tmp}\"}" _data="{\"ttl\": 60, \"records\": [${_tmp_str}]}" - _debug3 _record_seg "$_record_seg" - _debug3 _record_array "$_record_array" - _debug3 _record_array "$_record_id" + _debug2 _record_seg "$_record_seg" + _debug2 _record_array "$_record_array" + _debug2 _record_array "$_record_id" _debug "New data for record" "$_data" if _sl_rest PATCH "${_ext_uri}${_record_id}" "$_data"; then _info "Added, OK" @@ -121,11 +122,11 @@ dns_selectel_rm() { if ! _sl_init_vars "nosave"; then return 1 fi - _debug3 SL_Ver "$SL_Ver" - _debug3 SL_Expire "$SL_Expire" - _debug3 SL_Login_Name "$SL_Login_Name" - _debug3 SL_Login_ID "$SL_Login_ID" - _debug3 SL_Project_Name "$SL_Project_Name" + _debug2 SL_Ver "$SL_Ver" + _debug2 SL_Expire "$SL_Expire" + _debug2 SL_Login_Name "$SL_Login_Name" + _debug2 SL_Login_ID "$SL_Login_ID" + _debug2 SL_Project_Name "$SL_Project_Name" # _debug "First detect the root zone" if ! _get_root "$fulldomain"; then @@ -166,7 +167,7 @@ dns_selectel_rm() { _err "Error. Unsupported version API $SL_Ver" return 1 fi - _debug3 "_record_seg" "$_record_seg" + _debug2 "_record_seg" "$_record_seg" if [ -z "$_record_seg" ]; then _err "can not find _record_seg" return 1 @@ -181,7 +182,7 @@ dns_selectel_rm() { _err "can not find _record_id" return 1 fi - _debug3 "_record_id" "$_record_id" + _debug2 "_record_id" "$_record_id" # delete all record type TXT with text $txtvalue if [ "$SL_Ver" = "v2" ]; then # actual @@ -199,7 +200,7 @@ dns_selectel_rm() { else # update a record by removing one element in content _data="{\"ttl\": 60, \"records\": [${_new_arr}]}" - _debug3 _data "$_data" + _debug2 _data "$_data" # REST API PATCH call if _sl_rest PATCH "${_del_uri}" "$_data"; then _info "Patched, OK: ${_del_uri}" @@ -314,15 +315,16 @@ _sl_rest() { fi export _H1="${_h1_name}: ${_token}" export _H2="Content-Type: application/json" - _debug3 "Full URI: " "$SL_Api/${SL_Ver}${ep}" - _debug3 "_H1:" "$_H1" - _debug3 "_H2:" "$_H2" + _debug2 "Full URI: " "$SL_Api/${SL_Ver}${ep}" + _debug2 "_H1:" "$_H1" + _debug2 "_H2:" "$_H2" if [ "$m" != "GET" ]; then _debug data "$data" response="$(_post "$data" "$SL_Api/${SL_Ver}${ep}" "" "$m")" else response="$(_get "$SL_Api/${SL_Ver}${ep}")" fi + # shellcheck disable=SC2181 if [ "$?" != "0" ]; then _err "error $ep" return 1 @@ -353,13 +355,12 @@ _get_auth_token() { _project_name=$(_getfield "$token_v2" 4 "$_sl_sep") _receipt_time=$(_getfield "$token_v2" 5 "$_sl_sep") _login_id=$(_getfield "$token_v2" 3 "$_sl_sep") - _debug3 _login_name "$_login_name" - _debug3 _login_id "$_login_id" - _debug3 _project_name "$_project_name" - # _debug3 _receipt_time "$(date -d @"$_receipt_time" -u)" + _debug2 _login_name "$_login_name" + _debug2 _login_id "$_login_id" + _debug2 _project_name "$_project_name" # check the validity of the token for the user and the project and its lifetime _dt_diff_minute=$((($(date +%s) - _receipt_time) / 60)) - _debug3 _dt_diff_minute "$_dt_diff_minute" + _debug2 _dt_diff_minute "$_dt_diff_minute" [ "$_dt_diff_minute" -gt "$SL_Expire" ] && unset _token_keystone if [ "$_project_name" != "$SL_Project_Name" ] || [ "$_login_name" != "$SL_Login_Name" ] || [ "$_login_id" != "$SL_Login_ID" ]; then unset _token_keystone From 112bfccfd52f05db43f68946c9047399a541bfc5 Mon Sep 17 00:00:00 2001 From: Vladimir Alexeev <9141778236@mail.ru> Date: Tue, 24 Dec 2024 16:00:01 +1000 Subject: [PATCH 035/198] fix _get_root() make it start from 1. because we need to support --domain-alias (only version api actual v2) --- dnsapi/dns_selectel.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_selectel.sh b/dnsapi/dns_selectel.sh index 7782fa4462..309c6b17a5 100644 --- a/dnsapi/dns_selectel.sh +++ b/dnsapi/dns_selectel.sh @@ -267,7 +267,7 @@ _get_root() { _err "Error read records of all domains $SL_Ver" return 1 fi - i=2 + i=1 p=1 while true; do h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) From 4cc460be642d1fd9f3bddf82e953e1d783fd1def Mon Sep 17 00:00:00 2001 From: Peter Vos Date: Tue, 24 Dec 2024 13:33:15 +0100 Subject: [PATCH 036/198] Added dns challenge for mijn.host --- dnsapi/dns_mijn_host.sh | 145 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 dnsapi/dns_mijn_host.sh diff --git a/dnsapi/dns_mijn_host.sh b/dnsapi/dns_mijn_host.sh new file mode 100644 index 0000000000..5caf5a223a --- /dev/null +++ b/dnsapi/dns_mijn_host.sh @@ -0,0 +1,145 @@ +#!/usr/bin/env sh +# shellcheck disable=SC2034 +dns_mijnhost_info='mijn.host +Domains: mijn.host +Site: mijn.host +Docs: https://mijn.host/api/doc/api-3563900 +Options: + MIJN_HOST_API_KEY API Key +' + +######## Public functions ###################### Constants for your mijn-host API +MIJN_HOST_API="https://mijn.host/api/v2" + +# Add TXT record for domain verification +dns_mijn_host_add() { + fulldomain=$1 + txtvalue=$2 + + MIJN_HOST_API_KEY="${MIJN_HOST_API_KEY:-$(_readaccountconf_mutable MIJN_HOST_API_KEY)}" + if [ -z "$MIJN_HOST_API_KEY" ]; then + MIJN_HOST_API_KEY="" + _err "You haven't specified mijn-host API key yet." + _err "Please set it and try again." + return 1 + fi + + # Save the API key for future use + _saveaccountconf_mutable MIJN_HOST_API_KEY "$MIJN_HOST_API_KEY" + + _debug "First detect the root zone" + if ! _get_root "$fulldomain"; then + _err "Invalid domain" + return 1 + fi + + _debug "Add TXT record" + + # Build the payload for the API + data="{\"type\":\"TXT\",\"name\":\"$subdomain\",\"value\":\"$txtvalue\",\"ttl\":120}" + + export _H1="API-Key: $MIJN_HOST_API_KEY" + export _H2="Content-Type: application/json" + + extracted_domain="${fulldomain#*_acme-challenge.}" + + # Construct the API URL + api_url="$MIJN_HOST_API/domains/$extracted_domain/dns" + + # Getting preivous records + get_response="$(_get "$api_url")" + records=$(echo "$get_response" | jq -r '.data.records') + + # Updating the records + updated_records=$(echo "$records" | jq --argjson data "$data" '. += [$data]') + + # data + data="{\"records\": $updated_records}" + + # Use the _post method to make the API request + response="$(_post "$data" "$api_url" "" "PUT")" + + if _contains "$response" "error"; then + _err "Error adding TXT record: $response" + return 1 + fi + + _info "TXT record added successfully" + return 0 +} + +# Remove TXT record after verification +dns_mijn_host_rm() { + fulldomain=$1 + txtvalue=$2 + + MIJN_HOST_API_KEY="${MIJN_HOST_API_KEY:-$(_readaccountconf_mutable MIJN_HOST_API_KEY)}" + if [ -z "$MIJN_HOST_API_KEY" ]; then + MIJN_HOST_API_KEY="" + _err "You haven't specified mijn-host API key yet." + return 1 + fi + + _debug "First detect the root zone" + if ! _get_root "$fulldomain"; then + _err "Invalid domain" + return 1 + fi + + _debug "Removing TXT record" + + # Build the payload for the API + export _H1="API-Key: $MIJN_HOST_API_KEY" + export _H2="Content-Type: application/json" + + extracted_domain="${fulldomain#*_acme-challenge.}" + + # Construct the API URL + api_url="$MIJN_HOST_API/domains/$extracted_domain/dns" + + # Get current records + response="$(_get "$api_url")" + + updated_records=$(echo "$response" | jq '.data.records') + + updated_records=$(echo "$updated_records" | jq --arg value "$txtvalue" 'map(select(.value != $value))') + + # Build the new payload + data="{\"records\": $updated_records}" + + # Use the _put method to update the records + response="$(_post "$data" "$api_url" "" "PUT")" + + if _contains "$response" "error"; then + _err "Error updating TXT record: $response" + return 1 + fi + + _info "TXT record removed successfully" + return 0 +} + +# Helper function to detect the root zone +_get_root() { + domain=$1 + i=2 + p=1 + + while true; do + h=$(printf "%s" "$domain" | cut -d . -f "$i"-) + if [ -z "$h" ]; then + return 1 + fi + + if _contains "$(dig ns "$h")" "mijn.host"; then + root_zone="$h" + subdomain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") + return 0 + fi + + p=$i + i=$(_math "$i" + 1) + done + + return 1 +} From 5e9a067e8754a180b37f718154b33acde3651c80 Mon Sep 17 00:00:00 2001 From: peterv99 <_hidden_> Date: Tue, 24 Dec 2024 16:55:26 +0100 Subject: [PATCH 037/198] Fixed root domain detection and processing. --- dnsapi/dns_mijn_host.sh | 61 ++++++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 25 deletions(-) diff --git a/dnsapi/dns_mijn_host.sh b/dnsapi/dns_mijn_host.sh index 5caf5a223a..e8ad398d83 100644 --- a/dnsapi/dns_mijn_host.sh +++ b/dnsapi/dns_mijn_host.sh @@ -3,7 +3,7 @@ dns_mijnhost_info='mijn.host Domains: mijn.host Site: mijn.host -Docs: https://mijn.host/api/doc/api-3563900 +Docs: https://mijn.host/api/doc/ Options: MIJN_HOST_API_KEY API Key ' @@ -33,23 +33,26 @@ dns_mijn_host_add() { return 1 fi + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + _debug "Add TXT record" # Build the payload for the API - data="{\"type\":\"TXT\",\"name\":\"$subdomain\",\"value\":\"$txtvalue\",\"ttl\":120}" + data="{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"value\":\"$txtvalue\",\"ttl\":120}" export _H1="API-Key: $MIJN_HOST_API_KEY" export _H2="Content-Type: application/json" - extracted_domain="${fulldomain#*_acme-challenge.}" - # Construct the API URL - api_url="$MIJN_HOST_API/domains/$extracted_domain/dns" + api_url="$MIJN_HOST_API/domains/$_domain/dns" - # Getting preivous records + # Getting previous records get_response="$(_get "$api_url")" records=$(echo "$get_response" | jq -r '.data.records') + _debug2 "previous records" "$records" + # Updating the records updated_records=$(echo "$records" | jq --argjson data "$data" '. += [$data]') @@ -59,7 +62,9 @@ dns_mijn_host_add() { # Use the _post method to make the API request response="$(_post "$data" "$api_url" "" "PUT")" - if _contains "$response" "error"; then + _debug2 "Response" "$response" + + if ! _contains "$response" "200"; then _err "Error adding TXT record: $response" return 1 fi @@ -92,10 +97,8 @@ dns_mijn_host_rm() { export _H1="API-Key: $MIJN_HOST_API_KEY" export _H2="Content-Type: application/json" - extracted_domain="${fulldomain#*_acme-challenge.}" - # Construct the API URL - api_url="$MIJN_HOST_API/domains/$extracted_domain/dns" + api_url="$MIJN_HOST_API/domains/$_domain/dns" # Get current records response="$(_get "$api_url")" @@ -110,7 +113,7 @@ dns_mijn_host_rm() { # Use the _put method to update the records response="$(_post "$data" "$api_url" "" "PUT")" - if _contains "$response" "error"; then + if ! _contains "$response" "200"; then _err "Error updating TXT record: $response" return 1 fi @@ -122,24 +125,32 @@ dns_mijn_host_rm() { # Helper function to detect the root zone _get_root() { domain=$1 - i=2 - p=1 - while true; do - h=$(printf "%s" "$domain" | cut -d . -f "$i"-) - if [ -z "$h" ]; then - return 1 - fi + # Get all domains + export _H1="API-Key: $MIJN_HOST_API_KEY" + export _H2="Content-Type: application/json" - if _contains "$(dig ns "$h")" "mijn.host"; then - root_zone="$h" - subdomain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") + # Construct the API URL + api_url="$MIJN_HOST_API/domains" + + # Get current records + response="$(_get "$api_url")" + + if ! _contains "$response" "200"; then + _err "Error listing domains: $response" + return 1 + fi + + # Extract root oomains from response + rootDomains=$(echo "$response" | jq -r '.data.domains[].domain') + + for rootDomain in $rootDomains; do + if _contains "$domain" "$rootDomain"; then + _domain="$rootDomain" + _sub_domain=$(printf '%s\n' "${domain//."$rootDomain"/}") return 0 fi - - p=$i - i=$(_math "$i" + 1) done - return 1 + return 1 } From ab1a2045d9e5c1cca112a037d3b44d9e4174e834 Mon Sep 17 00:00:00 2001 From: peterv99 <_hidden_> Date: Tue, 24 Dec 2024 17:10:30 +0100 Subject: [PATCH 038/198] Made string removal in root domain detection posix compliant --- dnsapi/dns_mijn_host.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dnsapi/dns_mijn_host.sh b/dnsapi/dns_mijn_host.sh index e8ad398d83..55cd49a224 100644 --- a/dnsapi/dns_mijn_host.sh +++ b/dnsapi/dns_mijn_host.sh @@ -126,7 +126,7 @@ dns_mijn_host_rm() { _get_root() { domain=$1 - # Get all domains + # Get all domains export _H1="API-Key: $MIJN_HOST_API_KEY" export _H2="Content-Type: application/json" @@ -140,17 +140,17 @@ _get_root() { _err "Error listing domains: $response" return 1 fi - + # Extract root oomains from response rootDomains=$(echo "$response" | jq -r '.data.domains[].domain') for rootDomain in $rootDomains; do if _contains "$domain" "$rootDomain"; then _domain="$rootDomain" - _sub_domain=$(printf '%s\n' "${domain//."$rootDomain"/}") + _sub_domain=$(echo "$domain" | sed "s/$rootDomain//g") return 0 fi done - return 1 + return 1 } From c7cecd5b4fec49d9f4a67dbd04fe33fd21681de3 Mon Sep 17 00:00:00 2001 From: peterv99 <_hidden_> Date: Tue, 24 Dec 2024 17:30:50 +0100 Subject: [PATCH 039/198] Removed "." from _sub_domain to create a valid domain. --- dnsapi/dns_mijn_host.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_mijn_host.sh b/dnsapi/dns_mijn_host.sh index 55cd49a224..0e279a9823 100644 --- a/dnsapi/dns_mijn_host.sh +++ b/dnsapi/dns_mijn_host.sh @@ -147,7 +147,7 @@ _get_root() { for rootDomain in $rootDomains; do if _contains "$domain" "$rootDomain"; then _domain="$rootDomain" - _sub_domain=$(echo "$domain" | sed "s/$rootDomain//g") + _sub_domain=$(echo "$domain" | sed "s/.$rootDomain//g") return 0 fi done From 07220a324d53a3275659a0280a5d79932223a5d0 Mon Sep 17 00:00:00 2001 From: peterv99 <_hidden_> Date: Tue, 24 Dec 2024 23:21:50 +0100 Subject: [PATCH 040/198] Removed all jq references --- dnsapi/dns_mijn_host.sh | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/dnsapi/dns_mijn_host.sh b/dnsapi/dns_mijn_host.sh index 0e279a9823..16d652b704 100644 --- a/dnsapi/dns_mijn_host.sh +++ b/dnsapi/dns_mijn_host.sh @@ -49,20 +49,24 @@ dns_mijn_host_add() { # Getting previous records get_response="$(_get "$api_url")" - records=$(echo "$get_response" | jq -r '.data.records') + records=$(echo "$get_response" | _egrep_o '"records":\[.*\]' | sed 's/"records"://') - _debug2 "previous records" "$records" + _debug "Current records" "$records" # Updating the records - updated_records=$(echo "$records" | jq --argjson data "$data" '. += [$data]') + updated_records=$(echo "$records" | sed -E "s/\]( *$)/,$data\]/") + + _debug "Updated records" "$updatedrecords" # data data="{\"records\": $updated_records}" + _debug "json data add_dns PUT call:" "$data" + # Use the _post method to make the API request response="$(_post "$data" "$api_url" "" "PUT")" - _debug2 "Response" "$response" + _debug "Response to PUT dns_add" "$response" if ! _contains "$response" "200"; then _err "Error adding TXT record: $response" @@ -102,17 +106,27 @@ dns_mijn_host_rm() { # Get current records response="$(_get "$api_url")" + + _debug "Get current records response:" "$response" - updated_records=$(echo "$response" | jq '.data.records') + records=$(echo "$get_response" | _egrep_o '"records":\[.*\]' | sed 's/"records"://') + + _debug "Current records:" "$records" - updated_records=$(echo "$updated_records" | jq --arg value "$txtvalue" 'map(select(.value != $value))') + updated_records=$(echo "$updated_records" | sed -E "s/\{[^}]*\"value\":\"$txtvalue\"[^}]*\},?//g" | sed 's/,]/]/g') + + _debug "Updated records:" "$updated_records" # Build the new payload data="{\"records\": $updated_records}" + + _debug "Payload:" "$data" # Use the _put method to update the records response="$(_post "$data" "$api_url" "" "PUT")" + _debug "Response:" "$response" + if ! _contains "$response" "200"; then _err "Error updating TXT record: $response" return 1 @@ -141,8 +155,10 @@ _get_root() { return 1 fi - # Extract root oomains from response - rootDomains=$(echo "$response" | jq -r '.data.domains[].domain') + # Extract root domains from response + rootDomains=$(echo "$response" | _egrep_o '"domain":"[^"]*"' | sed -E 's/"domain":"([^"]*)"/\1/') + + _debug "Root domains:" "$rootDomains" for rootDomain in $rootDomains; do if _contains "$domain" "$rootDomain"; then From 35f3b7088d4b50ccd14a3cd7e63036562cb65f11 Mon Sep 17 00:00:00 2001 From: peterv99 <_hidden_> Date: Wed, 25 Dec 2024 00:00:19 +0100 Subject: [PATCH 041/198] Updated PUT request to hold only fqdn domain name values# --- dnsapi/dns_mijn_host.sh | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/dnsapi/dns_mijn_host.sh b/dnsapi/dns_mijn_host.sh index 16d652b704..62b0c14434 100644 --- a/dnsapi/dns_mijn_host.sh +++ b/dnsapi/dns_mijn_host.sh @@ -39,7 +39,7 @@ dns_mijn_host_add() { _debug "Add TXT record" # Build the payload for the API - data="{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"value\":\"$txtvalue\",\"ttl\":120}" + data="{\"type\":\"TXT\",\"name\":\"$fulldomain.\",\"value\":\"$txtvalue\",\"ttl\":120}" export _H1="API-Key: $MIJN_HOST_API_KEY" export _H2="Content-Type: application/json" @@ -55,8 +55,8 @@ dns_mijn_host_add() { # Updating the records updated_records=$(echo "$records" | sed -E "s/\]( *$)/,$data\]/") - - _debug "Updated records" "$updatedrecords" + + _debug "Updated records" "$updated_records" # data data="{\"records\": $updated_records}" @@ -106,20 +106,20 @@ dns_mijn_host_rm() { # Get current records response="$(_get "$api_url")" - + _debug "Get current records response:" "$response" records=$(echo "$get_response" | _egrep_o '"records":\[.*\]' | sed 's/"records"://') - + _debug "Current records:" "$records" updated_records=$(echo "$updated_records" | sed -E "s/\{[^}]*\"value\":\"$txtvalue\"[^}]*\},?//g" | sed 's/,]/]/g') - + _debug "Updated records:" "$updated_records" # Build the new payload data="{\"records\": $updated_records}" - + _debug "Payload:" "$data" # Use the _put method to update the records From 3cfa882fe1d88d49b99d55ab6c919e79957944f7 Mon Sep 17 00:00:00 2001 From: peterv99 <_hidden_> Date: Wed, 25 Dec 2024 08:52:09 +0100 Subject: [PATCH 042/198] Fixed error in dns_mijn_host_rm --- dnsapi/dns_mijn_host.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_mijn_host.sh b/dnsapi/dns_mijn_host.sh index 62b0c14434..e3f5bb6020 100644 --- a/dnsapi/dns_mijn_host.sh +++ b/dnsapi/dns_mijn_host.sh @@ -39,7 +39,7 @@ dns_mijn_host_add() { _debug "Add TXT record" # Build the payload for the API - data="{\"type\":\"TXT\",\"name\":\"$fulldomain.\",\"value\":\"$txtvalue\",\"ttl\":120}" + data="{\"type\":\"TXT\",\"name\":\"$fulldomain.\",\"value\":\"$txtvalue\",\"ttl\":300}" export _H1="API-Key: $MIJN_HOST_API_KEY" export _H2="Content-Type: application/json" @@ -95,7 +95,7 @@ dns_mijn_host_rm() { return 1 fi - _debug "Removing TXT record" + _debug "Removing TXT record" "$txtvalue" # Build the payload for the API export _H1="API-Key: $MIJN_HOST_API_KEY" @@ -105,7 +105,7 @@ dns_mijn_host_rm() { api_url="$MIJN_HOST_API/domains/$_domain/dns" # Get current records - response="$(_get "$api_url")" + get_response="$(_get "$api_url")" _debug "Get current records response:" "$response" From 7512dbffbbc0b7a9e2cd7cb55fc3c6a74c289df3 Mon Sep 17 00:00:00 2001 From: peterv99 <_hidden_> Date: Wed, 25 Dec 2024 09:50:27 +0100 Subject: [PATCH 043/198] Fixed yet another error in dns_rm --- dnsapi/dns_mijn_host.sh | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/dnsapi/dns_mijn_host.sh b/dnsapi/dns_mijn_host.sh index e3f5bb6020..5a5634dd8b 100644 --- a/dnsapi/dns_mijn_host.sh +++ b/dnsapi/dns_mijn_host.sh @@ -107,25 +107,23 @@ dns_mijn_host_rm() { # Get current records get_response="$(_get "$api_url")" - _debug "Get current records response:" "$response" + _debug "Get current records response:" "$get_response" records=$(echo "$get_response" | _egrep_o '"records":\[.*\]' | sed 's/"records"://') _debug "Current records:" "$records" - updated_records=$(echo "$updated_records" | sed -E "s/\{[^}]*\"value\":\"$txtvalue\"[^}]*\},?//g" | sed 's/,]/]/g') + updated_records=$(echo "$records" | sed -E "s/\{[^}]*\"value\":\"$txtvalue\"[^}]*\},?//g" | sed 's/,]/]/g') _debug "Updated records:" "$updated_records" # Build the new payload data="{\"records\": $updated_records}" - _debug "Payload:" "$data" - # Use the _put method to update the records response="$(_post "$data" "$api_url" "" "PUT")" - _debug "Response:" "$response" + _debug "Response to PUT dns_rm:" "$response" if ! _contains "$response" "200"; then _err "Error updating TXT record: $response" From 150c708726248e2dda8e2691e2e2211feac0fe5a Mon Sep 17 00:00:00 2001 From: peterv99 <_hidden_> Date: Wed, 25 Dec 2024 14:11:52 +0100 Subject: [PATCH 044/198] Better debug messages for root domain detection --- dnsapi/dns_mijn_host.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dnsapi/dns_mijn_host.sh b/dnsapi/dns_mijn_host.sh index 5a5634dd8b..2cd9a865f6 100644 --- a/dnsapi/dns_mijn_host.sh +++ b/dnsapi/dns_mijn_host.sh @@ -162,6 +162,9 @@ _get_root() { if _contains "$domain" "$rootDomain"; then _domain="$rootDomain" _sub_domain=$(echo "$domain" | sed "s/.$rootDomain//g") + + _debug "Found root domain" "$_domain" "and subdomain" "$_sub_domain" "for" "$domain" + return 0 fi done From 3f262fe872071c2fdc37c0528380e7f9d17ce669 Mon Sep 17 00:00:00 2001 From: Vladimir Alexeev <9141778236@mail.ru> Date: Thu, 26 Dec 2024 08:12:36 +1000 Subject: [PATCH 045/198] keep content: # 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 --- dnsapi/dns_selectel.sh | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/dnsapi/dns_selectel.sh b/dnsapi/dns_selectel.sh index 309c6b17a5..1e1a769a50 100644 --- a/dnsapi/dns_selectel.sh +++ b/dnsapi/dns_selectel.sh @@ -1,26 +1,28 @@ #!/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 -# export SL_Ver="v1" - version API: 'v2' (actual) or 'v1' (legacy). -# Default: v1 -# If SL_Ver="v1" -# export SL_Key="API_Key" - Token Selectel (API key) -# You can view or create in the control panel in the upper right corner, open the menu: "Profile and setting -> Keys API". -# https://my.selectel.ru/profile/apikeys -# If SL_Ver="v2" -# export SL_Expire=60 - token lifetime in minutes (0-1440). -# Default: 1400 minutes -# export SL_Login_ID= - account number in the control panel; -# export SL_Project_Name= - name project. -# export SL_Login_Name= - service user name. You can view the name in the control panel: -# in the upper right corner open menu: "Profile and setting → User management → Service users -# export SL_Pswd='pswd' - service user password, can be viewed when creating a user or changed to a new one. -# All these variables will be saved in ~/.acme.sh/account.conf and will be reused as needed. +# SL_Ver='v1', when using version API legacy (v1) +# OR +# SL_Ver='v2', when using version API actual (v2) +# default = 'v1' +# 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 # -# Authorization is described in: -# https://developers.selectel.ru/docs/control-panel/authorization/ -# https://developers.selectel.com/docs/control-panel/authorization/ SL_Api="https://api.selectel.ru/domains" auth_uri="https://cloud.api.selcloud.ru/identity/v3/auth/tokens" From d3f3a703507fdc8d9733baea846420bcbe3558e5 Mon Sep 17 00:00:00 2001 From: Vladimir Alexeev <9141778236@mail.ru> Date: Thu, 26 Dec 2024 08:45:03 +1000 Subject: [PATCH 046/198] keep content: # 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 --- dnsapi/dns_selectel.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dnsapi/dns_selectel.sh b/dnsapi/dns_selectel.sh index 1e1a769a50..434bc48304 100644 --- a/dnsapi/dns_selectel.sh +++ b/dnsapi/dns_selectel.sh @@ -7,10 +7,9 @@ # 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) -# OR # SL_Ver='v2', when using version API actual (v2) -# default = 'v1' # when using API version v1, i.e. SL_Ver is 'v1' or not defined: # SL_Key - API Key, required # when using API version v2: From b0f566a80dc9ac0913d2acbe254e592aca023d67 Mon Sep 17 00:00:00 2001 From: peterv99 <_hidden_> Date: Thu, 26 Dec 2024 23:36:55 +0100 Subject: [PATCH 047/198] Name change to be in line with other API scripts Added time-out to _get calls at 120s to fix API timeouts --- dnsapi/{dns_mijn_host.sh => dns_mijnhost.sh} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename dnsapi/{dns_mijn_host.sh => dns_mijnhost.sh} (100%) diff --git a/dnsapi/dns_mijn_host.sh b/dnsapi/dns_mijnhost.sh similarity index 100% rename from dnsapi/dns_mijn_host.sh rename to dnsapi/dns_mijnhost.sh From 9ad794f2cc9fa1d74b18cf81ca6b61d42a820fff Mon Sep 17 00:00:00 2001 From: peterv99 <_hidden_> Date: Fri, 27 Dec 2024 08:56:16 +0100 Subject: [PATCH 048/198] Name change, function name change to mijnhost --- dnsapi/dns_mijnhost.sh | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/dnsapi/dns_mijnhost.sh b/dnsapi/dns_mijnhost.sh index 2cd9a865f6..760602c39b 100644 --- a/dnsapi/dns_mijnhost.sh +++ b/dnsapi/dns_mijnhost.sh @@ -5,27 +5,27 @@ Domains: mijn.host Site: mijn.host Docs: https://mijn.host/api/doc/ Options: - MIJN_HOST_API_KEY API Key + MIJNHOST_API_KEY API Key ' ######## Public functions ###################### Constants for your mijn-host API -MIJN_HOST_API="https://mijn.host/api/v2" +MIJNHOST_API="https://mijn.host/api/v2" # Add TXT record for domain verification -dns_mijn_host_add() { +dns_mijnhost_add() { fulldomain=$1 txtvalue=$2 - MIJN_HOST_API_KEY="${MIJN_HOST_API_KEY:-$(_readaccountconf_mutable MIJN_HOST_API_KEY)}" - if [ -z "$MIJN_HOST_API_KEY" ]; then - MIJN_HOST_API_KEY="" + MIJNHOST_API_KEY="${MIJNHOST_API_KEY:-$(_readaccountconf_mutable MIJNHOST_API_KEY)}" + if [ -z "$MIJNHOST_API_KEY" ]; then + MIJNHOST_API_KEY="" _err "You haven't specified mijn-host API key yet." _err "Please set it and try again." return 1 fi # Save the API key for future use - _saveaccountconf_mutable MIJN_HOST_API_KEY "$MIJN_HOST_API_KEY" + _saveaccountconf_mutable MIJNHOST_API_KEY "$MIJNHOST_API_KEY" _debug "First detect the root zone" if ! _get_root "$fulldomain"; then @@ -41,14 +41,14 @@ dns_mijn_host_add() { # Build the payload for the API data="{\"type\":\"TXT\",\"name\":\"$fulldomain.\",\"value\":\"$txtvalue\",\"ttl\":300}" - export _H1="API-Key: $MIJN_HOST_API_KEY" + export _H1="API-Key: $MIJNHOST_API_KEY" export _H2="Content-Type: application/json" # Construct the API URL - api_url="$MIJN_HOST_API/domains/$_domain/dns" + api_url="$MIJNHOST_API/domains/$_domain/dns" # Getting previous records - get_response="$(_get "$api_url")" + get_response="$(_get "$api_url" "" "120")" records=$(echo "$get_response" | _egrep_o '"records":\[.*\]' | sed 's/"records"://') _debug "Current records" "$records" @@ -78,13 +78,13 @@ dns_mijn_host_add() { } # Remove TXT record after verification -dns_mijn_host_rm() { +dns_mijnhost_rm() { fulldomain=$1 txtvalue=$2 - MIJN_HOST_API_KEY="${MIJN_HOST_API_KEY:-$(_readaccountconf_mutable MIJN_HOST_API_KEY)}" - if [ -z "$MIJN_HOST_API_KEY" ]; then - MIJN_HOST_API_KEY="" + MIJNHOST_API_KEY="${MIJNHOST_API_KEY:-$(_readaccountconf_mutable MIJNHOST_API_KEY)}" + if [ -z "$MIJNHOST_API_KEY" ]; then + MIJNHOST_API_KEY="" _err "You haven't specified mijn-host API key yet." return 1 fi @@ -98,14 +98,14 @@ dns_mijn_host_rm() { _debug "Removing TXT record" "$txtvalue" # Build the payload for the API - export _H1="API-Key: $MIJN_HOST_API_KEY" + export _H1="API-Key: $MIJNHOST_API_KEY" export _H2="Content-Type: application/json" # Construct the API URL - api_url="$MIJN_HOST_API/domains/$_domain/dns" + api_url="$MIJNHOST_API/domains/$_domain/dns" # Get current records - get_response="$(_get "$api_url")" + get_response="$(_get "$api_url" "" "120")" _debug "Get current records response:" "$get_response" @@ -139,14 +139,14 @@ _get_root() { domain=$1 # Get all domains - export _H1="API-Key: $MIJN_HOST_API_KEY" + export _H1="API-Key: $MIJNHOST_API_KEY" export _H2="Content-Type: application/json" # Construct the API URL - api_url="$MIJN_HOST_API/domains" + api_url="$MIJNHOST_API/domains" # Get current records - response="$(_get "$api_url")" + response="$(_get "$api_url" "" "120")" if ! _contains "$response" "200"; then _err "Error listing domains: $response" From d093476da5ab6241e78dfe170e973f71f8dc2155 Mon Sep 17 00:00:00 2001 From: peterv99 <_hidden_> Date: Fri, 27 Dec 2024 12:55:12 +0100 Subject: [PATCH 049/198] Refactored REST calls to add generic retries, as mijn.host API times out at times. --- dnsapi/dns_mijnhost.sh | 151 +++++++++++++++++++++++++---------------- 1 file changed, 94 insertions(+), 57 deletions(-) diff --git a/dnsapi/dns_mijnhost.sh b/dnsapi/dns_mijnhost.sh index 760602c39b..3b0fc3f5aa 100644 --- a/dnsapi/dns_mijnhost.sh +++ b/dnsapi/dns_mijnhost.sh @@ -33,48 +33,47 @@ dns_mijnhost_add() { return 1 fi - _debug _sub_domain "$_sub_domain" - _debug _domain "$_domain" - - _debug "Add TXT record" - - # Build the payload for the API - data="{\"type\":\"TXT\",\"name\":\"$fulldomain.\",\"value\":\"$txtvalue\",\"ttl\":300}" - - export _H1="API-Key: $MIJNHOST_API_KEY" - export _H2="Content-Type: application/json" + _debug2 _sub_domain "$_sub_domain" + _debug2 _domain "$_domain" + _debug "Adding TXT record" # Construct the API URL api_url="$MIJNHOST_API/domains/$_domain/dns" # Getting previous records - get_response="$(_get "$api_url" "" "120")" - records=$(echo "$get_response" | _egrep_o '"records":\[.*\]' | sed 's/"records"://') + _mijnhost_rest GET "$api_url" "" - _debug "Current records" "$records" + if [ "$_code" != "200" ]; then + _err "Error getting current DNS enties ($_code)" + return 1 + fi + + records=$(echo "$response" | _egrep_o '"records":\[.*\]' | sed 's/"records"://') + + _debug2 "Current records" "$records" + + # Build the payload for the API + data="{\"type\":\"TXT\",\"name\":\"$fulldomain.\",\"value\":\"$txtvalue\",\"ttl\":300}" + + _debug2 "Record to add: " "$data" # Updating the records updated_records=$(echo "$records" | sed -E "s/\]( *$)/,$data\]/") - _debug "Updated records" "$updated_records" + _debug2 "Updated records" "$updated_records" # data data="{\"records\": $updated_records}" - _debug "json data add_dns PUT call:" "$data" - - # Use the _post method to make the API request - response="$(_post "$data" "$api_url" "" "PUT")" + _mijnhost_rest PUT "$api_url" "$data" - _debug "Response to PUT dns_add" "$response" - - if ! _contains "$response" "200"; then - _err "Error adding TXT record: $response" + if [ "$_code" = "200" ]; then + _info "DNS record succesfully added" + return 0 + else + _err "Error adding DNS record ($_code)" return 1 fi - - _info "TXT record added successfully" - return 0 } # Remove TXT record after verification @@ -95,79 +94,117 @@ dns_mijnhost_rm() { return 1 fi - _debug "Removing TXT record" "$txtvalue" - - # Build the payload for the API - export _H1="API-Key: $MIJNHOST_API_KEY" - export _H2="Content-Type: application/json" + _debug "Removing TXT record" "$txtvalue" "for" "$fulldomain" # Construct the API URL api_url="$MIJNHOST_API/domains/$_domain/dns" # Get current records - get_response="$(_get "$api_url" "" "120")" + _mijnhost_rest GET "$api_url" "" + + if [ "$_code" != "200" ]; then + _err "Error getting current DNS enties ($_code)" + return 1 + fi - _debug "Get current records response:" "$get_response" + _debug2 "Get current records response:" "$response" - records=$(echo "$get_response" | _egrep_o '"records":\[.*\]' | sed 's/"records"://') + records=$(echo "$response" | _egrep_o '"records":\[.*\]' | sed 's/"records"://') - _debug "Current records:" "$records" + _debug2 "Current records:" "$records" updated_records=$(echo "$records" | sed -E "s/\{[^}]*\"value\":\"$txtvalue\"[^}]*\},?//g" | sed 's/,]/]/g') - _debug "Updated records:" "$updated_records" + _debug2 "Updated records:" "$updated_records" # Build the new payload data="{\"records\": $updated_records}" # Use the _put method to update the records - response="$(_post "$data" "$api_url" "" "PUT")" - - _debug "Response to PUT dns_rm:" "$response" + _mijnhost_rest PUT "$api_url" "$data" - if ! _contains "$response" "200"; then - _err "Error updating TXT record: $response" + if [ "$_code" = "200" ]; then + _info "DNS record removed successfully" + return 0 + else + _err "Error removing DNS record ($_code)" return 1 fi - - _info "TXT record removed successfully" - return 0 } # Helper function to detect the root zone _get_root() { domain=$1 - # Get all domains - export _H1="API-Key: $MIJNHOST_API_KEY" - export _H2="Content-Type: application/json" - - # Construct the API URL - api_url="$MIJNHOST_API/domains" - # Get current records - response="$(_get "$api_url" "" "120")" + _debug "Getting current domains" + _mijnhost_rest GET "$MIJNHOST_API/domains" "" - if ! _contains "$response" "200"; then - _err "Error listing domains: $response" + if [ "$_code" != "200" ]; then + _err "error getting current domains ($_code)" return 1 fi # Extract root domains from response rootDomains=$(echo "$response" | _egrep_o '"domain":"[^"]*"' | sed -E 's/"domain":"([^"]*)"/\1/') - _debug "Root domains:" "$rootDomains" for rootDomain in $rootDomains; do if _contains "$domain" "$rootDomain"; then _domain="$rootDomain" _sub_domain=$(echo "$domain" | sed "s/.$rootDomain//g") - _debug "Found root domain" "$_domain" "and subdomain" "$_sub_domain" "for" "$domain" - return 0 fi done - return 1 } + +# Helper function for rest calls +_mijnhost_rest() { + m=$1 + ep="$2" + data="$3" + + MAX_REQUEST_RETRY_TIMES=5 + _request_retry_times=0 + while [ "${_request_retry_times}" -lt "$MAX_REQUEST_RETRY_TIMES" ]; do + _debug3 _request_retry_times "$_request_retry_times" + export _H1="API-Key: $MIJNHOST_API_KEY" + export _H2="Content-Type: application/json" + # clear headers from previous request to avoid getting wrong http code on timeouts + : >"$HTTP_HEADER" + _debug "$ep" + if [ "$m" != "GET" ]; then + _debug2 "data $data" + response="$(_post "$data" "$ep" "" "$m")" + else + response="$(_get "$ep")" + fi + _ret="$?" + _debug2 "response $response" + _code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\\r\\n")" + _debug "http response code $_code" + if [ "$_code" = "401" ]; then + # we have an invalid API token, maybe it is expired? + _err "Access denied. Invalid API token." + return 1 + fi + + if [ "$_ret" != "0" ] || [ -z "$_code" ]; then + _request_retry_times="$(_math "$_request_retry_times" + 1)" + _info "REST call error $_code retrying $ep in $_request_retry_times s" + # Sleep 10 times the number of retries in seconds, to increase backoff time + _sleep "$(_math "$_request_retry_times" \* 10)" + continue + fi + break + done + if [ "$_request_retry_times" = "$MAX_REQUEST_RETRY_TIMES" ]; then + _err "Error mijn.host API call was retried $MAX_REQUEST_RETRY_TIMES times." + _err "Calling $ep failed." + return 1 + fi + response="$(echo "$response" | _normalizeJson)" + return 0 +} From ac9852f9df6c904719e6241f8e9b049db06b21e4 Mon Sep 17 00:00:00 2001 From: peterv99 <_hidden_> Date: Fri, 27 Dec 2024 16:47:02 +0100 Subject: [PATCH 050/198] Added fix for specific API error that mijn.host sometimes throws. --- dnsapi/dns_mijnhost.sh | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/dnsapi/dns_mijnhost.sh b/dnsapi/dns_mijnhost.sh index 3b0fc3f5aa..ea20435304 100644 --- a/dnsapi/dns_mijnhost.sh +++ b/dnsapi/dns_mijnhost.sh @@ -19,8 +19,8 @@ dns_mijnhost_add() { MIJNHOST_API_KEY="${MIJNHOST_API_KEY:-$(_readaccountconf_mutable MIJNHOST_API_KEY)}" if [ -z "$MIJNHOST_API_KEY" ]; then MIJNHOST_API_KEY="" - _err "You haven't specified mijn-host API key yet." - _err "Please set it and try again." + _err "You haven't specified your mijn-host API key yet." + _err "Please add MIJNHOST_API_KEY to the env." return 1 fi @@ -35,7 +35,7 @@ dns_mijnhost_add() { _debug2 _sub_domain "$_sub_domain" _debug2 _domain "$_domain" - _debug "Adding TXT record" + _debug "Adding DNS record" "${fulldomain}." # Construct the API URL api_url="$MIJNHOST_API/domains/$_domain/dns" @@ -55,7 +55,7 @@ dns_mijnhost_add() { # Build the payload for the API data="{\"type\":\"TXT\",\"name\":\"$fulldomain.\",\"value\":\"$txtvalue\",\"ttl\":300}" - _debug2 "Record to add: " "$data" + _debug2 "Record to add" "$data" # Updating the records updated_records=$(echo "$records" | sed -E "s/\]( *$)/,$data\]/") @@ -68,10 +68,10 @@ dns_mijnhost_add() { _mijnhost_rest PUT "$api_url" "$data" if [ "$_code" = "200" ]; then - _info "DNS record succesfully added" + _info "DNS record succesfully added." return 0 else - _err "Error adding DNS record ($_code)" + _err "Error adding DNS record ($_code)." return 1 fi } @@ -84,17 +84,18 @@ dns_mijnhost_rm() { MIJNHOST_API_KEY="${MIJNHOST_API_KEY:-$(_readaccountconf_mutable MIJNHOST_API_KEY)}" if [ -z "$MIJNHOST_API_KEY" ]; then MIJNHOST_API_KEY="" - _err "You haven't specified mijn-host API key yet." + _err "You haven't specified your mijn-host API key yet." + _err "Please add MIJNHOST_API_KEY to the env." return 1 fi - _debug "First detect the root zone" + _debug "Detecting root zone for" "${fulldomain}." if ! _get_root "$fulldomain"; then _err "Invalid domain" return 1 fi - _debug "Removing TXT record" "$txtvalue" "for" "$fulldomain" + _debug "Removing DNS record for TXT value" "${txtvalue}." # Construct the API URL api_url="$MIJNHOST_API/domains/$_domain/dns" @@ -124,10 +125,10 @@ dns_mijnhost_rm() { _mijnhost_rest PUT "$api_url" "$data" if [ "$_code" = "200" ]; then - _info "DNS record removed successfully" + _info "DNS record removed successfully." return 0 else - _err "Error removing DNS record ($_code)" + _err "Error removing DNS record ($_code)." return 1 fi } @@ -191,7 +192,7 @@ _mijnhost_rest() { return 1 fi - if [ "$_ret" != "0" ] || [ -z "$_code" ]; then + if [ "$_ret" != "0" ] || [ -z "$_code" ] || [ "$_code" = "400" ] || _contains "$response" "DNS records not managed by mijn.host"; then #Sometimes API errors out _request_retry_times="$(_math "$_request_retry_times" + 1)" _info "REST call error $_code retrying $ep in $_request_retry_times s" # Sleep 10 times the number of retries in seconds, to increase backoff time From 588123ed117de0dfddeeea4d85a8d9b3a1f8d458 Mon Sep 17 00:00:00 2001 From: peterv99 <_hidden_> Date: Fri, 27 Dec 2024 23:56:13 +0100 Subject: [PATCH 051/198] Updated backoff algorithm --- dnsapi/dns_mijnhost.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_mijnhost.sh b/dnsapi/dns_mijnhost.sh index ea20435304..5fe43d9384 100644 --- a/dnsapi/dns_mijnhost.sh +++ b/dnsapi/dns_mijnhost.sh @@ -169,6 +169,8 @@ _mijnhost_rest() { MAX_REQUEST_RETRY_TIMES=5 _request_retry_times=0 + _retry_sleep=5 #Initial sleep time in seconds. + while [ "${_request_retry_times}" -lt "$MAX_REQUEST_RETRY_TIMES" ]; do _debug3 _request_retry_times "$_request_retry_times" export _H1="API-Key: $MIJNHOST_API_KEY" @@ -195,8 +197,8 @@ _mijnhost_rest() { if [ "$_ret" != "0" ] || [ -z "$_code" ] || [ "$_code" = "400" ] || _contains "$response" "DNS records not managed by mijn.host"; then #Sometimes API errors out _request_retry_times="$(_math "$_request_retry_times" + 1)" _info "REST call error $_code retrying $ep in $_request_retry_times s" - # Sleep 10 times the number of retries in seconds, to increase backoff time - _sleep "$(_math "$_request_retry_times" \* 10)" + _sleep "$_retry_sleep" + _retry_sleep="$(_math "$_retry_sleep" \* 2)" continue fi break From 7a6101c4175efbfb0b781fb4543a25ce3b92a171 Mon Sep 17 00:00:00 2001 From: peterv99 <_hidden_> Date: Fri, 27 Dec 2024 23:56:13 +0100 Subject: [PATCH 052/198] Corrected sleep time message --- dnsapi/dns_mijnhost.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_mijnhost.sh b/dnsapi/dns_mijnhost.sh index ea20435304..5fe43d9384 100644 --- a/dnsapi/dns_mijnhost.sh +++ b/dnsapi/dns_mijnhost.sh @@ -169,6 +169,8 @@ _mijnhost_rest() { MAX_REQUEST_RETRY_TIMES=5 _request_retry_times=0 + _retry_sleep=5 #Initial sleep time in seconds. + while [ "${_request_retry_times}" -lt "$MAX_REQUEST_RETRY_TIMES" ]; do _debug3 _request_retry_times "$_request_retry_times" export _H1="API-Key: $MIJNHOST_API_KEY" @@ -195,8 +197,8 @@ _mijnhost_rest() { if [ "$_ret" != "0" ] || [ -z "$_code" ] || [ "$_code" = "400" ] || _contains "$response" "DNS records not managed by mijn.host"; then #Sometimes API errors out _request_retry_times="$(_math "$_request_retry_times" + 1)" _info "REST call error $_code retrying $ep in $_request_retry_times s" - # Sleep 10 times the number of retries in seconds, to increase backoff time - _sleep "$(_math "$_request_retry_times" \* 10)" + _sleep "$_retry_sleep" + _retry_sleep="$(_math "$_retry_sleep" \* 2)" continue fi break From 42862852b81e2b8071a3e3515f6f30f000e5d100 Mon Sep 17 00:00:00 2001 From: peterv99 <_hidden_> Date: Sat, 28 Dec 2024 12:41:26 +0100 Subject: [PATCH 053/198] Corrected sleep message --- dnsapi/dns_mijnhost.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_mijnhost.sh b/dnsapi/dns_mijnhost.sh index 5fe43d9384..6dc9b8e058 100644 --- a/dnsapi/dns_mijnhost.sh +++ b/dnsapi/dns_mijnhost.sh @@ -196,7 +196,7 @@ _mijnhost_rest() { if [ "$_ret" != "0" ] || [ -z "$_code" ] || [ "$_code" = "400" ] || _contains "$response" "DNS records not managed by mijn.host"; then #Sometimes API errors out _request_retry_times="$(_math "$_request_retry_times" + 1)" - _info "REST call error $_code retrying $ep in $_request_retry_times s" + _info "REST call error $_code retrying $ep in $_retry_sleep s" _sleep "$_retry_sleep" _retry_sleep="$(_math "$_retry_sleep" \* 2)" continue From 234bc93ddbbe701348e9838014c7ec97cc1ef9a9 Mon Sep 17 00:00:00 2001 From: peterv99 <_hidden_> Date: Sat, 28 Dec 2024 12:42:50 +0100 Subject: [PATCH 054/198] Removed superfluous debug message --- dnsapi/dns_mijnhost.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_mijnhost.sh b/dnsapi/dns_mijnhost.sh index 6dc9b8e058..c1f74389a6 100644 --- a/dnsapi/dns_mijnhost.sh +++ b/dnsapi/dns_mijnhost.sh @@ -172,7 +172,7 @@ _mijnhost_rest() { _retry_sleep=5 #Initial sleep time in seconds. while [ "${_request_retry_times}" -lt "$MAX_REQUEST_RETRY_TIMES" ]; do - _debug3 _request_retry_times "$_request_retry_times" + _debug2 _request_retry_times "$_request_retry_times" export _H1="API-Key: $MIJNHOST_API_KEY" export _H2="Content-Type: application/json" # clear headers from previous request to avoid getting wrong http code on timeouts From 6ad469c6379636fc822f344235ee4341d5f1e5ac Mon Sep 17 00:00:00 2001 From: Sergey Ponomarev Date: Sat, 28 Dec 2024 17:38:22 +0200 Subject: [PATCH 055/198] dnsapi: Fix structured info Signed-off-by: Sergey Ponomarev --- dnsapi/dns_azure.sh | 2 +- dnsapi/dns_technitium.sh | 7 +++---- dnsapi/dns_zoneedit.sh | 20 ++++++++++++-------- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/dnsapi/dns_azure.sh b/dnsapi/dns_azure.sh index 3f0dfa3dfc..03feaf6384 100644 --- a/dnsapi/dns_azure.sh +++ b/dnsapi/dns_azure.sh @@ -9,7 +9,7 @@ Options: AZUREDNS_APPID App ID. App ID of the service principal AZUREDNS_CLIENTSECRET Client Secret. Secret from creating the service principal AZUREDNS_MANAGEDIDENTITY Use Managed Identity. Use Managed Identity assigned to a resource instead of a service principal. "true"/"false" - AZUREDNS_BEARERTOKEN Optional Bearer Token. Used instead of service principal credentials or managed identity + AZUREDNS_BEARERTOKEN Bearer Token. Used instead of service principal credentials or managed identity. Optional. ' wiki=https://github.com/acmesh-official/acme.sh/wiki/How-to-use-Azure-DNS diff --git a/dnsapi/dns_technitium.sh b/dnsapi/dns_technitium.sh index a50db97c4d..7bc0dd482e 100755 --- a/dnsapi/dns_technitium.sh +++ b/dnsapi/dns_technitium.sh @@ -1,13 +1,12 @@ #!/usr/bin/env sh # shellcheck disable=SC2034 -dns_Technitium_info='Technitium DNS Server - -Site: https://technitium.com/dns/ +dns_technitium_info='Technitium DNS Server +Site: Technitium.com/dns/ Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_technitium Options: Technitium_Server Server Address Technitium_Token API Token -Issues:https://github.com/acmesh-official/acme.sh/issues/6116 +Issues: github.com/acmesh-official/acme.sh/issues/6116 Author: Henning Reich ' diff --git a/dnsapi/dns_zoneedit.sh b/dnsapi/dns_zoneedit.sh index df01d8cf6f..77553f3cf3 100644 --- a/dnsapi/dns_zoneedit.sh +++ b/dnsapi/dns_zoneedit.sh @@ -1,19 +1,23 @@ #!/usr/bin/env sh +# shellcheck disable=SC2034 +dns_zoneedit_info='ZoneEdit.com +Site: ZoneEdit.com +Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_zoneedit +Options: + ZONEEDIT_ID ID + ZONEEDIT_Token API Token +Issues: github.com/acmesh-official/acme.sh/issues/6135 +' # https://github.com/blueslow/sslcertzoneedit -# Only need to export the credentials once, acme.sh will save for automatic renewal. -# export ZONEEDIT_ID="Your id" -# export ZONEEDIT_Token="Your token" -# acme.sh --issue --dns dns_zoneedit -d example.com -d www.example.com - ######## Public functions ##################### # Usage: dns_zoneedit_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_zoneedit_add() { fulldomain=$1 txtvalue=$2 - _info "Using Zoneedit" + _info "Using ZoneEdit" _debug fulldomain "$fulldomain" _debug txtvalue "$txtvalue" @@ -45,7 +49,7 @@ dns_zoneedit_add() { dns_zoneedit_rm() { fulldomain=$1 txtvalue=$2 - _info "Using Zoneedit" + _info "Using ZoneEdit" _debug fulldomain "$fulldomain" _debug txtvalue "$txtvalue" @@ -114,7 +118,7 @@ _zoneedit_api() { if [ "$ze_sleep" ]; then _sleep "$ze_sleep"; fi return 0 elif _contains "$response" "ERROR.*Minimum.*seconds"; then - _info "Zoneedit responded with a rate limit of..." + _info "ZoneEdit responded with a rate limit of..." ze_ratelimit=$(echo "$response" | sed -n 's/.*Minimum \([0-9]\+\) seconds.*/\1/p') if [ "$ze_ratelimit" ] && [ ! "$(echo "$ze_ratelimit" | tr -d '0-9')" ]; then _info "$ze_ratelimit seconds." From 9526dbadad48811f39bdc566dd99336aaa71e04c Mon Sep 17 00:00:00 2001 From: peterv99 <_hidden_> Date: Sat, 28 Dec 2024 17:26:52 +0100 Subject: [PATCH 056/198] mijn.host API unreliable, upped retry times to 15 --- dnsapi/dns_mijnhost.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_mijnhost.sh b/dnsapi/dns_mijnhost.sh index 699436ef18..b52d65d997 100644 --- a/dnsapi/dns_mijnhost.sh +++ b/dnsapi/dns_mijnhost.sh @@ -167,7 +167,7 @@ _mijnhost_rest() { ep="$2" data="$3" - MAX_REQUEST_RETRY_TIMES=5 + MAX_REQUEST_RETRY_TIMES=15 _request_retry_times=0 _retry_sleep=5 #Initial sleep time in seconds. From a3250fac6dd20734941acd5b3dddae2b80a7ea20 Mon Sep 17 00:00:00 2001 From: Sergey Ponomarev Date: Sat, 28 Dec 2024 22:31:24 +0200 Subject: [PATCH 057/198] dnsapi: Add structured info for lima-city and west.cn Signed-off-by: Sergey Ponomarev --- dnsapi/dns_limacity.sh | 18 +++++++++--------- dnsapi/dns_west_cn.sh | 14 +++++++++----- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/dnsapi/dns_limacity.sh b/dnsapi/dns_limacity.sh index fb12f8c6ed..96bae77f43 100644 --- a/dnsapi/dns_limacity.sh +++ b/dnsapi/dns_limacity.sh @@ -1,13 +1,13 @@ #!/usr/bin/env sh - -# Created by Laraveluser -# -# Pass credentials before "acme.sh --issue --dns dns_limacity ..." -# -- -# export LIMACITY_APIKEY="" -# -- -# -# Pleas note: APIKEY must have following roles: dns.admin, domains.reader +# shellcheck disable=SC2034 +dns_limacity_info='lima-city.de +Site: www.lima-city.de/ +Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_limacity +Options: + LIMACITY_APIKEY API Key. Note: The API Key must have following roles: dns.admin, domains.reader +Issues: github.com/acmesh-official/acme.sh/issues/4758 +Author: @Laraveluser +' ######## Public functions ##################### diff --git a/dnsapi/dns_west_cn.sh b/dnsapi/dns_west_cn.sh index d0bb7d490f..b873bfc038 100644 --- a/dnsapi/dns_west_cn.sh +++ b/dnsapi/dns_west_cn.sh @@ -1,9 +1,13 @@ #!/usr/bin/env sh - -# West.cn Domain api -#WEST_Username="username" -#WEST_Key="sADDsdasdgdsf" -#Set key at https://www.west.cn/manager/API/APIconfig.asp +# shellcheck disable=SC2034 +dns_west_cn_info='West.cn +Site: West.cn +Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_west_cn +Options: + WEST_Username API username + WEST_Key API Key. Set at https://www.west.cn/manager/API/APIconfig.asp +Issues: github.com/acmesh-official/acme.sh/issues/4894 +' REST_API="https://api.west.cn/API/v2" From 1ae7dd9b113513a24a6dcc7ef71ef6aa3943fa72 Mon Sep 17 00:00:00 2001 From: peterv99 <145142820+peterv99@users.noreply.github.com> Date: Sun, 29 Dec 2024 09:30:48 +0100 Subject: [PATCH 058/198] Updated info block --- dnsapi/dns_mijnhost.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dnsapi/dns_mijnhost.sh b/dnsapi/dns_mijnhost.sh index b52d65d997..9dafc702fc 100644 --- a/dnsapi/dns_mijnhost.sh +++ b/dnsapi/dns_mijnhost.sh @@ -4,6 +4,8 @@ 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 Options: MIJNHOST_API_KEY API Key ' From 4bb41cf88637a54ee530bee2df4c3ad819e47d2e Mon Sep 17 00:00:00 2001 From: 3VAbdAVE Date: Sun, 29 Dec 2024 12:52:09 -0500 Subject: [PATCH 059/198] Fixed bad variable. --- deploy/unifi.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/unifi.sh b/deploy/unifi.sh index 706b24e8bc..3e57f198f5 100644 --- a/deploy/unifi.sh +++ b/deploy/unifi.sh @@ -209,7 +209,7 @@ unifi_deploy() { fi fi - cp "_unifi_keystore" "${_cloudkey_certdir}/unifi.keystore.jks" + cp "${_unifi_keystore}" "${_cloudkey_certdir}/unifi.keystore.jks" cat "$_cfullchain" >"${_cloudkey_certdir}/cloudkey.crt" cat "$_ckey" >"${_cloudkey_certdir}/cloudkey.key" From 11de3aed51b42dcbbaeb64b099ce6f4930593b1a Mon Sep 17 00:00:00 2001 From: Sergey Ponomarev Date: Sun, 29 Dec 2024 13:59:08 +0200 Subject: [PATCH 060/198] dnsapi: structured info minor fixes Extend dns_myapi.sh info with samples. omglol: Split Address option by a dot to avoid incorrect parsing with a dot from omg.lol Signed-off-by: Sergey Ponomarev --- dnsapi/dns_limacity.sh | 2 +- dnsapi/dns_myapi.sh | 10 ++++++---- dnsapi/dns_omglol.sh | 4 ++-- dnsapi/dns_openprovider.sh | 1 + dnsapi/dns_pdns.sh | 2 +- dnsapi/dns_yandex360.sh | 2 +- 6 files changed, 12 insertions(+), 9 deletions(-) diff --git a/dnsapi/dns_limacity.sh b/dnsapi/dns_limacity.sh index 96bae77f43..5734be9e3d 100644 --- a/dnsapi/dns_limacity.sh +++ b/dnsapi/dns_limacity.sh @@ -1,7 +1,7 @@ #!/usr/bin/env sh # shellcheck disable=SC2034 dns_limacity_info='lima-city.de -Site: www.lima-city.de/ +Site: www.lima-city.de Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_limacity Options: LIMACITY_APIKEY API Key. Note: The API Key must have following roles: dns.admin, domains.reader diff --git a/dnsapi/dns_myapi.sh b/dnsapi/dns_myapi.sh index c9f5eb9f04..101854d541 100755 --- a/dnsapi/dns_myapi.sh +++ b/dnsapi/dns_myapi.sh @@ -1,12 +1,14 @@ #!/usr/bin/env sh # shellcheck disable=SC2034 dns_myapi_info='Custom API Example - A sample custom DNS API script. -Domains: example.com + A sample custom DNS API script description. +Domains: example.com example.net Site: github.com/acmesh-official/acme.sh/wiki/DNS-API-Dev-Guide -Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_duckdns +Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_myapi Options: - MYAPI_Token API Token. Get API Token from https://example.com/api/. Optional. + MYAPI_Token API Token. Get API Token from https://example.com/api/ + MYAPI_Variable2 Option 2. Default "default value". + MYAPI_Variable2 Option 3. Optional. Issues: github.com/acmesh-official/acme.sh Author: Neil Pang ' diff --git a/dnsapi/dns_omglol.sh b/dnsapi/dns_omglol.sh index 5c137c3f1a..df080bcf04 100644 --- a/dnsapi/dns_omglol.sh +++ b/dnsapi/dns_omglol.sh @@ -4,8 +4,8 @@ dns_omglol_info='omg.lol Site: omg.lol Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_omglol Options: - OMG_ApiKey API Key from omg.lol. This is accessible from the bottom of the account page at https://home.omg.lol/account - OMG_Address This is your omg.lol address, without the preceding @ - you can see your list on your dashboard at https://home.omg.lol/dashboard + OMG_ApiKey API Key. This is accessible from the bottom of the account page at https://home.omg.lol/account + OMG_Address Address. This is your omg.lol address, without the preceding @ - you can see your list on your dashboard at https://home.omg.lol/dashboard Issues: github.com/acmesh-official/acme.sh/issues/5299 Author: @Kholin ' diff --git a/dnsapi/dns_openprovider.sh b/dnsapi/dns_openprovider.sh index b584fad2b6..2dec9934c2 100755 --- a/dnsapi/dns_openprovider.sh +++ b/dnsapi/dns_openprovider.sh @@ -2,6 +2,7 @@ # shellcheck disable=SC2034 dns_openprovider_info='OpenProvider.eu Site: OpenProvider.eu +Domains: OpenProvider.com Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_openprovider Options: OPENPROVIDER_USER Username diff --git a/dnsapi/dns_pdns.sh b/dnsapi/dns_pdns.sh index 2478e19fed..ec19ad2571 100755 --- a/dnsapi/dns_pdns.sh +++ b/dnsapi/dns_pdns.sh @@ -7,7 +7,7 @@ Options: PDNS_Url API URL. E.g. "http://ns.example.com:8081" PDNS_ServerId Server ID. E.g. "localhost" PDNS_Token API Token - PDNS_Ttl=60 Domain TTL. Default: "60". + PDNS_Ttl Domain TTL. Default: "60". ' DEFAULT_PDNS_TTL=60 diff --git a/dnsapi/dns_yandex360.sh b/dnsapi/dns_yandex360.sh index c6b6053df5..18d013613e 100644 --- a/dnsapi/dns_yandex360.sh +++ b/dnsapi/dns_yandex360.sh @@ -1,7 +1,7 @@ #!/usr/bin/env sh # shellcheck disable=SC2034 dns_yandex360_info='Yandex 360 for Business DNS API. -Yandex 360 for Business is a digital environment for effective collaboration. + Yandex 360 for Business is a digital environment for effective collaboration. Site: https://360.yandex.com/ Docs: https://github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_yandex360 Options: From d37553e7b88e154ee2a72c5991397eb26d3a9972 Mon Sep 17 00:00:00 2001 From: Ludovic Ortega Date: Tue, 31 Dec 2024 18:04:39 +0100 Subject: [PATCH 061/198] fix: remove control characters Signed-off-by: Ludovic Ortega --- deploy/truenas.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/truenas.sh b/deploy/truenas.sh index 407395a34d..6a008bd75e 100644 --- a/deploy/truenas.sh +++ b/deploy/truenas.sh @@ -217,7 +217,7 @@ truenas_deploy() { _app_id=$(echo "$_app_id_list" | sed -n "${i}p") _app_config="$(_post "\"$_app_id\"" "$_api_url/app/config" "" "POST" "application/json")" # Check if the app use the same certificate TrueNAS web UI - _app_active_cert_config=$(echo "$_app_config" | _json_decode | jq -r ".ix_certificates[\"$_active_cert_id\"]") + _app_active_cert_config=$(echo "$_app_config" | tr -d '\000-\037' | _json_decode | jq -r ".ix_certificates[\"$_active_cert_id\"]") if [ "$_app_active_cert_config" != "null" ]; then _info "Updating certificate from $_active_cert_id to $_cert_id for app: $_app_id" #Replace the old certificate id with the new one in path From 0241552c0d5475d10e8e1a4f455d3c247b25c0c3 Mon Sep 17 00:00:00 2001 From: Markus Schenk Date: Thu, 2 Jan 2025 00:26:47 +0100 Subject: [PATCH 062/198] update dns_cyon for updated field names and add validation --- dnsapi/dns_cyon.sh | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_cyon.sh b/dnsapi/dns_cyon.sh index 04a515aab4..b5ab836957 100644 --- a/dnsapi/dns_cyon.sh +++ b/dnsapi/dns_cyon.sh @@ -232,7 +232,7 @@ _cyon_add_txt() { _info " - Adding DNS TXT entry..." add_txt_url="https://my.cyon.ch/domain/dnseditor/add-record-async" - add_txt_data="zone=${fulldomain_idn}.&ttl=900&type=TXT&value=${txtvalue}" + add_txt_data="name=${fulldomain_idn}.&ttl=900&type=TXT&dnscontent=${txtvalue}" add_txt_response="$(_post "$add_txt_data" "$add_txt_url")" _debug add_txt_response "${add_txt_response}" @@ -241,9 +241,10 @@ _cyon_add_txt() { add_txt_message="$(printf "%s" "${add_txt_response}" | _cyon_get_response_message)" add_txt_status="$(printf "%s" "${add_txt_response}" | _cyon_get_response_status)" + add_txt_validation="$(printf "%s" "${add_txt_response}" | _cyon_get_validation_status)" # Bail if adding TXT entry fails. - if [ "${add_txt_status}" != "true" ]; then + if [ "${add_txt_status}" != "true" ] || [ "${add_txt_validation}" != "true" ] ; then _err " ${add_txt_message}" _err "" return 1 @@ -308,6 +309,10 @@ _cyon_get_response_status() { _egrep_o '"status":\w*' | cut -d : -f 2 } +_cyon_get_validation_status() { + _egrep_o '"valid":\w*' | cut -d : -f 2 +} + _cyon_get_response_success() { _egrep_o '"onSuccess":"[^"]*"' | cut -d : -f 2 | tr -d '"' } From 524b40b75ff46f875ddd754d4bdd0715b212b752 Mon Sep 17 00:00:00 2001 From: Markus Schenk Date: Thu, 2 Jan 2025 00:36:28 +0100 Subject: [PATCH 063/198] adhere to shell formatting --- dnsapi/dns_cyon.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_cyon.sh b/dnsapi/dns_cyon.sh index b5ab836957..9a95d31734 100644 --- a/dnsapi/dns_cyon.sh +++ b/dnsapi/dns_cyon.sh @@ -244,7 +244,7 @@ _cyon_add_txt() { add_txt_validation="$(printf "%s" "${add_txt_response}" | _cyon_get_validation_status)" # Bail if adding TXT entry fails. - if [ "${add_txt_status}" != "true" ] || [ "${add_txt_validation}" != "true" ] ; then + if [ "${add_txt_status}" != "true" ] || [ "${add_txt_validation}" != "true" ]; then _err " ${add_txt_message}" _err "" return 1 From 6328496bfb13716cd44b4371d1309fa71c49a452 Mon Sep 17 00:00:00 2001 From: Markus Schenk Date: Thu, 2 Jan 2025 00:41:59 +0100 Subject: [PATCH 064/198] run tests --- dnsapi/dns_cyon.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/dnsapi/dns_cyon.sh b/dnsapi/dns_cyon.sh index 9a95d31734..5510bfc27d 100644 --- a/dnsapi/dns_cyon.sh +++ b/dnsapi/dns_cyon.sh @@ -228,6 +228,7 @@ _cyon_change_domain_env() { _info "" } + _cyon_add_txt() { _info " - Adding DNS TXT entry..." From 0e4fd5269b4b25ade954ce0648069e2c317f611c Mon Sep 17 00:00:00 2001 From: Markus Schenk Date: Thu, 2 Jan 2025 00:49:20 +0100 Subject: [PATCH 065/198] run tests --- dnsapi/dns_cyon.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/dnsapi/dns_cyon.sh b/dnsapi/dns_cyon.sh index 5510bfc27d..9a95d31734 100644 --- a/dnsapi/dns_cyon.sh +++ b/dnsapi/dns_cyon.sh @@ -228,7 +228,6 @@ _cyon_change_domain_env() { _info "" } - _cyon_add_txt() { _info " - Adding DNS TXT entry..." From 04aefbf28da6ceb27a3cece5484fc0b2ecca9988 Mon Sep 17 00:00:00 2001 From: Markus Schenk Date: Fri, 3 Jan 2025 00:31:27 +0100 Subject: [PATCH 066/198] moved the env change check to its own function --- dnsapi/dns_cyon.sh | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_cyon.sh b/dnsapi/dns_cyon.sh index 9a95d31734..175877c69a 100644 --- a/dnsapi/dns_cyon.sh +++ b/dnsapi/dns_cyon.sh @@ -215,10 +215,8 @@ _cyon_change_domain_env() { if ! _cyon_check_if_2fa_missed "${domain_env_response}"; then return 1; fi - domain_env_success="$(printf "%s" "${domain_env_response}" | _egrep_o '"authenticated":\w*' | cut -d : -f 2)" - # Bail if domain environment change fails. - if [ "${domain_env_success}" != "true" ]; then + if [ "$(printf "%s" "${domain_env_response}" | _cyon_get_envchange_success)" != "true" ]; then _err " $(printf "%s" "${domain_env_response}" | _cyon_get_response_message)" _err "" return 1 @@ -317,6 +315,10 @@ _cyon_get_response_success() { _egrep_o '"onSuccess":"[^"]*"' | cut -d : -f 2 | tr -d '"' } +_cyon_get_envchange_success() { + _egrep_o '"authenticated":\w*' | cut -d : -f 2 +} + _cyon_check_if_2fa_missed() { # Did we miss the 2FA? if test "${1#*multi_factor_form}" != "${1}"; then From b29d17f5228b15d1fae005adcf326a25b46c974d Mon Sep 17 00:00:00 2001 From: Markus Schenk Date: Fri, 3 Jan 2025 13:04:04 +0100 Subject: [PATCH 067/198] changed char class for compatibility with openbsd --- dnsapi/dns_cyon.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_cyon.sh b/dnsapi/dns_cyon.sh index 175877c69a..4b0dbfc04f 100644 --- a/dnsapi/dns_cyon.sh +++ b/dnsapi/dns_cyon.sh @@ -216,7 +216,7 @@ _cyon_change_domain_env() { if ! _cyon_check_if_2fa_missed "${domain_env_response}"; then return 1; fi # Bail if domain environment change fails. - if [ "$(printf "%s" "${domain_env_response}" | _cyon_get_envchange_success)" != "true" ]; then + if [ "$(printf "%s" "${domain_env_response}" | _cyon_get_environment_change_status)" != "true" ]; then _err " $(printf "%s" "${domain_env_response}" | _cyon_get_response_message)" _err "" return 1 @@ -315,8 +315,8 @@ _cyon_get_response_success() { _egrep_o '"onSuccess":"[^"]*"' | cut -d : -f 2 | tr -d '"' } -_cyon_get_envchange_success() { - _egrep_o '"authenticated":\w*' | cut -d : -f 2 +_cyon_get_environment_change_status() { + _egrep_o '"authenticated":[a-zA-z0-9]*' | cut -d : -f 2 } _cyon_check_if_2fa_missed() { From 1b123054b36fe3acdad6f871ec6f9f8b30caba17 Mon Sep 17 00:00:00 2001 From: Markus Schenk Date: Fri, 3 Jan 2025 13:08:18 +0100 Subject: [PATCH 068/198] also updated the other validation functions --- dnsapi/dns_cyon.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_cyon.sh b/dnsapi/dns_cyon.sh index 4b0dbfc04f..a585e77202 100644 --- a/dnsapi/dns_cyon.sh +++ b/dnsapi/dns_cyon.sh @@ -304,11 +304,11 @@ _cyon_get_response_message() { } _cyon_get_response_status() { - _egrep_o '"status":\w*' | cut -d : -f 2 + _egrep_o '"status":[a-zA-z0-9]*' | cut -d : -f 2 } _cyon_get_validation_status() { - _egrep_o '"valid":\w*' | cut -d : -f 2 + _egrep_o '"valid":[a-zA-z0-9]*' | cut -d : -f 2 } _cyon_get_response_success() { From fef4574c3c4523b9c6c8ba4f6ea305cad6b8483f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markku=20Leini=C3=B6?= <25136274+markkuleinio@users.noreply.github.com> Date: Sat, 4 Jan 2025 21:34:14 +0200 Subject: [PATCH 069/198] Fix option description --- dnsapi/dns_he_ddns.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_he_ddns.sh b/dnsapi/dns_he_ddns.sh index 0893f93850..7d56104c9e 100644 --- a/dnsapi/dns_he_ddns.sh +++ b/dnsapi/dns_he_ddns.sh @@ -4,7 +4,7 @@ dns_he_ddns_info='Hurricane Electric HE.net DDNS Site: dns.he.net Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_he_ddns Options: - HE_DDNS_KEY The DDNS key for updating the TXT record + HE_DDNS_KEY The DDNS key Author: Markku Leiniö ' From 5610d4782fe0954d884943f3e1f205923344bc47 Mon Sep 17 00:00:00 2001 From: Jan-Piet Mens Date: Tue, 7 Jan 2025 13:13:27 +0100 Subject: [PATCH 070/198] Correct typo in acme.sh --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 9842e3f17a..bcd6b92810 100755 --- a/acme.sh +++ b/acme.sh @@ -6061,7 +6061,7 @@ installcronjob() { _script="$(_readlink "$_SCRIPT_")" _debug _script "$_script" if [ -f "$_script" ]; then - _info "Usinging the current script from: $_script" + _info "Using the current script from: $_script" lesh="$_script" else _err "Cannot install cronjob, $PROJECT_ENTRY not found." From 6a249ca1dd62d1e6b71acfe670f20443b4d30b79 Mon Sep 17 00:00:00 2001 From: Yann DEMOULIN Date: Tue, 7 Jan 2025 22:23:27 +0100 Subject: [PATCH 071/198] Create script for deploy certificate on Proxmox Backup Server --- deploy/proxmoxbs.sh | 120 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 deploy/proxmoxbs.sh diff --git a/deploy/proxmoxbs.sh b/deploy/proxmoxbs.sh new file mode 100644 index 0000000000..d114645477 --- /dev/null +++ b/deploy/proxmoxbs.sh @@ -0,0 +1,120 @@ +#!/usr/bin/env sh + +# Deploy certificates to a proxmox backup server using the API. +# +# Environment variables that can be set are: +# `DEPLOY_PROXMOXBS_SERVER`: The hostname of the proxmox backup server. Defaults to +# _cdomain. +# `DEPLOY_PROXMOXBS_SERVER_PORT`: The port number the management interface is on. +# Defaults to 8007. +# `DEPLOY_PROXMOXBS_USER`: The user we'll connect as. Defaults to root. +# `DEPLOY_PROXMOXBS_USER_REALM`: The authentication realm the user authenticates +# with. Defaults to pam. +# `DEPLOY_PROXMOXBS_API_TOKEN_NAME`: The name of the API token created for the +# user account. Defaults to acme. +# `DEPLOY_PROXMOXBS_API_TOKEN_KEY`: The API token. Required. + +proxmoxbs_deploy() { + _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" + + # "Sane" defaults. + _getdeployconf DEPLOY_PROXMOXBS_SERVER + if [ -z "$DEPLOY_PROXMOXBS_SERVER" ]; then + _target_hostname="$_cdomain" + else + _target_hostname="$DEPLOY_PROXMOXBS_SERVER" + _savedeployconf DEPLOY_PROXMOXBS_SERVER "$DEPLOY_PROXMOXBS_SERVER" + fi + _debug2 DEPLOY_PROXMOXBS_SERVER "$_target_hostname" + + _getdeployconf DEPLOY_PROXMOXBS_SERVER_PORT + if [ -z "$DEPLOY_PROXMOXBS_SERVER_PORT" ]; then + _target_port="8007" + else + _target_port="$DEPLOY_PROXMOXBS_SERVER_PORT" + _savedeployconf DEPLOY_PROXMOXBS_SERVER_PORT "$DEPLOY_PROXMOXBS_SERVER_PORT" + fi + _debug2 DEPLOY_PROXMOXBS_SERVER_PORT "$_target_port" + + # Complete URL. + _target_url="https://${_target_hostname}:${_target_port}/api2/json/nodes/localhost/certificates/custom" + _debug TARGET_URL "$_target_url" + + # More "sane" defaults. + _getdeployconf DEPLOY_PROXMOXBS_USER + if [ -z "$DEPLOY_PROXMOXBS_USER" ]; then + _proxmoxbs_user="root" + else + _proxmoxbs_user="$DEPLOY_PROXMOXBS_USER" + _savedeployconf DEPLOY_PROXMOXBS_USER "$DEPLOY_PROXMOXBS_USER" + fi + _debug2 DEPLOY_PROXMOXBS_USER "$_proxmoxbs_user" + + _getdeployconf DEPLOY_PROXMOXBS_USER_REALM + if [ -z "$DEPLOY_PROXMOXBS_USER_REALM" ]; then + _proxmoxbs_user_realm="pam" + else + _proxmoxbs_user_realm="$DEPLOY_PROXMOXBS_USER_REALM" + _savedeployconf DEPLOY_PROXMOXBS_USER_REALM "$DEPLOY_PROXMOXBS_USER_REALM" + fi + _debug2 DEPLOY_PROXMOXBS_USER_REALM "$_proxmoxbs_user_realm" + + _getdeployconf DEPLOY_PROXMOXBS_API_TOKEN_NAME + if [ -z "$DEPLOY_PROXMOXBS_API_TOKEN_NAME" ]; then + _proxmoxbs_api_token_name="acme" + else + _proxmoxbs_api_token_name="$DEPLOY_PROXMOXBS_API_TOKEN_NAME" + _savedeployconf DEPLOY_PROXMOXBS_API_TOKEN_NAME "$DEPLOY_PROXMOXBS_API_TOKEN_NAME" + fi + _debug2 DEPLOY_PROXMOXBS_API_TOKEN_NAME "$_proxmoxbs_api_token_name" + + # This is required. + _getdeployconf DEPLOY_PROXMOXBS_API_TOKEN_KEY + if [ -z "$DEPLOY_PROXMOXBS_API_TOKEN_KEY" ]; then + _err "API key not provided." + return 1 + else + _proxmoxbs_api_token_key="$DEPLOY_PROXMOXBS_API_TOKEN_KEY" + _savedeployconf DEPLOY_PROXMOXBS_API_TOKEN_KEY "$DEPLOY_PROXMOXBS_API_TOKEN_KEY" + fi + _debug2 DEPLOY_PROXMOXBS_API_TOKEN_KEY "$_proxmoxbs_api_token_key" + + # PBS API Token header value. Used in "Authorization: PBSAPIToken". + _proxmoxbs_header_api_token="${_proxmoxbs_user}@${_proxmoxbs_user_realm}!${_proxmoxbs_api_token_name}:${_proxmoxbs_api_token_key}" + _debug2 "Auth Header" "$_proxmoxbs_header_api_token" + + # Ugly. I hate putting heredocs inside functions because heredocs don't + # account for whitespace correctly but it _does_ work and is several times + # cleaner than anything else I had here. + # + # This dumps the json payload to a variable that should be passable to the + # _psot function. + _json_payload=$( + cat < Date: Fri, 10 Jan 2025 12:39:30 +0100 Subject: [PATCH 072/198] Portability: use `uname -n` instead of `hostname`. `hostname` is not available by default on some modern Linux distributions (eg. Arch Linux), whereas `uname -n` is defined by POSIX, so guaranteed. --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 9842e3f17a..23bd9bc046 100755 --- a/acme.sh +++ b/acme.sh @@ -6813,7 +6813,7 @@ _send_notify() { _nsource="$NOTIFY_SOURCE" if [ -z "$_nsource" ]; then - _nsource="$(hostname)" + _nsource="$(uname -n)" fi _nsubject="$_nsubject by $_nsource" From 6c555cb6663ff5903af9ae7149813c8095335206 Mon Sep 17 00:00:00 2001 From: Lindsay Zhou Date: Mon, 13 Jan 2025 10:22:46 +0800 Subject: [PATCH 073/198] fix regex of matching hetzner dns api error responses --- dnsapi/dns_hetzner.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) mode change 100644 => 100755 dnsapi/dns_hetzner.sh diff --git a/dnsapi/dns_hetzner.sh b/dnsapi/dns_hetzner.sh old mode 100644 new mode 100755 index 5a9cf2d95a..f1bddc6175 --- a/dnsapi/dns_hetzner.sh +++ b/dnsapi/dns_hetzner.sh @@ -212,7 +212,7 @@ _get_root() { _response_has_error() { unset _response_error - err_part="$(echo "$response" | _egrep_o '"error":{[^}]*}')" + err_part="$(echo "$response" | _egrep_o '"error":\{[^\}]*\}')" if [ -n "$err_part" ]; then err_code=$(echo "$err_part" | _egrep_o '"code":[0-9]+' | cut -d : -f 2) From 077868604d275b9051baa8f27f2a66654e4f0785 Mon Sep 17 00:00:00 2001 From: ARNik Date: Wed, 15 Jan 2025 09:40:31 +0300 Subject: [PATCH 074/198] dnsapi: Add Beget.com DNS API --- dnsapi/dns_beget.sh | 225 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 225 insertions(+) create mode 100755 dnsapi/dns_beget.sh diff --git a/dnsapi/dns_beget.sh b/dnsapi/dns_beget.sh new file mode 100755 index 0000000000..2df41e2e74 --- /dev/null +++ b/dnsapi/dns_beget.sh @@ -0,0 +1,225 @@ +#!/usr/bin/env sh +# shellcheck disable=SC2034 +dns_beget_info='Beget.com +Site: Beget.com +Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_beget +Options: + BEGET_User API user + BEGET_Password API password +Issues: github.com/acmesh-official/acme.sh/issues/6200 +Author: ARNik arnik@arnik.ru +' + +Beget_Api="https://api.beget.com/api" + +######## Public functions ##################### + +# Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +# Used to add txt record +dns_beget_add() { + fulldomain=$1 + txtvalue=$2 + _debug "dns_beget_add $fulldomain $txtvalue" + + Beget_Username="${Beget_Username:-$(_readaccountconf_mutable Beget_Username)}" + Beget_Password="${Beget_Password:-$(_readaccountconf_mutable Beget_Password)}" + + if [ -z "$Beget_Username" ] || [ -z "$Beget_Password" ]; then + Beget_Username="" + Beget_Password="" + _err "You must export variables: Beget_Username, and Beget_Password" + return 1 + fi + + #save the credentials to the account conf file. + _saveaccountconf_mutable Beget_Username "$Beget_Username" + _saveaccountconf_mutable Beget_Password "$Beget_Password" + + _info "First detect the root zone" + if ! _get_root "$fulldomain"; then + _err "invalid domain" + return 1 + fi + _debug _domain_id "$_domain_id" + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + if [ -n "$_sub_domain" ]; then + _debug "Create subdomen for the record" + data="{\"subdomain\":\"$_sub_domain\",\"domain_id\":$_domain_id}" + res=$(_api_call "$Beget_Api/domain/addSubdomainVirtual" "$data") + + if _contains "$res" "^{\"status\":\"success\",\"answer\":{\"status\":\"success\",\"result\":[0-9]*}}$"; then + _debug "Cleanup subdomen records" + data="{\"fqdn\":\"$fulldomain\",\"records\":{}}" + res=$(_api_call "$Beget_Api/dns/changeRecords" "$data") + data="{\"fqdn\":\"www.$fulldomain\",\"records\":{}}" + res=$(_api_call "$Beget_Api/dns/changeRecords" "$data") + fi + fi + + _info "Get current domain records" + data="{\"fqdn\":\"$fulldomain\"}" + res=$(_api_call "$Beget_Api/dns/getData" "$data") + + if ! _contains "$res" "^{\"status\":\"success\",\"answer\":{\"status\":\"success\",\"result\":{.*}}}$"; then + _err "Can't get domain records." + return 1 + fi + + _info "Add new TXT record" + data="{\"fqdn\":\"$fulldomain\",\"records\":{" + data=${data}$(_parce_records "$res" "A") + data=${data}$(_parce_records "$res" "AAAA") + data=${data}$(_parce_records "$res" "CAA") + data=${data}$(_parce_records "$res" "MX") + data=${data}$(_parce_records "$res" "SRV") + data=${data}$(_parce_records "$res" "TXT") + data=$(echo "$data" | sed 's/,$//') + data=${data}'}}' + + str=$(_txt_to_dns_json "$txtvalue") + data=$(_add_record "$data" "TXT" "$str") + + res=$(_api_call "$Beget_Api/dns/changeRecords" "$data") + + return 0 +} + +# Usage: fulldomain txtvalue +# Used to remove the txt record after validation +dns_beget_rm() { + fulldomain=$1 + txtvalue=$2 + _debug "dns_beget_rm $fulldomain $txtvalue" + + Beget_Username="${Beget_Username:-$(_readaccountconf_mutable Beget_Username)}" + Beget_Password="${Beget_Password:-$(_readaccountconf_mutable Beget_Password)}" + + _info "Get current domain records" + data="{\"fqdn\":\"$fulldomain\"}" + res=$(_api_call "$Beget_Api/dns/getData" "$data") + + if ! _contains "$res" "^{\"status\":\"success\",\"answer\":{\"status\":\"success\",\"result\":{.*}}}$"; then + _err Can\'t get domain records. + return 1 + fi + + _info "Remove TXT record" + data="{\"fqdn\":\"$fulldomain\",\"records\":{" + data=${data}$(_parce_records "$res" "A") + data=${data}$(_parce_records "$res" "AAAA") + data=${data}$(_parce_records "$res" "CAA") + data=${data}$(_parce_records "$res" "MX") + data=${data}$(_parce_records "$res" "SRV") + data=${data}$(_parce_records "$res" "TXT") + data=$(echo "$data" | sed 's/,$//') + data=${data}'}}' + + str=$(_txt_to_dns_json "$txtvalue") + data=$(_rm_record "$data" "$str") + + res=$(_api_call "$Beget_Api/dns/changeRecords" "$data") + + return 0 +} + +#################### Private functions below ################################## + +# Usage: _get_root _acme-challenge.www.domain.com +#returns +# _sub_domain=_acme-challenge.www +# _domain=domain.com +# _domain_id=32436365 +_get_root() { + fulldomain=$1 + i=1 + p=1 + + _debug "Request domain list" + res=$(_api_call "$Beget_Api/domain/getList") + + while true; do + h=$(printf "%s" "$fulldomain" | cut -d . -f "$i"-100) + _debug h "$h" + + if [ -z "$h" ]; then + return 1 + fi + + if _contains "$res" "$h"; then + _domain_id=$(echo "$res" | _egrep_o "\"id\":[0-9]*,\"fqdn\":\"$h\"" | cut -d , -f1 | cut -d : -f2) + if [ "$_domain_id" ]; then + if [ "$h" != "$fulldomain" ]; then + _sub_domain=$(echo "$fulldomain" | cut -d . -f 1-"$p") + else + _sub_domain="" + fi + _domain=$h + return 0 + fi + return 1 + fi + p="$i" + i=$(_math "$i" + 1) + done + return 1 +} + +# Parce DNS records from json string +# Usage: _parce_records [j_str] [record_name] +_parce_records() { + j_str=$1 + record_name=$2 + res="\"$record_name\":[" + res=${res}$(echo "$j_str" | _egrep_o "\"$record_name\":\[.*" | cut -d '[' -f2 | cut -d ']' -f1) + res=${res}"]," + echo "$res" +} + +# Usage: _add_record [data] [record_name] [record_data] +_add_record() { + data=$1 + record_name=$2 + record_data=$3 + echo "$data" | sed "s/\"$record_name\":\[/\"$record_name\":\[$record_data,/" | sed "s/,\]/\]/" +} + +# Usage: _rm_record [data] [record_data] +_rm_record() { + data=$1 + record_data=$2 + echo "$data" | sed "s/$record_data,//" | sed "s/,$record_data//" | sed "s/$record_data//" +} + +_txt_to_dns_json() { + echo "{\"ttl\":600,\"txtdata\":\"$1\"}" +} + +# Usage: _api_call [api_url] [input_data] +_api_call() { + api_url="$1" + input_data="$2" + + _debug "_api_call $api_url" + _debug "Request: $input_data" + + # res=$(curl -s -L -D ./http.header \ + # "$api_url" \ + # --data-urlencode login=$Beget_Username \ + # --data-urlencode passwd=$Beget_Password \ + # --data-urlencode input_format=json \ + # --data-urlencode output_format=json \ + # --data-urlencode "input_data=$input_data") + + url="$api_url?login=$Beget_Username&passwd=$Beget_Password&input_format=json&output_format=json" + if [ -n "$input_data" ]; then + url=${url}"&input_data=" + url=${url}$(echo "$input_data" | _url_encode) + fi + + res=$(_get "$url") + + _debug "Reply: $res" + echo "$res" +} From 66dd51a09a0baadcf4f481a28e58c17881cff6ae Mon Sep 17 00:00:00 2001 From: ARNik Date: Thu, 16 Jan 2025 16:28:12 +0300 Subject: [PATCH 075/198] dnsapi: check Beget.com API replies --- dnsapi/dns_beget.sh | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/dnsapi/dns_beget.sh b/dnsapi/dns_beget.sh index 2df41e2e74..3e738e3f30 100755 --- a/dnsapi/dns_beget.sh +++ b/dnsapi/dns_beget.sh @@ -19,7 +19,7 @@ Beget_Api="https://api.beget.com/api" dns_beget_add() { fulldomain=$1 txtvalue=$2 - _debug "dns_beget_add $fulldomain $txtvalue" + _debug "dns_beget_add() $fulldomain $txtvalue" Beget_Username="${Beget_Username:-$(_readaccountconf_mutable Beget_Username)}" Beget_Password="${Beget_Password:-$(_readaccountconf_mutable Beget_Password)}" @@ -49,20 +49,27 @@ dns_beget_add() { data="{\"subdomain\":\"$_sub_domain\",\"domain_id\":$_domain_id}" res=$(_api_call "$Beget_Api/domain/addSubdomainVirtual" "$data") - if _contains "$res" "^{\"status\":\"success\",\"answer\":{\"status\":\"success\",\"result\":[0-9]*}}$"; then + if _is_api_reply_ok "$res"; then _debug "Cleanup subdomen records" data="{\"fqdn\":\"$fulldomain\",\"records\":{}}" res=$(_api_call "$Beget_Api/dns/changeRecords" "$data") + if ! _is_api_reply_ok "$res"; then + _err "Can't cleanup subdomain records." + return 1 + fi data="{\"fqdn\":\"www.$fulldomain\",\"records\":{}}" res=$(_api_call "$Beget_Api/dns/changeRecords" "$data") + if ! _is_api_reply_ok "$res"; then + _err "Can't cleanup subdomain records." + return 1 + fi fi fi _info "Get current domain records" data="{\"fqdn\":\"$fulldomain\"}" res=$(_api_call "$Beget_Api/dns/getData" "$data") - - if ! _contains "$res" "^{\"status\":\"success\",\"answer\":{\"status\":\"success\",\"result\":{.*}}}$"; then + if ! _is_api_reply_ok "$res"; then _err "Can't get domain records." return 1 fi @@ -82,6 +89,10 @@ dns_beget_add() { data=$(_add_record "$data" "TXT" "$str") res=$(_api_call "$Beget_Api/dns/changeRecords" "$data") + if ! _is_api_reply_ok "$res"; then + _err "Can't change domain records." + return 1 + fi return 0 } @@ -91,7 +102,7 @@ dns_beget_add() { dns_beget_rm() { fulldomain=$1 txtvalue=$2 - _debug "dns_beget_rm $fulldomain $txtvalue" + _debug "dns_beget_rm() $fulldomain $txtvalue" Beget_Username="${Beget_Username:-$(_readaccountconf_mutable Beget_Username)}" Beget_Password="${Beget_Password:-$(_readaccountconf_mutable Beget_Password)}" @@ -99,9 +110,8 @@ dns_beget_rm() { _info "Get current domain records" data="{\"fqdn\":\"$fulldomain\"}" res=$(_api_call "$Beget_Api/dns/getData" "$data") - - if ! _contains "$res" "^{\"status\":\"success\",\"answer\":{\"status\":\"success\",\"result\":{.*}}}$"; then - _err Can\'t get domain records. + if ! _is_api_reply_ok "$res"; then + _err "Can't get domain records." return 1 fi @@ -120,6 +130,10 @@ dns_beget_rm() { data=$(_rm_record "$data" "$str") res=$(_api_call "$Beget_Api/dns/changeRecords" "$data") + if ! _is_api_reply_ok "$res"; then + _err "Can't change domain records." + return 1 + fi return 0 } @@ -138,6 +152,10 @@ _get_root() { _debug "Request domain list" res=$(_api_call "$Beget_Api/domain/getList") + if ! _is_api_reply_ok "$res"; then + _err "Can't get domain list." + return 1 + fi while true; do h=$(printf "%s" "$fulldomain" | cut -d . -f "$i"-100) @@ -217,9 +235,13 @@ _api_call() { url=${url}"&input_data=" url=${url}$(echo "$input_data" | _url_encode) fi - res=$(_get "$url") _debug "Reply: $res" echo "$res" } + +# Usage: _is_api_reply_ok [api_reply] +_is_api_reply_ok() { + _contains "$1" '^{"status":"success","answer":{"status":"success","result":.*}}$' +} From 2fef0ebea83a792f437123fd90128d3192d240c8 Mon Sep 17 00:00:00 2001 From: ARNik Date: Thu, 16 Jan 2025 20:14:07 +0300 Subject: [PATCH 076/198] dnsapi: Beget.com subdomain preparation rework --- dnsapi/dns_beget.sh | 94 ++++++++++++++++++++++++++++++--------------- 1 file changed, 62 insertions(+), 32 deletions(-) diff --git a/dnsapi/dns_beget.sh b/dnsapi/dns_beget.sh index 3e738e3f30..0213e3effe 100755 --- a/dnsapi/dns_beget.sh +++ b/dnsapi/dns_beget.sh @@ -12,7 +12,7 @@ Author: ARNik arnik@arnik.ru Beget_Api="https://api.beget.com/api" -######## Public functions ##################### +#################### Public functions #################### # Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" # Used to add txt record @@ -35,38 +35,13 @@ dns_beget_add() { _saveaccountconf_mutable Beget_Username "$Beget_Username" _saveaccountconf_mutable Beget_Password "$Beget_Password" - _info "First detect the root zone" - if ! _get_root "$fulldomain"; then - _err "invalid domain" + _info "Prepare subdomain." + if ! _prepare_subdomain "$fulldomain"; then + _err "Can't prepare subdomain." return 1 fi - _debug _domain_id "$_domain_id" - _debug _sub_domain "$_sub_domain" - _debug _domain "$_domain" - if [ -n "$_sub_domain" ]; then - _debug "Create subdomen for the record" - data="{\"subdomain\":\"$_sub_domain\",\"domain_id\":$_domain_id}" - res=$(_api_call "$Beget_Api/domain/addSubdomainVirtual" "$data") - - if _is_api_reply_ok "$res"; then - _debug "Cleanup subdomen records" - data="{\"fqdn\":\"$fulldomain\",\"records\":{}}" - res=$(_api_call "$Beget_Api/dns/changeRecords" "$data") - if ! _is_api_reply_ok "$res"; then - _err "Can't cleanup subdomain records." - return 1 - fi - data="{\"fqdn\":\"www.$fulldomain\",\"records\":{}}" - res=$(_api_call "$Beget_Api/dns/changeRecords" "$data") - if ! _is_api_reply_ok "$res"; then - _err "Can't cleanup subdomain records." - return 1 - fi - fi - fi - - _info "Get current domain records" + _info "Get domain records" data="{\"fqdn\":\"$fulldomain\"}" res=$(_api_call "$Beget_Api/dns/getData" "$data") if ! _is_api_reply_ok "$res"; then @@ -138,7 +113,62 @@ dns_beget_rm() { return 0 } -#################### Private functions below ################################## +#################### Private functions below #################### + +# Create subdomain if needed +# Usage: _prepare_subdomain [fulldomain] +_prepare_subdomain() { + fulldomain=$1 + + _info "Detect the root zone" + if ! _get_root "$fulldomain"; then + _err "invalid domain" + return 1 + fi + _debug _domain_id "$_domain_id" + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + if [ -z "$_sub_domain" ]; then + _debug "$fulldomain is a root domain." + return 0 + fi + + _info "Get subdomain list" + res=$(_api_call "$Beget_Api/domain/getSubdomainList") + if ! _is_api_reply_ok "$res"; then + _err "Can't get subdomain list." + return 1 + fi + + if _contains "$res" "\"fqdn\":\"$fulldomain\""; then + _debug "Subdomain $fulldomain already exist." + return 0 + fi + + _info "Subdomain $fulldomain does not exist. Let's create one." + data="{\"subdomain\":\"$_sub_domain\",\"domain_id\":$_domain_id}" + res=$(_api_call "$Beget_Api/domain/addSubdomainVirtual" "$data") + if ! _is_api_reply_ok "$res"; then + _err "Can't create subdomain." + return 1 + fi + + _debug "Cleanup subdomen records" + data="{\"fqdn\":\"$fulldomain\",\"records\":{}}" + res=$(_api_call "$Beget_Api/dns/changeRecords" "$data") + if ! _is_api_reply_ok "$res"; then + _debug "Can't cleanup $fulldomain records." + fi + + data="{\"fqdn\":\"www.$fulldomain\",\"records\":{}}" + res=$(_api_call "$Beget_Api/dns/changeRecords" "$data") + if ! _is_api_reply_ok "$res"; then + _debug "Can't cleanup www.$fulldomain records." + fi + + return 0 +} # Usage: _get_root _acme-challenge.www.domain.com #returns @@ -150,7 +180,7 @@ _get_root() { i=1 p=1 - _debug "Request domain list" + _debug "Get domain list" res=$(_api_call "$Beget_Api/domain/getList") if ! _is_api_reply_ok "$res"; then _err "Can't get domain list." From aa6feb4b62b269c335e15a19ef65ab42dcd6a6be Mon Sep 17 00:00:00 2001 From: ARNik Date: Thu, 16 Jan 2025 19:25:56 +0300 Subject: [PATCH 077/198] dnsapi: Beget.com fix rm record --- dnsapi/dns_beget.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dnsapi/dns_beget.sh b/dnsapi/dns_beget.sh index 0213e3effe..e570fa108c 100755 --- a/dnsapi/dns_beget.sh +++ b/dnsapi/dns_beget.sh @@ -237,7 +237,9 @@ _add_record() { _rm_record() { data=$1 record_data=$2 - echo "$data" | sed "s/$record_data,//" | sed "s/,$record_data//" | sed "s/$record_data//" + echo "$data" | sed "s/$record_data//g" | sed "s/,\+/,/g" | + sed "s/{,/{/g" | sed "s/,}/}/g" | + sed "s/\[,/\[/g" | sed "s/,\]/\]/g" } _txt_to_dns_json() { From 26a5d48f634a49036a4de6e1a78962fa066179a9 Mon Sep 17 00:00:00 2001 From: ARNik Date: Thu, 16 Jan 2025 21:49:31 +0300 Subject: [PATCH 078/198] dnsapi: Beget.com fix case-sensitive domain names --- dnsapi/dns_beget.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dnsapi/dns_beget.sh b/dnsapi/dns_beget.sh index e570fa108c..aa43caedbc 100755 --- a/dnsapi/dns_beget.sh +++ b/dnsapi/dns_beget.sh @@ -20,6 +20,7 @@ dns_beget_add() { fulldomain=$1 txtvalue=$2 _debug "dns_beget_add() $fulldomain $txtvalue" + fulldomain=$(echo "$fulldomain" | _lower_case) Beget_Username="${Beget_Username:-$(_readaccountconf_mutable Beget_Username)}" Beget_Password="${Beget_Password:-$(_readaccountconf_mutable Beget_Password)}" @@ -78,6 +79,7 @@ dns_beget_rm() { fulldomain=$1 txtvalue=$2 _debug "dns_beget_rm() $fulldomain $txtvalue" + fulldomain=$(echo "$fulldomain" | _lower_case) Beget_Username="${Beget_Username:-$(_readaccountconf_mutable Beget_Username)}" Beget_Password="${Beget_Password:-$(_readaccountconf_mutable Beget_Password)}" From 6dbe49089e2ed8e53d5110c528e2f7099c968b3c Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 25 Jan 2025 21:00:25 +0100 Subject: [PATCH 079/198] minor --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 2ad50e6ac6..3f400283c6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,11 +15,11 @@ RUN apk --no-cache add -f \ jq \ cronie -ENV LE_CONFIG_HOME /acme.sh +ENV LE_CONFIG_HOME=/acme.sh ARG AUTO_UPGRADE=1 -ENV AUTO_UPGRADE $AUTO_UPGRADE +ENV AUTO_UPGRADE=$AUTO_UPGRADE #Install COPY ./ /install_acme.sh/ From def41a787899098eb014b669ca56116b2fd2ad76 Mon Sep 17 00:00:00 2001 From: David Ha Date: Sun, 9 Feb 2025 22:56:46 +0000 Subject: [PATCH 080/198] Fix bug saving SYNO_LOCAL_HOSTNAME Exporting SYNO_LOCAL_HOSTNAME=1 only works on the first deploy invocation. Subsequent deploys using the saved config fails because it saves $SYNO_HOSTNAME instead of $SYNO_LOCAL_HOSTNAME. --- deploy/synology_dsm.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deploy/synology_dsm.sh b/deploy/synology_dsm.sh index 0d01e199bf..5ea48ca10f 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -186,7 +186,7 @@ synology_dsm_deploy() { if [ -n "$SYNO_USE_TEMP_ADMIN" ]; then _getdeployconf SYNO_LOCAL_HOSTNAME _debug SYNO_LOCAL_HOSTNAME "${SYNO_LOCAL_HOSTNAME:-}" - if [ "$SYNO_LOCAL_HOSTNAME" != "1" ] && [ "$SYNO_LOCAL_HOSTNAME" == "$SYNO_HOSTNAME" ]; then + if [ "$SYNO_LOCAL_HOSTNAME" != "1" ]; then if [ "$SYNO_HOSTNAME" != "localhost" ] && [ "$SYNO_HOSTNAME" != "127.0.0.1" ]; then _err "SYNO_USE_TEMP_ADMIN=1 only support local deployment, though if you are sure that the hostname $SYNO_HOSTNAME is targeting to your **current local machine**, execute 'export SYNO_LOCAL_HOSTNAME=1' then rerun." return 1 @@ -320,7 +320,7 @@ synology_dsm_deploy() { _cleardeployconf SYNO_DEVICE_ID _cleardeployconf SYNO_DEVICE_NAME _savedeployconf SYNO_USE_TEMP_ADMIN "$SYNO_USE_TEMP_ADMIN" - _savedeployconf SYNO_LOCAL_HOSTNAME "$SYNO_HOSTNAME" + _savedeployconf SYNO_LOCAL_HOSTNAME "$SYNO_LOCAL_HOSTNAME" else _savedeployconf SYNO_USERNAME "$SYNO_USERNAME" _savedeployconf SYNO_PASSWORD "$SYNO_PASSWORD" From 899da0c6ea0fabd0709f185ef1dd3ee880bf2068 Mon Sep 17 00:00:00 2001 From: David Ha Date: Sun, 9 Feb 2025 23:43:55 +0000 Subject: [PATCH 081/198] Update synology_dsm.sh fix check logic --- deploy/synology_dsm.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deploy/synology_dsm.sh b/deploy/synology_dsm.sh index 5ea48ca10f..0c3dfb9568 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -186,8 +186,8 @@ synology_dsm_deploy() { if [ -n "$SYNO_USE_TEMP_ADMIN" ]; then _getdeployconf SYNO_LOCAL_HOSTNAME _debug SYNO_LOCAL_HOSTNAME "${SYNO_LOCAL_HOSTNAME:-}" - if [ "$SYNO_LOCAL_HOSTNAME" != "1" ]; then - if [ "$SYNO_HOSTNAME" != "localhost" ] && [ "$SYNO_HOSTNAME" != "127.0.0.1" ]; then + if [ "$SYNO_HOSTNAME" != "localhost" ] && [ "$SYNO_HOSTNAME" != "127.0.0.1" ]; then + if [ "$SYNO_LOCAL_HOSTNAME" != "1" ]; then _err "SYNO_USE_TEMP_ADMIN=1 only support local deployment, though if you are sure that the hostname $SYNO_HOSTNAME is targeting to your **current local machine**, execute 'export SYNO_LOCAL_HOSTNAME=1' then rerun." return 1 fi From b2eb70439489ada91988276d6cbf2f116b2aac36 Mon Sep 17 00:00:00 2001 From: tomo <49612544+tomo2403@users.noreply.github.com> Date: Sat, 15 Feb 2025 15:16:52 +0100 Subject: [PATCH 082/198] allowed deploying of pfx cert --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 9842e3f17a..1f3b9c93ae 100755 --- a/acme.sh +++ b/acme.sh @@ -5818,7 +5818,7 @@ _deploy() { return 1 fi - if ! $d_command "$_d" "$CERT_KEY_PATH" "$CERT_PATH" "$CA_CERT_PATH" "$CERT_FULLCHAIN_PATH"; then + if ! $d_command "$_d" "$CERT_KEY_PATH" "$CERT_PATH" "$CA_CERT_PATH" "$CERT_FULLCHAIN_PATH" "$CERT_PFX_PATH"; then _err "Error deploying for domain: $_d" return 1 fi From 7f19f8cf0ec8bb151e99a33e86ccfa15066734e8 Mon Sep 17 00:00:00 2001 From: tomo <49612544+tomo2403@users.noreply.github.com> Date: Sat, 15 Feb 2025 15:18:10 +0100 Subject: [PATCH 083/198] implemented deploying pfx to docker container --- deploy/docker.sh | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/deploy/docker.sh b/deploy/docker.sh index c9815d5b93..264963aedd 100755 --- a/deploy/docker.sh +++ b/deploy/docker.sh @@ -18,6 +18,7 @@ docker_deploy() { _ccert="$3" _cca="$4" _cfullchain="$5" + _cpfx="$6" _debug _cdomain "$_cdomain" _getdeployconf DEPLOY_DOCKER_CONTAINER_LABEL _debug2 DEPLOY_DOCKER_CONTAINER_LABEL "$DEPLOY_DOCKER_CONTAINER_LABEL" @@ -88,6 +89,12 @@ docker_deploy() { _savedeployconf DEPLOY_DOCKER_CONTAINER_FULLCHAIN_FILE "$DEPLOY_DOCKER_CONTAINER_FULLCHAIN_FILE" fi + _getdeployconf DEPLOY_DOCKER_CONTAINER_PFX_FILE + _debug2 DEPLOY_DOCKER_CONTAINER_PFX_FILE "$DEPLOY_DOCKER_CONTAINER_PFX_FILE" + if [ "$DEPLOY_DOCKER_CONTAINER_PFX_FILE" ]; then + _savedeployconf DEPLOY_DOCKER_CONTAINER_PFX_FILE "$DEPLOY_DOCKER_CONTAINER_PFX_FILE" + fi + _getdeployconf DEPLOY_DOCKER_CONTAINER_RELOAD_CMD _debug2 DEPLOY_DOCKER_CONTAINER_RELOAD_CMD "$DEPLOY_DOCKER_CONTAINER_RELOAD_CMD" if [ "$DEPLOY_DOCKER_CONTAINER_RELOAD_CMD" ]; then @@ -125,6 +132,12 @@ docker_deploy() { fi fi + if [ "$DEPLOY_DOCKER_CONTAINER_PFX_FILE" ]; then + if ! _docker_cp "$_cid" "$_cpfx" "$DEPLOY_DOCKER_CONTAINER_PFX_FILE"; then + return 1 + fi + fi + if [ "$DEPLOY_DOCKER_CONTAINER_RELOAD_CMD" ]; then _info "Reloading: $DEPLOY_DOCKER_CONTAINER_RELOAD_CMD" if ! _docker_exec "$_cid" "$DEPLOY_DOCKER_CONTAINER_RELOAD_CMD"; then From 449c542d5ae2d5fd8a5938a60d0d3a6e1376867d Mon Sep 17 00:00:00 2001 From: tomo <49612544+tomo2403@users.noreply.github.com> Date: Sat, 15 Feb 2025 17:16:07 +0100 Subject: [PATCH 084/198] fixed env warning while building --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 2ad50e6ac6..3f400283c6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,11 +15,11 @@ RUN apk --no-cache add -f \ jq \ cronie -ENV LE_CONFIG_HOME /acme.sh +ENV LE_CONFIG_HOME=/acme.sh ARG AUTO_UPGRADE=1 -ENV AUTO_UPGRADE $AUTO_UPGRADE +ENV AUTO_UPGRADE=$AUTO_UPGRADE #Install COPY ./ /install_acme.sh/ From 091c1f7ef10db6fa6401cc8fb416dbca275edccb Mon Sep 17 00:00:00 2001 From: Scruel Tao Date: Thu, 20 Feb 2025 17:16:23 +0800 Subject: [PATCH 085/198] chore(synology): remove personal mail --- deploy/synology_dsm.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/synology_dsm.sh b/deploy/synology_dsm.sh index 0c3dfb9568..3bfc9b02fb 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -411,7 +411,7 @@ _temp_admin_create() { _username="$1" _password="$2" synouser --del "$_username" >/dev/null 2>/dev/null - synouser --add "$_username" "$_password" "" 0 "scruelt@hotmail.com" 0 >/dev/null + synouser --add "$_username" "$_password" "" 0 "" 0 >/dev/null } _temp_admin_cleanup() { From 1d628bcf9e50a45089a33833dd40e5b1da20b323 Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Sat, 22 Feb 2025 18:56:15 +0100 Subject: [PATCH 086/198] dns_world4you: Adapt to change in world4you.com --- dnsapi/dns_world4you.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index 0febbad9c2..46cdc4fed5 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -202,7 +202,7 @@ _get_paketnr() { fqdn="$1" form="$2" - domains=$(echo "$form" | grep '