42 Commits
2.7.6 ... cron

Author SHA1 Message Date
neilpang
bbcc9d4b8e support multiple cronjobs 2018-02-17 11:33:43 +08:00
neilpang
d84665cb64 fix https://github.com/Neilpang/acme.sh/issues/1271 2018-02-17 10:16:04 +08:00
neil
4bb5d27c59 Merge pull request #1218 from hcouplet/standalone-listen-address-fix
Standalone listen address fix. #1217
2018-02-17 10:14:12 +08:00
neil
11a9f1d1f0 Merge pull request #1274 from jlduran/add-account-key-permissions
Set the account key file permissions
2018-02-17 10:04:06 +08:00
Jose Luis Duran
123e8f21b5 Set the account key file permissions 2018-02-16 15:42:32 -02:00
neilpang
6d6b2efdb5 fix he for solaris 2018-02-16 23:16:25 +08:00
neilpang
c1f5229906 update doc 2018-02-16 11:21:14 +08:00
neilpang
d5865989cf update doc 2018-02-16 10:48:25 +08:00
neilpang
a63766a005 fix format 2018-02-15 21:04:53 +08:00
neilpang
abd0dad2bf fix https://github.com/Neilpang/acme.sh/issues/1145#issuecomment-365863118 2018-02-15 20:35:31 +08:00
neilpang
54a52f7048 Merge branch 'dev' of https://github.com/Neilpang/acme.sh into dev 2018-02-15 12:39:06 +08:00
neilpang
f213215c81 fix lua 2018-02-15 12:38:45 +08:00
neil
96cde120b4 Merge pull request #1258 from wickerwaka/dreamhost_dns
Added DreamHost DNS API
2018-02-15 12:35:37 +08:00
neilpang
0096ef4ddb fix ali 2018-02-15 12:26:35 +08:00
neilpang
ce6c7d4b59 fix dp 2018-02-15 10:51:13 +08:00
neilpang
b51ed9bbb7 https://github.com/Neilpang/acme.sh/issues/1251 2018-02-15 10:29:03 +08:00
neilpang
d8eb08e214 fix format 2018-02-14 22:36:17 +08:00
neilpang
c6f5c7f1a3 fix gd 2018-02-14 22:31:02 +08:00
neilpang
a6b6e31cda fix dp 2018-02-14 20:52:06 +08:00
neilpang
28145a9deb fix ovh 2018-02-14 20:40:49 +08:00
neilpang
fa991c8501 Merge branch 'dev' of https://github.com/Neilpang/acme.sh into dev 2018-02-14 19:40:16 +08:00
neilpang
5f345d2089 fix https://github.com/Neilpang/acme.sh/issues/1262 2018-02-14 19:39:47 +08:00
neil
cc81668c8f Merge pull request #1094 from Daniel15/cloudns-sub
[cloudns] Add support for sub user IDs
2018-02-14 19:23:07 +08:00
neil
6426e044d6 Merge pull request #1263 from jlduran/fix-key-file-permissions
Fix key file permissions
2018-02-14 17:31:40 +08:00
Jose Luis Duran
7b92371a03 Fix key file permissions
Introduced in 8201458332.

Related to #1256.
2018-02-14 06:46:48 -02:00
Martin Donlon
6105d4a4e6 Merge branch 'dev' into dreamhost_dns 2018-02-13 21:04:09 -08:00
Martin Donlon
84649e9d20 Addressing PR feedback
Replace printf with echo
Move dreamhost to bottom of DNS API list
2018-02-13 21:02:38 -08:00
neilpang
3c394f08b0 fix format 2018-02-13 22:23:36 +08:00
neilpang
64f07d9bf3 fix aws for acme v2 2018-02-13 22:17:20 +08:00
neilpang
849a6c12be fix for acme v2 2018-02-13 20:08:05 +08:00
neilpang
9144ce746e fix for v2 wildcard 2018-02-13 19:30:54 +08:00
neilpang
2655e726c9 update dns he 2018-02-12 20:40:24 +08:00
neilpang
012dd6986b nginx 2018-02-12 20:01:40 +08:00
Martin Donlon
2ef9904d00 Merge branch 'dev' into dreamhost_dns 2018-02-11 07:54:10 -08:00
Martin Donlon
2c83224f07 Fixup dns_dreamhost travis failures 2018-02-11 07:37:15 -08:00
neilpang
0c63090a23 fix format 2018-02-10 23:34:34 +08:00
neilpang
0159277dbf fix format 2018-02-10 23:24:43 +08:00
neilpang
6ca5f3d8f6 support Zonomi.com dns api: https://github.com/Neilpang/acme.sh/issues/1255 2018-02-10 23:23:31 +08:00
neilpang
da0bd5a9dc begin 2.7.7 2018-02-10 09:03:55 +08:00
Herve Couplet
9134b6ea98 if local-address is present, bind to that ip instead of 0.0.0.0 2018-01-23 17:53:40 +01:00
Daniel Lo Nigro
bab4f691c5 Fix lint warning 2017-11-12 18:38:30 -08:00
Daniel Lo Nigro
212d0f24d8 [cloudns] Add support for sub user IDs 2017-10-31 22:36:17 -07:00
14 changed files with 505 additions and 260 deletions

View File

