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.

170 lines
4.4 KiB

  1. #!/usr/bin/env sh
  2. ##########
  3. # Custom servercow.de DNS API v1 for use with [acme.sh](https://github.com/acmesh-official/acme.sh)
  4. #
  5. # Usage:
  6. # export SERVERCOW_API_Username=username
  7. # export SERVERCOW_API_Password=password
  8. # acme.sh --issue -d example.com --dns dns_servercow
  9. #
  10. # Issues:
  11. # Any issues / questions / suggestions can be posted here:
  12. # https://github.com/jhartlep/servercow-dns-api/issues
  13. #
  14. # Author: Jens Hartlep
  15. ##########
  16. SERVERCOW_API="https://api.servercow.de/dns/v1/domains"
  17. # Usage dns_servercow_add _acme-challenge.www.domain.com "abcdefghijklmnopqrstuvwxyz"
  18. dns_servercow_add() {
  19. fulldomain=$1
  20. txtvalue=$2
  21. _info "Using servercow"
  22. _debug fulldomain "$fulldomain"
  23. _debug txtvalue "$txtvalue"
  24. SERVERCOW_API_Username="${SERVERCOW_API_Username:-$(_readaccountconf_mutable SERVERCOW_API_Username)}"
  25. SERVERCOW_API_Password="${SERVERCOW_API_Password:-$(_readaccountconf_mutable SERVERCOW_API_Password)}"
  26. if [ -z "$SERVERCOW_API_Username" ] || [ -z "$SERVERCOW_API_Password" ]; then
  27. SERVERCOW_API_Username=""
  28. SERVERCOW_API_Password=""
  29. _err "You don't specify servercow api username and password yet."
  30. _err "Please create your username and password and try again."
  31. return 1
  32. fi
  33. # save the credentials to the account conf file
  34. _saveaccountconf_mutable SERVERCOW_API_Username "$SERVERCOW_API_Username"
  35. _saveaccountconf_mutable SERVERCOW_API_Password "$SERVERCOW_API_Password"
  36. _debug "First detect the root zone"
  37. if ! _get_root "$fulldomain"; then
  38. _err "invalid domain"
  39. return 1
  40. fi
  41. _debug _sub_domain "$_sub_domain"
  42. _debug _domain "$_domain"
  43. if _servercow_api POST "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":\"$txtvalue\",\"ttl\":20}"; then
  44. if printf -- "%s" "$response" | grep "ok" >/dev/null; then
  45. _info "Added, OK"
  46. return 0
  47. else
  48. _err "add txt record error."
  49. return 1
  50. fi
  51. fi
  52. _err "add txt record error."
  53. return 1
  54. }
  55. # Usage fulldomain txtvalue
  56. # Remove the txt record after validation
  57. dns_servercow_rm() {
  58. fulldomain=$1
  59. txtvalue=$2
  60. _info "Using servercow"
  61. _debug fulldomain "$fulldomain"
  62. _debug txtvalue "$fulldomain"
  63. SERVERCOW_API_Username="${SERVERCOW_API_Username:-$(_readaccountconf_mutable SERVERCOW_API_Username)}"
  64. SERVERCOW_API_Password="${SERVERCOW_API_Password:-$(_readaccountconf_mutable SERVERCOW_API_Password)}"
  65. if [ -z "$SERVERCOW_API_Username" ] || [ -z "$SERVERCOW_API_Password" ]; then
  66. SERVERCOW_API_Username=""
  67. SERVERCOW_API_Password=""
  68. _err "You don't specify servercow api username and password yet."
  69. _err "Please create your username and password and try again."
  70. return 1
  71. fi
  72. _debug "First detect the root zone"
  73. if ! _get_root "$fulldomain"; then
  74. _err "invalid domain"
  75. return 1
  76. fi
  77. _debug _sub_domain "$_sub_domain"
  78. _debug _domain "$_domain"
  79. if _servercow_api DELETE "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\"}"; then
  80. if printf -- "%s" "$response" | grep "ok" >/dev/null; then
  81. _info "Deleted, OK"
  82. _contains "$response" '"message":"ok"'
  83. else
  84. _err "delete txt record error."
  85. return 1
  86. fi
  87. fi
  88. }
  89. #################### Private functions below ##################################
  90. # _acme-challenge.www.domain.com
  91. # returns
  92. # _sub_domain=_acme-challenge.www
  93. # _domain=domain.com
  94. _get_root() {
  95. fulldomain=$1
  96. i=2
  97. p=1
  98. while true; do
  99. _domain=$(printf "%s" "$fulldomain" | cut -d . -f $i-100)
  100. _debug _domain "$_domain"
  101. if [ -z "$_domain" ]; then
  102. # not valid
  103. return 1
  104. fi
  105. if ! _servercow_api GET "$_domain"; then
  106. return 1
  107. fi
  108. if ! _contains "$response" '"error":"no such domain in user context"' >/dev/null; then
  109. _sub_domain=$(printf "%s" "$fulldomain" | cut -d . -f 1-$p)
  110. if [ -z "$_sub_domain" ]; then
  111. # not valid
  112. return 1
  113. fi
  114. return 0
  115. fi
  116. p=$i
  117. i=$(_math "$i" + 1)
  118. done
  119. return 1
  120. }
  121. _servercow_api() {
  122. method=$1
  123. domain=$2
  124. data="$3"
  125. export _H1="Content-Type: application/json"
  126. export _H2="X-Auth-Username: $SERVERCOW_API_Username"
  127. export _H3="X-Auth-Password: $SERVERCOW_API_Password"
  128. if [ "$method" != "GET" ]; then
  129. _debug data "$data"
  130. response="$(_post "$data" "$SERVERCOW_API/$domain" "" "$method")"
  131. else
  132. response="$(_get "$SERVERCOW_API/$domain")"
  133. fi
  134. if [ "$?" != "0" ]; then
  135. _err "error $domain"
  136. return 1
  137. fi
  138. _debug2 response "$response"
  139. return 0
  140. }