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.

339 lines
7.8 KiB

  1. #!/usr/bin/env sh
  2. #
  3. # Dyn.com Domain API
  4. #
  5. # Author: Gerd Naschenweng
  6. # https://github.com/magicdude4eva
  7. #
  8. # Dyn Managed DNS API
  9. # https://help.dyn.com/dns-api-knowledge-base/
  10. #
  11. # It is recommended to add a "Dyn Managed DNS" user specific for API access.
  12. # The "Zones & Records Permissions" required by this script are:
  13. # --
  14. # RecordAdd
  15. # RecordUpdate
  16. # RecordDelete
  17. # RecordGet
  18. # ZoneGet
  19. # ZoneAddNode
  20. # ZoneRemoveNode
  21. # ZonePublish
  22. # --
  23. #
  24. # Pass credentials before "acme.sh --issue --dns dns_dyn ..."
  25. # --
  26. # export DYN_Customer="customer"
  27. # export DYN_Username="apiuser"
  28. # export DYN_Password="secret"
  29. # --
  30. DYN_API="https://api.dynect.net/REST"
  31. #REST_API
  32. ######## Public functions #####################
  33. #Usage: add _acme-challenge.www.domain.com "Challenge-code"
  34. dns_dyn_add() {
  35. fulldomain="$1"
  36. txtvalue="$2"
  37. DYN_Customer="${DYN_Customer:-$(_readaccountconf_mutable DYN_Customer)}"
  38. DYN_Username="${DYN_Username:-$(_readaccountconf_mutable DYN_Username)}"
  39. DYN_Password="${DYN_Password:-$(_readaccountconf_mutable DYN_Password)}"
  40. if [ -z "$DYN_Customer" ] || [ -z "$DYN_Username" ] || [ -z "$DYN_Password" ]; then
  41. DYN_Customer=""
  42. DYN_Username=""
  43. DYN_Password=""
  44. _err "You must export variables: DYN_Customer, DYN_Username and DYN_Password"
  45. return 1
  46. fi
  47. #save the config variables to the account conf file.
  48. _saveaccountconf_mutable DYN_Customer "$DYN_Customer"
  49. _saveaccountconf_mutable DYN_Username "$DYN_Username"
  50. _saveaccountconf_mutable DYN_Password "$DYN_Password"
  51. if ! _dyn_get_authtoken; then
  52. return 1
  53. fi
  54. if [ -z "$_dyn_authtoken" ]; then
  55. _dyn_end_session
  56. return 1
  57. fi
  58. if ! _dyn_get_zone; then
  59. _dyn_end_session
  60. return 1
  61. fi
  62. if ! _dyn_add_record; then
  63. _dyn_end_session
  64. return 1
  65. fi
  66. if ! _dyn_publish_zone; then
  67. _dyn_end_session
  68. return 1
  69. fi
  70. _dyn_end_session
  71. return 0
  72. }
  73. #Usage: fulldomain txtvalue
  74. #Remove the txt record after validation.
  75. dns_dyn_rm() {
  76. fulldomain="$1"
  77. txtvalue="$2"
  78. DYN_Customer="${DYN_Customer:-$(_readaccountconf_mutable DYN_Customer)}"
  79. DYN_Username="${DYN_Username:-$(_readaccountconf_mutable DYN_Username)}"
  80. DYN_Password="${DYN_Password:-$(_readaccountconf_mutable DYN_Password)}"
  81. if [ -z "$DYN_Customer" ] || [ -z "$DYN_Username" ] || [ -z "$DYN_Password" ]; then
  82. DYN_Customer=""
  83. DYN_Username=""
  84. DYN_Password=""
  85. _err "You must export variables: DYN_Customer, DYN_Username and DYN_Password"
  86. return 1
  87. fi
  88. if ! _dyn_get_authtoken; then
  89. return 1
  90. fi
  91. if [ -z "$_dyn_authtoken" ]; then
  92. _dyn_end_session
  93. return 1
  94. fi
  95. if ! _dyn_get_zone; then
  96. _dyn_end_session
  97. return 1
  98. fi
  99. if ! _dyn_get_record_id; then
  100. _dyn_end_session
  101. return 1
  102. fi
  103. if [ -z "$_dyn_record_id" ]; then
  104. _dyn_end_session
  105. return 1
  106. fi
  107. if ! _dyn_rm_record; then
  108. _dyn_end_session
  109. return 1
  110. fi
  111. if ! _dyn_publish_zone; then
  112. _dyn_end_session
  113. return 1
  114. fi
  115. _dyn_end_session
  116. return 0
  117. }
  118. #################### Private functions below ##################################
  119. #get Auth-Token
  120. _dyn_get_authtoken() {
  121. _info "Start Dyn API Session"
  122. data="{\"customer_name\":\"$DYN_Customer\", \"user_name\":\"$DYN_Username\", \"password\":\"$DYN_Password\"}"
  123. dyn_url="$DYN_API/Session/"
  124. method="POST"
  125. _debug data "$data"
  126. _debug dyn_url "$dyn_url"
  127. export _H1="Content-Type: application/json"
  128. response="$(_post "$data" "$dyn_url" "" "$method")"
  129. sessionstatus="$(printf "%s\n" "$response" | _egrep_o '"status" *: *"[^"]*' | _head_n 1 | sed 's#^"status" *: *"##')"
  130. _debug response "$response"
  131. _debug sessionstatus "$sessionstatus"
  132. if [ "$sessionstatus" = "success" ]; then
  133. _dyn_authtoken="$(printf "%s\n" "$response" | _egrep_o '"token" *: *"[^"]*' | _head_n 1 | sed 's#^"token" *: *"##')"
  134. _info "Token received"
  135. _debug _dyn_authtoken "$_dyn_authtoken"
  136. return 0
  137. fi
  138. _dyn_authtoken=""
  139. _err "get token failed"
  140. return 1
  141. }
  142. #fulldomain=_acme-challenge.www.domain.com
  143. #returns
  144. # _dyn_zone=domain.com
  145. _dyn_get_zone() {
  146. i=2
  147. while true; do
  148. domain="$(printf "%s" "$fulldomain" | cut -d . -f "$i-100")"
  149. if [ -z "$domain" ]; then
  150. break
  151. fi
  152. dyn_url="$DYN_API/Zone/$domain/"
  153. export _H1="Auth-Token: $_dyn_authtoken"
  154. export _H2="Content-Type: application/json"
  155. response="$(_get "$dyn_url" "" "")"
  156. sessionstatus="$(printf "%s\n" "$response" | _egrep_o '"status" *: *"[^"]*' | _head_n 1 | sed 's#^"status" *: *"##')"
  157. _debug dyn_url "$dyn_url"
  158. _debug response "$response"
  159. _debug sessionstatus "$sessionstatus"
  160. if [ "$sessionstatus" = "success" ]; then
  161. _dyn_zone="$domain"
  162. return 0
  163. fi
  164. i=$(_math "$i" + 1)
  165. done
  166. _dyn_zone=""
  167. _err "get zone failed"
  168. return 1
  169. }
  170. #add TXT record
  171. _dyn_add_record() {
  172. _info "Adding TXT record"
  173. data="{\"rdata\":{\"txtdata\":\"$txtvalue\"},\"ttl\":\"300\"}"
  174. dyn_url="$DYN_API/TXTRecord/$_dyn_zone/$fulldomain/"
  175. method="POST"
  176. export _H1="Auth-Token: $_dyn_authtoken"
  177. export _H2="Content-Type: application/json"
  178. response="$(_post "$data" "$dyn_url" "" "$method")"
  179. sessionstatus="$(printf "%s\n" "$response" | _egrep_o '"status" *: *"[^"]*' | _head_n 1 | sed 's#^"status" *: *"##')"
  180. _debug response "$response"
  181. _debug sessionstatus "$sessionstatus"
  182. if [ "$sessionstatus" = "success" ]; then
  183. _info "TXT Record successfully added"
  184. return 0
  185. fi
  186. _err "add TXT record failed"
  187. return 1
  188. }
  189. #publish the zone
  190. _dyn_publish_zone() {
  191. _info "Publishing zone"
  192. data="{\"publish\":\"true\"}"
  193. dyn_url="$DYN_API/Zone/$_dyn_zone/"
  194. method="PUT"
  195. export _H1="Auth-Token: $_dyn_authtoken"
  196. export _H2="Content-Type: application/json"
  197. response="$(_post "$data" "$dyn_url" "" "$method")"
  198. sessionstatus="$(printf "%s\n" "$response" | _egrep_o '"status" *: *"[^"]*' | _head_n 1 | sed 's#^"status" *: *"##')"
  199. _debug response "$response"
  200. _debug sessionstatus "$sessionstatus"
  201. if [ "$sessionstatus" = "success" ]; then
  202. _info "Zone published"
  203. return 0
  204. fi
  205. _err "publish zone failed"
  206. return 1
  207. }
  208. #get record_id of TXT record so we can delete the record
  209. _dyn_get_record_id() {
  210. _info "Getting record_id of TXT record"
  211. dyn_url="$DYN_API/TXTRecord/$_dyn_zone/$fulldomain/"
  212. export _H1="Auth-Token: $_dyn_authtoken"
  213. export _H2="Content-Type: application/json"
  214. response="$(_get "$dyn_url" "" "")"
  215. sessionstatus="$(printf "%s\n" "$response" | _egrep_o '"status" *: *"[^"]*' | _head_n 1 | sed 's#^"status" *: *"##')"
  216. _debug response "$response"
  217. _debug sessionstatus "$sessionstatus"
  218. if [ "$sessionstatus" = "success" ]; then
  219. _dyn_record_id="$(printf "%s\n" "$response" | _egrep_o "\"data\" *: *\[\"/REST/TXTRecord/$_dyn_zone/$fulldomain/[^\"]*" | _head_n 1 | sed "s#^\"data\" *: *\[\"/REST/TXTRecord/$_dyn_zone/$fulldomain/##")"
  220. _debug _dyn_record_id "$_dyn_record_id"
  221. return 0
  222. fi
  223. _dyn_record_id=""
  224. _err "getting record_id failed"
  225. return 1
  226. }
  227. #delete TXT record
  228. _dyn_rm_record() {
  229. _info "Deleting TXT record"
  230. dyn_url="$DYN_API/TXTRecord/$_dyn_zone/$fulldomain/$_dyn_record_id/"
  231. method="DELETE"
  232. _debug dyn_url "$dyn_url"
  233. export _H1="Auth-Token: $_dyn_authtoken"
  234. export _H2="Content-Type: application/json"
  235. response="$(_post "" "$dyn_url" "" "$method")"
  236. sessionstatus="$(printf "%s\n" "$response" | _egrep_o '"status" *: *"[^"]*' | _head_n 1 | sed 's#^"status" *: *"##')"
  237. _debug response "$response"
  238. _debug sessionstatus "$sessionstatus"
  239. if [ "$sessionstatus" = "success" ]; then
  240. _info "TXT record successfully deleted"
  241. return 0
  242. fi
  243. _err "delete TXT record failed"
  244. return 1
  245. }
  246. #logout
  247. _dyn_end_session() {
  248. _info "End Dyn API Session"
  249. dyn_url="$DYN_API/Session/"
  250. method="DELETE"
  251. _debug dyn_url "$dyn_url"
  252. export _H1="Auth-Token: $_dyn_authtoken"
  253. export _H2="Content-Type: application/json"
  254. response="$(_post "" "$dyn_url" "" "$method")"
  255. _debug response "$response"
  256. _dyn_authtoken=""
  257. return 0
  258. }