@@ -74,7 +74,7 @@ https://github.com/Neilpang/acmetest
- Webroot mode - Webroot mode
- Standalone mode - Standalone mode
- Apache mode - Apache mode
- Nginx mode ( Beta ) - Nginx mode
- DNS mode - DNS mode
- [Stateless mode](https://github.com/Neilpang/acme.sh/wiki/Stateless-Mode) - [Stateless mode](https://github.com/Neilpang/acme.sh/wiki/Stateless-Mode)
@@ -238,7 +238,7 @@ More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert
If you are running a web server, Apache or Nginx, it is recommended to use the `Webroot mode`. If you are running a web server, Apache or Nginx, it is recommended to use the `Webroot mode`.
Particularly, if you are running an Apache server, you should use Apache mode instead. This mode doesn't write any files to your web root folder. Particularly, if you are running an Apache server, you can use Apache mode instead. This mode doesn't write any files to your web root folder.
Just set string "apache" as the second argument and it will force use of apache plugin automatically. Just set string "apache" as the second argument and it will force use of apache plugin automatically.
@@ -246,6 +246,10 @@ Just set string "apache" as the second argument and it will force use of apache
acme.sh --issue --apache -d example.com -d www.example.com -d cp.example.com acme.sh --issue --apache -d example.com -d www.example.com -d cp.example.com
``` ```
**This apache mode is only to issue the cert, it will not change your apache config files.
You will need to configure your website config files to use the cert by yourself.
We don't want to mess your apache server, don't worry.**
More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert
# 7. Use Nginx mode # 7. Use Nginx mode
@@ -266,6 +270,10 @@ So, the config is not changed.
acme.sh --issue --nginx -d example.com -d www.example.com -d cp.example.com acme.sh --issue --nginx -d example.com -d www.example.com -d cp.example.com
``` ```
**This nginx mode is only to issue the cert, it will not change your nginx config files.
You will need to configure your website config files to use the cert by yourself.
We don't want to mess your nginx server, don't worry.**
More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert
# 8. Automatic DNS API integration # 8. Automatic DNS API integration
@@ -314,14 +322,16 @@ You don't have to do anything manually!
1. InternetX autoDNS API (https://internetx.com) 1. InternetX autoDNS API (https://internetx.com)
1. Azure DNS 1. Azure DNS
1. selectel.com(selectel.ru) DNS API 1. selectel.com(selectel.ru) DNS API
1. zonomi.com DNS API
1. DreamHost.com API
And: And:
1. lexicon DNS API: https://github.com/Neilpang/acme.sh/wiki/How-to-use-lexicon-dns-api **lexicon DNS API: https://github.com/Neilpang/acme.sh/wiki/How-to-use-lexicon-dns-api
(DigitalOcean, DNSimple, DNSMadeEasy, DNSPark, EasyDNS, Namesilo, NS1, PointHQ, Rage4 and Vultr etc.) (DigitalOcean, DNSimple, DNSMadeEasy, DNSPark, EasyDNS, Namesilo, NS1, PointHQ, Rage4 and Vultr etc.)**
**More APIs coming soon...** **More APIs coming soon...**
If your DNS provider is not on the supported list above, you can write your own DNS API script easily. If you do, please consider submitting a [Pull Request](https://github.com/Neilpang/acme.sh/pulls) and contribute it to the project. If your DNS provider is not on the supported list above, you can write your own DNS API script easily. If you do, please consider submitting a [Pull Request](https://github.com/Neilpang/acme.sh/pulls) and contribute it to the project.
@@ -330,7 +340,7 @@ For more details: [How to use DNS API](dnsapi)
# 9. Use DNS manual mode: # 9. Use DNS manual mode:
If your dns provider doesn't support any api access, you will have to add the txt record by your hand. If your dns provider doesn't support any api access, you can add the txt record by your hand.
```bash ```bash
acme.sh --issue --dns -d example.com -d www.example.com -d cp.example.com acme.sh --issue --dns -d example.com -d www.example.com -d cp.example.com
@@ -368,7 +378,7 @@ Ok, it's done.
And we support them too! And we support them too!
Just set the `length` parameter with a prefix `ec-`. Just set the `keylength` parameter with a prefix `ec-`.
For example: For example:
@@ -384,7 +394,7 @@ acme.sh --issue -w /home/wwwroot/example.com -d example.com --keylength ec-256
acme.sh --issue -w /home/wwwroot/example.com -d example.com -d www.example.com --keylength ec-256 acme.sh --issue -w /home/wwwroot/example.com -d example.com -d www.example.com --keylength ec-256
``` ```
Please look at the last parameter above. Please look at the `keylength` parameter above.
Valid values are: Valid values are:

62
acme.sh
View File

@@ -1,6 +1,6 @@
#!/usr/bin/env sh #!/usr/bin/env sh
VER=2.7.6 VER=2.7.7
PROJECT_NAME="acme.sh" PROJECT_NAME="acme.sh"
@@ -1281,6 +1281,7 @@ _create_account_key() {
else else
#generate account key #generate account key
_createkey "$length" "$ACCOUNT_KEY_PATH" _createkey "$length" "$ACCOUNT_KEY_PATH"
chmod 600 "$ACCOUNT_KEY_PATH"
fi fi
} }
@@ -1561,6 +1562,9 @@ _inithttp() {
_ACME_CURL="$_ACME_CURL --cacert $CA_BUNDLE " _ACME_CURL="$_ACME_CURL --cacert $CA_BUNDLE "
fi fi
if _contains "$(curl --help 2>&1)" "--globoff"; then
_ACME_CURL="$_ACME_CURL -g "
fi
fi fi
if [ -z "$_ACME_WGET" ] && _exists "wget"; then if [ -z "$_ACME_WGET" ] && _exists "wget"; then
@@ -1835,7 +1839,7 @@ _send_signed_request() {
_body="$response" _body="$response"
if [ "$needbase64" ]; then if [ "$needbase64" ]; then
_body="$(echo "$_body" | _dbase64)" _body="$(echo "$_body" | _dbase64)"
_debug2 _body "$_body" _debug3 _body "$_body"
fi fi
if _contains "$_body" "JWS has invalid anti-replay nonce"; then if _contains "$_body" "JWS has invalid anti-replay nonce"; then
@@ -2003,9 +2007,15 @@ _startserver() {
_NC="$_NC -6" _NC="$_NC -6"
fi fi
SOCAT_OPTIONS=TCP-LISTEN:$Le_HTTPPort,crlf,reuseaddr,fork
#Adding bind to local-address
if [ "$ncaddr" ]; then
$SOCAT_OPTIONS="$SOCAT_OPTIONS,bind=${ncaddr}"
fi
_debug "_NC" "$_NC" _debug "_NC" "$_NC"
#todo listen address $_NC $SOCAT_OPTIONS SYSTEM:"sleep 0.5; echo HTTP/1.1 200 OK; echo ; echo $content; echo;" &
$_NC TCP-LISTEN:$Le_HTTPPort,crlf,reuseaddr,fork SYSTEM:"sleep 0.5; echo HTTP/1.1 200 OK; echo ; echo $content; echo;" &
serverproc="$!" serverproc="$!"
} }
@@ -2760,9 +2770,9 @@ _isRealNginxConf() {
_left="$(sed -n "${_start_nn},99999p" "$2")" _left="$(sed -n "${_start_nn},99999p" "$2")"
_debug2 _left "$_left" _debug2 _left "$_left"
if echo "$_left" | tr "\t" ' ' | grep -n "^ *server *" >/dev/null; then _end="$(echo "$_left" | tr "\t" ' ' | grep -n "^ *server *" | grep -v server_name | _head_n 1)"
_end=$(echo "$_left" | tr "\t" ' ' | grep -n "^ *server *" | _head_n 1) _debug "_end" "$_end"
_debug "_end" "$_end" if [ "$_end" ]; then
_end_n=$(echo "$_end" | cut -d : -f 1) _end_n=$(echo "$_end" | cut -d : -f 1)
_debug "_end_n" "$_end_n" _debug "_end_n" "$_end_n"
_seg_n=$(echo "$_left" | sed -n "1,${_end_n}p") _seg_n=$(echo "$_left" | sed -n "1,${_end_n}p")
@@ -3595,6 +3605,10 @@ $_authorizations_map"
_debug entry "$entry" _debug entry "$entry"
if [ -z "$entry" ]; then if [ -z "$entry" ]; then
_err "Error, can not get domain token entry $d" _err "Error, can not get domain token entry $d"
_supported_vtypes="$(echo "$response" | _egrep_o "\"challenges\":\[[^]]*]" | tr '{' "\n" | grep type | cut -d '"' -f 4 | tr "\n" ' ')"
if [ "$_supported_vtypes" ]; then
_err "The supported validation types are: $_supported_vtypes, but you specified: $vtype"
fi
_clearup _clearup
_on_issue_err "$_post_hook" _on_issue_err "$_post_hook"
return 1 return 1
@@ -4542,7 +4556,7 @@ _installcert() {
cat "$CERT_KEY_PATH" >"$_real_key" cat "$CERT_KEY_PATH" >"$_real_key"
else else
cat "$CERT_KEY_PATH" >"$_real_key" cat "$CERT_KEY_PATH" >"$_real_key"
chmod 700 "$_real_key" chmod 600 "$_real_key"
fi fi
fi fi
@@ -4587,29 +4601,31 @@ installcronjob() {
return 1 return 1
fi fi
_c_cron_param="--home \"$LE_WORKING_DIR\""
if [ "$_c_home" ]; then
_c_entry="--config-home \"$_c_home\""
_c_cron_param="--home \"$LE_WORKING_DIR\" $_c_entry"
fi
_debug "_c_cron_param" "$_c_cron_param"
_info "Installing cron job" _info "Installing cron job"
if ! $_CRONTAB -l | grep "$PROJECT_ENTRY --cron"; then if ! $_CRONTAB -l | grep -- "$PROJECT_ENTRY --cron $_c_cron_param >"; then
if [ -f "$LE_WORKING_DIR/$PROJECT_ENTRY" ]; then if [ -f "$LE_WORKING_DIR/$PROJECT_ENTRY" ]; then
lesh="\"$LE_WORKING_DIR\"/$PROJECT_ENTRY" lesh="\"$LE_WORKING_DIR\"/$PROJECT_ENTRY"
else else
_err "Can not install cronjob, $PROJECT_ENTRY not found." _err "Can not install cronjob, $PROJECT_ENTRY not found."
return 1 return 1
fi fi
if [ "$_c_home" ]; then
_c_entry="--config-home \"$_c_home\" "
fi
_t=$(_time) _t=$(_time)
random_minute=$(_math $_t % 60) random_minute=$(_math $_t % 60)
if _exists uname && uname -a | grep SunOS >/dev/null; then if _exists uname && uname -a | grep SunOS >/dev/null; then
$_CRONTAB -l | { $_CRONTAB -l | {
cat cat
echo "$random_minute 0 * * * $lesh --cron --home \"$LE_WORKING_DIR\" $_c_entry> /dev/null" echo "$random_minute 0 * * * $lesh --cron $_c_cron_param > /dev/null"
} | $_CRONTAB -- } | $_CRONTAB --
else else
$_CRONTAB -l | { $_CRONTAB -l | {
cat cat
echo "$random_minute 0 * * * $lesh --cron --home \"$LE_WORKING_DIR\" $_c_entry> /dev/null" echo "$random_minute 0 * * * $lesh --cron $_c_cron_param > /dev/null"
} | $_CRONTAB - } | $_CRONTAB -
fi fi
fi fi
@@ -4622,6 +4638,7 @@ installcronjob() {
} }
uninstallcronjob() { uninstallcronjob() {
_c_home="$1"
_CRONTAB="crontab" _CRONTAB="crontab"
if ! _exists "$_CRONTAB" && _exists "fcrontab"; then if ! _exists "$_CRONTAB" && _exists "fcrontab"; then
_CRONTAB="fcrontab" _CRONTAB="fcrontab"
@@ -4630,13 +4647,20 @@ uninstallcronjob() {
if ! _exists "$_CRONTAB"; then if ! _exists "$_CRONTAB"; then
return return
fi fi
_c_cron_param="--home \"$LE_WORKING_DIR\""
if [ "$_c_home" ]; then
_c_entry="--config-home \"$_c_home\""
_c_cron_param="--home \"$LE_WORKING_DIR\" $_c_entry"
fi
_debug "_c_cron_param" "$_c_cron_param"
_info "Removing cron job" _info "Removing cron job"
cr="$($_CRONTAB -l | grep "$PROJECT_ENTRY --cron")" cr="$($_CRONTAB -l | grep "$PROJECT_ENTRY --cron $_c_cron_param >")"
_debug "cr" "$cr"
if [ "$cr" ]; then if [ "$cr" ]; then
if _exists uname && uname -a | grep solaris >/dev/null; then if _exists uname && uname -a | grep solaris >/dev/null; then
$_CRONTAB -l | sed "/$PROJECT_ENTRY --cron/d" | $_CRONTAB -- $_CRONTAB -l | grep -v "$PROJECT_ENTRY --cron $_c_cron_param >" | $_CRONTAB --
else else
$_CRONTAB -l | sed "/$PROJECT_ENTRY --cron/d" | $_CRONTAB - $_CRONTAB -l | grep -v "$PROJECT_ENTRY --cron $_c_cron_param >" | $_CRONTAB -
fi fi
LE_WORKING_DIR="$(echo "$cr" | cut -d ' ' -f 9 | tr -d '"')" LE_WORKING_DIR="$(echo "$cr" | cut -d ' ' -f 9 | tr -d '"')"
_info LE_WORKING_DIR "$LE_WORKING_DIR" _info LE_WORKING_DIR "$LE_WORKING_DIR"
@@ -5995,7 +6019,7 @@ _process() {
list "$_listraw" list "$_listraw"
;; ;;
installcronjob) installcronjob "$_confighome" ;; installcronjob) installcronjob "$_confighome" ;;
uninstallcronjob) uninstallcronjob ;; uninstallcronjob) uninstallcronjob "$_confighome" ;;
cron) cron ;; cron) cron ;;
toPkcs) toPkcs)
toPkcs "$_domain" "$_password" "$_ecc" toPkcs "$_domain" "$_password" "$_ecc"

