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.

164 lines
5.0 KiB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 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. # To support wildcard certificates, try to find existig TXT record and update it.
  25. _info "Search existing 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. else
  48. _err "Error updating TXT record"
  49. fi
  50. fi
  51. fi
  52. fi
  53. fi
  54. return 1
  55. }
  56. # Usage: fulldomain txtvalue
  57. # Used to remove the txt record after validation
  58. dns_constellix_rm() {
  59. fulldomain=$1
  60. txtvalue=$2
  61. CONSTELLIX_Key="${CONSTELLIX_Key:-$(_readaccountconf_mutable CONSTELLIX_Key)}"
  62. CONSTELLIX_Secret="${CONSTELLIX_Secret:-$(_readaccountconf_mutable CONSTELLIX_Secret)}"
  63. if [ -z "$CONSTELLIX_Key" ] || [ -z "$CONSTELLIX_Secret" ]; then
  64. _err "You did not specify the Contellix API key and secret yet."
  65. return 1
  66. fi
  67. if ! _get_root "$fulldomain"; then
  68. _err "Invalid domain"
  69. return 1
  70. fi
  71. _info "Removing TXT record"
  72. if _constellix_rest POST "domains/${_domain_id}/records" "[{\"type\":\"txt\",\"delete\":true,\"filter\":{\"field\":\"name\",\"op\":\"eq\",\"value\":\"${_sub_domain}\"}}]"; then
  73. if printf -- "%s" "$response" | grep "{\"success\":\"0 record(s) added, 0 record(s) updated, 1 record(s) deleted\"}" >/dev/null; then
  74. _info "Removed"
  75. return 0
  76. else
  77. _err "Error removing TXT record"
  78. fi
  79. fi
  80. return 1
  81. }
  82. #################### Private functions below ##################################
  83. _get_root() {
  84. domain=$1
  85. i=2
  86. p=1
  87. _debug "Detecting root zone"
  88. while true; do
  89. h=$(printf "%s" "$domain" | cut -d . -f $i-100)
  90. if [ -z "$h" ]; then
  91. return 1
  92. fi
  93. if ! _constellix_rest GET "domains/search?exact=$h"; then
  94. return 1
  95. fi
  96. if _contains "$response" "\"name\":\"$h\""; then
  97. _domain_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[0-9]+" | cut -d ':' -f 2)
  98. if [ "$_domain_id" ]; then
  99. _sub_domain=$(printf "%s" "$domain" | cut -d '.' -f 1-$p)
  100. _domain="$h"
  101. _debug _domain_id "$_domain_id"
  102. _debug _sub_domain "$_sub_domain"
  103. _debug _domain "$_domain"
  104. return 0
  105. fi
  106. return 1
  107. fi
  108. p=$i
  109. i=$(_math "$i" + 1)
  110. done
  111. return 1
  112. }
  113. _constellix_rest() {
  114. m=$1
  115. ep="$2"
  116. data="$3"
  117. _debug "$ep"
  118. rdate=$(date +"%s")"000"
  119. hmac=$(printf "%s" "$rdate" | _hmac sha1 "$(printf "%s" "$CONSTELLIX_Secret" | _hex_dump | tr -d ' ')" | _base64)
  120. export _H1="x-cnsdns-apiKey: $CONSTELLIX_Key"
  121. export _H2="x-cnsdns-requestDate: $rdate"
  122. export _H3="x-cnsdns-hmac: $hmac"
  123. export _H4="Accept: application/json"
  124. export _H5="Content-Type: application/json"
  125. if [ "$m" != "GET" ]; then
  126. _debug data "$data"
  127. response="$(_post "$data" "$CONSTELLIX_Api/$ep" "" "$m")"
  128. else
  129. response="$(_get "$CONSTELLIX_Api/$ep")"
  130. fi
  131. if [ "$?" != "0" ]; then
  132. _err "Error $ep"
  133. return 1
  134. fi
  135. _debug response "$response"
  136. return 0
  137. }