diff --git a/dnsapi/README.md b/dnsapi/README.md index 1f394f92..8279ee83 100644 --- a/dnsapi/README.md +++ b/dnsapi/README.md @@ -897,6 +897,30 @@ 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. Please report any issues to https://github.com/initit/acme.sh or to + +## 48. Use dns_cpaneldns API + +Before you start using acme.sh with this CPanel plugin you have to set the following variables once and only on first use, these are: + +* CPANELDNS_AUTH_ID = Your CPanel's User ID +* CPANELDNS_AUTH_PASSWORD = Your CPanel's User ID password +* CPANELDNS_API = Your CPanel's web address including portnumber, mostly 2083 + +Like: + +``` +export CPANELDNS_AUTH_ID="Administrator" +export CPANELDNS_AUTH_PASSWORD="34Flip787!" +export CPANELDNS_API="https://www.example.com:2083/" +``` + +Then execute: + +``` +acme.sh --issue --dns dns_cpaneldns -d example.com -d www.example.com +``` + +The CPANELDNS_AUTH_ID, CPANELDNS_AUTH_PASSWORD and CPANELDNS_API values will be saved in ~/.acme.sh/account.conf and will be reused when needed. # Use custom API If your API is not supported yet, you can write your own DNS API. @@ -917,4 +941,4 @@ See: https://github.com/Neilpang/acme.sh/wiki/DNS-API-Dev-Guide # Use lexicon DNS API -https://github.com/Neilpang/acme.sh/wiki/How-to-use-lexicon-dns-api \ No newline at end of file +https://github.com/Neilpang/acme.sh/wiki/How-to-use-lexicon-dns-api diff --git a/dnsapi/dns_cpaneldns.sh b/dnsapi/dns_cpaneldns.sh new file mode 100755 index 00000000..6befe087 --- /dev/null +++ b/dnsapi/dns_cpaneldns.sh @@ -0,0 +1,229 @@ +#!/usr/bin/env sh + +# Author: K.D. Eenkhoorn +# Based on work of Boyan Peychev + +# This script is a plugin for acme.sh found in te repository https://github.com/Neilpang/acme.sh. +# It's use is to add TXT verificationrecords to CPanel's DNS for Letsencrypt certificates. +# In general, before you start issueing a new certificate, you have to set a few variables for this plugin once. +# These variables can be found in the first lines of the script. + +# These are: + +# CPANELDNS_AUTH_ID = Your CPanel's User ID +# CPANELDNS_AUTH_PASSWORD = Your CPanel's User ID password +# CPANELDNS_API = Your Cpanel's web adress including portnumber, mostly 2083 + +# These one-time set variables will be saved for later use in the configuration of acme.sh. + +# Usage example: + +# export CPANELDNS_AUTH_ID="MY_Account" +# export CPANELDNS_AUTH_PASSWORD="My_Password" +# export CPANELDNS_API="https://www.example.com:2083/" + +# ./acme.sh --issue --dns dns_cpaneldns -d example.com -d www.example.com + +# Default variables, set these only in specific cases +#CPANELDNS_AUTH_ID="xxxxxxxx" +#CPANELDNS_AUTH_PASSWORD="yyyyyyyyyyy" +#CPANELDNS_API="https://zzz.zzz.zzz:2083/" + +##################### Public functions ##################### + +#Usage: dns_cpaneldns_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_cpaneldns_add() { + _info "Using CPanelDNS" + + if ! _dns_cpaneldns_init_check; then + return 1 + fi + + zone="$(_dns_cpaneldns_get_zone_name "$1")" + if [ -z "$zone" ]; then + _err "Missing DNS zone at CPanelDNS. Please log into your control panel and create the required DNS zone for the initial setup." + return 1 + fi + + host="$(echo "$1" | sed "s/\.$zone\$//")" + + record=$2 + + _debug zone "$zone" + _debug host "$host" + _debug record "$record" + + _info "Adding the TXT record for $1" + _dns_cpaneldns_http_api_call "cpanel_jsonapi_module=ZoneEdit" "cpanel_jsonapi_func=add_zone_record&domain=$zone&name=$host&type=TXT&txtdata=$record&ttl=60" + if ! _contains "$response" "\"status\":1"; then + _err "Record cannot be added." + return 1 + fi + _info "Added." + + return 0 +} + +#Usage: dns_cpaneldns_rm _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_cpaneldns_rm() { + _info "Using CPanelDNS" + + if ! _dns_cpaneldns_init_check; then + return 1 + fi + + if [ -z "$zone" ]; then + zone="$(_dns_cpaneldns_get_zone_name "$1")" + if [ -z "$zone" ]; then + _err "Missing DNS zone at CPanelDNS. Please log into your control panel and create the required DNS zone for the initial setup." + return 1 + fi + fi + + host="$(echo "$1" | sed "s/\.$zone\$//")" + record=$2 + + while _dns_cpaneldns_get_record $zone $host $record ; + do + record_id="$( _dns_cpaneldns_get_record $zone $host $record )" + + if [ ! -z "$record_id" ]; then + _debug zone "$zone" + _debug host "$host" + _debug record "$record" + _debug record_id "$record_id" + + _info "Deleting the TXT record for $1" + _dns_cpaneldns_http_api_call "cpanel_jsonapi_module=ZoneEdit" "cpanel_jsonapi_func=remove_zone_record&domain=$zone&line=$record_id" + + if ! _contains "$response" "\"status\":1"; then + _err "The TXT record for $1 cannot be deleted." + else + _info "Deleted." + fi + fi + done + + return 0 +} + +#################### Private functions below ################################## +_dns_cpaneldns_init_check() { + if [ ! -z "$CPANELDNS_INIT_CHECK_COMPLETED" ]; then + return 0 + fi + + CPANELDNS_AUTH_ID="${CPANELDNS_AUTH_ID:-$(_readaccountconf_mutable CPANELDNS_AUTH_ID)}" + CPANELDNS_AUTH_PASSWORD="${CPANELDNS_AUTH_PASSWORD:-$(_readaccountconf_mutable CPANELDNS_AUTH_PASSWORD)}" + CPANELDNS_API="${CPANELDNS_API:-$(_readaccountconf_mutable CPANELDNS_API)}" + + if [ -z "$CPANELDNS_AUTH_ID" ] || [ -z "$CPANELDNS_AUTH_PASSWORD" ] || [ -z "$CPANELDNS_API" ]; then + CPANELDNS_AUTH_ID="" + CPANELDNS_AUTH_PASSWORD="" + CPANELDNS_API="" + _err "You don't specify cpaneldns api id and password or api web interface yet." + _err "Please create you id and password and api and try again." + return 1 + fi + + if [ -z "$CPANELDNS_AUTH_ID" ] ; then + _err "CPANELDNS_AUTH_ID is not configured" + return 1 + fi + + if [ -z "$CPANELDNS_AUTH_PASSWORD" ]; then + _err "CPANELDNS_AUTH_PASSWORD is not configured" + return 1 + fi + + if [ -z "$CPANELDNS_API" ]; then + _err "CPANELDNS_API is not configured" + return 1 + fi + + # There is no login function for the API so checking if there is news to verify credentials + _dns_cpaneldns_http_api_call "cpanel_jsonapi_module=News" "cpanel_jsonapi_func=does_news_exist" + + if ! _contains "$response" "\"func\":\"does_news_exist\""; then + _err "Invalid CPANELDNS_AUTH_ID or CPANELDNS_AUTH_PASSWORD. Please check your login credentials." + return 1 + fi + + # save the api id and password to the account conf file. + _saveaccountconf_mutable CPANELDNS_AUTH_ID "$CPANELDNS_AUTH_ID" + _saveaccountconf_mutable CPANELDNS_AUTH_PASSWORD "$CPANELDNS_AUTH_PASSWORD" + _saveaccountconf_mutable CPANELDNS_API "$CPANELDNS_API" + + CPANELDNS_INIT_CHECK_COMPLETED=1 + + return 0 +} + +_dns_cpaneldns_get_zone_name() { + i=2 + while true; do + zoneForCheck="$(printf "%s" "$1" | cut -d . -f $i-100)" + if [ -z "$zoneForCheck" ]; then + return 1 + fi + + _debug zoneForCheck "$zoneForCheck" + + _dns_cpaneldns_http_api_call "cpanel_jsonapi_module=ZoneEdit" "cpanel_jsonapi_func=fetchzone&domain=$zoneForCheck" + + if ! _contains "$response" "\"status\":0"; then + echo "$zoneForCheck" + return 0 + fi + + i="$(_math "$i" + 1)" + done + return 1 +} + +_dns_cpaneldns_http_api_call() { + method=$1 + + _debug CPANELDNS_AUTH_ID "$CPANELDNS_AUTH_ID" + _debug CPANELDNS_AUTH_PASSWORD "$CPANELDNS_AUTH_PASSWORD" + + if [ -z "$2" ]; then + data="&$method" + else + data="&$method&$2" + fi + + export _H1="Authorization: Basic $(printf %s "$CPANELDNS_AUTH_ID:$CPANELDNS_AUTH_PASSWORD" | _base64 )" + + response="$(_get "$CPANELDNS_API/json-api/cpanel?cpanel_jsonapi_user=user&cpanel_jsonapi_apiversion=2$data")" + _debug response "$response" + return 0 +} + +_dns_cpaneldns_get_record() { + + zone=$1 + host=$2 + record=$3 + + _debug zone $zone + _debug host $host + _debug record $record + + _dns_cpaneldns_http_api_call "cpanel_jsonapi_module=ZoneEdit" "cpanel_jsonapi_func=fetchzone_records&domain=$zone&$name=$host&type=TXT&txtdata=$record" + if ! _contains "$response" "\"line\":"; then + _info "No records left matching TXT host." + return 1 + fi + + if $respose ; + then + recordlist="$(echo "$response" | tr '{' "\n" | grep "$record" | _head_n 1 )" + record_id="$(echo "$recordlist" | tr ',' "\n" | grep -E '^"line"' | sed -re 's/^\"line\"\:\"([0-9]+)\"$/\1/g' | cut -d ":" -f 2)" + echo $record_id + + _debug record_id $record_id + + return 0 + fi +} diff --git a/dnsapi/dns_inwx.sh b/dnsapi/dns_inwx.sh index cd5af91b..f4590cf8 100755 --- a/dnsapi/dns_inwx.sh +++ b/dnsapi/dns_inwx.sh @@ -158,7 +158,8 @@ _inwx_login() { export _H1 #https://github.com/inwx/php-client/blob/master/INWX/Domrobot.php#L71 - if _contains "$response" "tfa"; then + if _contains "$response" "code1000" \ + && _contains "$response" "tfaGOOGLE-AUTH"; then if [ -z "$INWX_Shared_Secret" ]; then _err "Mobile TAN detected." _err "Please define a shared secret."