View File

@@ -409,10 +409,13 @@ acme.sh --issue --dns dns_dgon -d example.com -d www.example.com
## 21. Use ClouDNS.net API ## 21. Use ClouDNS.net API
You need to set the HTTP API user ID and password credentials. See: https://www.cloudns.net/wiki/article/42/ You need to set the HTTP API user ID and password credentials. See: https://www.cloudns.net/wiki/article/42/. For security reasons, it's recommended to use a sub user ID that only has access to the necessary zones, as a regular API user has access to your entire account.
``` ```
export CLOUDNS_AUTH_ID=XXXXX # Use this for a sub auth ID
export CLOUDNS_SUB_AUTH_ID=XXXXX
# Use this for a regular auth ID
#export CLOUDNS_AUTH_ID=XXXXX
export CLOUDNS_AUTH_PASSWORD="YYYYYYYYY" export CLOUDNS_AUTH_PASSWORD="YYYYYYYYY"
``` ```
@@ -512,7 +515,7 @@ acme.sh --issue --dns dns_nsone -d example.com -d www.example.com
export DuckDNS_Token="aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee" export DuckDNS_Token="aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
``` ```
Please note that since DuckDNS uses StartSSL as their cert provider, thus Please note that since DuckDNS uses StartSSL as their cert provider, thus
--insecure may need to be used when issuing certs: --insecure may need to be used when issuing certs:
``` ```
acme.sh --insecure --issue --dns dns_duckdns -d mydomain.duckdns.org acme.sh --insecure --issue --dns dns_duckdns -d mydomain.duckdns.org
@@ -585,7 +588,7 @@ For issues, please report to https://github.com/non7top/acme.sh/issues.
## 31. Use Hurricane Electric ## 31. Use Hurricane Electric
Hurricane Electric doesn't have an API so just set your login credentials like so: Hurricane Electric (https://dns.he.net/) doesn't have an API so just set your login credentials like so:
``` ```
export HE_Username="yourusername" export HE_Username="yourusername"
@@ -719,6 +722,40 @@ acme.sh --issue --dns dns_selectel -d example.com -d www.example.com
The `SL_Key` will be saved in `~/.acme.sh/account.conf` and will be reused when needed. The `SL_Key` will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
## 39. Use zonomi.com domain API to automatically issue cert
First you need to login to your account to find your API key from: http://zonomi.com/app/dns/dyndns.jsp
Your will find your api key in the example urls:
```sh
https://zonomi.com/app/dns/dyndns.jsp?host=example.com&api_key=1063364558943540954358668888888888
```
```sh
export ZM_Key="1063364558943540954358668888888888"
```
Ok, let's issue a cert now:
```
acme.sh --issue --dns dns_zonomi -d example.com -d www.example.com
```
The `ZM_Key` will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
## 40. Use DreamHost DNS API
DNS API keys may be created at https://panel.dreamhost.com/?tree=home.api.
Ensure the created key has add and remove privelages.
```
export DH_API_Key="<api key>"
acme.sh --issue --dns dns_dreamhost -d example.com -d www.example.com
```
The 'DH_API_KEY' will be saved in `~/.acme.sh/account.conf` and will
be reused when needed.
# Use custom API # Use custom API

View File

