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.

243 lines
5.9 KiB

  1. #!/usr/bin/env sh
  2. #
  3. # DNS API for Versio.nl/Versio.eu/Versio.uk
  4. # Author: lebaned <github@bakker.cloud>
  5. # Author: Tom Blauwendraat <tom@sunflowerweb.nl>
  6. #
  7. ######## Public functions #####################
  8. #Usage: dns_versio_add _acme-challenge.www.domain.com "[txtvalue]"
  9. dns_versio_add() {
  10. fulldomain=$1
  11. txtvalue=$2
  12. _info "Using Versio"
  13. _debug fulldomain "$fulldomain"
  14. _debug txtvalue "$txtvalue"
  15. if ! _get_configuration; then
  16. return 1
  17. fi
  18. _debug "First detect the root zone"
  19. if ! _get_root "$fulldomain"; then
  20. _err "invalid domain"
  21. return 1
  22. fi
  23. _info fulldomain "$fulldomain"
  24. _info _domain "$_domain"
  25. _info _sub_domain "$_sub_domain"
  26. if ! _get_dns_records "$_domain"; then
  27. _err "invalid domain"
  28. return 1
  29. fi
  30. _debug "original dnsrecords" "$_dns_records"
  31. _add_dns_record "TXT" "$fulldomain." "\\\"$txtvalue\\\"" 0 300
  32. _debug "dnsrecords after add record" "{\"dns_records\":[$_dns_records]}"
  33. while [ "$j" -le 3 ]; do
  34. _versio_rest POST "domains/$_domain/update" "{\"dns_records\":[$_dns_records]}"
  35. if [ "$?" = "0" ]; then
  36. _debug "rest update response" "$response"
  37. _debug "changed dnsrecords" "$_dns_records"
  38. return 0
  39. fi
  40. if [ "$?" != "2" ]; then
  41. break
  42. fi
  43. j=$((j + 1))
  44. done
  45. _err "Error!"
  46. return 1
  47. }
  48. #Usage: fulldomain txtvalue
  49. #Remove the txt record after validation.
  50. dns_versio_rm() {
  51. fulldomain=$1
  52. txtvalue=$2
  53. _info "Using Versio"
  54. _debug fulldomain "$fulldomain"
  55. _debug txtvalue "$txtvalue"
  56. if ! _get_configuration; then
  57. return 1
  58. fi
  59. _debug "First detect the root zone"
  60. if ! _get_root "$fulldomain"; then
  61. _err "invalid domain"
  62. return 1
  63. fi
  64. _debug fulldomain "$fulldomain"
  65. _debug _domain "$_domain"
  66. _debug _sub_domain "$_sub_domain"
  67. if ! _get_dns_records "$_domain"; then
  68. _err "invalid domain"
  69. return 1
  70. fi
  71. _debug "original dnsrecords" "$_dns_records"
  72. _delete_dns_record "TXT" "$fulldomain."
  73. _debug "dnsrecords after deleted old record" "$_dns_records"
  74. if _versio_rest POST "domains/$_domain/update" "{\"dns_records\":[$_dns_records]}"; then
  75. _debug "rest update response" "$response"
  76. _debug "changed dnsrecords" "$_dns_records"
  77. return 0
  78. fi
  79. _err "Error!"
  80. return 1
  81. }
  82. #################### Private functions below ##################################
  83. #_acme-challenge.www.domain.com
  84. #returns
  85. # _sub_domain=_acme-challenge.www
  86. # _domain=domain.com
  87. _get_root() {
  88. domain=$1
  89. i=1
  90. p=1
  91. if _versio_rest GET "domains?status=OK"; then
  92. response="$(echo "$response" | tr -d "\n")"
  93. while true; do
  94. h=$(printf "%s" "$domain" | cut -d . -f $i-100)
  95. _info h "$h"
  96. _debug h "$h"
  97. if [ -z "$h" ]; then
  98. #not valid
  99. return 1
  100. fi
  101. hostedzone="$(echo "$response" | _egrep_o "{.*\"domain\":\s*\"$h\"")"
  102. if [ "$hostedzone" ]; then
  103. _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
  104. _domain=$h
  105. return 0
  106. fi
  107. p=$i
  108. i=$(_math "$i" + 1)
  109. done
  110. fi
  111. return 1
  112. }
  113. #parameters: [record type] [record name]
  114. _delete_dns_record() {
  115. _dns_records=$(echo "$_dns_records" | sed 's/{"type":"'"$1"'","name":"'"$2"'"[^}]*}[,]\?//' | sed 's/,$//')
  116. }
  117. #parameters: [type] [name] [value] [prio] [ttl]
  118. _add_dns_record() {
  119. _dns_records="$_dns_records,{\"type\":\"$1\",\"name\":\"$2\",\"value\":\"$3\",\"prio\":$4,\"ttl\":$5}"
  120. }
  121. #parameters: [root domain]
  122. #returns
  123. # _dns_records
  124. _get_dns_records() {
  125. if _versio_rest GET "domains/$1?show_dns_records=true"; then
  126. _dns_records="$(echo "$response" | sed -n 's/.*\"dns\_records\":\[\([^][]*\).*/\1/p')"
  127. return 0
  128. fi
  129. return 1
  130. }
  131. #method uri qstr data
  132. _versio_rest() {
  133. mtd="$1"
  134. ep="$2"
  135. data="$3"
  136. _debug mtd "$mtd"
  137. _debug ep "$ep"
  138. VERSIO_API_URL="https://www.versio.nl/api/v1"
  139. VERSIO_CREDENTIALS_BASE64=$(printf "%s:%s" "$VERSIO_Username" "$VERSIO_Password" | _base64)
  140. export _H1="Accept: application/json"
  141. export _H2="Authorization: Basic $VERSIO_CREDENTIALS_BASE64"
  142. export _H3=""
  143. export _H4=""
  144. export _H5=""
  145. if [ "$mtd" != "GET" ]; then
  146. # both POST and DELETE.
  147. _debug data "$data"
  148. response="$(_post "$data" "$VERSIO_API_URL/$ep" "" "$mtd" "application/json")"
  149. else
  150. response="$(_get "$VERSIO_API_URL/$ep")"
  151. fi
  152. # sleeping in order not to exceed rate limit
  153. if [ -n "$VERSIO_Slow_rate" ]; then
  154. _info "Sleeping $VERSIO_Slow_rate seconds to slow down hit rate on API"
  155. _sleep "$VERSIO_Slow_rate"
  156. fi
  157. case $? in
  158. 0)
  159. if [ "$response" = "Rate limit exceeded" ]; then
  160. _err "Rate limit exceeded. Try again later."
  161. return 1
  162. fi
  163. case $response in
  164. "<"*)
  165. _err "Invalid non-JSON response! $response"
  166. return 2 # retryable
  167. ;;
  168. "{\"error\":"*)
  169. _err "Error response! $response"
  170. return 1
  171. ;;
  172. esac
  173. _debug response "$response"
  174. return 0
  175. ;;
  176. 6)
  177. _err "Authentication failure. Check your Versio email address and password"
  178. return 1
  179. ;;
  180. *)
  181. _err "Unknown error"
  182. return 1
  183. ;;
  184. esac
  185. }
  186. #parameters: []
  187. #returns:
  188. # VERSIO_Username
  189. # VERSIO_Password
  190. # VERSIO_Slow_rate
  191. _get_configuration() {
  192. VERSIO_Username="${VERSIO_Username:-$(_readaccountconf_mutable VERSIO_Username)}"
  193. VERSIO_Password="${VERSIO_Password:-$(_readaccountconf_mutable VERSIO_Password)}"
  194. if [ -z "$VERSIO_Username" ] || [ -z "$VERSIO_Password" ]; then
  195. VERSIO_Username=""
  196. VERSIO_Password=""
  197. _err "You don't specify Versio email address and/or password yet."
  198. _err "Example:"
  199. _err "export VERSIO_Username=[email address]"
  200. _err "export VERSIO_Password=[password]"
  201. return 1
  202. fi
  203. VERSIO_Slow_rate="${VERSIO_Slow_rate:-$(_readaccountconf_mutable VERSIO_Slow_rate)}"
  204. _info "Using slowdown rate: $VERSIO_Slow_rate seconds"
  205. if [ -z "$VERSIO_Slow_rate" ]; then
  206. VERSIO_Slow_rate=""
  207. fi
  208. _saveaccountconf_mutable VERSIO_Username "$VERSIO_Username"
  209. _saveaccountconf_mutable VERSIO_Password "$VERSIO_Password"
  210. _saveaccountconf_mutable VERSIO_Slow_rate "$VERSIO_Slow_rate"
  211. return 0
  212. }