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.

145 lines
3.5 KiB

  1. #!/usr/bin/env sh
  2. # shellcheck disable=SC2034
  3. dns_vercel_info='Vercel.com
  4. Site: Vercel.com
  5. Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_vercel
  6. Options:
  7. VERCEL_TOKEN API Token
  8. '
  9. # This is your API token which can be acquired on the account page.
  10. # https://vercel.com/account/tokens
  11. VERCEL_API="https://api.vercel.com"
  12. #Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
  13. dns_vercel_add() {
  14. fulldomain=$1
  15. txtvalue=$2
  16. _debug fulldomain "$fulldomain"
  17. _debug txtvalue "$txtvalue"
  18. VERCEL_TOKEN="${VERCEL_TOKEN:-$(_readaccountconf_mutable VERCEL_TOKEN)}"
  19. if [ -z "$VERCEL_TOKEN" ]; then
  20. VERCEL_TOKEN=""
  21. _err "You have not set the Vercel API token yet."
  22. _err "Please visit https://vercel.com/account/tokens to generate it."
  23. return 1
  24. fi
  25. _saveaccountconf_mutable VERCEL_TOKEN "$VERCEL_TOKEN"
  26. if ! _get_root "$fulldomain"; then
  27. _err "invalid domain"
  28. return 1
  29. fi
  30. _debug _sub_domain "$_sub_domain"
  31. _debug _domain "$_domain"
  32. _info "Adding record"
  33. if _vercel_rest POST "v2/domains/$_domain/records" "{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"value\":\"$txtvalue\"}"; then
  34. if printf -- "%s" "$response" | grep "\"uid\":\"" >/dev/null; then
  35. _info "Added"
  36. return 0
  37. else
  38. _err "Unexpected response while adding text record."
  39. return 1
  40. fi
  41. fi
  42. _err "Add txt record error."
  43. }
  44. dns_vercel_rm() {
  45. fulldomain=$1
  46. txtvalue=$2
  47. if ! _get_root "$fulldomain"; then
  48. _err "invalid domain"
  49. return 1
  50. fi
  51. _vercel_rest GET "v2/domains/$_domain/records"
  52. count=$(printf "%s\n" "$response" | _egrep_o "\"name\":\"$_sub_domain\",[^{]*\"type\":\"TXT\"" | wc -l | tr -d " ")
  53. if [ "$count" = "0" ]; then
  54. _info "Don't need to remove."
  55. else
  56. _record_id=$(printf "%s" "$response" | _egrep_o "\"id\":[^,]*,\"slug\":\"[^,]*\",\"name\":\"$_sub_domain\",[^{]*\"type\":\"TXT\",\"value\":\"$txtvalue\"" | cut -d: -f2 | cut -d, -f1 | tr -d '"')
  57. if [ "$_record_id" ]; then
  58. echo "$_record_id" | while read -r item; do
  59. if _vercel_rest DELETE "v2/domains/$_domain/records/$item"; then
  60. _info "removed record" "$item"
  61. return 0
  62. else
  63. _err "failed to remove record" "$item"
  64. return 1
  65. fi
  66. done
  67. fi
  68. fi
  69. }
  70. #################### Private functions below ##################################
  71. #_acme-challenge.www.domain.com
  72. #returns
  73. # _sub_domain=_acme-challenge.www
  74. # _domain=domain.com
  75. _get_root() {
  76. domain="$1"
  77. ep="$2"
  78. i=1
  79. p=1
  80. while true; do
  81. h=$(printf "%s" "$domain" | cut -d . -f $i-100)
  82. if [ -z "$h" ]; then
  83. #not valid
  84. return 1
  85. fi
  86. if ! _vercel_rest GET "v4/domains/$h"; then
  87. return 1
  88. fi
  89. if _contains "$response" "\"name\":\"$h\"" >/dev/null; then
  90. _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
  91. _domain=$h
  92. return 0
  93. fi
  94. p=$i
  95. i=$(_math "$i" + 1)
  96. done
  97. return 1
  98. }
  99. _vercel_rest() {
  100. m="$1"
  101. ep="$2"
  102. data="$3"
  103. path="$VERCEL_API/$ep"
  104. export _H1="Content-Type: application/json"
  105. export _H2="Authorization: Bearer $VERCEL_TOKEN"
  106. if [ "$m" != "GET" ]; then
  107. _secure_debug2 data "$data"
  108. response="$(_post "$data" "$path" "" "$m")"
  109. else
  110. response="$(_get "$path")"
  111. fi
  112. _ret="$?"
  113. _code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\\r\\n")"
  114. _debug "http response code $_code"
  115. _secure_debug2 response "$response"
  116. if [ "$_ret" != "0" ]; then
  117. _err "error $ep"
  118. return 1
  119. fi
  120. response="$(printf "%s" "$response" | _normalizeJson)"
  121. return 0
  122. }