add Nexcess/Thermo/FH DNS providers

This commit is contained in:
Frank Laszlo 2018-08-23 12:25:57 -04:00
parent c883ec40d7
commit 02d64cf0cc
4 changed files with 591 additions and 3 deletions

View File

@ -897,6 +897,57 @@ acme.sh --issue --dns dns_euserv -d example.com -d *.example.com --insecure
The `EUSERV_Username` and `EUSERV_Password` will be saved in `~/.acme.sh/account.conf` and will be reused when needed. The `EUSERV_Username` and `EUSERV_Password` will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
Please report any issues to https://github.com/initit/acme.sh or to <github@initit.de> Please report any issues to https://github.com/initit/acme.sh or to <github@initit.de>
## 48. Use Nexcess.net API
First, you'll need to login to the [Nexcess.net Client Portal](https://portal.nexcess.net) and [generate a new API token](https://portal.nexcess.net/api-token).
Once you have a token, set it in your systems environment:
```
export NEXCESS_API_TOKEN="YOUR_TOKEN_HERE"
```
Finally, we'll issue the certificate: (Nexcess DNS publishes at max every 15 minutes, we recommend setting a 1200 second `--dnssleep`)
```
acme.sh --issue --dns dns_nexcess -d example.com --dnssleep 1200
```
The `NEXCESS_API_TOKEN will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
## 49. Use Thermo.io API
First, you'll need to login to the [Thermo.io Client Portal](https://core.thermo.io) and [generate a new API token](https://core.thermo.io/api-token).
Once you have a token, set it in your systems environment:
```
export THERMO_API_TOKEN="YOUR_TOKEN_HERE"
```
Finally, we'll issue the certificate: (Thermo DNS publishes at max every 15 minutes, we recommend setting a 1200 second `--dnssleep`)
```
acme.sh --issue --dns dns_thermo -d example.com --dnssleep 1200
```
The `THERMO_API_TOKEN will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
## 50. Use Futurehosting API
First, you'll need to login to the [Futurehosting Client Portal](https://my.futurehosting.com) and [generate a new API token](https://my.futurehosting.com/api-token).
Once you have a token, set it in your systems environment:
```
export FH_API_TOKEN="YOUR_TOKEN_HERE"
```
Finally, we'll issue the certificate: (Futurehosting DNS publishes at max every 15 minutes, we recommend setting a 1200 second `--dnssleep`)
```
acme.sh --issue --dns dns_fh -d example.com --dnssleep 1200
```
The `FH_API_TOKEN will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
# Use custom API # Use custom API
If your API is not supported yet, you can write your own DNS API. If your API is not supported yet, you can write your own DNS API.

179
dnsapi/dns_fh.sh Normal file
View File

@ -0,0 +1,179 @@
#!/usr/bin/env sh
########################################################################
# Futurehosting script for acme.sh
#
# Environment variables:
#
# - FH_API_TOKEN (your Futurehosting API Token)
# Note: If you do not have an API token, one can be generated at:
# https://my.futurehosting.net/api-token
#
# Author: Frank Laszlo <flaszlo@nexcess.net>
FH_API_URL="https://my.futurehosting.com/"
FH_API_VERSION="0"
# dns_futurehosting_add() - Add TXT record
# Usage: dns_futurehosting_add _acme-challenge.subdomain.domain.com "XyZ123..."
dns_futurehosting_add() {
host="${1}"
txtvalue="${2}"
if ! _check_futurehosting_api_token; then
return 1
fi
_info "Using Futurehosting"
_debug "Calling: dns_futurehosting_add() '${host}' '${txtvalue}'"
_debug "Detecting root zone"
if ! _get_root "${host}"; then
_err "Zone for domain does not exist."
return 1
fi
_debug _zone_id "${_zone_id}"
_debug _sub_domain "${_sub_domain}"
_debug _domain "${_domain}"
_post_data="{\"zone_id\": \"${_zone_id}\", \"type\": \"TXT\", \"host\": \"${host}\", \"target\": \"${txtvalue}\", \"ttl\": \"300\"}"
if _rest POST "dns-record" "${_post_data}" && [ -n "${response}" ]; then
_record_id=$(printf "%s\n" "${response}" | _egrep_o "\"record_id\":\s*[0-9]+" | cut -d : -f 2 | tr -d " " | _head_n 1)
_debug _record_id "${_record_id}"
if [ -z "$_record_id" ]; then
_err "Error adding the TXT record."
return 1
fi
_info "TXT record successfully added."
return 0
fi
return 1
}
# dns_futurehosting_rm() - Remove TXT record
# Usage: dns_futurehosting_rm _acme-challenge.subdomain.domain.com
dns_futurehosting_rm() {
host="${1}"
if ! _check_futurehosting_api_token; then
return 1
fi
_info "Using Futurehosting"
_debug "Calling: dns_futurehosting_rm() '${host}'"
_debug "Detecting root zone"
if ! _get_root "${host}"; then
_err "Zone for domain does not exist."
return 1
fi
_debug _zone_id "${_zone_id}"
_debug _sub_domain "${_sub_domain}"
_debug _domain "${_domain}"
_parameters="?zone_id=${_zone_id}"
if _rest GET "dns-record" "${_parameters}" && [ -n "${response}" ]; then
response="$(echo "${response}" | tr -d "\n" | sed 's/^\[\(.*\)\]$/\1/' | sed -e 's/{"record_id":/|"record_id":/g' | sed 's/|/&{/g' | tr "|" "\n")"
record="$(echo "${response}" | _egrep_o "{.*\"host\":\s*\"${_sub_domain}\".*}")"
if [ "${record}" ]; then
_record_id=$(printf "%s\n" "${record}" | _egrep_o "\"record_id\":\s*[0-9]+" | _head_n 1 | cut -d : -f 2 | tr -d \ )
if [ "${_record_id}" ]; then
_debug _record_id "${_record_id}"
_rest DELETE "dns-record/${_record_id}"
_info "TXT record successfully deleted."
return 0
fi
return 1
fi
return 0
fi
return 1
}
_check_futurehosting_api_token() {
if [ -z "${FH_API_TOKEN}" ]; then
FH_API_TOKEN=""
_err "You have not defined your FH_API_TOKEN."
_err "Please create your token and try again."
_err "If you need to generate a new token, please visit:"
_err "https://portal.futurehosting.net/api-token"
return 1
fi
_saveaccountconf FH_API_TOKEN "${FH_API_TOKEN}"
}
_get_root() {
domain="${1}"
i=2
p=1
if _rest GET "dns-zone"; then
response="$(echo "${response}" | tr -d "\n" | sed 's/^\[\(.*\)\]$/\1/' | sed -e 's/{"zone_id":/|"zone_id":/g' | sed 's/|/&{/g' | tr "|" "\n")"
_debug response "${response}"
while true; do
h=$(printf "%s" "${domain}" | cut -d . -f $i-100)
_debug h "${h}"
if [ -z "${h}" ]; then
#not valid
return 1
fi
hostedzone="$(echo "${response}" | _egrep_o "{.*\"domain\":\s*\"${h}\".*}")"
if [ "${hostedzone}" ]; then
_zone_id=$(printf "%s\n" "${hostedzone}" | _egrep_o "\"zone_id\":\s*[0-9]+" | _head_n 1 | cut -d : -f 2 | tr -d \ )
if [ "${_zone_id}" ]; then
_sub_domain=$(printf "%s" "${domain}" | cut -d . -f 1-${p})
_domain="${h}"
return 0
fi
return 1
fi
p=$i
i=$(_math "${i}" + 1)
done
fi
return 1
}
_rest() {
method="${1}"
ep="${2}"
data="${3}"
_debug method "${method}"
_debug ep "${ep}"
export _H1="Accept: application/json"
export _H2="Content-Type: application/json"
export _H3="Api-Version: ${FH_API_VERSION}"
export _H4="User-Agent: FH-ACME-CLIENT"
export _H5="Authorization: Bearer ${FH_API_TOKEN}"
if [ "${method}" != "GET" ]; then
_debug data "${data}"
response="$(_post "${data}" "${FH_API_URL}${ep}" "" "${method}")"
else
response="$(_get "${FH_API_URL}${ep}${data}")"
fi
if [ "${?}" != "0" ]; then
_err "error ${ep}"
return 1
fi
_debug2 response "${response}"
return 0
}

179
dnsapi/dns_nexcess.sh Normal file
View File

@ -0,0 +1,179 @@
#!/usr/bin/env sh
########################################################################
# Nexcess script for acme.sh
#
# Environment variables:
#
# - NEXCESS_API_TOKEN (your Nexcess API Token)
# Note: If you do not have an API token, one can be generated at:
# https://portal.nexcess.net/api-token
#
# Author: Frank Laszlo <flaszlo@nexcess.net>
NEXCESS_API_URL="https://portal.nexcess.net/"
NEXCESS_API_VERSION="0"
# dns_nexcess_add() - Add TXT record
# Usage: dns_nexcess_add _acme-challenge.subdomain.domain.com "XyZ123..."
dns_nexcess_add() {
host="${1}"
txtvalue="${2}"
if ! _check_nexcess_api_token; then
return 1
fi
_info "Using Nexcess"
_debug "Calling: dns_nexcess_add() '${host}' '${txtvalue}'"
_debug "Detecting root zone"
if ! _get_root "${host}"; then
_err "Zone for domain does not exist."
return 1
fi
_debug _zone_id "${_zone_id}"
_debug _sub_domain "${_sub_domain}"
_debug _domain "${_domain}"
_post_data="{\"zone_id\": \"${_zone_id}\", \"type\": \"TXT\", \"host\": \"${host}\", \"target\": \"${txtvalue}\", \"ttl\": \"300\"}"
if _rest POST "dns-record" "${_post_data}" && [ -n "${response}" ]; then
_record_id=$(printf "%s\n" "${response}" | _egrep_o "\"record_id\":\s*[0-9]+" | cut -d : -f 2 | tr -d " " | _head_n 1)
_debug _record_id "${_record_id}"
if [ -z "$_record_id" ]; then
_err "Error adding the TXT record."
return 1
fi
_info "TXT record successfully added."
return 0
fi
return 1
}
# dns_nexcess_rm() - Remove TXT record
# Usage: dns_nexcess_rm _acme-challenge.subdomain.domain.com
dns_nexcess_rm() {
host="${1}"
if ! _check_nexcess_api_token; then
return 1
fi
_info "Using Nexcess"
_debug "Calling: dns_nexcess_rm() '${host}'"
_debug "Detecting root zone"
if ! _get_root "${host}"; then
_err "Zone for domain does not exist."
return 1
fi
_debug _zone_id "${_zone_id}"
_debug _sub_domain "${_sub_domain}"
_debug _domain "${_domain}"
_parameters="?zone_id=${_zone_id}"
if _rest GET "dns-record" "${_parameters}" && [ -n "${response}" ]; then
response="$(echo "${response}" | tr -d "\n" | sed 's/^\[\(.*\)\]$/\1/' | sed -e 's/{"record_id":/|"record_id":/g' | sed 's/|/&{/g' | tr "|" "\n")"
record="$(echo "${response}" | _egrep_o "{.*\"host\":\s*\"${_sub_domain}\".*}")"
if [ "${record}" ]; then
_record_id=$(printf "%s\n" "${record}" | _egrep_o "\"record_id\":\s*[0-9]+" | _head_n 1 | cut -d : -f 2 | tr -d \ )
if [ "${_record_id}" ]; then
_debug _record_id "${_record_id}"
_rest DELETE "dns-record/${_record_id}"
_info "TXT record successfully deleted."
return 0
fi
return 1
fi
return 0
fi
return 1
}
_check_nexcess_api_token() {
if [ -z "${NEXCESS_API_TOKEN}" ]; then
NEXCESS_API_TOKEN=""
_err "You have not defined your NEXCESS_API_TOKEN."
_err "Please create your token and try again."
_err "If you need to generate a new token, please visit:"
_err "https://portal.nexcess.net/api-token"
return 1
fi
_saveaccountconf NEXCESS_API_TOKEN "${NEXCESS_API_TOKEN}"
}
_get_root() {
domain="${1}"
i=2
p=1
if _rest GET "dns-zone"; then
response="$(echo "${response}" | tr -d "\n" | sed 's/^\[\(.*\)\]$/\1/' | sed -e 's/{"zone_id":/|"zone_id":/g' | sed 's/|/&{/g' | tr "|" "\n")"
_debug response "${response}"
while true; do
h=$(printf "%s" "${domain}" | cut -d . -f $i-100)
_debug h "${h}"
if [ -z "${h}" ]; then
#not valid
return 1
fi
hostedzone="$(echo "${response}" | _egrep_o "{.*\"domain\":\s*\"${h}\".*}")"
if [ "${hostedzone}" ]; then
_zone_id=$(printf "%s\n" "${hostedzone}" | _egrep_o "\"zone_id\":\s*[0-9]+" | _head_n 1 | cut -d : -f 2 | tr -d \ )
if [ "${_zone_id}" ]; then
_sub_domain=$(printf "%s" "${domain}" | cut -d . -f 1-${p})
_domain="${h}"
return 0
fi
return 1
fi
p=$i
i=$(_math "${i}" + 1)
done
fi
return 1
}
_rest() {
method="${1}"
ep="${2}"
data="${3}"
_debug method "${method}"
_debug ep "${ep}"
export _H1="Accept: application/json"
export _H2="Content-Type: application/json"
export _H3="Api-Version: ${NEXCESS_API_VERSION}"
export _H4="User-Agent: NEXCESS-ACME-CLIENT"
export _H5="Authorization: Bearer ${NEXCESS_API_TOKEN}"
if [ "${method}" != "GET" ]; then
_debug data "${data}"
response="$(_post "${data}" "${NEXCESS_API_URL}${ep}" "" "${method}")"
else
response="$(_get "${NEXCESS_API_URL}${ep}${data}")"
fi
if [ "${?}" != "0" ]; then
_err "error ${ep}"
return 1
fi
_debug2 response "${response}"
return 0
}

179
dnsapi/dns_thermo.sh Normal file
View File

@ -0,0 +1,179 @@
#!/usr/bin/env sh
########################################################################
# Thermo.io script for acme.sh
#
# Environment variables:
#
# - THERMO_API_TOKEN (your Thermo.io API Token)
# Note: If you do not have an API token, one can be generated at:
# https://portal.thermo.net/api-token
#
# Author: Frank Laszlo <flaszlo@nexcess.net>
THERMO_API_URL="https://core.thermo.io/"
THERMO_API_VERSION="0"
# dns_thermo_add() - Add TXT record
# Usage: dns_thermo_add _acme-challenge.subdomain.domain.com "XyZ123..."
dns_thermo_add() {
host="${1}"
txtvalue="${2}"
if ! _check_thermo_api_token; then
return 1
fi
_info "Using Thermo.io"
_debug "Calling: dns_thermo_add() '${host}' '${txtvalue}'"
_debug "Detecting root zone"
if ! _get_root "${host}"; then
_err "Zone for domain does not exist."
return 1
fi
_debug _zone_id "${_zone_id}"
_debug _sub_domain "${_sub_domain}"
_debug _domain "${_domain}"
_post_data="{\"zone_id\": \"${_zone_id}\", \"type\": \"TXT\", \"host\": \"${host}\", \"target\": \"${txtvalue}\", \"ttl\": \"300\"}"
if _rest POST "dns-record" "${_post_data}" && [ -n "${response}" ]; then
_record_id=$(printf "%s\n" "${response}" | _egrep_o "\"record_id\":\s*[0-9]+" | cut -d : -f 2 | tr -d " " | _head_n 1)
_debug _record_id "${_record_id}"
if [ -z "$_record_id" ]; then
_err "Error adding the TXT record."
return 1
fi
_info "TXT record successfully added."
return 0
fi
return 1
}
# dns_thermo_rm() - Remove TXT record
# Usage: dns_thermo_rm _acme-challenge.subdomain.domain.com
dns_thermo_rm() {
host="${1}"
if ! _check_thermo_api_token; then
return 1
fi
_info "Using Thermo.io"
_debug "Calling: dns_thermo_rm() '${host}'"
_debug "Detecting root zone"
if ! _get_root "${host}"; then
_err "Zone for domain does not exist."
return 1
fi
_debug _zone_id "${_zone_id}"
_debug _sub_domain "${_sub_domain}"
_debug _domain "${_domain}"
_parameters="?zone_id=${_zone_id}"
if _rest GET "dns-record" "${_parameters}" && [ -n "${response}" ]; then
response="$(echo "${response}" | tr -d "\n" | sed 's/^\[\(.*\)\]$/\1/' | sed -e 's/{"record_id":/|"record_id":/g' | sed 's/|/&{/g' | tr "|" "\n")"
record="$(echo "${response}" | _egrep_o "{.*\"host\":\s*\"${_sub_domain}\".*}")"
if [ "${record}" ]; then
_record_id=$(printf "%s\n" "${record}" | _egrep_o "\"record_id\":\s*[0-9]+" | _head_n 1 | cut -d : -f 2 | tr -d \ )
if [ "${_record_id}" ]; then
_debug _record_id "${_record_id}"
_rest DELETE "dns-record/${_record_id}"
_info "TXT record successfully deleted."
return 0
fi
return 1
fi
return 0
fi
return 1
}
_check_thermo_api_token() {
if [ -z "${THERMO_API_TOKEN}" ]; then
THERMO_API_TOKEN=""
_err "You have not defined your THERMO_API_TOKEN."
_err "Please create your token and try again."
_err "If you need to generate a new token, please visit:"
_err "https://portal.thermo.net/api-token"
return 1
fi
_saveaccountconf THERMO_API_TOKEN "${THERMO_API_TOKEN}"
}
_get_root() {
domain="${1}"
i=2
p=1
if _rest GET "dns-zone"; then
response="$(echo "${response}" | tr -d "\n" | sed 's/^\[\(.*\)\]$/\1/' | sed -e 's/{"zone_id":/|"zone_id":/g' | sed 's/|/&{/g' | tr "|" "\n")"
_debug response "${response}"
while true; do
h=$(printf "%s" "${domain}" | cut -d . -f $i-100)
_debug h "${h}"
if [ -z "${h}" ]; then
#not valid
return 1
fi
hostedzone="$(echo "${response}" | _egrep_o "{.*\"domain\":\s*\"${h}\".*}")"
if [ "${hostedzone}" ]; then
_zone_id=$(printf "%s\n" "${hostedzone}" | _egrep_o "\"zone_id\":\s*[0-9]+" | _head_n 1 | cut -d : -f 2 | tr -d \ )
if [ "${_zone_id}" ]; then
_sub_domain=$(printf "%s" "${domain}" | cut -d . -f 1-${p})
_domain="${h}"
return 0
fi
return 1
fi
p=$i
i=$(_math "${i}" + 1)
done
fi
return 1
}
_rest() {
method="${1}"
ep="${2}"
data="${3}"
_debug method "${method}"
_debug ep "${ep}"
export _H1="Accept: application/json"
export _H2="Content-Type: application/json"
export _H3="Api-Version: ${THERMO_API_VERSION}"
export _H4="User-Agent: THERMO-ACME-CLIENT"
export _H5="Authorization: Bearer ${THERMO_API_TOKEN}"
if [ "${method}" != "GET" ]; then
_debug data "${data}"
response="$(_post "${data}" "${THERMO_API_URL}${ep}" "" "${method}")"
else
response="$(_get "${THERMO_API_URL}${ep}${data}")"
fi
if [ "${?}" != "0" ]; then
_err "error ${ep}"
return 1
fi
_debug2 response "${response}"
return 0
}