-
-
Save scr34m/c7af866d9c3e0c4bc5850d651c59b770 to your computer and use it in GitHub Desktop.
#!/usr/bin/bash | |
# Dotroll domain api | |
# - api access values stored per domain, including migration from account stored values | |
# - zone data is POST-ed to avoid "414 Request-URI Too Large" errors | |
# | |
# Initially export values Dotroll_User and Dotroll_Password | |
# export Dotroll_User='<your.dotroll@user>'; export Dotroll_Password='<dotroll_api_password>'; acme.sh --issue --dns dns_dotroll -d <domain.tld> -d '*.<domain.tld>' | |
# Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" | |
dns_dotroll_add() { | |
fulldomain=$1 | |
txtvalue=$2 | |
_info "Adding TXT record using dotroll API" | |
_debug fulldomain "$fulldomain" | |
_debug txtvalue "$txtvalue" | |
Dotroll_User="${Dotroll_User:-$(_readdomainconf Dotroll_User)}" | |
Dotroll_Password="${Dotroll_Password:-$(_readdomainconf Dotroll_Password)}" | |
if [ -z "$Dotroll_User" ] || [ -z "$Dotroll_Password" ]; then | |
_debug "Try to migrate from account conf" | |
Acc_Dotroll_User="$(_readaccountconf_mutable Dotroll_User)" | |
Acc_Dotroll_Password="$(_readaccountconf_mutable Dotroll_Password)" | |
if [ -n "$Acc_Dotroll_User" ] && [ -n "$Acc_Dotroll_Password" ]; then | |
Dotroll_User="$Acc_Dotroll_User" | |
Dotroll_Password="$Acc_Dotroll_Password" | |
_savedomainconf Dotroll_User "$Acc_Dotroll_User" | |
_savedomainconf Dotroll_Password "$Acc_Dotroll_Password" | |
else | |
Dotroll_User="" | |
Dotroll_Password="" | |
_err "You don't specify dotroll user accounts." | |
_err "Please create you key and try again." | |
return 1 | |
fi | |
fi | |
#save the user and password to the domain conf file. | |
_savedomainconf Dotroll_User "$Dotroll_User" | |
_savedomainconf Dotroll_Password "$Dotroll_Password" | |
_debug "First detect the root zone" | |
if ! _get_root "$fulldomain"; then | |
_err "invalid domain" | |
return 1 | |
fi | |
_debug _sub_domain "$_sub_domain" | |
_debug _domain "$_domain" | |
_debug "Getting existing records" | |
_dotroll_rest GET "$_domain/get" | |
if ! _contains "$response" 'message":"OK"'; then | |
return 1 | |
fi | |
if _contains "$response" "$txtvalue"; then | |
_info "The record is existing, skip" | |
return 0 | |
fi | |
# IMPORTANT this does only add new records, the original records are not altered, but are required by the API | |
records=$(echo "$response" | cut -c 12- | rev | cut -c 40- | rev) | |
records_list=$(printf "{%s}" "$records") | |
# unchanged records_list | |
modify=$(echo "$records_list" | _url_encode) | |
new=$(echo '[{"name": "'${fulldomain}'.", "type": "TXT", "ttl": 3600, "txtdata": "'${txtvalue}'"}]' | _url_encode) | |
_dotroll_rest POST "$_domain/modify" "modify=${modify}&new=${new}" | |
if ! _contains "$response" 'message":"OK"'; then | |
_err "Add txt record error." | |
return 1 | |
fi | |
_info "Added, sleeping 10 seconds" | |
_sleep 10 | |
#todo: check if the record takes effect | |
return 0 | |
} | |
# Usage: rm _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" | |
dns_dotroll_rm() { | |
fulldomain=$1 | |
txtvalue=$2 | |
_info "Removing TXT record using dotroll API" | |
_debug fulldomain "$fulldomain" | |
_debug txtvalue "$txtvalue" | |
Dotroll_User="${Dotroll_User:-$(_readdomainconf Dotroll_User)}" | |
Dotroll_Password="${Dotroll_Password:-$(_readdomainconf Dotroll_Password)}" | |
if [ -z "$Dotroll_User" ] || [ -z "$Dotroll_Password" ]; then | |
_debug "Try to migrate from account conf" | |
Acc_Dotroll_User="$(_readaccountconf_mutable Dotroll_User)" | |
Acc_Dotroll_Password="$(_readaccountconf_mutable Dotroll_Password)" | |
if [ -n "$Acc_Dotroll_User" ] && [ -n "$Acc_Dotroll_Password" ]; then | |
Dotroll_User="$Acc_Dotroll_User" | |
Dotroll_Password="$Acc_Dotroll_Password" | |
_savedomainconf Dotroll_User "$Acc_Dotroll_User" | |
_savedomainconf Dotroll_Password "$Acc_Dotroll_Password" | |
else | |
Dotroll_User="" | |
Dotroll_Password="" | |
_err "You don't specify dotroll user accounts." | |
_err "Please create you key and try again." | |
return 1 | |
fi | |
fi | |
#save the user and password to the domain conf file. | |
_savedomainconf Dotroll_User "$Dotroll_User" | |
_savedomainconf Dotroll_Password "$Dotroll_Password" | |
_debug "First detect the root zone" | |
if ! _get_root "$fulldomain"; then | |
_err "invalid domain" | |
return 1 | |
fi | |
_debug _sub_domain "$_sub_domain" | |
_debug _domain "$_domain" | |
_debug "Getting existing records" | |
_dotroll_rest GET "$_domain/get" | |
if ! _contains "$response" 'message":"OK"'; then | |
return 1 | |
fi | |
if ! _contains "$response" "$txtvalue"; then | |
_info "The TXT record is missing, skip" | |
return 0 | |
fi | |
# IMPORTANT this does only remove a single record by pairs of fulldomain + txtvalue | |
records=$(echo "$response" | cut -c 12- | rev | cut -c 40- | rev) | |
records_list=$(printf "{%s}" "$records") | |
record=$(echo $records_list | _egrep_o ",\"[0-9]+\"\:{*\"name\":\"$fulldomain\.\"[^}]*\"${txtvalue}\"}") | |
record_cnt=$(echo $records_list | _egrep_o ",\"[0-9]+\"\:{*\"name\":\"$fulldomain\.\"[^}]*\"${txtvalue}\"}" | wc -l) | |
if [ ! -z "${record}" ]; then | |
if [ $record_cnt -gt 1 ]; then | |
while read recordline | |
do | |
records_list=$(echo "${records_list}" | sed -e "s|${recordline}||") | |
_debug _records_list "${records_list}" | |
done < <(echo "${record}") | |
else | |
records_list=$(echo "${records_list}" | sed -e "s|${record}||") | |
_debug _records_list "${records_list}" | |
fi | |
fi | |
# remove whitespaces | |
records_list=$(echo "$records_list" | xargs) | |
# modified records_list | |
modify=$(echo "$records_list" | _url_encode) | |
# URL-param 'modify' only! | |
_dotroll_rest POST "$_domain/modify" "modify=${modify}" | |
if ! _contains "$response" 'message":"OK"'; then | |
_err "Remove txt record error." | |
return 1 | |
fi | |
_info "Removed, sleeping 10 seconds" | |
_sleep 10 | |
#todo: check if the record takes effect | |
return 0 | |
} | |
#_acme-challenge.www.domain.com | |
#returns | |
# _sub_domain=_acme-challenge.www | |
# _domain=domain.com | |
_get_root() { | |
domain=$1 | |
i=2 | |
p=1 | |
while true; do | |
h=$(printf "%s" "$domain" | cut -d . -f $i-100) | |
if [ -z "$h" ]; then | |
#not valid | |
return 1 | |
fi | |
_dotroll_rest GET "$h/get" | |
if ! _contains "$response" 'message":"OK"'; then | |
_debug "$h not found or error" | |
else | |
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) | |
_domain="$h" | |
return 0 | |
fi | |
p="$i" | |
i=$(_math "$i" + 1) | |
done | |
return 1 | |
} | |
_dotroll_rest() { | |
m="$1" | |
ep="$2" | |
data="$3" | |
_debug m $m | |
_debug ep $ep | |
_dotroll_auth=$(printf "%s:%s" "$Dotroll_User" "$Dotroll_Password" | _base64) | |
export _H1="Authorization: Basic $_dotroll_auth" | |
#response=$(_get "https://api.dotroll.com/domains/zone/$ep") | |
if [ "$m" != "GET" ]; then | |
_debug data "$data" | |
response="$(_post "$data" "https://api.dotroll.com/domains/zone/$ep" "" "$m")" | |
else | |
response=$(_get "https://api.dotroll.com/domains/zone/$ep") | |
fi | |
if [ "$?" != "0" ]; then | |
_err "error $ep" | |
return 1 | |
fi | |
_debug response "$response" | |
return 0 | |
} |
Elviekben nem okozna problémát csak a kommunikáció mikéntje adja a nehézséget és ha úgy akarjuk megoldani, hogy független legyen külső tool-októl.
Szóval teszteléshez mindenképen a staging rendszerben végezz próbákat, ellenkező esetben hamar rate limit lesz a vége. Na meg a debug módot kapcsold be.
Én a "brutál sebészi" módszerre gondoltam, és a dotrollapi felé küldött kommunikációt elkülönítve teszteltem volna, amolyan unit-testing formában:
lekövetni milyen paraméterek jönnek át ha wildcard (ott ugye egyszer a domain,és egyszer a *.domain) egyáltalán egyben küldi,vagy külön hívásokra szedve,stb. de igen staging szerót ismerem :D
@scr34m szerintem ez a kis részlet okozza az egyik gondot, mert ha még bennt a wildcard miatt 2xugyanaz a rekord két külön tokennel, akkor a sed nek átadott $record sortöréssel együtt megy. Közben rájöttem, hogy tudatos, hogy sed "s/$record}//"
egy } jelet tartalmaz...
record=$(echo $records_list | _egrep_o ",\"[0-9]+\"\:{*\"name\":\"$fulldomain\.\"[^}]*")
_debug record $record
if [ ! -z "$record" ]; then
records_list=$(echo "$records_list" | sed "s/$record}//")
fi
ezt kisérletként én átírtam úgy, hogy kezelje ha több soros eredménye van a $record -nak:
record=$(echo $records_list | _egrep_o ",\"[0-9]+\"\:{*\"name\":\"$fulldomain\.\"[^}]*}")
record_cnt=$(echo $records_list | _egrep_o ",\"[0-9]+\"\:{*\"name\":\"$fulldomain\.\"[^}]*}" | wc -l)
_debug record "${record}"
if [ ! -z "${record}" ]; then
if [ $record_cnt -gt 1 ]; then
echo "${record}" | while read recordline
do
records_list=$(echo "$records_list" | sed -e "s|${recordline}||")
done
else
records_list=$(echo "$records_list" | sed -e "s|${record}||")
fi
fi
és miután igen faintra megírtam a fenti snippetet, rájöttem,hogy ezzel épp hogy mindig csak az utolsó TXT marad meg 🤦
lehet most kéne egy rekesz...hellenergy meg a Na akkor gondolkodjunk
És a leírás megadta a választ:
https://github.com/acmesh-official/acme.sh/wiki/DNS-API-Dev-Guide
... it's
highly recommended
to implement the rm function too. ...
A dns_dotroll_add() a meglévő rekordokat a lekérdezésekor változatlan tartalommal adja vissza, és hozzáadja az új rekordot
A dns_dotroll_rm() a meglévő rekordokból a neki paraméterben átadott hosztnév és token párost eltávolitja, így egyesével is törölhetőek a wildcard miatt átadott ugyanazon hosztnevek
Igen az RM nem lett itt implementálva és elírás amit fent írsz.
Igen az RM nem lett itt implementálva és elírás amit fent írsz.
Nem elírás, amikor lekéred a $record -ot, az a grep séma nem veszi bele a JSON element lezáró } -ját. Amikor a sed ben a $record}
áll akkor az így jelenik meg:
"9999999":{"name":"_acme-challenge.DOMAIN.","type":"TXT","ttl":"3600","txtdata":"DNS-TOKEN"}
Ha kihagyom a } -ot,akkor ez lesz:
"9999999":{"name":"_acme-challenge.DOMAIN.","type":"TXT","ttl":"3600","txtdata":"DNS-TOKEN"
És a JSON szerkezethibás lesz.
Egyenlőre még API lekérdezés és a műveletek eredményének stringként kiírás szintjén prototípus van meg, de bizakodó vagyok. ;)
@scr34m az alábbi változásokra vetnél egy pillantást?
--- dns_dotroll.sh 2021-07-03 05:24:46.432577041 +0200
+++ dns_dotroll.sh 2021-09-16 06:26:47.853243691 +0200
@@ -8,6 +8,10 @@
fulldomain=$1
txtvalue=$2
+ _info "Adding TXT record using dotroll API"
+ _debug fulldomain "$fulldomain"
+ _debug txtvalue "$txtvalue"
+
Dotroll_User="${Dotroll_User:-$(_readaccountconf_mutable Dotroll_User)}"
Dotroll_Password="${Dotroll_Password:-$(_readaccountconf_mutable Dotroll_Password)}"
if [ -z "$Dotroll_User" ] || [ -z "$Dotroll_Password" ]; then
@@ -43,15 +47,11 @@
return 0
fi
+ # IMPORTANT this does only add new records, the original records are not altered, but are required by the API
records=$(echo "$response" | cut -c 12- | rev | cut -c 40- | rev)
records_list=$(printf "{%s}" "$records")
- record=$(echo $records_list | _egrep_o ",\"[0-9]+\"\:{*\"name\":\"$fulldomain\.\"[^}]*")
- _debug record $record
- if [ ! -z "$record" ]; then
- records_list=$(echo "$records_list" | sed "s/$record}//")
- fi
-
+ # unchanged records_list
modify=$(echo "$records_list" | _url_encode)
new=$(echo '[{"name": "'${fulldomain}'.", "type": "TXT", "ttl": 3600, "txtdata": "'${txtvalue}'"}]' | _url_encode)
@@ -67,11 +67,84 @@
return 0
}
+
+# Usage: rm _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_dotroll_rm() {
fulldomain=$1
txtvalue=$2
- #todo
+ _info "Removing TXT record using dotroll API"
+ _debug fulldomain "$fulldomain"
+ _debug txtvalue "$txtvalue"
+
+ Dotroll_User="${Dotroll_User:-$(_readaccountconf_mutable Dotroll_User)}"
+ Dotroll_Password="${Dotroll_Password:-$(_readaccountconf_mutable Dotroll_Password)}"
+ if [ -z "$Dotroll_User" ] || [ -z "$Dotroll_Password" ]; then
+ Dotroll_User=""
+ Dotroll_Password=""
+ _err "You don't specify dotroll user accounts."
+ _err "Please create you key and try again."
+ return 1
+ fi
+
+ #save the user and password to the account conf file.
+ _saveaccountconf_mutable Dotroll_User "$Dotroll_User"
+ _saveaccountconf_mutable Dotroll_Password "$Dotroll_Password"
+
+ _debug "First detect the root zone"
+ if ! _get_root "$fulldomain"; then
+ _err "invalid domain"
+ return 1
+ fi
+
+ _debug _sub_domain "$_sub_domain"
+ _debug _domain "$_domain"
+
+ _debug "Getting existing records"
+
+ _dotroll_rest "$_domain/get"
+ if ! _contains "$response" 'message":"OK"'; then
+ return 1
+ fi
+
+ if ! _contains "$response" "$txtvalue"; then
+ _info "The TXT record is missing, skip"
+ return 0
+ fi
+
+ # IMPORTANT this does only remove a single record by pairs of fulldomain + txtvalue
+ records=$(echo "$response" | cut -c 12- | rev | cut -c 40- | rev)
+ records_list=$(printf "{%s}" "$records")
+
+ record=$(echo $records_list | _egrep_o ",\"[0-9]+\"\:{*\"name\":\"$fulldomain\.\"[^}]*\"${txtvalue}\"}")
+ record_cnt=$(echo $records_list | _egrep_o ",\"[0-9]+\"\:{*\"name\":\"$fulldomain\.\"[^}]*\"${txtvalue}\"}" | wc -l)
+ if [ ! -z "${record}" ]; then
+ if [ $record_cnt -gt 1 ]; then
+ while read recordline
+ do
+ records_list=$(echo "${records_list}" | sed -e "s|${recordline}||")
+ _debug _records_list "${records_list}"
+ done < <(echo "${record}")
+ else
+ records_list=$(echo "${records_list}" | sed -e "s|${record}||")
+ _debug _records_list "${records_list}"
+ fi
+ fi
+
+ # modified records_list
+ modify=$(echo "$records_list" | _url_encode)
+
+ # URL-param 'modify' only!
+ _dotroll_rest "$_domain/modify?modify=${modify}"
+ if ! _contains "$response" 'message":"OK"'; then
+ _err "Remove txt record error."
+ return 1
+ fi
+
+ _info "Removed, sleeping 10 seconds"
+ _sleep 10
+ #todo: check if the record takes effect
+ return 0
}
#_acme-challenge.www.domain.com
Úgy gondolom ezekkel a módosításokkal működni fog.
Ránézésre parádés 🎺
Pár nap múlva kiderül, hogy sikerült-e a módositás, aztán küldöm egyben a módosított scriptet
Tegnap reggel egy wildcard megújitás cronból sikerrel lefutott, tehát a módosítások működtek. @scr34m emailben mehet a script ?
Jöhet igen, köszi!
@koceka kiegészítése
@scr34m a wildcard megújítás aztán megint nemjött ösze, plusz van hogy ugyanazon telepítésben több különböző dotroll fiókban vannak domainek, és a wildcard igénylésnél horror méretű zónába kell hozzááadni majd letörölni a TXT rekordot. néhány hete ezért átnéztem a scriptet, az eredmény egy POST képes, a dotroll adatokat a domain konfigjába mentő változat lett.
forkolom, aztán lesz egy diff a mostani állapothoz, remélem könnyen mergelhető lesz
@scr34m hát igen ezt picit nagyobb változás lett:
https://gist.github.com/gnanet/0f78f81afbed91b6235b8a7c4eed1681/revisions#diff-5ebc9433f9e54ab61c2019176a868fbc5146de6dfaeea3732df6e3ec69096c5f
Ahh látom én hibásan account conf használtam a domain szintű beállítás helyett, szuper de ez annyira nem is nagy módosítás összeségében.
@gnanet mergelve, köszi
Ahh látom én hibásan account conf használtam a domain szintű beállítás helyett, szuper de ez annyira nem is nagy módosítás összeségében.
nem hibáztál, a legtöbb dns plugin így működik, csak tudod: "olyan hiba/helyzet nem létezik amit a gina nem szopott be"
Ezt ugye benne hagytad?
@koceka kiegészítése
Nem mert azt a commitod kiszedte de most berakom újra :)
Gyorsan visszaszívtam, mert nem tuti. Ugyan a szkript látszólag megjavul tőle és nem dob hibát, de a rekord nem törlődik.
A scripttől függetlenül nálatok amúgy működik az API rendesen? Nem igazán tudok törölni, próbáltam manuál módszerekkel is (postman-nel) és habár rekordokat hozzáadni gond nélkül tudok vele, de törölni azzal sem.
Azt amit én hasznalok es nemreg mergelte @scr34m azt par honapja már folyamatos wildcard sslekhez hasznalom es nem lattam hogy gondja kett volna
@scr34m @koceka rájöttem miért nem jó nálam a törlés (mert nekem is 404 jön rá):
alaphiba, hogy ha már url-encode-ot használok, ugyanúgy mint a md5 és más hash-eknél is, az echo
alapban rátesz egy sortörést, tehát az lesz a gond, hogy a modify data egy 0a
ra végződik, amit echo -n
-el kikapcsolhatunk:
# modified records_list
modify=$(echo -n "$records_list" | _url_encode)
És igazából csodálom, hogy az új hozzáadásánál nem pánikol rá erre a new-linera pedig az url-encode mindkét esetben a végére odatette a new-line-t
Ezzel igazán az a bajom, hogy egy tr -d ' ' | tr -d "\n"
egyértelműen a szóközöket és new-lineokat kitakarítja, mindegy mekkora stringről volt szó, az xargs alapműködésénél használt echo
mint parancs bizonyos hosszúságig működik így alapértelmezésben.
# remove whitespaces
records_list=$(echo "$records_list" | xargs)
Másik megoldás, hogy a beépített funkciók közül több helyen használt normalizeJson-t lehetne bevetni:
_normalizeJson() {
sed "s/\" *: *\([\"{\[]\)/\":\1/g" | sed "s/^ *\([^ ]\)/\1/" | tr -d "\r\n"
}
Azután már ha json-t kell POST-olni, akkor egyben leszedte a szóközöket és sortörést, ezt url_encode-olni már gond nélkül lehetne.
Hát szerintem ha most ezt tudod tesztelni a _normalizeJson-val kellene menni mivel azért alakították ki, hogy ilyen eseteket kezeljenek.
Hát szerintem ha most ezt tudod tesztelni a _normalizeJson-val kellene menni mivel azért alakították ki, hogy ilyen eseteket kezeljenek.
@scr34m
Épp május 31-én volt utoljára, de a fork-ban, és a használatban lévő szerveren átírtam_normalizeJson
használatára
Belefutottam autorenew során, hogy a wildcard certhez 2 TXT -t ellenőrizne, ami nem igazán sikerült a megújítás.
Utánaolvasva https://github.com/acmesh-official/acme.sh/wiki/DNS-API-Dev-Guide
Megnézem, hogy tudok-e erre fixet készíteni, hogy kezelje wildcard esetén a dupla TXT rekordot, ami ráadásul ugyanazon _acme-challenge rekordon kerül a dns-be normál esetben. Ha sikerül akkor majd küldöm a diffet.