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.

162 lines
3.8 KiB

  1. #!/usr/bin/env sh
  2. # Supports IONOS DNS API Beta v1.0.0
  3. #
  4. # Usage:
  5. # Export IONOS_PREFIX and IONOS_SECRET before calling acme.sh:
  6. #
  7. # $ export IONOS_PREFIX="..."
  8. # $ export IONOS_SECRET="..."
  9. #
  10. # $ acme.sh --issue --dns dns_ionos ...
  11. IONOS_API="https://api.hosting.ionos.com/dns"
  12. IONOS_ROUTE_ZONES="/v1/zones"
  13. IONOS_TXT_TTL=60 # minimum accepted by API
  14. IONOS_TXT_PRIO=10
  15. dns_ionos_add() {
  16. fulldomain=$1
  17. txtvalue=$2
  18. if ! _ionos_init; then
  19. return 1
  20. fi
  21. _body="[{\"name\":\"$_sub_domain.$_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"ttl\":$IONOS_TXT_TTL,\"prio\":$IONOS_TXT_PRIO,\"disabled\":false}]"
  22. if _ionos_rest POST "$IONOS_ROUTE_ZONES/$_zone_id/records" "$_body" && [ -z "$response" ]; then
  23. _info "TXT record has been created successfully."
  24. return 0
  25. fi
  26. return 1
  27. }
  28. dns_ionos_rm() {
  29. fulldomain=$1
  30. txtvalue=$2
  31. if ! _ionos_init; then
  32. return 1
  33. fi
  34. if ! _ionos_get_record "$fulldomain" "$_zone_id" "$txtvalue"; then
  35. _err "Could not find _acme-challenge TXT record."
  36. return 1
  37. fi
  38. if _ionos_rest DELETE "$IONOS_ROUTE_ZONES/$_zone_id/records/$_record_id" && [ -z "$response" ]; then
  39. _info "TXT record has been deleted successfully."
  40. return 0
  41. fi
  42. return 1
  43. }
  44. _ionos_init() {
  45. IONOS_PREFIX="${IONOS_PREFIX:-$(_readaccountconf_mutable IONOS_PREFIX)}"
  46. IONOS_SECRET="${IONOS_SECRET:-$(_readaccountconf_mutable IONOS_SECRET)}"
  47. if [ -z "$IONOS_PREFIX" ] || [ -z "$IONOS_SECRET" ]; then
  48. _err "You didn't specify an IONOS api prefix and secret yet."
  49. _err "Read https://beta.developer.hosting.ionos.de/docs/getstarted to learn how to get a prefix and secret."
  50. _err ""
  51. _err "Then set them before calling acme.sh:"
  52. _err "\$ export IONOS_PREFIX=\"...\""
  53. _err "\$ export IONOS_SECRET=\"...\""
  54. _err "\$ acme.sh --issue -d ... --dns dns_ionos"
  55. return 1
  56. fi
  57. _saveaccountconf_mutable IONOS_PREFIX "$IONOS_PREFIX"
  58. _saveaccountconf_mutable IONOS_SECRET "$IONOS_SECRET"
  59. if ! _get_root "$fulldomain"; then
  60. _err "Cannot find this domain in your IONOS account."
  61. return 1
  62. fi
  63. }
  64. _get_root() {
  65. domain=$1
  66. i=1
  67. p=1
  68. if _ionos_rest GET "$IONOS_ROUTE_ZONES"; then
  69. response="$(echo "$response" | tr -d "\n")"
  70. while true; do
  71. h=$(printf "%s" "$domain" | cut -d . -f $i-100)
  72. if [ -z "$h" ]; then
  73. return 1
  74. fi
  75. _zone="$(echo "$response" | _egrep_o "\"name\":\"$h\".*\}")"
  76. if [ "$_zone" ]; then
  77. _zone_id=$(printf "%s\n" "$_zone" | _egrep_o "\"id\":\"[a-fA-F0-9\-]*\"" | _head_n 1 | cut -d : -f 2 | tr -d '\"')
  78. if [ "$_zone_id" ]; then
  79. _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
  80. _domain=$h
  81. return 0
  82. fi
  83. return 1
  84. fi
  85. p=$i
  86. i=$(_math "$i" + 1)
  87. done
  88. fi
  89. return 1
  90. }
  91. _ionos_get_record() {
  92. fulldomain=$1
  93. zone_id=$2
  94. txtrecord=$3
  95. if _ionos_rest GET "$IONOS_ROUTE_ZONES/$zone_id?recordName=$fulldomain&recordType=TXT"; then
  96. response="$(echo "$response" | tr -d "\n")"
  97. _record="$(echo "$response" | _egrep_o "\"name\":\"$fulldomain\"[^\}]*\"type\":\"TXT\"[^\}]*\"content\":\"\\\\\"$txtrecord\\\\\"\".*\}")"
  98. if [ "$_record" ]; then
  99. _record_id=$(printf "%s\n" "$_record" | _egrep_o "\"id\":\"[a-fA-F0-9\-]*\"" | _head_n 1 | cut -d : -f 2 | tr -d '\"')
  100. return 0
  101. fi
  102. fi
  103. return 1
  104. }
  105. _ionos_rest() {
  106. method="$1"
  107. route="$2"
  108. data="$3"
  109. IONOS_API_KEY="$(printf "%s.%s" "$IONOS_PREFIX" "$IONOS_SECRET")"
  110. export _H1="X-API-Key: $IONOS_API_KEY"
  111. if [ "$method" != "GET" ]; then
  112. export _H2="Accept: application/json"
  113. export _H3="Content-Type: application/json"
  114. response="$(_post "$data" "$IONOS_API$route" "" "$method" "application/json")"
  115. else
  116. export _H2="Accept: */*"
  117. response="$(_get "$IONOS_API$route")"
  118. fi
  119. if [ "$?" != "0" ]; then
  120. _err "Error $route"
  121. return 1
  122. fi
  123. return 0
  124. }