You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

225 lines
6.2 KiB

  1. #!/usr/bin/env sh
  2. # shellcheck disable=SC2034
  3. dns_beget_info='Beget.com
  4. Site: Beget.com
  5. Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_beget
  6. Options:
  7. BEGET_User API user
  8. BEGET_Password API password
  9. Issues: github.com/acmesh-official/acme.sh/issues/6200
  10. Author: ARNik arnik@arnik.ru
  11. '
  12. Beget_Api="https://api.beget.com/api"
  13. ######## Public functions #####################
  14. # Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
  15. # Used to add txt record
  16. dns_beget_add() {
  17. fulldomain=$1
  18. txtvalue=$2
  19. _debug "dns_beget_add $fulldomain $txtvalue"
  20. Beget_Username="${Beget_Username:-$(_readaccountconf_mutable Beget_Username)}"
  21. Beget_Password="${Beget_Password:-$(_readaccountconf_mutable Beget_Password)}"
  22. if [ -z "$Beget_Username" ] || [ -z "$Beget_Password" ]; then
  23. Beget_Username=""
  24. Beget_Password=""
  25. _err "You must export variables: Beget_Username, and Beget_Password"
  26. return 1
  27. fi
  28. #save the credentials to the account conf file.
  29. _saveaccountconf_mutable Beget_Username "$Beget_Username"
  30. _saveaccountconf_mutable Beget_Password "$Beget_Password"
  31. _info "First detect the root zone"
  32. if ! _get_root "$fulldomain"; then
  33. _err "invalid domain"
  34. return 1
  35. fi
  36. _debug _domain_id "$_domain_id"
  37. _debug _sub_domain "$_sub_domain"
  38. _debug _domain "$_domain"
  39. if [ -n "$_sub_domain" ]; then
  40. _debug "Create subdomen for the record"
  41. data="{\"subdomain\":\"$_sub_domain\",\"domain_id\":$_domain_id}"
  42. res=$(_api_call "$Beget_Api/domain/addSubdomainVirtual" "$data")
  43. if _contains "$res" "^{\"status\":\"success\",\"answer\":{\"status\":\"success\",\"result\":[0-9]*}}$"; then
  44. _debug "Cleanup subdomen records"
  45. data="{\"fqdn\":\"$fulldomain\",\"records\":{}}"
  46. res=$(_api_call "$Beget_Api/dns/changeRecords" "$data")
  47. data="{\"fqdn\":\"www.$fulldomain\",\"records\":{}}"
  48. res=$(_api_call "$Beget_Api/dns/changeRecords" "$data")
  49. fi
  50. fi
  51. _info "Get current domain records"
  52. data="{\"fqdn\":\"$fulldomain\"}"
  53. res=$(_api_call "$Beget_Api/dns/getData" "$data")
  54. if ! _contains "$res" "^{\"status\":\"success\",\"answer\":{\"status\":\"success\",\"result\":{.*}}}$"; then
  55. _err "Can't get domain records."
  56. return 1
  57. fi
  58. _info "Add new TXT record"
  59. data="{\"fqdn\":\"$fulldomain\",\"records\":{"
  60. data=${data}$(_parce_records "$res" "A")
  61. data=${data}$(_parce_records "$res" "AAAA")
  62. data=${data}$(_parce_records "$res" "CAA")
  63. data=${data}$(_parce_records "$res" "MX")
  64. data=${data}$(_parce_records "$res" "SRV")
  65. data=${data}$(_parce_records "$res" "TXT")
  66. data=$(echo "$data" | sed 's/,$//')
  67. data=${data}'}}'
  68. str=$(_txt_to_dns_json "$txtvalue")
  69. data=$(_add_record "$data" "TXT" "$str")
  70. res=$(_api_call "$Beget_Api/dns/changeRecords" "$data")
  71. return 0
  72. }
  73. # Usage: fulldomain txtvalue
  74. # Used to remove the txt record after validation
  75. dns_beget_rm() {
  76. fulldomain=$1
  77. txtvalue=$2
  78. _debug "dns_beget_rm $fulldomain $txtvalue"
  79. Beget_Username="${Beget_Username:-$(_readaccountconf_mutable Beget_Username)}"
  80. Beget_Password="${Beget_Password:-$(_readaccountconf_mutable Beget_Password)}"
  81. _info "Get current domain records"
  82. data="{\"fqdn\":\"$fulldomain\"}"
  83. res=$(_api_call "$Beget_Api/dns/getData" "$data")
  84. if ! _contains "$res" "^{\"status\":\"success\",\"answer\":{\"status\":\"success\",\"result\":{.*}}}$"; then
  85. _err Can\'t get domain records.
  86. return 1
  87. fi
  88. _info "Remove TXT record"
  89. data="{\"fqdn\":\"$fulldomain\",\"records\":{"
  90. data=${data}$(_parce_records "$res" "A")
  91. data=${data}$(_parce_records "$res" "AAAA")
  92. data=${data}$(_parce_records "$res" "CAA")
  93. data=${data}$(_parce_records "$res" "MX")
  94. data=${data}$(_parce_records "$res" "SRV")
  95. data=${data}$(_parce_records "$res" "TXT")
  96. data=$(echo "$data" | sed 's/,$//')
  97. data=${data}'}}'
  98. str=$(_txt_to_dns_json "$txtvalue")
  99. data=$(_rm_record "$data" "$str")
  100. res=$(_api_call "$Beget_Api/dns/changeRecords" "$data")
  101. return 0
  102. }
  103. #################### Private functions below ##################################
  104. # Usage: _get_root _acme-challenge.www.domain.com
  105. #returns
  106. # _sub_domain=_acme-challenge.www
  107. # _domain=domain.com
  108. # _domain_id=32436365
  109. _get_root() {
  110. fulldomain=$1
  111. i=1
  112. p=1
  113. _debug "Request domain list"
  114. res=$(_api_call "$Beget_Api/domain/getList")
  115. while true; do
  116. h=$(printf "%s" "$fulldomain" | cut -d . -f "$i"-100)
  117. _debug h "$h"
  118. if [ -z "$h" ]; then
  119. return 1
  120. fi
  121. if _contains "$res" "$h"; then
  122. _domain_id=$(echo "$res" | _egrep_o "\"id\":[0-9]*,\"fqdn\":\"$h\"" | cut -d , -f1 | cut -d : -f2)
  123. if [ "$_domain_id" ]; then
  124. if [ "$h" != "$fulldomain" ]; then
  125. _sub_domain=$(echo "$fulldomain" | cut -d . -f 1-"$p")
  126. else
  127. _sub_domain=""
  128. fi
  129. _domain=$h
  130. return 0
  131. fi
  132. return 1
  133. fi
  134. p="$i"
  135. i=$(_math "$i" + 1)
  136. done
  137. return 1
  138. }
  139. # Parce DNS records from json string
  140. # Usage: _parce_records [j_str] [record_name]
  141. _parce_records() {
  142. j_str=$1
  143. record_name=$2
  144. res="\"$record_name\":["
  145. res=${res}$(echo "$j_str" | _egrep_o "\"$record_name\":\[.*" | cut -d '[' -f2 | cut -d ']' -f1)
  146. res=${res}"],"
  147. echo "$res"
  148. }
  149. # Usage: _add_record [data] [record_name] [record_data]
  150. _add_record() {
  151. data=$1
  152. record_name=$2
  153. record_data=$3
  154. echo "$data" | sed "s/\"$record_name\":\[/\"$record_name\":\[$record_data,/" | sed "s/,\]/\]/"
  155. }
  156. # Usage: _rm_record [data] [record_data]
  157. _rm_record() {
  158. data=$1
  159. record_data=$2
  160. echo "$data" | sed "s/$record_data,//" | sed "s/,$record_data//" | sed "s/$record_data//"
  161. }
  162. _txt_to_dns_json() {
  163. echo "{\"ttl\":600,\"txtdata\":\"$1\"}"
  164. }
  165. # Usage: _api_call [api_url] [input_data]
  166. _api_call() {
  167. api_url="$1"
  168. input_data="$2"
  169. _debug "_api_call $api_url"
  170. _debug "Request: $input_data"
  171. # res=$(curl -s -L -D ./http.header \
  172. # "$api_url" \
  173. # --data-urlencode login=$Beget_Username \
  174. # --data-urlencode passwd=$Beget_Password \
  175. # --data-urlencode input_format=json \
  176. # --data-urlencode output_format=json \
  177. # --data-urlencode "input_data=$input_data")
  178. url="$api_url?login=$Beget_Username&passwd=$Beget_Password&input_format=json&output_format=json"
  179. if [ -n "$input_data" ]; then
  180. url=${url}"&input_data="
  181. url=${url}$(echo "$input_data" | _url_encode)
  182. fi
  183. res=$(_get "$url")
  184. _debug "Reply: $res"
  185. echo "$res"
  186. }