@@ -10,6 +10,8 @@ dns_ali_add() {
fulldomain=$1 fulldomain=$1
txtvalue=$2 txtvalue=$2
Ali_Key="${Ali_Key:-$(_readaccountconf_mutable Ali_Key)}"
Ali_Secret="${Ali_Secret:-$(_readaccountconf_mutable Ali_Secret)}"
if [ -z "$Ali_Key" ] || [ -z "$Ali_Secret" ]; then if [ -z "$Ali_Key" ] || [ -z "$Ali_Secret" ]; then
Ali_Key="" Ali_Key=""
Ali_Secret="" Ali_Secret=""
@@ -18,8 +20,8 @@ dns_ali_add() {
fi fi
#save the api key and secret to the account conf file. #save the api key and secret to the account conf file.
_saveaccountconf Ali_Key "$Ali_Key" _saveaccountconf_mutable Ali_Key "$Ali_Key"
_saveaccountconf Ali_Secret "$Ali_Secret" _saveaccountconf_mutable Ali_Secret "$Ali_Secret"
_debug "First detect the root zone" _debug "First detect the root zone"
if ! _get_root "$fulldomain"; then if ! _get_root "$fulldomain"; then
@@ -32,6 +34,15 @@ dns_ali_add() {
dns_ali_rm() { dns_ali_rm() {
fulldomain=$1 fulldomain=$1
txtvalue=$2
Ali_Key="${Ali_Key:-$(_readaccountconf_mutable Ali_Key)}"
Ali_Secret="${Ali_Secret:-$(_readaccountconf_mutable Ali_Secret)}"
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
return 1
fi
_clean _clean
} }
@@ -76,16 +87,14 @@ _ali_rest() {
return 1 return 1
fi fi
_debug2 response "$response"
if [ -z "$2" ]; then if [ -z "$2" ]; then
message="$(printf "%s" "$response" | _egrep_o "\"Message\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \")" message="$(echo "$response" | _egrep_o "\"Message\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \")"
if [ -n "$message" ]; then if [ "$message" ]; then
_err "$message" _err "$message"
return 1 return 1
fi fi
fi fi
_debug2 response "$response"
return 0
} }
_ali_urlencode() { _ali_urlencode() {
@@ -112,12 +121,14 @@ _ali_nonce() {
} }
_check_exist_query() { _check_exist_query() {
_qdomain="$1"
_qsubdomain="$2"
query='' query=''
query=$query'AccessKeyId='$Ali_Key query=$query'AccessKeyId='$Ali_Key
query=$query'&Action=DescribeDomainRecords' query=$query'&Action=DescribeDomainRecords'
query=$query'&DomainName='$1 query=$query'&DomainName='$_qdomain
query=$query'&Format=json' query=$query'&Format=json'
query=$query'&RRKeyWord=_acme-challenge' query=$query'&RRKeyWord='$_qsubdomain
query=$query'&SignatureMethod=HMAC-SHA1' query=$query'&SignatureMethod=HMAC-SHA1'
query=$query"&SignatureNonce=$(_ali_nonce)" query=$query"&SignatureNonce=$(_ali_nonce)"
query=$query'&SignatureVersion=1.0' query=$query'&SignatureVersion=1.0'
@@ -169,17 +180,21 @@ _describe_records_query() {
} }
_clean() { _clean() {
_check_exist_query "$_domain" _check_exist_query "$_domain" "$_sub_domain"
if ! _ali_rest "Check exist records" "ignore"; then if ! _ali_rest "Check exist records" "ignore"; then
return 1 return 1
fi fi
records="$(echo "$response" -n | _egrep_o "\"RecordId\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \")" record_id="$(echo "$response" | tr '{' "\n" | grep "$_sub_domain" | grep "$txtvalue" | tr "," "\n" | grep RecordId | cut -d '"' -f 4)"
printf "%s" "$records" \ _debug2 record_id "$record_id"
| while read -r record_id; do
_delete_record_query "$record_id" if [ -z "$record_id" ]; then
_ali_rest "Delete record $record_id" "ignore" _debug "record not found, skip"
done else
_delete_record_query "$record_id"
_ali_rest "Delete record $record_id" "ignore"
fi
} }
_timestamp() { _timestamp() {

View File

@@ -42,7 +42,26 @@ dns_aws_add() {
_debug _sub_domain "$_sub_domain" _debug _sub_domain "$_sub_domain"
_debug _domain "$_domain" _debug _domain "$_domain"
_aws_tmpl_xml="<ChangeResourceRecordSetsRequest xmlns=\"https://route53.amazonaws.com/doc/2013-04-01/\"><ChangeBatch><Changes><Change><Action>UPSERT</Action><ResourceRecordSet><Name>$fulldomain</Name><Type>TXT</Type><TTL>300</TTL><ResourceRecords><ResourceRecord><Value>\"$txtvalue\"</Value></ResourceRecord></ResourceRecords></ResourceRecordSet></Change></Changes></ChangeBatch></ChangeResourceRecordSetsRequest>" _info "Geting existing records for $fulldomain"
if ! aws_rest GET "2013-04-01$_domain_id/rrset" "name=$fulldomain&type=TXT"; then
return 1
fi
if _contains "$response" "<Name>$fulldomain.</Name>"; then
_resource_record="$(echo "$response" | sed 's/<ResourceRecordSet>/"/g' | tr '"' "\n" | grep "<Name>$fulldomain.</Name>" | _egrep_o "<ResourceRecords.*</ResourceRecords>" | sed "s/<ResourceRecords>//" | sed "s#</ResourceRecords>##")"
_debug "_resource_record" "$_resource_record"
else
_debug "single new add"
fi
if [ "$_resource_record" ] && _contains "$response" "$txtvalue"; then
_info "The txt record already exists, skip"
return 0
fi
_debug "Adding records"
_aws_tmpl_xml="<ChangeResourceRecordSetsRequest xmlns=\"https://route53.amazonaws.com/doc/2013-04-01/\"><ChangeBatch><Changes><Change><Action>UPSERT</Action><ResourceRecordSet><Name>$fulldomain</Name><Type>TXT</Type><TTL>300</TTL><ResourceRecords>$_resource_record<ResourceRecord><Value>\"$txtvalue\"</Value></ResourceRecord></ResourceRecords></ResourceRecordSet></Change></Changes></ChangeBatch></ChangeResourceRecordSetsRequest>"
if aws_rest POST "2013-04-01$_domain_id/rrset/" "" "$_aws_tmpl_xml" && _contains "$response" "ChangeResourceRecordSetsResponse"; then if aws_rest POST "2013-04-01$_domain_id/rrset/" "" "$_aws_tmpl_xml" && _contains "$response" "ChangeResourceRecordSetsResponse"; then
_info "txt record updated success." _info "txt record updated success."
@@ -68,7 +87,20 @@ dns_aws_rm() {
_debug _sub_domain "$_sub_domain" _debug _sub_domain "$_sub_domain"
_debug _domain "$_domain" _debug _domain "$_domain"
_aws_tmpl_xml="<ChangeResourceRecordSetsRequest xmlns=\"https://route53.amazonaws.com/doc/2013-04-01/\"><ChangeBatch><Changes><Change><Action>DELETE</Action><ResourceRecordSet><ResourceRecords><ResourceRecord><Value>\"$txtvalue\"</Value></ResourceRecord></ResourceRecords><Name>$fulldomain.</Name><Type>TXT</Type><TTL>300</TTL></ResourceRecordSet></Change></Changes></ChangeBatch></ChangeResourceRecordSetsRequest>" _info "Geting existing records for $fulldomain"
if ! aws_rest GET "2013-04-01$_domain_id/rrset" "name=$fulldomain&type=TXT"; then
return 1
fi
if _contains "$response" "<Name>$fulldomain.</Name>"; then
_resource_record="$(echo "$response" | sed 's/<ResourceRecordSet>/"/g' | tr '"' "\n" | grep "<Name>$fulldomain.</Name>" | _egrep_o "<ResourceRecords.*</ResourceRecords>" | sed "s/<ResourceRecords>//" | sed "s#</ResourceRecords>##")"
_debug "_resource_record" "$_resource_record"
else
_debug "no records exists, skip"
return 0
fi
_aws_tmpl_xml="<ChangeResourceRecordSetsRequest xmlns=\"https://route53.amazonaws.com/doc/2013-04-01/\"><ChangeBatch><Changes><Change><Action>DELETE</Action><ResourceRecordSet><ResourceRecords>$_resource_record</ResourceRecords><Name>$fulldomain.</Name><Type>TXT</Type><TTL>300</TTL></ResourceRecordSet></Change></Changes></ChangeBatch></ChangeResourceRecordSetsRequest>"
if aws_rest POST "2013-04-01$_domain_id/rrset/" "" "$_aws_tmpl_xml" && _contains "$response" "ChangeResourceRecordSetsResponse"; then if aws_rest POST "2013-04-01$_domain_id/rrset/" "" "$_aws_tmpl_xml" && _contains "$response" "ChangeResourceRecordSetsResponse"; then
_info "txt record deleted success." _info "txt record deleted success."
@@ -87,7 +119,6 @@ _get_root() {
p=1 p=1
if aws_rest GET "2013-04-01/hostedzone"; then if aws_rest GET "2013-04-01/hostedzone"; then
_debug "response" "$response"
while true; do while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100) h=$(printf "%s" "$domain" | cut -d . -f $i-100)
_debug2 "Checking domain: $h" _debug2 "Checking domain: $h"
@@ -236,6 +267,7 @@ aws_rest() {
fi fi
_ret="$?" _ret="$?"
_debug2 response "$response"
if [ "$_ret" = "0" ]; then if [ "$_ret" = "0" ]; then
if _contains "$response" "<ErrorResponse"; then if _contains "$response" "<ErrorResponse"; then
_err "Response error:$response" _err "Response error:$response"

View File

@@ -4,6 +4,7 @@
# Repository: https://github.com/ClouDNS/acme.sh/ # Repository: https://github.com/ClouDNS/acme.sh/
#CLOUDNS_AUTH_ID=XXXXX #CLOUDNS_AUTH_ID=XXXXX
#CLOUDNS_SUB_AUTH_ID=XXXXX
#CLOUDNS_AUTH_PASSWORD="YYYYYYYYY" #CLOUDNS_AUTH_PASSWORD="YYYYYYYYY"
CLOUDNS_API="https://api.cloudns.net" CLOUDNS_API="https://api.cloudns.net"
@@ -97,17 +98,19 @@ _dns_cloudns_init_check() {
fi fi
CLOUDNS_AUTH_ID="${CLOUDNS_AUTH_ID:-$(_readaccountconf_mutable CLOUDNS_AUTH_ID)}" CLOUDNS_AUTH_ID="${CLOUDNS_AUTH_ID:-$(_readaccountconf_mutable CLOUDNS_AUTH_ID)}"
CLOUDNS_SUB_AUTH_ID="${CLOUDNS_SUB_AUTH_ID:-$(_readaccountconf_mutable CLOUDNS_SUB_AUTH_ID)}"
CLOUDNS_AUTH_PASSWORD="${CLOUDNS_AUTH_PASSWORD:-$(_readaccountconf_mutable CLOUDNS_AUTH_PASSWORD)}" CLOUDNS_AUTH_PASSWORD="${CLOUDNS_AUTH_PASSWORD:-$(_readaccountconf_mutable CLOUDNS_AUTH_PASSWORD)}"
if [ -z "$CLOUDNS_AUTH_ID" ] || [ -z "$CLOUDNS_AUTH_PASSWORD" ]; then if [ -z "$CLOUDNS_AUTH_ID$CLOUDNS_SUB_AUTH_ID" ] || [ -z "$CLOUDNS_AUTH_PASSWORD" ]; then
CLOUDNS_AUTH_ID="" CLOUDNS_AUTH_ID=""
CLOUDNS_SUB_AUTH_ID=""
CLOUDNS_AUTH_PASSWORD="" CLOUDNS_AUTH_PASSWORD=""
_err "You don't specify cloudns api id and password yet." _err "You don't specify cloudns api id and password yet."
_err "Please create you id and password and try again." _err "Please create you id and password and try again."
return 1 return 1
fi fi
if [ -z "$CLOUDNS_AUTH_ID" ]; then if [ -z "$CLOUDNS_AUTH_ID" ] && [ -z "$CLOUDNS_SUB_AUTH_ID" ]; then
_err "CLOUDNS_AUTH_ID is not configured" _err "CLOUDNS_AUTH_ID or CLOUDNS_SUB_AUTH_ID is not configured"
return 1 return 1
fi fi
@@ -125,6 +128,7 @@ _dns_cloudns_init_check() {
#save the api id and password to the account conf file. #save the api id and password to the account conf file.
_saveaccountconf_mutable CLOUDNS_AUTH_ID "$CLOUDNS_AUTH_ID" _saveaccountconf_mutable CLOUDNS_AUTH_ID "$CLOUDNS_AUTH_ID"
_saveaccountconf_mutable CLOUDNS_SUB_AUTH_ID "$CLOUDNS_SUB_AUTH_ID"
_saveaccountconf_mutable CLOUDNS_AUTH_PASSWORD "$CLOUDNS_AUTH_PASSWORD" _saveaccountconf_mutable CLOUDNS_AUTH_PASSWORD "$CLOUDNS_AUTH_PASSWORD"
CLOUDNS_INIT_CHECK_COMPLETED=1 CLOUDNS_INIT_CHECK_COMPLETED=1
@@ -168,12 +172,19 @@ _dns_cloudns_http_api_call() {
method=$1 method=$1
_debug CLOUDNS_AUTH_ID "$CLOUDNS_AUTH_ID" _debug CLOUDNS_AUTH_ID "$CLOUDNS_AUTH_ID"
_debug CLOUDNS_SUB_AUTH_ID "$CLOUDNS_SUB_AUTH_ID"
_debug CLOUDNS_AUTH_PASSWORD "$CLOUDNS_AUTH_PASSWORD" _debug CLOUDNS_AUTH_PASSWORD "$CLOUDNS_AUTH_PASSWORD"
if [ -z "$2" ]; then if [ ! -z "$CLOUDNS_SUB_AUTH_ID" ]; then
data="auth-id=$CLOUDNS_AUTH_ID&auth-password=$CLOUDNS_AUTH_PASSWORD" auth_user="sub-auth-id=$CLOUDNS_SUB_AUTH_ID"
else else
data="auth-id=$CLOUDNS_AUTH_ID&auth-password=$CLOUDNS_AUTH_PASSWORD&$2" auth_user="auth-id=$CLOUDNS_AUTH_ID"
fi
if [ -z "$2" ]; then
data="$auth_user&auth-password=$CLOUDNS_AUTH_PASSWORD"
else
data="$auth_user&auth-password=$CLOUDNS_AUTH_PASSWORD&$2"
fi fi
response="$(_get "$CLOUDNS_API/$method?$data")" response="$(_get "$CLOUDNS_API/$method?$data")"

View File

@@ -36,33 +36,18 @@ dns_cx_add() {
return 1 return 1
fi fi
existing_records "$_domain" "$_sub_domain" add_record "$_domain" "$_sub_domain" "$txtvalue"
_debug count "$count"
if [ "$?" != "0" ]; then
_err "Error get existing records."
return 1
fi
if [ "$count" = "0" ]; then
add_record "$_domain" "$_sub_domain" "$txtvalue"
else
update_record "$_domain" "$_sub_domain" "$txtvalue"
fi
if [ "$?" = "0" ]; then
return 0
fi
return 1
} }
#fulldomain #fulldomain txtvalue
dns_cx_rm() { dns_cx_rm() {
fulldomain=$1 fulldomain=$1
txtvalue=$2
REST_API="$CX_Api" REST_API="$CX_Api"
if _get_root "$fulldomain"; then if _get_root "$fulldomain"; then
record_id="" record_id=""
existing_records "$_domain" "$_sub_domain" existing_records "$_domain" "$_sub_domain" "$txtvalue"
if ! [ "$record_id" = "" ]; then if [ "$record_id" ]; then
_rest DELETE "record/$record_id/$_domain_id" "{}" _rest DELETE "record/$record_id/$_domain_id" "{}"
_info "Deleted record ${fulldomain}" _info "Deleted record ${fulldomain}"
fi fi
@@ -77,7 +62,6 @@ existing_records() {
_debug "Getting txt records" _debug "Getting txt records"
root=$1 root=$1
sub=$2 sub=$2
count=0
if ! _rest GET "record/$_domain_id?:domain_id?host_id=0&offset=0&row_num=100"; then if ! _rest GET "record/$_domain_id?:domain_id?host_id=0&offset=0&row_num=100"; then
return 1 return 1
fi fi
@@ -89,7 +73,6 @@ existing_records() {
fi fi
if printf "%s" "$response" | grep '"type":"TXT"' >/dev/null; then if printf "%s" "$response" | grep '"type":"TXT"' >/dev/null; then
count=1
record_id=$(printf "%s\n" "$seg" | _egrep_o '"record_id":"[^"]*"' | cut -d : -f 2 | tr -d \" | _head_n 1) record_id=$(printf "%s\n" "$seg" | _egrep_o '"record_id":"[^"]*"' | cut -d : -f 2 | tr -d \" | _head_n 1)
_debug record_id "$record_id" _debug record_id "$record_id"
return 0 return 0
@@ -114,23 +97,6 @@ add_record() {
return 0 return 0
} }
#update the txt record
#Usage: root sub txtvalue
update_record() {
root=$1
sub=$2
txtvalue=$3
fulldomain="$sub.$root"
_info "Updating record"
if _rest PUT "record/$record_id" "{\"domain_id\": $_domain_id, \"host\":\"$_sub_domain\", \"value\":\"$txtvalue\", \"type\":\"TXT\",\"ttl\":600, \"line_id\":1}"; then
return 0
fi
return 1
}
#################### Private functions below ################################## #################### Private functions below ##################################
#_acme-challenge.www.domain.com #_acme-challenge.www.domain.com
#returns #returns

View File

@@ -15,6 +15,8 @@ dns_dp_add() {
fulldomain=$1 fulldomain=$1
txtvalue=$2 txtvalue=$2
DP_Id="${DP_Id:-$(_readaccountconf_mutable DP_Id)}"
DP_Key="${DP_Key:-$(_readaccountconf_mutable DP_Key)}"
if [ -z "$DP_Id" ] || [ -z "$DP_Key" ]; then if [ -z "$DP_Id" ] || [ -z "$DP_Key" ]; then
DP_Id="" DP_Id=""
DP_Key="" DP_Key=""
@@ -24,8 +26,8 @@ dns_dp_add() {
fi fi
#save the api key and email to the account conf file. #save the api key and email to the account conf file.
_saveaccountconf DP_Id "$DP_Id" _saveaccountconf_mutable DP_Id "$DP_Id"
_saveaccountconf DP_Key "$DP_Key" _saveaccountconf_mutable DP_Key "$DP_Key"
_debug "First detect the root zone" _debug "First detect the root zone"
if ! _get_root "$fulldomain"; then if ! _get_root "$fulldomain"; then
@@ -33,24 +35,18 @@ dns_dp_add() {
return 1 return 1
fi fi
existing_records "$_domain" "$_sub_domain" add_record "$_domain" "$_sub_domain" "$txtvalue"
_debug count "$count"
if [ "$?" != "0" ]; then
_err "Error get existing records."
return 1
fi
if [ "$count" = "0" ]; then
add_record "$_domain" "$_sub_domain" "$txtvalue"
else
update_record "$_domain" "$_sub_domain" "$txtvalue"
fi
} }
#fulldomain txtvalue #fulldomain txtvalue
dns_dp_rm() { dns_dp_rm() {
fulldomain=$1 fulldomain=$1
txtvalue=$2 txtvalue=$2
DP_Id="${DP_Id:-$(_readaccountconf_mutable DP_Id)}"
DP_Key="${DP_Key:-$(_readaccountconf_mutable DP_Key)}"
_debug "First detect the root zone" _debug "First detect the root zone"
if ! _get_root "$fulldomain"; then if ! _get_root "$fulldomain"; then
_err "invalid domain" _err "invalid domain"
@@ -83,37 +79,6 @@ dns_dp_rm() {
} }
#usage: root sub
#return if the sub record already exists.
#echos the existing records count.
# '0' means doesn't exist
existing_records() {
_debug "Getting txt records"
root=$1
sub=$2
if ! _rest POST "Record.List" "login_token=$DP_Id,$DP_Key&domain_id=$_domain_id&sub_domain=$_sub_domain"; then
return 1
fi
if _contains "$response" 'No records'; then
count=0
return 0
fi
if _contains "$response" "Action completed successful"; then
count=$(printf "%s" "$response" | grep -c '<type>TXT</type>' | tr -d ' ')
record_id=$(printf "%s" "$response" | grep '^<id>' | tail -1 | cut -d '>' -f 2 | cut -d '<' -f 1)
_debug record_id "$record_id"
return 0
else
_err "get existing records error."
return 1
fi
count=0
}
#add the txt record. #add the txt record.
#usage: root sub txtvalue #usage: root sub txtvalue
add_record() { add_record() {
@@ -128,34 +93,7 @@ add_record() {
return 1 return 1
fi fi
if _contains "$response" "Action completed successful"; then _contains "$response" "Action completed successful" || _contains "$response" "Domain record already exists"
return 0
fi
return 1 #error
}
#update the txt record
#Usage: root sub txtvalue
update_record() {
root=$1
sub=$2
txtvalue=$3
fulldomain="$sub.$root"
_info "Updating record"
if ! _rest POST "Record.Modify" "login_token=$DP_Id,$DP_Key&format=json&domain_id=$_domain_id&sub_domain=$_sub_domain&record_type=TXT&value=$txtvalue&record_line=默认&record_id=$record_id"; then
return 1
fi
if _contains "$response" "Action completed successful"; then
return 0
fi
return 1 #error
} }
#################### Private functions below ################################## #################### Private functions below ##################################

97
dnsapi/dns_dreamhost.sh Normal file
View File

@@ -0,0 +1,97 @@
#!/usr/bin/env sh
#Author: RhinoLance
#Report Bugs here: https://github.com/RhinoLance/acme.sh
#
#define the api endpoint
DH_API_ENDPOINT="https://api.dreamhost.com/"
querystring=""
######## Public functions #####################
#Usage: dns_myapi_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_dreamhost_add() {
fulldomain=$1
txtvalue=$2
if ! validate "$fulldomain" "$txtvalue"; then
return 1
fi
querystring="key=$DH_API_KEY&cmd=dns-add_record&record=$fulldomain&type=TXT&value=$txtvalue"
if ! submit "$querystring"; then
return 1
fi
return 0
}
#Usage: fulldomain txtvalue
#Remove the txt record after validation.
dns_dreamhost_rm() {
fulldomain=$1
txtvalue=$2
if ! validate "$fulldomain" "$txtvalue"; then
return 1
fi
querystring="key=$DH_API_KEY&cmd=dns-remove_record&record=$fulldomain&type=TXT&value=$txtvalue"
if ! submit "$querystring"; then
return 1
fi
return 0
}
#################### Private functions below ##################################
#send the command to the api endpoint.
submit() {
querystring=$1
url="$DH_API_ENDPOINT?$querystring"
_debug url "$url"
if ! response="$(_get "$url")"; then
_err "Error <$1>"
return 1
fi
if [ -z "$2" ]; then
message="$(echo "$response" | _egrep_o "\"Message\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \")"
if [ -n "$message" ]; then
_err "$message"
return 1
fi
fi
_debug response "$response"
return 0
}
#check that we have a valid API Key
validate() {
fulldomain=$1
txtvalue=$2
_info "Using dreamhost"
_debug fulldomain "$fulldomain"
_debug txtvalue "$txtvalue"
#retrieve the API key from the environment variable if it exists, otherwise look for a saved key.
DH_API_KEY="${DH_API_KEY:-$(_readaccountconf_mutable DH_API_KEY)}"
if [ -z "$DH_API_KEY" ]; then
DH_API_KEY=""
_err "You didn't specify the DreamHost api key yet (export DH_API_KEY=\"<api key>\")"
_err "Please login to your control panel, create a key and try again."
return 1
fi
#save the api key to the account conf file.
_saveaccountconf_mutable DH_API_KEY "$DH_API_KEY"
}

View File

@@ -15,6 +15,8 @@ dns_gd_add() {
fulldomain=$1 fulldomain=$1
txtvalue=$2 txtvalue=$2
GD_Key="${GD_Key:-$(_readaccountconf_mutable GD_Key)}"
GD_Secret="${GD_Secret:-$(_readaccountconf_mutable GD_Secret)}"
if [ -z "$GD_Key" ] || [ -z "$GD_Secret" ]; then if [ -z "$GD_Key" ] || [ -z "$GD_Secret" ]; then
GD_Key="" GD_Key=""
GD_Secret="" GD_Secret=""
@@ -24,8 +26,8 @@ dns_gd_add() {
fi fi
#save the api key and email to the account conf file. #save the api key and email to the account conf file.
_saveaccountconf GD_Key "$GD_Key" _saveaccountconf_mutable GD_Key "$GD_Key"
_saveaccountconf GD_Secret "$GD_Secret" _saveaccountconf_mutable GD_Secret "$GD_Secret"
_debug "First detect the root zone" _debug "First detect the root zone"
if ! _get_root "$fulldomain"; then if ! _get_root "$fulldomain"; then
@@ -36,8 +38,27 @@ dns_gd_add() {
_debug _sub_domain "$_sub_domain" _debug _sub_domain "$_sub_domain"
_debug _domain "$_domain" _debug _domain "$_domain"
_debug "Getting existing records"
if ! _gd_rest GET "domains/$_domain/records/TXT/$_sub_domain"; then
return 1
fi
if _contains "$response" "$txtvalue"; then
_info "The record is existing, skip"
return 0
fi
_add_data="{\"data\":\"$txtvalue\"}"
for t in $(echo "$response" | tr '{' "\n" | grep "\"name\":\"$_sub_domain\"" | tr ',' "\n" | grep '"data"' | cut -d : -f 2); do
_debug2 t "$t"
if [ "$t" ]; then
_add_data="$_add_data,{\"data\":$t}"
fi
done
_debug2 _add_data "$_add_data"
_info "Adding record" _info "Adding record"
if _gd_rest PUT "domains/$_domain/records/TXT/$_sub_domain" "[{\"data\":\"$txtvalue\"}]"; then if _gd_rest PUT "domains/$_domain/records/TXT/$_sub_domain" "[$_add_data]"; then
if [ "$response" = "{}" ]; then if [ "$response" = "{}" ]; then
_info "Added, sleeping 10 seconds" _info "Added, sleeping 10 seconds"
_sleep 10 _sleep 10
@@ -56,7 +77,47 @@ dns_gd_add() {
#fulldomain #fulldomain
dns_gd_rm() { dns_gd_rm() {
fulldomain=$1 fulldomain=$1
txtvalue=$2
GD_Key="${GD_Key:-$(_readaccountconf_mutable GD_Key)}"
GD_Secret="${GD_Secret:-$(_readaccountconf_mutable GD_Secret)}"
_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"
if ! _gd_rest GET "domains/$_domain/records/TXT/$_sub_domain"; then
return 1
fi
if ! _contains "$response" "$txtvalue"; then
_info "The record is not existing, skip"
return 0
fi
_add_data=""
for t in $(echo "$response" | tr '{' "\n" | grep "\"name\":\"$_sub_domain\"" | tr ',' "\n" | grep '"data"' | cut -d : -f 2); do
_debug2 t "$t"
if [ "$t" ] && [ "$t" != "\"$txtvalue\"" ]; then
if [ "$_add_data" ]; then
_add_data="$_add_data,{\"data\":$t}"
else
_add_data="{\"data\":$t}"
fi
fi
done
if [ -z "$_add_data" ]; then
_add_data="{\"data\":\"\"}"
fi
_debug2 _add_data "$_add_data"
_gd_rest PUT "domains/$_domain/records/TXT/$_sub_domain" "[$_add_data]"
} }
#################### Private functions below ################################## #################### Private functions below ##################################

View File

@@ -19,14 +19,16 @@ dns_he_add() {
_txt_value=$2 _txt_value=$2
_info "Using DNS-01 Hurricane Electric hook" _info "Using DNS-01 Hurricane Electric hook"
HE_Username="${HE_Username:-$(_readaccountconf_mutable HE_Username)}"
HE_Password="${HE_Password:-$(_readaccountconf_mutable HE_Password)}"
if [ -z "$HE_Username" ] || [ -z "$HE_Password" ]; then if [ -z "$HE_Username" ] || [ -z "$HE_Password" ]; then
HE_Username= HE_Username=
HE_Password= HE_Password=
_err "No auth details provided. Please set user credentials using the \$HE_Username and \$HE_Password envoronment variables." _err "No auth details provided. Please set user credentials using the \$HE_Username and \$HE_Password envoronment variables."
return 1 return 1
fi fi
_saveaccountconf HE_Username "$HE_Username" _saveaccountconf_mutable HE_Username "$HE_Username"
_saveaccountconf HE_Password "$HE_Password" _saveaccountconf_mutable HE_Password "$HE_Password"
# Fills in the $_zone_id # Fills in the $_zone_id
_find_zone "$_full_domain" || return 1 _find_zone "$_full_domain" || return 1
@@ -62,7 +64,8 @@ dns_he_rm() {
_full_domain=$1 _full_domain=$1
_txt_value=$2 _txt_value=$2
_info "Cleaning up after DNS-01 Hurricane Electric hook" _info "Cleaning up after DNS-01 Hurricane Electric hook"
HE_Username="${HE_Username:-$(_readaccountconf_mutable HE_Username)}"
HE_Password="${HE_Password:-$(_readaccountconf_mutable HE_Password)}"
# fills in the $_zone_id # fills in the $_zone_id
_find_zone "$_full_domain" || return 1 _find_zone "$_full_domain" || return 1
_debug "Zone id \"$_zone_id\" will be used." _debug "Zone id \"$_zone_id\" will be used."
@@ -72,17 +75,19 @@ dns_he_rm() {
body="$body&hosted_dns_zoneid=$_zone_id" body="$body&hosted_dns_zoneid=$_zone_id"
body="$body&menu=edit_zone" body="$body&menu=edit_zone"
body="$body&hosted_dns_editzone=" body="$body&hosted_dns_editzone="
domain_regex="$(echo "$_full_domain" | sed 's/\./\\./g')" # escape dots
_record_id=$(_post "$body" "https://dns.he.net/" \
| tr -d '\n' \
| _egrep_o "data=\"&quot;${_txt_value}&quot;([^>]+>){6}[^<]+<[^;]+;deleteRecord\('[0-9]+','${domain_regex}','TXT'\)" \
| _egrep_o "[0-9]+','${domain_regex}','TXT'\)$" \
| _egrep_o "^[0-9]+"
)
# The series of egreps above could have been done a bit shorter but
# I wanted to double-check whether it's the correct record (in case
# HE changes their website somehow).
response="$(_post "$body" "https://dns.he.net/")"
_debug2 "response" "$response"
if ! _contains "$response" "$_txt_value"; then
_debug "The txt record is not found, just skip"
return 0
fi
_record_id="$(echo "$response" | tr -d "#" | sed "s/<tr/#<tr/g" | tr -d "\n" | tr "#" "\n" | grep "$_full_domain" | grep '"dns_tr"' | grep "$_txt_value" | cut -d '"' -f 4)"
_debug2 _record_id "$_record_id"
if [ -z "$_record_id" ]; then
_err "Can not find record id"
return 1
fi
# Remove the record # Remove the record
body="email=${HE_Username}&pass=${HE_Password}" body="email=${HE_Username}&pass=${HE_Password}"
body="$body&menu=edit_zone" body="$body&menu=edit_zone"
@@ -105,41 +110,26 @@ dns_he_rm() {
########################## PRIVATE FUNCTIONS ########################### ########################## PRIVATE FUNCTIONS ###########################
#-- _find_zone() -------------------------------------------------------
# Returns the most specific zone found in administration interface.
#
# Example:
#
# _find_zone first.second.third.co.uk
#
# ... will return the first zone that exists in admin out of these:
# - "first.second.third.co.uk"
# - "second.third.co.uk"
# - "third.co.uk"
# - "co.uk" <-- unlikely
# - "uk" <-'
#
# (another approach would be something like this:
# https://github.com/hlandau/acme/blob/master/_doc/dns.hook
# - that's better if there are multiple pages. It's so much simpler.
# )
_find_zone() { _find_zone() {
_domain="$1" _domain="$1"
body="email=${HE_Username}&pass=${HE_Password}" body="email=${HE_Username}&pass=${HE_Password}"
_matches=$(_post "$body" "https://dns.he.net/" \ response="$(_post "$body" "https://dns.he.net/")"
| _egrep_o "delete_dom.*name=\"[^\"]+\" value=\"[0-9]+" _debug2 response "$response"
) _table="$(echo "$response" | tr -d "#" | sed "s/<table/#<table/g" | tr -d "\n" | tr "#" "\n" | grep 'id="domains_table"')"
_debug2 _table "$_table"
_matches="$(echo "$_table" | sed "s/<tr/#<tr/g" | tr "#" "\n" | grep 'alt="edit"' | tr -d " " | sed "s/<td/#<td/g" | tr "#" "\n" | sed -n 3p)"
_debug2 _matches "$_matches"
# Zone names and zone IDs are in same order # Zone names and zone IDs are in same order
_zone_ids=$(echo "$_matches" | cut -d '"' -f 5) _zone_ids=$(echo "$_matches" | _egrep_o "hosted_dns_zoneid=[0-9]*&" | cut -d = -f 2 | tr -d '&')
_zone_names=$(echo "$_matches" | cut -d '"' -f 3) _zone_names=$(echo "$_matches" | _egrep_o "name=.*onclick" | cut -d '"' -f 2)
_debug2 "These are the zones on this HE account:" _debug2 "These are the zones on this HE account:"
_debug2 "$_zone_names" _debug2 "$_zone_names"
_debug2 "And these are their respective IDs:" _debug2 "And these are their respective IDs:"
_debug2 "$_zone_ids" _debug2 "$_zone_ids"
if [ -z "$_zone_names" ] || [ -z "$_zone_ids" ]; then
_err "Can not get zone names."
return 1
fi
# Walk through all possible zone names # Walk through all possible zone names
_strip_counter=1 _strip_counter=1
while true; do while true; do
@@ -153,17 +143,10 @@ _find_zone() {
_debug "Looking for zone \"${_attempted_zone}\"" _debug "Looking for zone \"${_attempted_zone}\""
# Take care of "." and only match whole lines. Note that grep -F line_num="$(echo "$_zone_names" | grep -n "$_attempted_zone" | cut -d : -f 1)"
# cannot be used because there's no way to make it match whole
# lines.
regex="^$(echo "$_attempted_zone" | sed 's/\./\\./g')$"
line_num=$(echo "$_zone_names" \
| grep -n "$regex" \
| cut -d : -f 1
)
if [ -n "$line_num" ]; then if [ "$line_num" ]; then
_zone_id=$(echo "$_zone_ids" | sed "${line_num}q;d") _zone_id=$(echo "$_zone_ids" | sed -n "${line_num}p")
_debug "Found relevant zone \"$_attempted_zone\" with id \"$_zone_id\" - will be used for domain \"$_domain\"." _debug "Found relevant zone \"$_attempted_zone\" with id \"$_zone_id\" - will be used for domain \"$_domain\"."
return 0 return 0
fi fi

View File

@@ -17,6 +17,8 @@ dns_lua_add() {
fulldomain=$1 fulldomain=$1
txtvalue=$2 txtvalue=$2
LUA_Key="${LUA_Key:-$(_readaccountconf_mutable LUA_Key)}"
LUA_Email="${LUA_Email:-$(_readaccountconf_mutable LUA_Email)}"
if [ -z "$LUA_Key" ] || [ -z "$LUA_Email" ]; then if [ -z "$LUA_Key" ] || [ -z "$LUA_Email" ]; then
LUA_Key="" LUA_Key=""
LUA_Email="" LUA_Email=""
@@ -26,8 +28,8 @@ dns_lua_add() {
fi fi
#save the api key and email to the account conf file. #save the api key and email to the account conf file.
_saveaccountconf LUA_Key "$LUA_Key" _saveaccountconf_mutable LUA_Key "$LUA_Key"
_saveaccountconf LUA_Email "$LUA_Email" _saveaccountconf_mutable LUA_Email "$LUA_Email"
_debug "First detect the root zone" _debug "First detect the root zone"
if ! _get_root "$fulldomain"; then if ! _get_root "$fulldomain"; then
@@ -38,50 +40,26 @@ dns_lua_add() {
_debug _sub_domain "$_sub_domain" _debug _sub_domain "$_sub_domain"
_debug _domain "$_domain" _debug _domain "$_domain"
_debug "Getting txt records" _info "Adding record"
_LUA_rest GET "zones/${_domain_id}/records" if _LUA_rest POST "zones/$_domain_id/records" "{\"type\":\"TXT\",\"name\":\"$fulldomain.\",\"content\":\"$txtvalue\",\"ttl\":120}"; then
if _contains "$response" "$fulldomain"; then
if ! _contains "$response" "\"id\":"; then _info "Added"
_err "Error"
return 1
fi
count=$(printf "%s\n" "$response" | _egrep_o "\"name\":\"$fulldomain.\",\"type\":\"TXT\"" | wc -l | tr -d " ")
_debug count "$count"
if [ "$count" = "0" ]; then
_info "Adding record"
if _LUA_rest POST "zones/$_domain_id/records" "{\"type\":\"TXT\",\"name\":\"$fulldomain.\",\"content\":\"$txtvalue\",\"ttl\":120}"; then
if _contains "$response" "$fulldomain"; then
_info "Added"
#todo: check if the record takes effect
return 0
else
_err "Add txt record error."
return 1
fi
fi
_err "Add txt record error."
else
_info "Updating record"
record_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[^,]*,\"name\":\"$fulldomain.\",\"type\":\"TXT\"" | _head_n 1 | cut -d: -f2 | cut -d, -f1)
_debug "record_id" "$record_id"
_LUA_rest PUT "zones/$_domain_id/records/$record_id" "{\"id\":$record_id,\"type\":\"TXT\",\"name\":\"$fulldomain.\",\"content\":\"$txtvalue\",\"zone_id\":$_domain_id,\"ttl\":120}"
if [ "$?" = "0" ] && _contains "$response" "updated_at"; then
_info "Updated!"
#todo: check if the record takes effect #todo: check if the record takes effect
return 0 return 0
else
_err "Add txt record error."
return 1
fi fi
_err "Update error"
return 1
fi fi
} }
#fulldomain #fulldomain
dns_lua_rm() { dns_lua_rm() {
fulldomain=$1 fulldomain=$1
txtvalue=$2 txtvalue=$2
LUA_Key="${LUA_Key:-$(_readaccountconf_mutable LUA_Key)}"
LUA_Email="${LUA_Email:-$(_readaccountconf_mutable LUA_Email)}"
_debug "First detect the root zone" _debug "First detect the root zone"
if ! _get_root "$fulldomain"; then if ! _get_root "$fulldomain"; then
_err "invalid domain" _err "invalid domain"

View File

@@ -79,6 +79,9 @@ _ovh_get_api() {
} }
_initAuth() { _initAuth() {
OVH_AK="${OVH_AK:-$(_readaccountconf_mutable OVH_AK)}"
OVH_AS="${OVH_AS:-$(_readaccountconf_mutable OVH_AS)}"
if [ -z "$OVH_AK" ] || [ -z "$OVH_AS" ]; then if [ -z "$OVH_AK" ] || [ -z "$OVH_AS" ]; then
OVH_AK="" OVH_AK=""
OVH_AS="" OVH_AS=""
@@ -87,21 +90,26 @@ _initAuth() {
return 1 return 1
fi fi
#save the api key and email to the account conf file. if [ "$OVH_AK" != "$(_readaccountconf OVH_AK)" ]; then
_saveaccountconf OVH_AK "$OVH_AK" _info "It seems that your ovh key is changed, let's clear consumer key first."
_saveaccountconf OVH_AS "$OVH_AS" _clearaccountconf OVH_CK
fi
_saveaccountconf_mutable OVH_AK "$OVH_AK"
_saveaccountconf_mutable OVH_AS "$OVH_AS"
OVH_END_POINT="${OVH_END_POINT:-$(_readaccountconf_mutable OVH_END_POINT)}"
if [ -z "$OVH_END_POINT" ]; then if [ -z "$OVH_END_POINT" ]; then
OVH_END_POINT="ovh-eu" OVH_END_POINT="ovh-eu"
fi fi
_info "Using OVH endpoint: $OVH_END_POINT" _info "Using OVH endpoint: $OVH_END_POINT"
if [ "$OVH_END_POINT" != "ovh-eu" ]; then if [ "$OVH_END_POINT" != "ovh-eu" ]; then
_saveaccountconf OVH_END_POINT "$OVH_END_POINT" _saveaccountconf_mutable OVH_END_POINT "$OVH_END_POINT"
fi fi
OVH_API="$(_ovh_get_api $OVH_END_POINT)" OVH_API="$(_ovh_get_api $OVH_END_POINT)"
_debug OVH_API "$OVH_API" _debug OVH_API "$OVH_API"
OVH_CK="${OVH_CK:-$(_readaccountconf_mutable OVH_CK)}"
if [ -z "$OVH_CK" ]; then if [ -z "$OVH_CK" ]; then
_info "OVH consumer key is empty, Let's get one:" _info "OVH consumer key is empty, Let's get one:"
if ! _ovh_authentication; then if ! _ovh_authentication; then

85
dnsapi/dns_zonomi.sh Normal file
View File

@@ -0,0 +1,85 @@
#!/usr/bin/env sh
#
#ZM_Key="sdfsdfsdfljlbjkljlkjsdfoiwje"
#
#https://zonomi.com dns api
ZM_Api="https://zonomi.com/app/dns/dyndns.jsp"
######## Public functions #####################
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_zonomi_add() {
fulldomain=$1
txtvalue=$2
ZM_Key="${ZM_Key:-$(_readaccountconf_mutable ZM_Key)}"
if [ -z "$ZM_Key" ]; then
ZM_Key=""
_err "You don't specify zonomi api key yet."
_err "Please create your key and try again."
return 1
fi
#save the api key to the account conf file.
_saveaccountconf_mutable ZM_Key "$ZM_Key"
_info "Get existing txt records for $fulldomain"
if ! _zm_request "action=QUERY&name=$fulldomain"; then
_err "error"
return 1
fi
if _contains "$response" "<record"; then
_debug "get and update records"
_qstr="action[1]=SET&type[1]=TXT&name[1]=$fulldomain&value[1]=$txtvalue"
_qindex=2
for t in $(echo "$response" | tr -d "\r\n" | _egrep_o '<action.*</action>' | tr "<" "\n" | grep record | grep 'type="TXT"' | cut -d '"' -f 6); do
_debug2 t "$t"
_qstr="$_qstr&action[$_qindex]=SET&type[$_qindex]=TXT&name[$_qindex]=$fulldomain&value[$_qindex]=$t"
_qindex="$(_math "$_qindex" + 1)"
done
_zm_request "$_qstr"
else
_debug "Just add record"
_zm_request "action=SET&type=TXT&name=$fulldomain&value=$txtvalue"
fi
}
#fulldomain txtvalue
dns_zonomi_rm() {
fulldomain=$1
txtvalue=$2
ZM_Key="${ZM_Key:-$(_readaccountconf_mutable ZM_Key)}"
if [ -z "$ZM_Key" ]; then
ZM_Key=""
_err "You don't specify zonomi api key yet."
_err "Please create your key and try again."
return 1
fi
_zm_request "action=DELETE&type=TXT&name=$fulldomain"
}
#################### Private functions below ##################################
#qstr
_zm_request() {
qstr="$1"
_debug2 "qstr" "$qstr"
_zm_url="$ZM_Api?api_key=$ZM_Key&$qstr"
_debug2 "_zm_url" "$_zm_url"
response="$(_get "$_zm_url")"
if [ "$?" != "0" ]; then
return 1
fi
_debug2 response "$response"
_contains "$response" "<is_ok>OK:"
}