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 01/73] 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 1b09882d..f5b6b1b9 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 02/73] 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 f5b6b1b9..99f031dd 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 03/73] 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 99f031dd..73210164 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 04/73] 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 73210164..04c9a388 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 05/73] 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 04c9a388..f5b6b1b9 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 06/73] 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 f5b6b1b9..99f031dd 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 07/73] 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 99f031dd..73210164 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 08/73] 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 73210164..4806773d 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 09/73] 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 4806773d..65729804 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 10/73] 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 65729804..9868cb12 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 11/73] 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 9868cb12..d4ca13b2 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 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 12/73] 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 c8aa2db7..511ab7f5 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 13/73] 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 00000000..7338ab18 --- /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 14/73] 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 7338ab18..44e6783e 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 15/73] 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 44e6783e..95ec290b 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 16/73] 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 95ec290b..0893f938 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 17/73] 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 00000000..b5ba51ab --- /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 18/73] 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 687b99bc..8609adf6 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 30db45ad..07e0c48c 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 19/73] 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 b5ba51ab..4b3a5c72 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 20/73] 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 4b3a5c72..952cfc42 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 21/73] 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 952cfc42..3ee983a3 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 22/73] 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 3ee983a3..7292987b 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 23/73] 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 7292987b..940cde2e 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 24/73] 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 4d8c058e..706b24e8 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 03e9c612b9138a8174aaf8a3a9c81b7866fdbccf Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 20 Dec 2024 10:34:51 +0100 Subject: [PATCH 25/73] 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 4d8c058e..9ee7114c 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 26/73] 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 9ee7114c..9ae54f2b 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 27/73] fix format --- deploy/unifi.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/deploy/unifi.sh b/deploy/unifi.sh index 9ae54f2b..23784099 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 28/73] fix format --- deploy/unifi.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/deploy/unifi.sh b/deploy/unifi.sh index 23784099..a50b06ff 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 29/73] fix format --- deploy/unifi.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deploy/unifi.sh b/deploy/unifi.sh index a50b06ff..1c9dfb44 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 30/73] 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 511ab7f5..7782fa44 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 31/73] 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 7782fa44..309c6b17 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 32/73] 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 00000000..5caf5a22 --- /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 33/73] 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 5caf5a22..e8ad398d 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 34/73] 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 e8ad398d..55cd49a2 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 35/73] 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 55cd49a2..0e279a98 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 36/73] 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 0e279a98..16d652b7 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 37/73] 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 16d652b7..62b0c144 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 38/73] 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 62b0c144..e3f5bb60 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 39/73] 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 e3f5bb60..5a5634dd 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 40/73] 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 5a5634dd..2cd9a865 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 41/73] 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 309c6b17..1e1a769a 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 42/73] 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 1e1a769a..434bc483 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 43/73] 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 44/73] 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 2cd9a865..760602c3 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 45/73] 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 760602c3..3b0fc3f5 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 46/73] 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 3b0fc3f5..ea204353 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 47/73] 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 ea204353..5fe43d93 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 48/73] 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 ea204353..5fe43d93 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 49/73] 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 5fe43d93..6dc9b8e0 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 50/73] 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 6dc9b8e0..c1f74389 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 51/73] 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 3f0dfa3d..03feaf63 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 a50db97c..7bc0dd48 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 df01d8cf..77553f3c 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 52/73] 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 699436ef..b52d65d9 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 53/73] 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 fb12f8c6..96bae77f 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 d0bb7d49..b873bfc0 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 54/73] 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 b52d65d9..9dafc702 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 55/73] 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 706b24e8..3e57f198 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 56/73] 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 96bae77f..5734be9e 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 c9f5eb9f..101854d5 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 5c137c3f..df080bcf 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 b584fad2..2dec9934 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 2478e19f..ec19ad25 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 c6b6053d..18d01361 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 57/73] 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 407395a3..6a008bd7 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 58/73] 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 04a515aa..b5ab8369 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 59/73] 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 b5ab8369..9a95d317 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 60/73] 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 9a95d317..5510bfc2 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 61/73] 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 5510bfc2..9a95d317 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 62/73] 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 9a95d317..175877c6 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 63/73] 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 175877c6..4b0dbfc0 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 64/73] 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 4b0dbfc0..a585e772 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 65/73] 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 0893f938..7d56104c 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 66/73] Correct typo in acme.sh --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 9842e3f1..bcd6b928 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 67/73] 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 00000000..d1146454 --- /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 68/73] 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 9842e3f1..23bd9bc0 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 077868604d275b9051baa8f27f2a66654e4f0785 Mon Sep 17 00:00:00 2001 From: ARNik Date: Wed, 15 Jan 2025 09:40:31 +0300 Subject: [PATCH 69/73] 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 00000000..2df41e2e --- /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 70/73] 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 2df41e2e..3e738e3f 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 71/73] 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 3e738e3f..0213e3ef 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 72/73] 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 0213e3ef..e570fa10 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 73/73] 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 e570fa10..aa43caed 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)}"