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.

176 lines
5.6 KiB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
3 years ago
3 years ago
3 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. #!/usr/bin/env sh
  2. # Author: Wout Decre <wout@canodus.be>
  3. CONSTELLIX_Api="https://api.dns.constellix.com/v1"
  4. #CONSTELLIX_Key="XXX"
  5. #CONSTELLIX_Secret="XXX"
  6. ######## Public functions #####################
  7. # Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
  8. # Used to add txt record
  9. dns_constellix_add() {
  10. fulldomain=$1
  11. txtvalue=$2
  12. CONSTELLIX_Key="${CONSTELLIX_Key:-$(_readaccountconf_mutable CONSTELLIX_Key)}"
  13. CONSTELLIX_Secret="${CONSTELLIX_Secret:-$(_readaccountconf_mutable CONSTELLIX_Secret)}"
  14. if [ -z "$CONSTELLIX_Key" ] || [ -z "$CONSTELLIX_Secret" ]; then
  15. _err "You did not specify the Contellix API key and secret yet."
  16. return 1
  17. fi
  18. _saveaccountconf_mutable CONSTELLIX_Key "$CONSTELLIX_Key"
  19. _saveaccountconf_mutable CONSTELLIX_Secret "$CONSTELLIX_Secret"
  20. if ! _get_root "$fulldomain"; then
  21. _err "Invalid domain"
  22. return 1
  23. fi
  24. # The TXT record might already exist when working with wildcard certificates. In that case, update the record by adding the new value.
  25. _debug "Search TXT record"
  26. if _constellix_rest GET "domains/${_domain_id}/records/TXT/search?exact=${_sub_domain}"; then
  27. if printf -- "%s" "$response" | grep "{\"errors\":\[\"Requested record was not found\"\]}" >/dev/null; then
  28. _info "Adding TXT record"
  29. if _constellix_rest POST "domains/${_domain_id}/records" "[{\"type\":\"txt\",\"add\":true,\"set\":{\"name\":\"${_sub_domain}\",\"ttl\":60,\"roundRobin\":[{\"value\":\"${txtvalue}\"}]}}]"; then
  30. if printf -- "%s" "$response" | grep "{\"success\":\"1 record(s) added, 0 record(s) updated, 0 record(s) deleted\"}" >/dev/null; then
  31. _info "Added"
  32. return 0
  33. else
  34. _err "Error adding TXT record"
  35. fi
  36. fi
  37. else
  38. _record_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[0-9]*" | cut -d ':' -f 2)
  39. if _constellix_rest GET "domains/${_domain_id}/records/TXT/${_record_id}"; then
  40. _new_rr_values=$(printf "%s\n" "$response" | _egrep_o '"roundRobin":\[[^]]*\]' | sed "s/\]$/,{\"value\":\"${txtvalue}\"}]/")
  41. _debug _new_rr_values "$_new_rr_values"
  42. _info "Updating TXT record"
  43. if _constellix_rest PUT "domains/${_domain_id}/records/TXT/${_record_id}" "{\"name\":\"${_sub_domain}\",\"ttl\":60,${_new_rr_values}}"; then
  44. if printf -- "%s" "$response" | grep "{\"success\":\"Record.*updated successfully\"}" >/dev/null; then
  45. _info "Updated"
  46. return 0
  47. elif printf -- "%s" "$response" | grep "{\"errors\":\[\"Contents are identical\"\]}" >/dev/null; then
  48. _info "Already exists, no need to update"
  49. return 0
  50. else
  51. _err "Error updating TXT record"
  52. fi
  53. fi
  54. fi
  55. fi
  56. fi
  57. return 1
  58. }
  59. # Usage: fulldomain txtvalue
  60. # Used to remove the txt record after validation
  61. dns_constellix_rm() {
  62. fulldomain=$1
  63. txtvalue=$2
  64. CONSTELLIX_Key="${CONSTELLIX_Key:-$(_readaccountconf_mutable CONSTELLIX_Key)}"
  65. CONSTELLIX_Secret="${CONSTELLIX_Secret:-$(_readaccountconf_mutable CONSTELLIX_Secret)}"
  66. if [ -z "$CONSTELLIX_Key" ] || [ -z "$CONSTELLIX_Secret" ]; then
  67. _err "You did not specify the Contellix API key and secret yet."
  68. return 1
  69. fi
  70. if ! _get_root "$fulldomain"; then
  71. _err "Invalid domain"
  72. return 1
  73. fi
  74. # The TXT record might have been removed already when working with some wildcard certificates.
  75. _debug "Search TXT record"
  76. if _constellix_rest GET "domains/${_domain_id}/records/TXT/search?exact=${_sub_domain}"; then
  77. if printf -- "%s" "$response" | grep "{\"errors\":\[\"Requested record was not found\"\]}" >/dev/null; then
  78. _info "Removed"
  79. return 0
  80. else
  81. _info "Removing TXT record"
  82. if _constellix_rest POST "domains/${_domain_id}/records" "[{\"type\":\"txt\",\"delete\":true,\"filter\":{\"field\":\"name\",\"op\":\"eq\",\"value\":\"${_sub_domain}\"}}]"; then
  83. if printf -- "%s" "$response" | grep "{\"success\":\"0 record(s) added, 0 record(s) updated, 1 record(s) deleted\"}" >/dev/null; then
  84. _info "Removed"
  85. return 0
  86. else
  87. _err "Error removing TXT record"
  88. fi
  89. fi
  90. fi
  91. fi
  92. return 1
  93. }
  94. #################### Private functions below ##################################
  95. _get_root() {
  96. domain=$1
  97. i=2
  98. p=1
  99. _debug "Detecting root zone"
  100. while true; do
  101. h=$(printf "%s" "$domain" | cut -d . -f $i-100)
  102. if [ -z "$h" ]; then
  103. return 1
  104. fi
  105. if ! _constellix_rest GET "domains/search?exact=$h"; then
  106. return 1
  107. fi
  108. if _contains "$response" "\"name\":\"$h\""; then
  109. _domain_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[0-9]*" | cut -d ':' -f 2)
  110. if [ "$_domain_id" ]; then
  111. _sub_domain=$(printf "%s" "$domain" | cut -d '.' -f 1-$p)
  112. _domain="$h"
  113. _debug _domain_id "$_domain_id"
  114. _debug _sub_domain "$_sub_domain"
  115. _debug _domain "$_domain"
  116. return 0
  117. fi
  118. return 1
  119. fi
  120. p=$i
  121. i=$(_math "$i" + 1)
  122. done
  123. return 1
  124. }
  125. _constellix_rest() {
  126. m=$1
  127. ep="$2"
  128. data="$3"
  129. _debug "$ep"
  130. rdate=$(date +"%s")"000"
  131. hmac=$(printf "%s" "$rdate" | _hmac sha1 "$(printf "%s" "$CONSTELLIX_Secret" | _hex_dump | tr -d ' ')" | _base64)
  132. export _H1="x-cnsdns-apiKey: $CONSTELLIX_Key"
  133. export _H2="x-cnsdns-requestDate: $rdate"
  134. export _H3="x-cnsdns-hmac: $hmac"
  135. export _H4="Accept: application/json"
  136. export _H5="Content-Type: application/json"
  137. if [ "$m" != "GET" ]; then
  138. _debug data "$data"
  139. response="$(_post "$data" "$CONSTELLIX_Api/$ep" "" "$m")"
  140. else
  141. response="$(_get "$CONSTELLIX_Api/$ep")"
  142. fi
  143. if [ "$?" != "0" ]; then
  144. _err "Error $ep"
  145. return 1
  146. fi
  147. _debug response "$response"
  148. return 0
  149. }