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.

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