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.

179 lines
5.8 KiB

  1. #!/usr/bin/env sh
  2. # -*- mode: sh; tab-width: 2; indent-tabs-mode: s; coding: utf-8 -*-
  3. # This is the west.cn api v2.0 wrapper for acme.sh
  4. # Author: riubin@qq.com
  5. # Version: 0.0.2
  6. # Created: 2022-10-30
  7. # Updated: 2022-11-02
  8. #
  9. # export DWEST_USERNAME="your username"
  10. # export DWEST_PASSWORD="your api password not acount password"
  11. #
  12. # Usage:
  13. # acme.sh --issue --dns dns_west -d example.com
  14. DWEST_API_URL="https://api.west.cn/api/v2"
  15. ######## Public functions #####################
  16. # Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
  17. dns_west_add() {
  18. fulldomain=$1
  19. txtvalue=$2
  20. _debug fulldomain "$fulldomain"
  21. _debug txtvalue "$txtvalue"
  22. DWEST_USERNAME="${DWEST_USERNAME:-$(_readaccountconf_mutable DWEST_USERNAME)}"
  23. DWEST_PASSWORD="${DWEST_PASSWORD:-$(_readaccountconf_mutable DWEST_PASSWORD)}"
  24. if [ -z "$DWEST_USERNAME" ] || [ -z "$DWEST_PASSWORD" ]; then
  25. DWEST_USERNAME=""
  26. DWEST_PASSWORD=""
  27. _err "You didn't specify a west.cn account name or api password yet."
  28. _err "You can get yours from here https://www.west.cn/manager/API/APIconfig.asp"
  29. return 1
  30. fi
  31. # save the username and api password to the account conf file.
  32. _saveaccountconf_mutable DWEST_USERNAME "$DWEST_USERNAME"
  33. _saveaccountconf_mutable DWEST_PASSWORD "$DWEST_PASSWORD"
  34. _domain=$(expr "$fulldomain" : ".*\.\(.*\..*\)")
  35. _host=$(expr "$fulldomain" : '\(.*\)\..*\..*')
  36. _debug _domain "$_domain"
  37. _debug _host "$_host"
  38. if ! _dns_west_records "$_domain" "$_host"; then
  39. return 1
  40. fi
  41. _debug _host_records "$_host_records"
  42. # if record type is not TXT,delete it
  43. _none_txt_record_id=$(echo "$_host_records" | grep -v "$(printf '\tTXT')" |cut -f1)
  44. if [ -n "$_none_txt_record_id" ]; then
  45. if ! _dns_west_post "domain=${_domain}&id=${_none_txt_record_id}" "/domain/?act=deldnsrecord"; then
  46. _err "Delete record error."
  47. return 1
  48. fi
  49. fi
  50. # will return ok when the txtvalue exists
  51. _host_id=$(echo "$_host_records" | grep "$(printf '\t')$txtvalue" | cut -f1)
  52. _debug _host_id "$_host_id"
  53. if [ -n "$_host_id" ]; then
  54. _info "Already exists, OK"
  55. return 0
  56. fi
  57. # will add txt record
  58. if ! _dns_west_post "domain=${_domain}&host=${_host}&type=TXT&value=${txtvalue}&ttl=60&level=10" "/domain/?act=adddnsrecord"; then
  59. _err "Add txt record error."
  60. return 1
  61. fi
  62. _info "Added, OK"
  63. _info "Sleep 30sec"
  64. sleep 30
  65. return 0
  66. }
  67. # Usage: rm _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
  68. dns_west_rm() {
  69. fulldomain=$1
  70. txtvalue=$2
  71. DWEST_USERNAME="${DWEST_USERNAME:-$(_readaccountconf_mutable DWEST_USERNAME)}"
  72. DWEST_PASSWORD="${DWEST_PASSWORD:-$(_readaccountconf_mutable DWEST_PASSWORD)}"
  73. _domain=$(expr "$fulldomain" : ".*\.\(.*\..*\)")
  74. _host=$(expr "$fulldomain" : "\(.*\)\..*\..*")
  75. _debug _domain "$_domain"
  76. _debug _host "$_host"
  77. # get domain records if the host already exists will return the host's id and value
  78. if ! _dns_west_records "$_domain" "$_host"; then
  79. return 1
  80. fi
  81. _debug _host_records "$_host_records"
  82. if [ -z "$_host_records" ]; then
  83. _info "Don't need to remove."
  84. return 0
  85. fi
  86. _host_id=$(echo "$_host_records" | grep "$(printf '\t')$txtvalue" | cut -f1)
  87. _debug _host_id "$_host_id"
  88. if [ -z "$_host_id" ]; then
  89. _info "Don't need to remove."
  90. return 0
  91. fi
  92. if ! _dns_west_post "domain=${_domain}&id=${_host_id}" "/domain/?act=deldnsrecord"; then
  93. _err " Delete record error."
  94. return 1
  95. fi
  96. _info "Deleted record, OK"
  97. return 0
  98. }
  99. #################### Private functions below ##################################
  100. # Usage: _dns_west_records <domain.com> <_acme-challenge.www>
  101. # because the TXT records can be more than one,so get domain records by host will return the more records rows,like:
  102. # {"id":113046690,"item":"_acme-challenge","value":"XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs","type":"TXT"...}
  103. # {"id":103790839,"item":"_acme-challenge","value":"x2mbcaewb52890s8fht2lcpts5w74a1pfq44q1hnmu1","type":"TXT"...}
  104. # we only need id,value,type,so this function will store records to _host_records inform of <id \t value \t type> each line in stdout,like
  105. # 113046690 XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs TXT
  106. # 103790839 x2mbcaewb52890s8fht2lcpts5w74a1pfq44q1hnmu1 TXT
  107. # so you can simply use grep and cut to get some data form it
  108. _dns_west_records() {
  109. _domain=$1
  110. _host=$2
  111. _value=$3
  112. _dns_west_post "limit=100&domain=${_domain}" "/domain/?act=getdnsrecord"
  113. if ! _dns_west_msg "$response"; then
  114. _err "error: " "$_error"
  115. return 1
  116. fi
  117. _host_records=$(printf "%s" "$response" | sed 's/{/&\n/g'|grep "$_host" | sed -n 's/.*\"id\"\:\([0-9]*\).*\"value\"\:\"\([^\"]*\)\",\"type\":\"\([^\"]*\)\".*/\1\t\2\t\3/p')
  118. return 0
  119. }
  120. # Usage: _dns_west_post <post data url encoded> <path start with '/'>
  121. # returns:
  122. # response={}
  123. _dns_west_post() {
  124. body=$1
  125. ep=$2
  126. _time_in_millisecond=$(($(date +%s%N)/1000000))
  127. _token=$(printf "%s" "$DWEST_USERNAME$DWEST_PASSWORD$_time_in_millisecond" | md5sum |cut -d ' ' -f1)
  128. _debug "create token" "$_token"
  129. _common_params="username=$DWEST_USERNAME&time=$_time_in_millisecond&token=$_token"
  130. _debug "common params" "$_common_params"
  131. _debug body "$body"
  132. _debug path "$ep"
  133. # west.cn api use gbk encode,so response must convert gbk to utf-8
  134. # post body didn't convert to gbk because the data content is english at all,so it don't need to convert
  135. response="$(_post "$_common_params&$body" "$DWEST_API_URL$ep" "" POST "application/x-www-form-urlencoded" | iconv -f GBK -t UTF-8)"
  136. if ! _dns_west_msg "$response"; then
  137. _err "error $ep" "$_error"
  138. return 1
  139. fi
  140. _debug2 response "$response"
  141. return 0
  142. }
  143. # Usage: _dns_west_msg response
  144. # returns:
  145. # msg
  146. _dns_west_msg(){
  147. _result=$(expr "$1" : '.*result\"\:\([0-9]*\)')
  148. if [ "$_result" != "200" ]; then
  149. _error=$(printf "%s" "$1" sed -n 's/.*msg\"\:\"\(\[^\"\]*\)\".*/\1/p')
  150. return 1
  151. fi
  152. return 0
  153. }