mirror of
https://github.com/acmesh-official/acme.sh.git
synced 2025-05-10 07:02:56 +00:00
Merge branch 'dev' into dnsapi/dns_dnsever
This commit is contained in:
commit
b0dfd5f94d
11
.travis.yml
11
.travis.yml
@ -13,12 +13,6 @@ env:
|
|||||||
global:
|
global:
|
||||||
- SHFMT_URL=https://github.com/mvdan/sh/releases/download/v0.4.0/shfmt_v0.4.0_linux_amd64
|
- SHFMT_URL=https://github.com/mvdan/sh/releases/download/v0.4.0/shfmt_v0.4.0_linux_amd64
|
||||||
|
|
||||||
addons:
|
|
||||||
apt:
|
|
||||||
sources:
|
|
||||||
- debian-sid # Grab shellcheck from the Debian repo (o_O)
|
|
||||||
packages:
|
|
||||||
- shellcheck
|
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- if [ "$TRAVIS_OS_NAME" = 'osx' ]; then
|
- if [ "$TRAVIS_OS_NAME" = 'osx' ]; then
|
||||||
@ -29,9 +23,7 @@ install:
|
|||||||
script:
|
script:
|
||||||
- echo "NGROK_TOKEN=$(echo "$NGROK_TOKEN" | wc -c)"
|
- echo "NGROK_TOKEN=$(echo "$NGROK_TOKEN" | wc -c)"
|
||||||
- command -V openssl && openssl version
|
- command -V openssl && openssl version
|
||||||
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then curl -sSL $SHFMT_URL -o ~/shfmt ; fi
|
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then curl -sSL $SHFMT_URL -o ~/shfmt && chmod +x ~/shfmt && ~/shfmt -l -w -i 2 . ; fi
|
||||||
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then chmod +x ~/shfmt ; fi
|
|
||||||
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then ~/shfmt -l -w -i 2 . ; fi
|
|
||||||
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then git diff --exit-code && echo "shfmt OK" ; fi
|
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then git diff --exit-code && echo "shfmt OK" ; fi
|
||||||
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then shellcheck -V ; fi
|
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then shellcheck -V ; fi
|
||||||
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then shellcheck -e SC2181 **/*.sh && echo "shellcheck OK" ; fi
|
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then shellcheck -e SC2181 **/*.sh && echo "shellcheck OK" ; fi
|
||||||
@ -40,7 +32,6 @@ script:
|
|||||||
- if [ "$TRAVIS_OS_NAME" = "linux" -a "$NGROK_TOKEN" ]; then sudo TEST_LOCAL="$TEST_LOCAL" NGROK_TOKEN="$NGROK_TOKEN" ./rundocker.sh testplat ubuntu:latest ; fi
|
- if [ "$TRAVIS_OS_NAME" = "linux" -a "$NGROK_TOKEN" ]; then sudo TEST_LOCAL="$TEST_LOCAL" NGROK_TOKEN="$NGROK_TOKEN" ./rundocker.sh testplat ubuntu:latest ; fi
|
||||||
- if [ "$TRAVIS_OS_NAME" = "osx" -a "$NGROK_TOKEN" ]; then sudo TEST_LOCAL="$TEST_LOCAL" NGROK_TOKEN="$NGROK_TOKEN" ACME_OPENSSL_BIN="$ACME_OPENSSL_BIN" ./letest.sh ; fi
|
- if [ "$TRAVIS_OS_NAME" = "osx" -a "$NGROK_TOKEN" ]; then sudo TEST_LOCAL="$TEST_LOCAL" NGROK_TOKEN="$NGROK_TOKEN" ACME_OPENSSL_BIN="$ACME_OPENSSL_BIN" ./letest.sh ; fi
|
||||||
|
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
fast_finish: true
|
fast_finish: true
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ FROM alpine:3.6
|
|||||||
RUN apk update -f \
|
RUN apk update -f \
|
||||||
&& apk --no-cache add -f \
|
&& apk --no-cache add -f \
|
||||||
openssl \
|
openssl \
|
||||||
|
coreutils \
|
||||||
curl \
|
curl \
|
||||||
socat \
|
socat \
|
||||||
&& rm -rf /var/cache/apk/*
|
&& rm -rf /var/cache/apk/*
|
||||||
|
61
README.md
61
README.md
@ -37,6 +37,8 @@ Twitter: [@neilpangxa](https://twitter.com/neilpangxa)
|
|||||||
- [splynx](https://forum.splynx.com/t/free-ssl-cert-for-splynx-lets-encrypt/297)
|
- [splynx](https://forum.splynx.com/t/free-ssl-cert-for-splynx-lets-encrypt/297)
|
||||||
- [archlinux](https://aur.archlinux.org/packages/acme.sh-git/)
|
- [archlinux](https://aur.archlinux.org/packages/acme.sh-git/)
|
||||||
- [opnsense.org](https://github.com/opnsense/plugins/tree/master/security/acme-client/src/opnsense/scripts/OPNsense/AcmeClient)
|
- [opnsense.org](https://github.com/opnsense/plugins/tree/master/security/acme-client/src/opnsense/scripts/OPNsense/AcmeClient)
|
||||||
|
- [CentOS Web Panel](http://centos-webpanel.com/)
|
||||||
|
- [lnmp.org](https://lnmp.org/)
|
||||||
- [more...](https://github.com/Neilpang/acme.sh/wiki/Blogs-and-tutorials)
|
- [more...](https://github.com/Neilpang/acme.sh/wiki/Blogs-and-tutorials)
|
||||||
|
|
||||||
# Tested OS
|
# Tested OS
|
||||||
@ -220,22 +222,7 @@ acme.sh --issue --standalone -d example.com -d www.example.com -d cp.example.com
|
|||||||
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
|
||||||
|
|
||||||
|
|
||||||
# 5. Use Standalone TLS server to issue cert
|
# 5. Use Apache mode
|
||||||
|
|
||||||
**(requires you to be root/sudoer or have permission to listen on port 443 (TCP))**
|
|
||||||
|
|
||||||
acme.sh supports `tls-sni-01` validation.
|
|
||||||
|
|
||||||
Port `443` (TCP) **MUST** be free to listen on, otherwise you will be prompted to free it and try again.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
acme.sh --issue --tls -d example.com -d www.example.com -d cp.example.com
|
|
||||||
```
|
|
||||||
|
|
||||||
More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert
|
|
||||||
|
|
||||||
|
|
||||||
# 6. Use Apache mode
|
|
||||||
|
|
||||||
**(requires you to be root/sudoer, since it is required to interact with Apache server)**
|
**(requires you to be root/sudoer, since it is required to interact with Apache server)**
|
||||||
|
|
||||||
@ -255,7 +242,7 @@ 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
|
# 6. Use Nginx mode
|
||||||
|
|
||||||
**(requires you to be root/sudoer, since it is required to interact with Nginx server)**
|
**(requires you to be root/sudoer, since it is required to interact with Nginx server)**
|
||||||
|
|
||||||
@ -279,7 +266,7 @@ 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
|
# 7. Automatic DNS API integration
|
||||||
|
|
||||||
If your DNS provider supports API access, we can use that API to automatically issue the certs.
|
If your DNS provider supports API access, we can use that API to automatically issue the certs.
|
||||||
|
|
||||||
@ -327,14 +314,14 @@ You don't have to do anything manually!
|
|||||||
1. selectel.com(selectel.ru) DNS API
|
1. selectel.com(selectel.ru) DNS API
|
||||||
1. zonomi.com DNS API
|
1. zonomi.com DNS API
|
||||||
1. DreamHost.com API
|
1. DreamHost.com API
|
||||||
|
1. DirectAdmin API
|
||||||
|
1. KingHost (https://www.kinghost.com.br/)
|
||||||
|
1. Zilore (https://zilore.com)
|
||||||
|
1. Loopia.se API
|
||||||
|
1. acme-dns (https://github.com/joohoi/acme-dns)
|
||||||
|
1. TELE3 (https://www.tele3.cz)
|
||||||
1. DNSEver(https://www.dnsever.com)
|
1. DNSEver(https://www.dnsever.com)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
And:
|
And:
|
||||||
|
|
||||||
**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
|
||||||
@ -347,7 +334,9 @@ If your DNS provider is not on the supported list above, you can write your own
|
|||||||
|
|
||||||
For more details: [How to use DNS API](dnsapi)
|
For more details: [How to use DNS API](dnsapi)
|
||||||
|
|
||||||
# 9. Use DNS manual mode:
|
# 8. Use DNS manual mode:
|
||||||
|
|
||||||
|
See: https://github.com/Neilpang/acme.sh/wiki/dns-manual-mode first.
|
||||||
|
|
||||||
If your dns provider doesn't support any api access, you can 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.
|
||||||
|
|
||||||
@ -381,7 +370,7 @@ Ok, it's done.
|
|||||||
|
|
||||||
**Please use dns api mode instead.**
|
**Please use dns api mode instead.**
|
||||||
|
|
||||||
# 10. Issue ECC certificates
|
# 9. Issue ECC certificates
|
||||||
|
|
||||||
`Let's Encrypt` can now issue **ECDSA** certificates.
|
`Let's Encrypt` can now issue **ECDSA** certificates.
|
||||||
|
|
||||||
@ -413,17 +402,17 @@ Valid values are:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
# 11. Issue Wildcard certificates
|
# 10. Issue Wildcard certificates
|
||||||
|
|
||||||
It's simple, just give a wildcard domain as the `-d` parameter.
|
It's simple, just give a wildcard domain as the `-d` parameter.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
acme.sh --issue -d example.com -d *.example.com --dns dns_cf
|
acme.sh --issue -d example.com -d '*.example.com' --dns dns_cf
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# 12. How to renew the certs
|
# 11. How to renew the certs
|
||||||
|
|
||||||
No, you don't need to renew the certs manually. All the certs will be renewed automatically every **60** days.
|
No, you don't need to renew the certs manually. All the certs will be renewed automatically every **60** days.
|
||||||
|
|
||||||
@ -440,7 +429,7 @@ acme.sh --renew -d example.com --force --ecc
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
# 13. How to stop cert renewal
|
# 12. How to stop cert renewal
|
||||||
|
|
||||||
To stop renewal of a cert, you can execute the following to remove the cert from the renewal list:
|
To stop renewal of a cert, you can execute the following to remove the cert from the renewal list:
|
||||||
|
|
||||||
@ -453,7 +442,7 @@ The cert/key file is not removed from the disk.
|
|||||||
You can remove the respective directory (e.g. `~/.acme.sh/example.com`) by yourself.
|
You can remove the respective directory (e.g. `~/.acme.sh/example.com`) by yourself.
|
||||||
|
|
||||||
|
|
||||||
# 14. How to upgrade `acme.sh`
|
# 13. How to upgrade `acme.sh`
|
||||||
|
|
||||||
acme.sh is in constant development, so it's strongly recommended to use the latest code.
|
acme.sh is in constant development, so it's strongly recommended to use the latest code.
|
||||||
|
|
||||||
@ -478,25 +467,25 @@ acme.sh --upgrade --auto-upgrade 0
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
# 15. Issue a cert from an existing CSR
|
# 14. Issue a cert from an existing CSR
|
||||||
|
|
||||||
https://github.com/Neilpang/acme.sh/wiki/Issue-a-cert-from-existing-CSR
|
https://github.com/Neilpang/acme.sh/wiki/Issue-a-cert-from-existing-CSR
|
||||||
|
|
||||||
|
|
||||||
# 16. Under the Hood
|
# 15. Under the Hood
|
||||||
|
|
||||||
Speak ACME language using shell, directly to "Let's Encrypt".
|
Speak ACME language using shell, directly to "Let's Encrypt".
|
||||||
|
|
||||||
TODO:
|
TODO:
|
||||||
|
|
||||||
|
|
||||||
# 17. Acknowledgments
|
# 16. Acknowledgments
|
||||||
|
|
||||||
1. Acme-tiny: https://github.com/diafygi/acme-tiny
|
1. Acme-tiny: https://github.com/diafygi/acme-tiny
|
||||||
2. ACME protocol: https://github.com/ietf-wg-acme/acme
|
2. ACME protocol: https://github.com/ietf-wg-acme/acme
|
||||||
|
|
||||||
|
|
||||||
# 18. License & Others
|
# 17. License & Others
|
||||||
|
|
||||||
License is GPLv3
|
License is GPLv3
|
||||||
|
|
||||||
@ -505,7 +494,7 @@ Please Star and Fork me.
|
|||||||
[Issues](https://github.com/Neilpang/acme.sh/issues) and [pull requests](https://github.com/Neilpang/acme.sh/pulls) are welcome.
|
[Issues](https://github.com/Neilpang/acme.sh/issues) and [pull requests](https://github.com/Neilpang/acme.sh/pulls) are welcome.
|
||||||
|
|
||||||
|
|
||||||
# 19. Donate
|
# 18. Donate
|
||||||
Your donation makes **acme.sh** better:
|
Your donation makes **acme.sh** better:
|
||||||
|
|
||||||
1. PayPal/Alipay(支付宝)/Wechat(微信): [https://donate.acme.sh/](https://donate.acme.sh/)
|
1. PayPal/Alipay(支付宝)/Wechat(微信): [https://donate.acme.sh/](https://donate.acme.sh/)
|
||||||
|
246
acme.sh
246
acme.sh
@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env sh
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
VER=2.7.7
|
VER=2.7.9
|
||||||
|
|
||||||
PROJECT_NAME="acme.sh"
|
PROJECT_NAME="acme.sh"
|
||||||
|
|
||||||
@ -47,6 +47,7 @@ DEFAULT_DNS_SLEEP=120
|
|||||||
NO_VALUE="no"
|
NO_VALUE="no"
|
||||||
|
|
||||||
W_TLS="tls"
|
W_TLS="tls"
|
||||||
|
W_DNS="dns"
|
||||||
DNS_ALIAS_PREFIX="="
|
DNS_ALIAS_PREFIX="="
|
||||||
|
|
||||||
MODE_STATELESS="stateless"
|
MODE_STATELESS="stateless"
|
||||||
@ -63,6 +64,7 @@ END_CSR="-----END CERTIFICATE REQUEST-----"
|
|||||||
BEGIN_CERT="-----BEGIN CERTIFICATE-----"
|
BEGIN_CERT="-----BEGIN CERTIFICATE-----"
|
||||||
END_CERT="-----END CERTIFICATE-----"
|
END_CERT="-----END CERTIFICATE-----"
|
||||||
|
|
||||||
|
CONTENT_TYPE_JSON="application/jose+json"
|
||||||
RENEW_SKIP=2
|
RENEW_SKIP=2
|
||||||
|
|
||||||
ECC_SEP="_"
|
ECC_SEP="_"
|
||||||
@ -108,31 +110,35 @@ _STATELESS_WIKI="https://github.com/Neilpang/acme.sh/wiki/Stateless-Mode"
|
|||||||
|
|
||||||
_DNS_ALIAS_WIKI="https://github.com/Neilpang/acme.sh/wiki/DNS-alias-mode"
|
_DNS_ALIAS_WIKI="https://github.com/Neilpang/acme.sh/wiki/DNS-alias-mode"
|
||||||
|
|
||||||
|
_DNS_MANUAL_WIKI="https://github.com/Neilpang/acme.sh/wiki/dns-manual-mode"
|
||||||
|
|
||||||
_DNS_MANUAL_ERR="The dns manual mode can not renew automatically, you must issue it again manually. You'd better use the other modes instead."
|
_DNS_MANUAL_ERR="The dns manual mode can not renew automatically, you must issue it again manually. You'd better use the other modes instead."
|
||||||
|
|
||||||
_DNS_MANUAL_WARN="It seems that you are using dns manual mode. please take care: $_DNS_MANUAL_ERR"
|
_DNS_MANUAL_WARN="It seems that you are using dns manual mode. please take care: $_DNS_MANUAL_ERR"
|
||||||
|
|
||||||
|
_DNS_MANUAL_ERROR="It seems that you are using dns manual mode. Read this link first: $_DNS_MANUAL_WIKI"
|
||||||
|
|
||||||
__INTERACTIVE=""
|
__INTERACTIVE=""
|
||||||
if [ -t 1 ]; then
|
if [ -t 1 ]; then
|
||||||
__INTERACTIVE="1"
|
__INTERACTIVE="1"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
__green() {
|
__green() {
|
||||||
if [ "$__INTERACTIVE${ACME_NO_COLOR}" = "1" ]; then
|
if [ "$__INTERACTIVE${ACME_NO_COLOR}" = "1" -o "${ACME_FORCE_COLOR}" = "1" ]; then
|
||||||
printf '\033[1;31;32m'
|
printf '\033[1;31;32m'
|
||||||
fi
|
fi
|
||||||
printf -- "%b" "$1"
|
printf -- "%b" "$1"
|
||||||
if [ "$__INTERACTIVE${ACME_NO_COLOR}" = "1" ]; then
|
if [ "$__INTERACTIVE${ACME_NO_COLOR}" = "1" -o "${ACME_FORCE_COLOR}" = "1" ]; then
|
||||||
printf '\033[0m'
|
printf '\033[0m'
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
__red() {
|
__red() {
|
||||||
if [ "$__INTERACTIVE${ACME_NO_COLOR}" = "1" ]; then
|
if [ "$__INTERACTIVE${ACME_NO_COLOR}" = "1" -o "${ACME_FORCE_COLOR}" = "1" ]; then
|
||||||
printf '\033[1;31;40m'
|
printf '\033[1;31;40m'
|
||||||
fi
|
fi
|
||||||
printf -- "%b" "$1"
|
printf -- "%b" "$1"
|
||||||
if [ "$__INTERACTIVE${ACME_NO_COLOR}" = "1" ]; then
|
if [ "$__INTERACTIVE${ACME_NO_COLOR}" = "1" -o "${ACME_FORCE_COLOR}" = "1" ]; then
|
||||||
printf '\033[0m'
|
printf '\033[0m'
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
@ -848,6 +854,16 @@ _dbase64() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#file
|
||||||
|
_checkcert() {
|
||||||
|
_cf="$1"
|
||||||
|
if [ "$DEBUG" ]; then
|
||||||
|
openssl x509 -noout -text -in "$_cf"
|
||||||
|
else
|
||||||
|
openssl x509 -noout -text -in "$_cf" >/dev/null 2>&1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
#Usage: hashalg [outputhex]
|
#Usage: hashalg [outputhex]
|
||||||
#Output Base64-encoded digest
|
#Output Base64-encoded digest
|
||||||
_digest() {
|
_digest() {
|
||||||
@ -1591,12 +1607,13 @@ _inithttp() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# body url [needbase64] [POST|PUT]
|
# body url [needbase64] [POST|PUT] [ContentType]
|
||||||
_post() {
|
_post() {
|
||||||
body="$1"
|
body="$1"
|
||||||
_post_url="$2"
|
_post_url="$2"
|
||||||
needbase64="$3"
|
needbase64="$3"
|
||||||
httpmethod="$4"
|
httpmethod="$4"
|
||||||
|
_postContentType="$5"
|
||||||
|
|
||||||
if [ -z "$httpmethod" ]; then
|
if [ -z "$httpmethod" ]; then
|
||||||
httpmethod="POST"
|
httpmethod="POST"
|
||||||
@ -1604,6 +1621,7 @@ _post() {
|
|||||||
_debug $httpmethod
|
_debug $httpmethod
|
||||||
_debug "_post_url" "$_post_url"
|
_debug "_post_url" "$_post_url"
|
||||||
_debug2 "body" "$body"
|
_debug2 "body" "$body"
|
||||||
|
_debug2 "_postContentType" "$_postContentType"
|
||||||
|
|
||||||
_inithttp
|
_inithttp
|
||||||
|
|
||||||
@ -1614,9 +1632,17 @@ _post() {
|
|||||||
fi
|
fi
|
||||||
_debug "_CURL" "$_CURL"
|
_debug "_CURL" "$_CURL"
|
||||||
if [ "$needbase64" ]; then
|
if [ "$needbase64" ]; then
|
||||||
response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url" | _base64)"
|
if [ "$_postContentType" ]; then
|
||||||
|
response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "Content-Type: $_postContentType" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url" | _base64)"
|
||||||
|
else
|
||||||
|
response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url" | _base64)"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url")"
|
if [ "$_postContentType" ]; then
|
||||||
|
response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "Content-Type: $_postContentType" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url")"
|
||||||
|
else
|
||||||
|
response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url")"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
_ret="$?"
|
_ret="$?"
|
||||||
if [ "$_ret" != "0" ]; then
|
if [ "$_ret" != "0" ]; then
|
||||||
@ -1634,15 +1660,31 @@ _post() {
|
|||||||
_debug "_WGET" "$_WGET"
|
_debug "_WGET" "$_WGET"
|
||||||
if [ "$needbase64" ]; then
|
if [ "$needbase64" ]; then
|
||||||
if [ "$httpmethod" = "POST" ]; then
|
if [ "$httpmethod" = "POST" ]; then
|
||||||
response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --post-data="$body" "$_post_url" 2>"$HTTP_HEADER" | _base64)"
|
if [ "$_postContentType" ]; then
|
||||||
|
response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --header "Content-Type: $_postContentType" --post-data="$body" "$_post_url" 2>"$HTTP_HEADER" | _base64)"
|
||||||
|
else
|
||||||
|
response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --post-data="$body" "$_post_url" 2>"$HTTP_HEADER" | _base64)"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --method $httpmethod --body-data="$body" "$_post_url" 2>"$HTTP_HEADER" | _base64)"
|
if [ "$_postContentType" ]; then
|
||||||
|
response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --header "Content-Type: $_postContentType" --method $httpmethod --body-data="$body" "$_post_url" 2>"$HTTP_HEADER" | _base64)"
|
||||||
|
else
|
||||||
|
response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --method $httpmethod --body-data="$body" "$_post_url" 2>"$HTTP_HEADER" | _base64)"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
if [ "$httpmethod" = "POST" ]; then
|
if [ "$httpmethod" = "POST" ]; then
|
||||||
response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --post-data="$body" "$_post_url" 2>"$HTTP_HEADER")"
|
if [ "$_postContentType" ]; then
|
||||||
|
response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --header "Content-Type: $_postContentType" --post-data="$body" "$_post_url" 2>"$HTTP_HEADER")"
|
||||||
|
else
|
||||||
|
response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --post-data="$body" "$_post_url" 2>"$HTTP_HEADER")"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --method $httpmethod --body-data="$body" "$_post_url" 2>"$HTTP_HEADER")"
|
if [ "$_postContentType" ]; then
|
||||||
|
response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --header "Content-Type: $_postContentType" --method $httpmethod --body-data="$body" "$_post_url" 2>"$HTTP_HEADER")"
|
||||||
|
else
|
||||||
|
response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --method $httpmethod --body-data="$body" "$_post_url" 2>"$HTTP_HEADER")"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
_ret="$?"
|
_ret="$?"
|
||||||
@ -1753,19 +1795,25 @@ _send_signed_request() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ "$ACME_VERSION" = "2" ]; then
|
||||||
|
__request_conent_type="$CONTENT_TYPE_JSON"
|
||||||
|
else
|
||||||
|
__request_conent_type=""
|
||||||
|
fi
|
||||||
payload64=$(printf "%s" "$payload" | _base64 | _url_replace)
|
payload64=$(printf "%s" "$payload" | _base64 | _url_replace)
|
||||||
_debug3 payload64 "$payload64"
|
_debug3 payload64 "$payload64"
|
||||||
|
|
||||||
MAX_REQUEST_RETRY_TIMES=5
|
MAX_REQUEST_RETRY_TIMES=5
|
||||||
_request_retry_times=0
|
_request_retry_times=0
|
||||||
while [ "${_request_retry_times}" -lt "$MAX_REQUEST_RETRY_TIMES" ]; do
|
while [ "${_request_retry_times}" -lt "$MAX_REQUEST_RETRY_TIMES" ]; do
|
||||||
|
_request_retry_times=$(_math "$_request_retry_times" + 1)
|
||||||
_debug3 _request_retry_times "$_request_retry_times"
|
_debug3 _request_retry_times "$_request_retry_times"
|
||||||
if [ -z "$_CACHED_NONCE" ]; then
|
if [ -z "$_CACHED_NONCE" ]; then
|
||||||
_headers=""
|
_headers=""
|
||||||
if [ "$ACME_NEW_NONCE" ]; then
|
if [ "$ACME_NEW_NONCE" ]; then
|
||||||
_debug2 "Get nonce. ACME_NEW_NONCE" "$ACME_NEW_NONCE"
|
_debug2 "Get nonce. ACME_NEW_NONCE" "$ACME_NEW_NONCE"
|
||||||
nonceurl="$ACME_NEW_NONCE"
|
nonceurl="$ACME_NEW_NONCE"
|
||||||
if _post "" "$nonceurl" "" "HEAD"; then
|
if _post "" "$nonceurl" "" "HEAD" "$__request_conent_type"; then
|
||||||
_headers="$(cat "$HTTP_HEADER")"
|
_headers="$(cat "$HTTP_HEADER")"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
@ -1789,7 +1837,11 @@ _send_signed_request() {
|
|||||||
fi
|
fi
|
||||||
nonce="$_CACHED_NONCE"
|
nonce="$_CACHED_NONCE"
|
||||||
_debug2 nonce "$nonce"
|
_debug2 nonce "$nonce"
|
||||||
|
if [ -z "$nonce" ]; then
|
||||||
|
_info "Could not get nonce, let's try again."
|
||||||
|
_sleep 2
|
||||||
|
continue
|
||||||
|
fi
|
||||||
if [ "$ACME_VERSION" = "2" ]; then
|
if [ "$ACME_VERSION" = "2" ]; then
|
||||||
if [ "$url" = "$ACME_NEW_ACCOUNT" ] || [ "$url" = "$ACME_REVOKE_CERT" ]; then
|
if [ "$url" = "$ACME_NEW_ACCOUNT" ] || [ "$url" = "$ACME_REVOKE_CERT" ]; then
|
||||||
protected="$JWK_HEADERPLACE_PART1$nonce\", \"url\": \"${url}$JWK_HEADERPLACE_PART2, \"jwk\": $jwk"'}'
|
protected="$JWK_HEADERPLACE_PART1$nonce\", \"url\": \"${url}$JWK_HEADERPLACE_PART2, \"jwk\": $jwk"'}'
|
||||||
@ -1820,7 +1872,7 @@ _send_signed_request() {
|
|||||||
fi
|
fi
|
||||||
_debug3 body "$body"
|
_debug3 body "$body"
|
||||||
|
|
||||||
response="$(_post "$body" "$url" "$needbase64")"
|
response="$(_post "$body" "$url" "$needbase64" "POST" "$__request_conent_type")"
|
||||||
_CACHED_NONCE=""
|
_CACHED_NONCE=""
|
||||||
|
|
||||||
if [ "$?" != "0" ]; then
|
if [ "$?" != "0" ]; then
|
||||||
@ -1841,13 +1893,12 @@ _send_signed_request() {
|
|||||||
|
|
||||||
_body="$response"
|
_body="$response"
|
||||||
if [ "$needbase64" ]; then
|
if [ "$needbase64" ]; then
|
||||||
_body="$(echo "$_body" | _dbase64)"
|
_body="$(echo "$_body" | _dbase64 | tr -d '\0')"
|
||||||
_debug3 _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
|
||||||
_info "It seems the CA server is busy now, let's wait and retry."
|
_info "It seems the CA server is busy now, let's wait and retry."
|
||||||
_request_retry_times=$(_math "$_request_retry_times" + 1)
|
|
||||||
_sleep 5
|
_sleep 5
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
@ -2310,7 +2361,7 @@ _initpath() {
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
_debug2 ACME_DIRECTORY "$ACME_DIRECTORY"
|
_debug ACME_DIRECTORY "$ACME_DIRECTORY"
|
||||||
_ACME_SERVER_HOST="$(echo "$ACME_DIRECTORY" | cut -d : -f 2 | tr -s / | cut -d / -f 2)"
|
_ACME_SERVER_HOST="$(echo "$ACME_DIRECTORY" | cut -d : -f 2 | tr -s / | cut -d / -f 2)"
|
||||||
_debug2 "_ACME_SERVER_HOST" "$_ACME_SERVER_HOST"
|
_debug2 "_ACME_SERVER_HOST" "$_ACME_SERVER_HOST"
|
||||||
|
|
||||||
@ -2967,6 +3018,8 @@ _on_before_issue() {
|
|||||||
_chk_pre_hook="$4"
|
_chk_pre_hook="$4"
|
||||||
_chk_local_addr="$5"
|
_chk_local_addr="$5"
|
||||||
_debug _on_before_issue
|
_debug _on_before_issue
|
||||||
|
_debug _chk_main_domain "$_chk_main_domain"
|
||||||
|
_debug _chk_alt_domains "$_chk_alt_domains"
|
||||||
#run pre hook
|
#run pre hook
|
||||||
if [ "$_chk_pre_hook" ]; then
|
if [ "$_chk_pre_hook" ]; then
|
||||||
_info "Run pre hook:'$_chk_pre_hook'"
|
_info "Run pre hook:'$_chk_pre_hook'"
|
||||||
@ -2987,11 +3040,17 @@ _on_before_issue() {
|
|||||||
|
|
||||||
_debug Le_LocalAddress "$_chk_local_addr"
|
_debug Le_LocalAddress "$_chk_local_addr"
|
||||||
|
|
||||||
alldomains=$(echo "$_chk_main_domain,$_chk_alt_domains" | tr ',' ' ')
|
|
||||||
_index=1
|
_index=1
|
||||||
_currentRoot=""
|
_currentRoot=""
|
||||||
_addrIndex=1
|
_addrIndex=1
|
||||||
for d in $alldomains; do
|
_w_index=1
|
||||||
|
while true; do
|
||||||
|
d="$(echo "$_chk_main_domain,$_chk_alt_domains," | cut -d , -f "$_w_index")"
|
||||||
|
_w_index="$(_math "$_w_index" + 1)"
|
||||||
|
_debug d "$d"
|
||||||
|
if [ -z "$d" ]; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
_debug "Check for domain" "$d"
|
_debug "Check for domain" "$d"
|
||||||
_currentRoot="$(_getfield "$_chk_web_roots" $_index)"
|
_currentRoot="$(_getfield "$_chk_web_roots" $_index)"
|
||||||
_debug "_currentRoot" "$_currentRoot"
|
_debug "_currentRoot" "$_currentRoot"
|
||||||
@ -3087,7 +3146,7 @@ _on_issue_err() {
|
|||||||
)
|
)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$IS_RENEW" = "1" ] && _hasfield "$Le_Webroot" "dns"; then
|
if [ "$IS_RENEW" = "1" ] && _hasfield "$Le_Webroot" "$W_DNS"; then
|
||||||
_err "$_DNS_MANUAL_ERR"
|
_err "$_DNS_MANUAL_ERR"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -3123,7 +3182,7 @@ _on_issue_success() {
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if _hasfield "$Le_Webroot" "dns"; then
|
if _hasfield "$Le_Webroot" "$W_DNS"; then
|
||||||
_err "$_DNS_MANUAL_WARN"
|
_err "$_DNS_MANUAL_WARN"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -3207,10 +3266,16 @@ _regAccount() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
_debug2 responseHeaders "$responseHeaders"
|
||||||
_accUri="$(echo "$responseHeaders" | grep "^Location:" | _head_n 1 | cut -d ' ' -f 2 | tr -d "\r\n")"
|
_accUri="$(echo "$responseHeaders" | grep "^Location:" | _head_n 1 | cut -d ' ' -f 2 | tr -d "\r\n")"
|
||||||
_debug "_accUri" "$_accUri"
|
_debug "_accUri" "$_accUri"
|
||||||
|
if [ -z "$_accUri" ]; then
|
||||||
|
_err "Can not find account id url."
|
||||||
|
_err "$responseHeaders"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
_savecaconf "ACCOUNT_URL" "$_accUri"
|
_savecaconf "ACCOUNT_URL" "$_accUri"
|
||||||
export ACCOUNT_URL="$ACCOUNT_URL"
|
export ACCOUNT_URL="$_accUri"
|
||||||
|
|
||||||
CA_KEY_HASH="$(__calcAccountKeyHash)"
|
CA_KEY_HASH="$(__calcAccountKeyHash)"
|
||||||
_debug "Calc CA_KEY_HASH" "$CA_KEY_HASH"
|
_debug "Calc CA_KEY_HASH" "$CA_KEY_HASH"
|
||||||
@ -3390,6 +3455,9 @@ issue() {
|
|||||||
_main_domain=$(echo "$2,$3" | cut -d , -f 1)
|
_main_domain=$(echo "$2,$3" | cut -d , -f 1)
|
||||||
_alt_domains=$(echo "$2,$3" | cut -d , -f 2- | sed "s/,${NO_VALUE}$//")
|
_alt_domains=$(echo "$2,$3" | cut -d , -f 2- | sed "s/,${NO_VALUE}$//")
|
||||||
fi
|
fi
|
||||||
|
_debug _main_domain "$_main_domain"
|
||||||
|
_debug _alt_domains "$_alt_domains"
|
||||||
|
|
||||||
_key_length="$4"
|
_key_length="$4"
|
||||||
_real_cert="$5"
|
_real_cert="$5"
|
||||||
_real_key="$6"
|
_real_key="$6"
|
||||||
@ -3417,6 +3485,11 @@ issue() {
|
|||||||
mkdir -p "$DOMAIN_PATH"
|
mkdir -p "$DOMAIN_PATH"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if _hasfield "$_web_roots" "$W_DNS" && [ -z "$FORCE_DNS_MANUAL" ]; then
|
||||||
|
_err "$_DNS_MANUAL_ERROR"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
_debug "Using ACME_DIRECTORY: $ACME_DIRECTORY"
|
_debug "Using ACME_DIRECTORY: $ACME_DIRECTORY"
|
||||||
|
|
||||||
_initAPI
|
_initAPI
|
||||||
@ -3478,7 +3551,7 @@ issue() {
|
|||||||
_saved_account_key_hash="$(_readcaconf "CA_KEY_HASH")"
|
_saved_account_key_hash="$(_readcaconf "CA_KEY_HASH")"
|
||||||
_debug2 _saved_account_key_hash "$_saved_account_key_hash"
|
_debug2 _saved_account_key_hash "$_saved_account_key_hash"
|
||||||
|
|
||||||
if [ -z "$_saved_account_key_hash" ] || [ "$_saved_account_key_hash" != "$(__calcAccountKeyHash)" ]; then
|
if [ -z "$ACCOUNT_URL" ] || [ -z "$_saved_account_key_hash" ] || [ "$_saved_account_key_hash" != "$(__calcAccountKeyHash)" ]; then
|
||||||
if ! _regAccount "$_accountkeylength"; then
|
if ! _regAccount "$_accountkeylength"; then
|
||||||
_on_issue_err "$_post_hook"
|
_on_issue_err "$_post_hook"
|
||||||
return 1
|
return 1
|
||||||
@ -3520,10 +3593,15 @@ issue() {
|
|||||||
if [ "$ACME_VERSION" = "2" ]; then
|
if [ "$ACME_VERSION" = "2" ]; then
|
||||||
#make new order request
|
#make new order request
|
||||||
_identifiers="{\"type\":\"dns\",\"value\":\"$_main_domain\"}"
|
_identifiers="{\"type\":\"dns\",\"value\":\"$_main_domain\"}"
|
||||||
for d in $(echo "$_alt_domains" | tr ',' ' '); do
|
_w_index=1
|
||||||
if [ "$d" ]; then
|
while true; do
|
||||||
_identifiers="$_identifiers,{\"type\":\"dns\",\"value\":\"$d\"}"
|
d="$(echo "$_alt_domains," | cut -d , -f "$_w_index")"
|
||||||
|
_w_index="$(_math "$_w_index" + 1)"
|
||||||
|
_debug d "$d"
|
||||||
|
if [ -z "$d" ]; then
|
||||||
|
break
|
||||||
fi
|
fi
|
||||||
|
_identifiers="$_identifiers,{\"type\":\"dns\",\"value\":\"$d\"}"
|
||||||
done
|
done
|
||||||
_debug2 _identifiers "$_identifiers"
|
_debug2 _identifiers "$_identifiers"
|
||||||
if ! _send_signed_request "$ACME_NEW_ORDER" "{\"identifiers\": [$_identifiers]}"; then
|
if ! _send_signed_request "$ACME_NEW_ORDER" "{\"identifiers\": [$_identifiers]}"; then
|
||||||
@ -3560,6 +3638,8 @@ issue() {
|
|||||||
_debug2 "_authz_url" "$_authz_url"
|
_debug2 "_authz_url" "$_authz_url"
|
||||||
if ! response="$(_get "$_authz_url")"; then
|
if ! response="$(_get "$_authz_url")"; then
|
||||||
_err "get to authz error."
|
_err "get to authz error."
|
||||||
|
_err "_authorizations_seg" "$_authorizations_seg"
|
||||||
|
_err "_authz_url" "$_authz_url"
|
||||||
_clearup
|
_clearup
|
||||||
_on_issue_err "$_post_hook"
|
_on_issue_err "$_post_hook"
|
||||||
return 1
|
return 1
|
||||||
@ -3578,10 +3658,16 @@ $_authorizations_map"
|
|||||||
_debug2 _authorizations_map "$_authorizations_map"
|
_debug2 _authorizations_map "$_authorizations_map"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
alldomains=$(echo "$_main_domain,$_alt_domains" | tr ',' ' ')
|
|
||||||
_index=0
|
_index=0
|
||||||
_currentRoot=""
|
_currentRoot=""
|
||||||
for d in $alldomains; do
|
_w_index=1
|
||||||
|
while true; do
|
||||||
|
d="$(echo "$_main_domain,$_alt_domains," | cut -d , -f "$_w_index")"
|
||||||
|
_w_index="$(_math "$_w_index" + 1)"
|
||||||
|
_debug d "$d"
|
||||||
|
if [ -z "$d" ]; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
_info "Getting webroot for domain" "$d"
|
_info "Getting webroot for domain" "$d"
|
||||||
_index=$(_math $_index + 1)
|
_index=$(_math $_index + 1)
|
||||||
_w="$(echo $_web_roots | cut -d , -f $_index)"
|
_w="$(echo $_web_roots | cut -d , -f $_index)"
|
||||||
@ -3593,7 +3679,7 @@ $_authorizations_map"
|
|||||||
|
|
||||||
vtype="$VTYPE_HTTP"
|
vtype="$VTYPE_HTTP"
|
||||||
#todo, v2 wildcard force to use dns
|
#todo, v2 wildcard force to use dns
|
||||||
if _startswith "$_currentRoot" "dns"; then
|
if _startswith "$_currentRoot" "$W_DNS"; then
|
||||||
vtype="$VTYPE_DNS"
|
vtype="$VTYPE_DNS"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -3610,6 +3696,7 @@ $_authorizations_map"
|
|||||||
_debug2 "response" "$response"
|
_debug2 "response" "$response"
|
||||||
if [ -z "$response" ]; then
|
if [ -z "$response" ]; then
|
||||||
_err "get to authz error."
|
_err "get to authz error."
|
||||||
|
_err "_authorizations_map" "$_authorizations_map"
|
||||||
_clearup
|
_clearup
|
||||||
_on_issue_err "$_post_hook"
|
_on_issue_err "$_post_hook"
|
||||||
return 1
|
return 1
|
||||||
@ -3720,6 +3807,10 @@ $_authorizations_map"
|
|||||||
if [ "$d_api" ]; then
|
if [ "$d_api" ]; then
|
||||||
_info "Found domain api file: $d_api"
|
_info "Found domain api file: $d_api"
|
||||||
else
|
else
|
||||||
|
if [ "$_currentRoot" != "$W_DNS" ]; then
|
||||||
|
_err "Can not find dns api hook for: $_currentRoot"
|
||||||
|
_info "You need to add the txt record manually."
|
||||||
|
fi
|
||||||
_info "$(__red "Add the following TXT record:")"
|
_info "$(__red "Add the following TXT record:")"
|
||||||
_info "$(__red "Domain: '$(__green "$txtdomain")'")"
|
_info "$(__red "Domain: '$(__green "$txtdomain")'")"
|
||||||
_info "$(__red "TXT value: '$(__green "$txt")'")"
|
_info "$(__red "TXT value: '$(__green "$txt")'")"
|
||||||
@ -3758,7 +3849,7 @@ $_authorizations_map"
|
|||||||
if [ "$dnsadded" = '0' ]; then
|
if [ "$dnsadded" = '0' ]; then
|
||||||
_savedomainconf "Le_Vlist" "$vlist"
|
_savedomainconf "Le_Vlist" "$vlist"
|
||||||
_debug "Dns record not added yet, so, save to $DOMAIN_CONF and exit."
|
_debug "Dns record not added yet, so, save to $DOMAIN_CONF and exit."
|
||||||
_err "Please add the TXT records to the domains, and retry again."
|
_err "Please add the TXT records to the domains, and re-run with --renew."
|
||||||
_clearup
|
_clearup
|
||||||
_on_issue_err "$_post_hook"
|
_on_issue_err "$_post_hook"
|
||||||
return 1
|
return 1
|
||||||
@ -4022,13 +4113,15 @@ $_authorizations_map"
|
|||||||
fi
|
fi
|
||||||
if [ "$code" != "200" ]; then
|
if [ "$code" != "200" ]; then
|
||||||
_err "Sign failed, code is not 200."
|
_err "Sign failed, code is not 200."
|
||||||
|
_err "$response"
|
||||||
_on_issue_err "$_post_hook"
|
_on_issue_err "$_post_hook"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
Le_LinkCert="$(echo "$response" | tr -d '\r\n' | _egrep_o '"certificate" *: *"[^"]*"' | cut -d '"' -f 4)"
|
Le_LinkCert="$(echo "$response" | tr -d '\r\n' | _egrep_o '"certificate" *: *"[^"]*"' | cut -d '"' -f 4)"
|
||||||
|
|
||||||
if ! _get "$Le_LinkCert" >"$CERT_PATH"; then
|
if ! _get "$Le_LinkCert" >"$CERT_PATH"; then
|
||||||
_err "Sign failed, code is not 200."
|
_err "Sign failed, can not download cert:$Le_LinkCert."
|
||||||
|
_err "$response"
|
||||||
_on_issue_err "$_post_hook"
|
_on_issue_err "$_post_hook"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
@ -4044,12 +4137,12 @@ $_authorizations_map"
|
|||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
if ! _send_signed_request "${ACME_NEW_ORDER}" "{\"resource\": \"$ACME_NEW_ORDER_RES\", \"csr\": \"$der\"}" "needbase64"; then
|
if ! _send_signed_request "${ACME_NEW_ORDER}" "{\"resource\": \"$ACME_NEW_ORDER_RES\", \"csr\": \"$der\"}" "needbase64"; then
|
||||||
_err "Sign failed."
|
_err "Sign failed. $response"
|
||||||
_on_issue_err "$_post_hook"
|
_on_issue_err "$_post_hook"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
_rcert="$response"
|
_rcert="$response"
|
||||||
Le_LinkCert="$(grep -i '^Location.*$' "$HTTP_HEADER" | _head_n 1 | tr -d "\r\n" | cut -d " " -f 2)"
|
Le_LinkCert="$(grep -i '^Location.*$' "$HTTP_HEADER" | _tail_n 1 | tr -d "\r\n" | cut -d " " -f 2)"
|
||||||
echo "$BEGIN_CERT" >"$CERT_PATH"
|
echo "$BEGIN_CERT" >"$CERT_PATH"
|
||||||
|
|
||||||
#if ! _get "$Le_LinkCert" | _base64 "multiline" >> "$CERT_PATH" ; then
|
#if ! _get "$Le_LinkCert" | _base64 "multiline" >> "$CERT_PATH" ; then
|
||||||
@ -4068,6 +4161,13 @@ $_authorizations_map"
|
|||||||
_debug "Le_LinkCert" "$Le_LinkCert"
|
_debug "Le_LinkCert" "$Le_LinkCert"
|
||||||
_savedomainconf "Le_LinkCert" "$Le_LinkCert"
|
_savedomainconf "Le_LinkCert" "$Le_LinkCert"
|
||||||
|
|
||||||
|
if [ -z "$Le_LinkCert" ] || ! _checkcert "$CERT_PATH"; then
|
||||||
|
response="$(echo "$response" | _dbase64 "multiline" | tr -d '\0' | _normalizeJson)"
|
||||||
|
_err "Sign failed: $(echo "$response" | _egrep_o '"detail":"[^"]*"')"
|
||||||
|
_on_issue_err "$_post_hook"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
if [ "$Le_LinkCert" ]; then
|
if [ "$Le_LinkCert" ]; then
|
||||||
_info "$(__green "Cert success.")"
|
_info "$(__green "Cert success.")"
|
||||||
cat "$CERT_PATH"
|
cat "$CERT_PATH"
|
||||||
@ -4078,26 +4178,18 @@ $_authorizations_map"
|
|||||||
_info "Your cert key is in $(__green " $CERT_KEY_PATH ")"
|
_info "Your cert key is in $(__green " $CERT_KEY_PATH ")"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cp "$CERT_PATH" "$CERT_FULLCHAIN_PATH"
|
|
||||||
|
|
||||||
if [ ! "$USER_PATH" ] || [ ! "$IN_CRON" ]; then
|
if [ ! "$USER_PATH" ] || [ ! "$IN_CRON" ]; then
|
||||||
USER_PATH="$PATH"
|
USER_PATH="$PATH"
|
||||||
_saveaccountconf "USER_PATH" "$USER_PATH"
|
_saveaccountconf "USER_PATH" "$USER_PATH"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "$Le_LinkCert" ]; then
|
|
||||||
response="$(echo "$response" | _dbase64 "multiline" | _normalizeJson)"
|
|
||||||
_err "Sign failed: $(echo "$response" | _egrep_o '"detail":"[^"]*"')"
|
|
||||||
_on_issue_err "$_post_hook"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
_cleardomainconf "Le_Vlist"
|
_cleardomainconf "Le_Vlist"
|
||||||
|
|
||||||
if [ "$ACME_VERSION" = "2" ]; then
|
if [ "$ACME_VERSION" = "2" ]; then
|
||||||
_debug "v2 chain."
|
_debug "v2 chain."
|
||||||
else
|
else
|
||||||
|
cp "$CERT_PATH" "$CERT_FULLCHAIN_PATH"
|
||||||
Le_LinkIssuer=$(grep -i '^Link' "$HTTP_HEADER" | _head_n 1 | cut -d " " -f 2 | cut -d ';' -f 1 | tr -d '<>')
|
Le_LinkIssuer=$(grep -i '^Link' "$HTTP_HEADER" | _head_n 1 | cut -d " " -f 2 | cut -d ';' -f 1 | tr -d '<>')
|
||||||
|
|
||||||
if [ "$Le_LinkIssuer" ]; then
|
if [ "$Le_LinkIssuer" ]; then
|
||||||
@ -4121,6 +4213,10 @@ $_authorizations_map"
|
|||||||
echo "$BEGIN_CERT" >"$CA_CERT_PATH"
|
echo "$BEGIN_CERT" >"$CA_CERT_PATH"
|
||||||
_base64 "multiline" <"$CA_CERT_PATH.der" >>"$CA_CERT_PATH"
|
_base64 "multiline" <"$CA_CERT_PATH.der" >>"$CA_CERT_PATH"
|
||||||
echo "$END_CERT" >>"$CA_CERT_PATH"
|
echo "$END_CERT" >>"$CA_CERT_PATH"
|
||||||
|
if ! _checkcert "$CA_CERT_PATH"; then
|
||||||
|
_err "Can not get the ca cert."
|
||||||
|
break
|
||||||
|
fi
|
||||||
cat "$CA_CERT_PATH" >>"$CERT_FULLCHAIN_PATH"
|
cat "$CA_CERT_PATH" >>"$CERT_FULLCHAIN_PATH"
|
||||||
rm -f "$CA_CERT_PATH.der"
|
rm -f "$CA_CERT_PATH.der"
|
||||||
break
|
break
|
||||||
@ -4191,20 +4287,21 @@ $_authorizations_map"
|
|||||||
Le_NextRenewTime=$(_math "$Le_NextRenewTime" - 86400)
|
Le_NextRenewTime=$(_math "$Le_NextRenewTime" - 86400)
|
||||||
_savedomainconf "Le_NextRenewTime" "$Le_NextRenewTime"
|
_savedomainconf "Le_NextRenewTime" "$Le_NextRenewTime"
|
||||||
|
|
||||||
if ! _on_issue_success "$_post_hook" "$_renew_hook"; then
|
|
||||||
_err "Call hook error."
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$_real_cert$_real_key$_real_ca$_reload_cmd$_real_fullchain" ]; then
|
if [ "$_real_cert$_real_key$_real_ca$_reload_cmd$_real_fullchain" ]; then
|
||||||
_savedomainconf "Le_RealCertPath" "$_real_cert"
|
_savedomainconf "Le_RealCertPath" "$_real_cert"
|
||||||
_savedomainconf "Le_RealCACertPath" "$_real_ca"
|
_savedomainconf "Le_RealCACertPath" "$_real_ca"
|
||||||
_savedomainconf "Le_RealKeyPath" "$_real_key"
|
_savedomainconf "Le_RealKeyPath" "$_real_key"
|
||||||
_savedomainconf "Le_ReloadCmd" "$_reload_cmd"
|
_savedomainconf "Le_ReloadCmd" "$_reload_cmd"
|
||||||
_savedomainconf "Le_RealFullChainPath" "$_real_fullchain"
|
_savedomainconf "Le_RealFullChainPath" "$_real_fullchain"
|
||||||
_installcert "$_main_domain" "$_real_cert" "$_real_key" "$_real_ca" "$_real_fullchain" "$_reload_cmd"
|
if ! _installcert "$_main_domain" "$_real_cert" "$_real_key" "$_real_ca" "$_real_fullchain" "$_reload_cmd"; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if ! _on_issue_success "$_post_hook" "$_renew_hook"; then
|
||||||
|
_err "Call hook error."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
#domain [isEcc]
|
#domain [isEcc]
|
||||||
@ -4230,7 +4327,7 @@ renew() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
. "$DOMAIN_CONF"
|
. "$DOMAIN_CONF"
|
||||||
|
_debug Le_API "$Le_API"
|
||||||
if [ "$Le_API" ]; then
|
if [ "$Le_API" ]; then
|
||||||
if [ "$_OLD_CA_HOST" = "$Le_API" ]; then
|
if [ "$_OLD_CA_HOST" = "$Le_API" ]; then
|
||||||
export Le_API="$DEFAULT_CA"
|
export Le_API="$DEFAULT_CA"
|
||||||
@ -4579,19 +4676,19 @@ _installcert() {
|
|||||||
if [ -f "$_real_cert" ] && [ ! "$IS_RENEW" ]; then
|
if [ -f "$_real_cert" ] && [ ! "$IS_RENEW" ]; then
|
||||||
cp "$_real_cert" "$_backup_path/cert.bak"
|
cp "$_real_cert" "$_backup_path/cert.bak"
|
||||||
fi
|
fi
|
||||||
cat "$CERT_PATH" >"$_real_cert"
|
cat "$CERT_PATH" >"$_real_cert" || return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$_real_ca" ]; then
|
if [ "$_real_ca" ]; then
|
||||||
_info "Installing CA to:$_real_ca"
|
_info "Installing CA to:$_real_ca"
|
||||||
if [ "$_real_ca" = "$_real_cert" ]; then
|
if [ "$_real_ca" = "$_real_cert" ]; then
|
||||||
echo "" >>"$_real_ca"
|
echo "" >>"$_real_ca"
|
||||||
cat "$CA_CERT_PATH" >>"$_real_ca"
|
cat "$CA_CERT_PATH" >>"$_real_ca" || return 1
|
||||||
else
|
else
|
||||||
if [ -f "$_real_ca" ] && [ ! "$IS_RENEW" ]; then
|
if [ -f "$_real_ca" ] && [ ! "$IS_RENEW" ]; then
|
||||||
cp "$_real_ca" "$_backup_path/ca.bak"
|
cp "$_real_ca" "$_backup_path/ca.bak"
|
||||||
fi
|
fi
|
||||||
cat "$CA_CERT_PATH" >"$_real_ca"
|
cat "$CA_CERT_PATH" >"$_real_ca" || return 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -4601,9 +4698,9 @@ _installcert() {
|
|||||||
cp "$_real_key" "$_backup_path/key.bak"
|
cp "$_real_key" "$_backup_path/key.bak"
|
||||||
fi
|
fi
|
||||||
if [ -f "$_real_key" ]; then
|
if [ -f "$_real_key" ]; then
|
||||||
cat "$CERT_KEY_PATH" >"$_real_key"
|
cat "$CERT_KEY_PATH" >"$_real_key" || return 1
|
||||||
else
|
else
|
||||||
cat "$CERT_KEY_PATH" >"$_real_key"
|
cat "$CERT_KEY_PATH" >"$_real_key" || return 1
|
||||||
chmod 600 "$_real_key"
|
chmod 600 "$_real_key"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
@ -4613,7 +4710,7 @@ _installcert() {
|
|||||||
if [ -f "$_real_fullchain" ] && [ ! "$IS_RENEW" ]; then
|
if [ -f "$_real_fullchain" ] && [ ! "$IS_RENEW" ]; then
|
||||||
cp "$_real_fullchain" "$_backup_path/fullchain.bak"
|
cp "$_real_fullchain" "$_backup_path/fullchain.bak"
|
||||||
fi
|
fi
|
||||||
cat "$CERT_FULLCHAIN_PATH" >"$_real_fullchain"
|
cat "$CERT_FULLCHAIN_PATH" >"$_real_fullchain" || return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$_reload_cmd" ]; then
|
if [ "$_reload_cmd" ]; then
|
||||||
@ -4834,6 +4931,8 @@ _deactivate() {
|
|||||||
_debug2 "authzUri" "$authzUri"
|
_debug2 "authzUri" "$authzUri"
|
||||||
if ! response="$(_get "$authzUri")"; then
|
if ! response="$(_get "$authzUri")"; then
|
||||||
_err "get to authz error."
|
_err "get to authz error."
|
||||||
|
_err "_authorizations_seg" "$_authorizations_seg"
|
||||||
|
_err "authzUri" "$authzUri"
|
||||||
_clearup
|
_clearup
|
||||||
_on_issue_err "$_post_hook"
|
_on_issue_err "$_post_hook"
|
||||||
return 1
|
return 1
|
||||||
@ -5365,7 +5464,6 @@ Parameters:
|
|||||||
--webroot, -w /path/to/webroot Specifies the web root folder for web root mode.
|
--webroot, -w /path/to/webroot Specifies the web root folder for web root mode.
|
||||||
--standalone Use standalone mode.
|
--standalone Use standalone mode.
|
||||||
--stateless Use stateless mode, see: $_STATELESS_WIKI
|
--stateless Use stateless mode, see: $_STATELESS_WIKI
|
||||||
--tls Use standalone tls mode.
|
|
||||||
--apache Use apache mode.
|
--apache Use apache mode.
|
||||||
--dns [dns_cf|dns_dp|dns_cx|/path/to/api/file] Use dns mode or dns api.
|
--dns [dns_cf|dns_dp|dns_cx|/path/to/api/file] Use dns mode or dns api.
|
||||||
--dnssleep [$DEFAULT_DNS_SLEEP] The time in seconds to wait for all the txt records to take effect in dns api mode. Default $DEFAULT_DNS_SLEEP seconds.
|
--dnssleep [$DEFAULT_DNS_SLEEP] The time in seconds to wait for all the txt records to take effect in dns api mode. Default $DEFAULT_DNS_SLEEP seconds.
|
||||||
@ -5391,11 +5489,10 @@ Parameters:
|
|||||||
--cert-home Specifies the home dir to save all the certs, only valid for '--install' command.
|
--cert-home Specifies the home dir to save all the certs, only valid for '--install' command.
|
||||||
--config-home Specifies the home dir to save all the configurations.
|
--config-home Specifies the home dir to save all the configurations.
|
||||||
--useragent Specifies the user agent string. it will be saved for future use too.
|
--useragent Specifies the user agent string. it will be saved for future use too.
|
||||||
--accountemail Specifies the account email for registering, Only valid for the '--install' command.
|
--accountemail Specifies the account email, only valid for the '--install' and '--update-account' command.
|
||||||
--accountkey Specifies the account key path, Only valid for the '--install' command.
|
--accountkey Specifies the account key path, only valid for the '--install' command.
|
||||||
--days Specifies the days to renew the cert when using '--issue' command. The max value is $MAX_RENEW days.
|
--days Specifies the days to renew the cert when using '--issue' command. The max value is $MAX_RENEW days.
|
||||||
--httpport Specifies the standalone listening port. Only valid if the server is behind a reverse proxy or load balancer.
|
--httpport Specifies the standalone listening port. Only valid if the server is behind a reverse proxy or load balancer.
|
||||||
--tlsport Specifies the standalone tls listening port. Only valid if the server is behind a reverse proxy or load balancer.
|
|
||||||
--local-address Specifies the standalone/tls server listening address, in case you have multiple ip addresses.
|
--local-address Specifies the standalone/tls server listening address, in case you have multiple ip addresses.
|
||||||
--listraw Only used for '--list' command, list the certs in raw format.
|
--listraw Only used for '--list' command, list the certs in raw format.
|
||||||
--stopRenewOnError, -se Only valid for '--renew-all' command. Stop if one cert has error in renewal.
|
--stopRenewOnError, -se Only valid for '--renew-all' command. Stop if one cert has error in renewal.
|
||||||
@ -5404,6 +5501,7 @@ Parameters:
|
|||||||
--ca-path Specifies directory containing CA certificates in PEM format, used by wget or curl.
|
--ca-path Specifies directory containing CA certificates in PEM format, used by wget or curl.
|
||||||
--nocron Only valid for '--install' command, which means: do not install the default cron job. In this case, the certs will not be renewed automatically.
|
--nocron Only valid for '--install' command, which means: do not install the default cron job. In this case, the certs will not be renewed automatically.
|
||||||
--no-color Do not output color text.
|
--no-color Do not output color text.
|
||||||
|
--force-color Force output of color text. Useful for non-interactive use with the aha tool for HTML E-Mails.
|
||||||
--ecc Specifies to use the ECC cert. Valid for '--install-cert', '--renew', '--revoke', '--toPkcs' and '--createCSR'
|
--ecc Specifies to use the ECC cert. Valid for '--install-cert', '--renew', '--revoke', '--toPkcs' and '--createCSR'
|
||||||
--csr Specifies the input csr.
|
--csr Specifies the input csr.
|
||||||
--pre-hook Command to be run before obtaining any certificates.
|
--pre-hook Command to be run before obtaining any certificates.
|
||||||
@ -5417,6 +5515,8 @@ Parameters:
|
|||||||
--listen-v6 Force standalone/tls server to listen at ipv6.
|
--listen-v6 Force standalone/tls server to listen at ipv6.
|
||||||
--openssl-bin Specifies a custom openssl bin location.
|
--openssl-bin Specifies a custom openssl bin location.
|
||||||
--use-wget Force to use wget, if you have both curl and wget installed.
|
--use-wget Force to use wget, if you have both curl and wget installed.
|
||||||
|
--yes-I-know-dns-manual-mode-enough-go-ahead-please Force to use dns manual mode: $_DNS_MANUAL_WIKI
|
||||||
|
--branch, -b Only valid for '--upgrade' command, specifies the branch name to upgrade to.
|
||||||
"
|
"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5746,16 +5846,8 @@ _process() {
|
|||||||
_webroot="$_webroot,$wvalue"
|
_webroot="$_webroot,$wvalue"
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
--tls)
|
|
||||||
wvalue="$W_TLS"
|
|
||||||
if [ -z "$_webroot" ]; then
|
|
||||||
_webroot="$wvalue"
|
|
||||||
else
|
|
||||||
_webroot="$_webroot,$wvalue"
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
--dns)
|
--dns)
|
||||||
wvalue="dns"
|
wvalue="$W_DNS"
|
||||||
if [ "$2" ] && ! _startswith "$2" "-"; then
|
if [ "$2" ] && ! _startswith "$2" "-"; then
|
||||||
wvalue="$2"
|
wvalue="$2"
|
||||||
shift
|
shift
|
||||||
@ -5849,12 +5941,6 @@ _process() {
|
|||||||
Le_HTTPPort="$_httpport"
|
Le_HTTPPort="$_httpport"
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
--tlsport)
|
|
||||||
_tlsport="$2"
|
|
||||||
Le_TLSPort="$_tlsport"
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
|
|
||||||
--listraw)
|
--listraw)
|
||||||
_listraw="raw"
|
_listraw="raw"
|
||||||
;;
|
;;
|
||||||
@ -5881,6 +5967,9 @@ _process() {
|
|||||||
--no-color)
|
--no-color)
|
||||||
export ACME_NO_COLOR=1
|
export ACME_NO_COLOR=1
|
||||||
;;
|
;;
|
||||||
|
--force-color)
|
||||||
|
export ACME_FORCE_COLOR=1
|
||||||
|
;;
|
||||||
--ecc)
|
--ecc)
|
||||||
_ecc="isEcc"
|
_ecc="isEcc"
|
||||||
;;
|
;;
|
||||||
@ -5919,6 +6008,9 @@ _process() {
|
|||||||
shift
|
shift
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
|
--yes-I-know-dns-manual-mode-enough-go-ahead-please)
|
||||||
|
export FORCE_DNS_MANUAL=1
|
||||||
|
;;
|
||||||
--log | --logfile)
|
--log | --logfile)
|
||||||
_log="1"
|
_log="1"
|
||||||
_logfile="$2"
|
_logfile="$2"
|
||||||
@ -5972,6 +6064,10 @@ _process() {
|
|||||||
_use_wget="1"
|
_use_wget="1"
|
||||||
ACME_USE_WGET="1"
|
ACME_USE_WGET="1"
|
||||||
;;
|
;;
|
||||||
|
--branch | -b)
|
||||||
|
export BRANCH="$2"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
_err "Unknown parameter : $1"
|
_err "Unknown parameter : $1"
|
||||||
return 1
|
return 1
|
||||||
|
@ -2,8 +2,12 @@
|
|||||||
# Here is the script to deploy the cert to your cpanel using the cpanel API.
|
# Here is the script to deploy the cert to your cpanel using the cpanel API.
|
||||||
# Uses command line uapi. --user option is needed only if run as root.
|
# Uses command line uapi. --user option is needed only if run as root.
|
||||||
# Returns 0 when success.
|
# Returns 0 when success.
|
||||||
# Written by Santeri Kannisto <santeri.kannisto@2globalnomads.info>
|
#
|
||||||
# Public domain, 2017
|
# Please note that I am no longer using Github. If you want to report an issue
|
||||||
|
# or contact me, visit https://forum.webseodesigners.com/web-design-seo-and-hosting-f16/
|
||||||
|
#
|
||||||
|
# Written by Santeri Kannisto <santeri.kannisto@webseodesigners.com>
|
||||||
|
# Public domain, 2017-2018
|
||||||
|
|
||||||
#export DEPLOY_CPANEL_USER=myusername
|
#export DEPLOY_CPANEL_USER=myusername
|
||||||
|
|
||||||
@ -28,15 +32,9 @@ cpanel_uapi_deploy() {
|
|||||||
_err "The command uapi is not found."
|
_err "The command uapi is not found."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
if ! _exists php; then
|
|
||||||
_err "The command php is not found."
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
# read cert and key files and urlencode both
|
# read cert and key files and urlencode both
|
||||||
_certstr=$(cat "$_ccert")
|
_cert=$(_url_encode <"$_ccert")
|
||||||
_keystr=$(cat "$_ckey")
|
_key=$(_url_encode <"$_ckey")
|
||||||
_cert=$(php -r "echo urlencode(\"$_certstr\");")
|
|
||||||
_key=$(php -r "echo urlencode(\"$_keystr\");")
|
|
||||||
|
|
||||||
_debug _cert "$_cert"
|
_debug _cert "$_cert"
|
||||||
_debug _key "$_key"
|
_debug _key "$_key"
|
||||||
|
@ -1,11 +1,5 @@
|
|||||||
#!/usr/bin/env sh
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
#Here is a sample custom api script.
|
|
||||||
#This file name is "myapi.sh"
|
|
||||||
#So, here must be a method myapi_deploy()
|
|
||||||
#Which will be called by acme.sh to deploy the cert
|
|
||||||
#returns 0 means success, otherwise error.
|
|
||||||
|
|
||||||
######## Public functions #####################
|
######## Public functions #####################
|
||||||
|
|
||||||
#domain keyfile certfile cafile fullchain
|
#domain keyfile certfile cafile fullchain
|
||||||
|
@ -51,6 +51,7 @@ vault_cli_deploy() {
|
|||||||
|
|
||||||
$VAULT_CMD write "${VAULT_PREFIX}/${_cdomain}/cert.pem" value=@"$_ccert" || return 1
|
$VAULT_CMD write "${VAULT_PREFIX}/${_cdomain}/cert.pem" value=@"$_ccert" || return 1
|
||||||
$VAULT_CMD write "${VAULT_PREFIX}/${_cdomain}/cert.key" value=@"$_ckey" || return 1
|
$VAULT_CMD write "${VAULT_PREFIX}/${_cdomain}/cert.key" value=@"$_ckey" || return 1
|
||||||
|
$VAULT_CMD write "${VAULT_PREFIX}/${_cdomain}/chain.pem" value=@"$_cca" || return 1
|
||||||
$VAULT_CMD write "${VAULT_PREFIX}/${_cdomain}/fullchain.pem" value=@"$_cfullchain" || return 1
|
$VAULT_CMD write "${VAULT_PREFIX}/${_cdomain}/fullchain.pem" value=@"$_cfullchain" || return 1
|
||||||
|
|
||||||
}
|
}
|
||||||
|
131
dnsapi/README.md
131
dnsapi/README.md
@ -1,5 +1,9 @@
|
|||||||
# How to use DNS API
|
# How to use DNS API
|
||||||
|
|
||||||
|
If your dns provider doesn't provide api access, you can use our dns alias mode:
|
||||||
|
|
||||||
|
https://github.com/Neilpang/acme.sh/wiki/DNS-alias-mode
|
||||||
|
|
||||||
## 1. Use CloudFlare domain API to automatically issue cert
|
## 1. Use CloudFlare domain API to automatically issue cert
|
||||||
|
|
||||||
First you need to login to your CloudFlare account to get your API key.
|
First you need to login to your CloudFlare account to get your API key.
|
||||||
@ -325,6 +329,8 @@ The `CY_Username`, `CY_Password` and `CY_OTP_Secret` will be saved in `~/.acme.s
|
|||||||
|
|
||||||
## 17. Use Domain-Offensive/Resellerinterface/Domainrobot API
|
## 17. Use Domain-Offensive/Resellerinterface/Domainrobot API
|
||||||
|
|
||||||
|
ATTENTION: You need to be a registered Reseller to be able to use the ResellerInterface. As a normal user you can not use this method.
|
||||||
|
|
||||||
You will need your login credentials (Partner ID+Password) to the Resellerinterface, and export them before you run `acme.sh`:
|
You will need your login credentials (Partner ID+Password) to the Resellerinterface, and export them before you run `acme.sh`:
|
||||||
```
|
```
|
||||||
export DO_PID="KD-1234567"
|
export DO_PID="KD-1234567"
|
||||||
@ -525,8 +531,9 @@ For issues, please report to https://github.com/raidenii/acme.sh/issues.
|
|||||||
|
|
||||||
## 28. Use Name.com API
|
## 28. Use Name.com API
|
||||||
|
|
||||||
You'll need to fill out the form at https://www.name.com/reseller/apply to apply
|
Create your API token here: https://www.name.com/account/settings/api
|
||||||
for API username and token.
|
|
||||||
|
Note: `Namecom_Username` should be your Name.com username and not the token name. If you accidentally run the script with the token name as the username see `~/.acme.sh/account.conf` to fix the issue
|
||||||
|
|
||||||
```
|
```
|
||||||
export Namecom_Username="testuser"
|
export Namecom_Username="testuser"
|
||||||
@ -638,6 +645,14 @@ acme.sh --issue --dns dns_inwx -d example.com -d www.example.com
|
|||||||
|
|
||||||
The `INWX_User` and `INWX_Password` settings will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
|
The `INWX_User` and `INWX_Password` settings will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
|
||||||
|
|
||||||
|
If your account is secured by mobile tan you have also defined the shared secret.
|
||||||
|
|
||||||
|
```
|
||||||
|
export INWX_Shared_Secret="shared secret"
|
||||||
|
```
|
||||||
|
|
||||||
|
You may need to re-enable the mobile tan to gain the shared secret.
|
||||||
|
|
||||||
## 34. User Servercow API v1
|
## 34. User Servercow API v1
|
||||||
|
|
||||||
Create a new user from the servercow control center. Don't forget to activate **DNS API** for this user.
|
Create a new user from the servercow control center. Don't forget to activate **DNS API** for this user.
|
||||||
@ -750,23 +765,125 @@ DNS API keys may be created at https://panel.dreamhost.com/?tree=home.api.
|
|||||||
Ensure the created key has add and remove privelages.
|
Ensure the created key has add and remove privelages.
|
||||||
|
|
||||||
```
|
```
|
||||||
export DH_API_Key="<api key>"
|
export DH_API_KEY="<api key>"
|
||||||
acme.sh --issue --dns dns_dreamhost -d example.com -d www.example.com
|
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
|
The 'DH_API_KEY' will be saved in `~/.acme.sh/account.conf` and will
|
||||||
be reused when needed.
|
be reused when needed.
|
||||||
|
|
||||||
## 41. Use DNSEver (https://www.dnsever.com/)
|
## 41. Use DirectAdmin API
|
||||||
|
The DirectAdmin interface has it's own Let's encrypt functionality, but this
|
||||||
|
script can be used to generate certificates for names which are not hosted on
|
||||||
|
DirectAdmin
|
||||||
|
|
||||||
|
User must provide login data and URL to the DirectAdmin incl. port.
|
||||||
|
You can create an user which only has access to
|
||||||
|
|
||||||
|
- CMD_API_DNS_CONTROL
|
||||||
|
- CMD_API_SHOW_DOMAINS
|
||||||
|
|
||||||
|
By using the Login Keys function.
|
||||||
|
See also https://www.directadmin.com/api.php and https://www.directadmin.com/features.php?id=1298
|
||||||
|
|
||||||
|
```
|
||||||
|
export DA_Api="https://remoteUser:remotePassword@da.domain.tld:8443"
|
||||||
|
export DA_Api_Insecure=1
|
||||||
|
```
|
||||||
|
Set `DA_Api_Insecure` to 1 for insecure and 0 for secure -> difference is whether ssl cert is checked for validity (0) or whether it is just accepted (1)
|
||||||
|
|
||||||
|
Ok, let's issue a cert now:
|
||||||
|
```
|
||||||
|
acme.sh --issue --dns dns_da -d example.com -d www.example.com
|
||||||
|
```
|
||||||
|
|
||||||
|
The `DA_Api` and `DA_Api_Insecure` will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
|
||||||
|
|
||||||
|
## 42. Use KingHost DNS API
|
||||||
|
|
||||||
|
API access must be enabled at https://painel.kinghost.com.br/painel.api.php
|
||||||
|
|
||||||
|
```
|
||||||
|
export KINGHOST_Username="yourusername"
|
||||||
|
export KINGHOST_Password="yourpassword"
|
||||||
|
acme.sh --issue --dns dns_kinghost -d example.com -d *.example.com
|
||||||
|
```
|
||||||
|
|
||||||
|
The `KINGHOST_username` and `KINGHOST_Password` will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
|
||||||
|
|
||||||
|
## 43. Use Zilore DNS API
|
||||||
|
|
||||||
|
First, get your API key at https://my.zilore.com/account/api
|
||||||
|
|
||||||
|
```
|
||||||
|
export Zilore_Key="5dcad3a2-36cb-50e8-cb92-000002f9"
|
||||||
|
```
|
||||||
|
|
||||||
|
Ok, let's issue a cert now:
|
||||||
|
```
|
||||||
|
acme.sh --issue --dns dns_zilore -d example.com -d *.example.com
|
||||||
|
```
|
||||||
|
|
||||||
|
The `Zilore_Key` will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
|
||||||
|
|
||||||
|
## 44. Use Loopia.se API
|
||||||
|
User must provide login credentials to the Loopia API.
|
||||||
|
The user needs the following permissions:
|
||||||
|
|
||||||
|
- addSubdomain
|
||||||
|
- updateZoneRecord
|
||||||
|
- getDomains
|
||||||
|
- removeSubdomain
|
||||||
|
|
||||||
|
Set the login credentials:
|
||||||
|
```
|
||||||
|
export LOOPIA_User="user@loopiaapi"
|
||||||
|
export LOOPIA_Password="password"
|
||||||
|
```
|
||||||
|
|
||||||
|
And to issue a cert:
|
||||||
|
```
|
||||||
|
acme.sh --issue --dns dns_loopia -d example.com -d *.example.com
|
||||||
|
```
|
||||||
|
|
||||||
|
The username and password will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
|
||||||
|
## 45. Use ACME DNS API
|
||||||
|
|
||||||
|
ACME DNS is a limited DNS server with RESTful HTTP API to handle ACME DNS challenges easily and securely.
|
||||||
|
https://github.com/joohoi/acme-dns
|
||||||
|
|
||||||
|
```
|
||||||
|
export ACMEDNS_UPDATE_URL="https://auth.acme-dns.io/update"
|
||||||
|
export ACMEDNS_USERNAME="<username>"
|
||||||
|
export ACMEDNS_PASSWORD="<password>"
|
||||||
|
export ACMEDNS_SUBDOMAIN="<subdomain>"
|
||||||
|
|
||||||
|
acme.sh --issue --dns dns_acmedns -d example.com -d www.example.com
|
||||||
|
```
|
||||||
|
|
||||||
|
The credentials will be saved in `~/.acme.sh/account.conf` and will
|
||||||
|
be reused when needed.
|
||||||
|
## 46. Use TELE3 API
|
||||||
|
|
||||||
|
First you need to login to your TELE3 account to set your API-KEY.
|
||||||
|
https://www.tele3.cz/system-acme-api.html
|
||||||
|
|
||||||
|
```
|
||||||
|
export TELE3_Key="MS2I4uPPaI..."
|
||||||
|
export TELE3_Secret="kjhOIHGJKHg"
|
||||||
|
|
||||||
|
acme.sh --issue --dns dns_tele3 -d example.com -d *.example.com
|
||||||
|
```
|
||||||
|
|
||||||
|
The TELE3_Key and TELE3_Secret will be saved in ~/.acme.sh/account.conf and will be reused when needed.
|
||||||
|
|
||||||
|
## 47. Use DNSEver (https://www.dnsever.com/)
|
||||||
|
|
||||||
You will need your login credentials (ID+PW) to the DNSEver, and export them before you run acme.sh:
|
You will need your login credentials (ID+PW) to the DNSEver, and export them before you run acme.sh:
|
||||||
```
|
```
|
||||||
export DNSEVER_ID="KD-1234567"
|
export DNSEVER_ID="KD-1234567"
|
||||||
export DNSEVER_PW="cdfkjl3n2"
|
export DNSEVER_PW="cdfkjl3n2"
|
||||||
```
|
|
||||||
|
|
||||||
Ok, let's issue a cert now:
|
|
||||||
```
|
|
||||||
acme.sh --issue --dns dns_dnsever -d example.com -d www.example.com
|
acme.sh --issue --dns dns_dnsever -d example.com -d www.example.com
|
||||||
```
|
```
|
||||||
The DNSEVER_ID and DNSEVER_PW will be saved in ~/.acme.sh/account.conf and will be reused when needed.
|
The DNSEVER_ID and DNSEVER_PW will be saved in ~/.acme.sh/account.conf and will be reused when needed.
|
||||||
|
55
dnsapi/dns_acmedns.sh
Normal file
55
dnsapi/dns_acmedns.sh
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
#
|
||||||
|
#Author: Wolfgang Ebner
|
||||||
|
#Report Bugs here: https://github.com/webner/acme.sh
|
||||||
|
#
|
||||||
|
######## Public functions #####################
|
||||||
|
|
||||||
|
#Usage: dns_acmedns_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||||
|
dns_acmedns_add() {
|
||||||
|
fulldomain=$1
|
||||||
|
txtvalue=$2
|
||||||
|
_info "Using acme-dns"
|
||||||
|
_debug fulldomain "$fulldomain"
|
||||||
|
_debug txtvalue "$txtvalue"
|
||||||
|
|
||||||
|
ACMEDNS_UPDATE_URL="${ACMEDNS_UPDATE_URL:-$(_readaccountconf_mutable ACMEDNS_UPDATE_URL)}"
|
||||||
|
ACMEDNS_USERNAME="${ACMEDNS_USERNAME:-$(_readaccountconf_mutable ACMEDNS_USERNAME)}"
|
||||||
|
ACMEDNS_PASSWORD="${ACMEDNS_PASSWORD:-$(_readaccountconf_mutable ACMEDNS_PASSWORD)}"
|
||||||
|
ACMEDNS_SUBDOMAIN="${ACMEDNS_SUBDOMAIN:-$(_readaccountconf_mutable ACMEDNS_SUBDOMAIN)}"
|
||||||
|
|
||||||
|
if [ "$ACMEDNS_UPDATE_URL" = "" ]; then
|
||||||
|
ACMEDNS_UPDATE_URL="https://auth.acme-dns.io/update"
|
||||||
|
fi
|
||||||
|
|
||||||
|
_saveaccountconf_mutable ACMEDNS_UPDATE_URL "$ACMEDNS_UPDATE_URL"
|
||||||
|
_saveaccountconf_mutable ACMEDNS_USERNAME "$ACMEDNS_USERNAME"
|
||||||
|
_saveaccountconf_mutable ACMEDNS_PASSWORD "$ACMEDNS_PASSWORD"
|
||||||
|
_saveaccountconf_mutable ACMEDNS_SUBDOMAIN "$ACMEDNS_SUBDOMAIN"
|
||||||
|
|
||||||
|
export _H1="X-Api-User: $ACMEDNS_USERNAME"
|
||||||
|
export _H2="X-Api-Key: $ACMEDNS_PASSWORD"
|
||||||
|
data="{\"subdomain\":\"$ACMEDNS_SUBDOMAIN\", \"txt\": \"$txtvalue\"}"
|
||||||
|
|
||||||
|
_debug data "$data"
|
||||||
|
response="$(_post "$data" "$ACMEDNS_UPDATE_URL" "" "POST")"
|
||||||
|
_debug response "$response"
|
||||||
|
|
||||||
|
if ! echo "$response" | grep "\"$txtvalue\"" >/dev/null; then
|
||||||
|
_err "invalid response of acme-dns"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#Usage: fulldomain txtvalue
|
||||||
|
#Remove the txt record after validation.
|
||||||
|
dns_acmedns_rm() {
|
||||||
|
fulldomain=$1
|
||||||
|
txtvalue=$2
|
||||||
|
_info "Using acme-dns"
|
||||||
|
_debug fulldomain "$fulldomain"
|
||||||
|
_debug txtvalue "$txtvalue"
|
||||||
|
}
|
||||||
|
|
||||||
|
#################### Private functions below ##################################
|
@ -76,10 +76,10 @@ dns_azure_add() {
|
|||||||
values="{\"value\":[\"$txtvalue\"]}"
|
values="{\"value\":[\"$txtvalue\"]}"
|
||||||
timestamp="$(_time)"
|
timestamp="$(_time)"
|
||||||
if [ "$_code" = "200" ]; then
|
if [ "$_code" = "200" ]; then
|
||||||
vlist="$(echo "$response" | _egrep_o "\"value\"\s*:\s*\[\s*\"[^\"]*\"\s*]" | cut -d : -f 2 | tr -d "[]\"")"
|
vlist="$(echo "$response" | _egrep_o "\"value\"\\s*:\\s*\\[\\s*\"[^\"]*\"\\s*]" | cut -d : -f 2 | tr -d "[]\"")"
|
||||||
_debug "existing TXT found"
|
_debug "existing TXT found"
|
||||||
_debug "$vlist"
|
_debug "$vlist"
|
||||||
existingts="$(echo "$response" | _egrep_o "\"acmetscheck\"\s*:\s*\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d "\"")"
|
existingts="$(echo "$response" | _egrep_o "\"acmetscheck\"\\s*:\\s*\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d "\"")"
|
||||||
if [ -z "$existingts" ]; then
|
if [ -z "$existingts" ]; then
|
||||||
# the record was not created by acme.sh. Copy the exisiting entires
|
# the record was not created by acme.sh. Copy the exisiting entires
|
||||||
existingts=$timestamp
|
existingts=$timestamp
|
||||||
@ -99,6 +99,7 @@ dns_azure_add() {
|
|||||||
_azure_rest PUT "$acmeRecordURI" "$body" "$accesstoken"
|
_azure_rest PUT "$acmeRecordURI" "$body" "$accesstoken"
|
||||||
if [ "$_code" = "200" ] || [ "$_code" = '201' ]; then
|
if [ "$_code" = "200" ] || [ "$_code" = '201' ]; then
|
||||||
_info "validation value added"
|
_info "validation value added"
|
||||||
|
return 0
|
||||||
else
|
else
|
||||||
_err "error adding validation value ($_code)"
|
_err "error adding validation value ($_code)"
|
||||||
return 1
|
return 1
|
||||||
@ -171,7 +172,7 @@ dns_azure_rm() {
|
|||||||
_azure_rest GET "$acmeRecordURI" "" "$accesstoken"
|
_azure_rest GET "$acmeRecordURI" "" "$accesstoken"
|
||||||
timestamp="$(_time)"
|
timestamp="$(_time)"
|
||||||
if [ "$_code" = "200" ]; then
|
if [ "$_code" = "200" ]; then
|
||||||
vlist="$(echo "$response" | _egrep_o "\"value\"\s*:\s*\[\s*\"[^\"]*\"\s*]" | cut -d : -f 2 | tr -d "[]\"" | grep -v "$txtvalue")"
|
vlist="$(echo "$response" | _egrep_o "\"value\"\\s*:\\s*\\[\\s*\"[^\"]*\"\\s*]" | cut -d : -f 2 | tr -d "[]\"" | grep -v "$txtvalue")"
|
||||||
values=""
|
values=""
|
||||||
comma=""
|
comma=""
|
||||||
for v in $vlist; do
|
for v in $vlist; do
|
||||||
@ -194,6 +195,7 @@ dns_azure_rm() {
|
|||||||
_azure_rest PUT "$acmeRecordURI" "$body" "$accesstoken"
|
_azure_rest PUT "$acmeRecordURI" "$body" "$accesstoken"
|
||||||
if [ "$_code" = "200" ] || [ "$_code" = '201' ]; then
|
if [ "$_code" = "200" ] || [ "$_code" = '201' ]; then
|
||||||
_info "validation value removed"
|
_info "validation value removed"
|
||||||
|
return 0
|
||||||
else
|
else
|
||||||
_err "error removing validation value ($_code)"
|
_err "error removing validation value ($_code)"
|
||||||
return 1
|
return 1
|
||||||
@ -226,8 +228,9 @@ _azure_rest() {
|
|||||||
else
|
else
|
||||||
response="$(_get "$ep")"
|
response="$(_get "$ep")"
|
||||||
fi
|
fi
|
||||||
|
_ret="$?"
|
||||||
_secure_debug2 "response $response"
|
_secure_debug2 "response $response"
|
||||||
_code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\r\n")"
|
_code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\\r\\n")"
|
||||||
_debug "http response code $_code"
|
_debug "http response code $_code"
|
||||||
if [ "$_code" = "401" ]; then
|
if [ "$_code" = "401" ]; then
|
||||||
# we have an invalid access token set to expired
|
# we have an invalid access token set to expired
|
||||||
@ -236,7 +239,7 @@ _azure_rest() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
# See https://docs.microsoft.com/en-us/azure/architecture/best-practices/retry-service-specific#general-rest-and-retry-guidelines for retryable HTTP codes
|
# See https://docs.microsoft.com/en-us/azure/architecture/best-practices/retry-service-specific#general-rest-and-retry-guidelines for retryable HTTP codes
|
||||||
if [ "$?" != "0" ] || [ -z "$_code" ] || [ "$_code" = "408" ] || [ "$_code" = "500" ] || [ "$_code" = "503" ] || [ "$_code" = "504" ]; then
|
if [ "$_ret" != "0" ] || [ -z "$_code" ] || [ "$_code" = "408" ] || [ "$_code" = "500" ] || [ "$_code" = "503" ] || [ "$_code" = "504" ]; then
|
||||||
_request_retry_times="$(_math "$_request_retry_times" + 1)"
|
_request_retry_times="$(_math "$_request_retry_times" + 1)"
|
||||||
_info "REST call error $_code retrying $ep in $_request_retry_times s"
|
_info "REST call error $_code retrying $ep in $_request_retry_times s"
|
||||||
_sleep "$_request_retry_times"
|
_sleep "$_request_retry_times"
|
||||||
@ -281,6 +284,7 @@ _azure_getaccess_token() {
|
|||||||
body="resource=$(printf "%s" 'https://management.core.windows.net/' | _url_encode)&client_id=$(printf "%s" "$clientID" | _url_encode)&client_secret=$(printf "%s" "$clientSecret" | _url_encode)&grant_type=client_credentials"
|
body="resource=$(printf "%s" 'https://management.core.windows.net/' | _url_encode)&client_id=$(printf "%s" "$clientID" | _url_encode)&client_secret=$(printf "%s" "$clientSecret" | _url_encode)&grant_type=client_credentials"
|
||||||
_secure_debug2 "data $body"
|
_secure_debug2 "data $body"
|
||||||
response="$(_post "$body" "https://login.microsoftonline.com/$tenantID/oauth2/token" "" "POST")"
|
response="$(_post "$body" "https://login.microsoftonline.com/$tenantID/oauth2/token" "" "POST")"
|
||||||
|
_ret="$?"
|
||||||
_secure_debug2 "response $response"
|
_secure_debug2 "response $response"
|
||||||
response="$(echo "$response" | _normalizeJson)"
|
response="$(echo "$response" | _normalizeJson)"
|
||||||
accesstoken=$(echo "$response" | _egrep_o "\"access_token\":\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \")
|
accesstoken=$(echo "$response" | _egrep_o "\"access_token\":\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \")
|
||||||
@ -290,7 +294,7 @@ _azure_getaccess_token() {
|
|||||||
_err "no acccess token received. Check your Azure settings see $WIKI"
|
_err "no acccess token received. Check your Azure settings see $WIKI"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
if [ "$?" != "0" ]; then
|
if [ "$_ret" != "0" ]; then
|
||||||
_err "error $response"
|
_err "error $response"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
@ -304,7 +308,7 @@ _get_root() {
|
|||||||
domain=$1
|
domain=$1
|
||||||
subscriptionId=$2
|
subscriptionId=$2
|
||||||
accesstoken=$3
|
accesstoken=$3
|
||||||
i=2
|
i=1
|
||||||
p=1
|
p=1
|
||||||
|
|
||||||
## Ref: https://docs.microsoft.com/en-us/rest/api/dns/zones/list
|
## Ref: https://docs.microsoft.com/en-us/rest/api/dns/zones/list
|
||||||
@ -324,9 +328,14 @@ _get_root() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if _contains "$response" "\"name\":\"$h\"" >/dev/null; then
|
if _contains "$response" "\"name\":\"$h\"" >/dev/null; then
|
||||||
_domain_id=$(echo "$response" | _egrep_o "\{\"id\":\"[^\"]*$h\"" | head -n 1 | cut -d : -f 2 | tr -d \")
|
_domain_id=$(echo "$response" | _egrep_o "\\{\"id\":\"[^\"]*$h\"" | head -n 1 | cut -d : -f 2 | tr -d \")
|
||||||
if [ "$_domain_id" ]; then
|
if [ "$_domain_id" ]; then
|
||||||
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
|
if [ "$i" = 1 ]; then
|
||||||
|
#create the record at the domain apex (@) if only the domain name was provided as --domain-alias
|
||||||
|
_sub_domain="@"
|
||||||
|
else
|
||||||
|
_sub_domain=$(echo "$domain" | cut -d . -f 1-$p)
|
||||||
|
fi
|
||||||
_domain=$h
|
_domain=$h
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
@ -19,8 +19,8 @@ dns_cf_add() {
|
|||||||
if [ -z "$CF_Key" ] || [ -z "$CF_Email" ]; then
|
if [ -z "$CF_Key" ] || [ -z "$CF_Email" ]; then
|
||||||
CF_Key=""
|
CF_Key=""
|
||||||
CF_Email=""
|
CF_Email=""
|
||||||
_err "You don't specify cloudflare api key and email yet."
|
_err "You didn't specify a cloudflare api key and email yet."
|
||||||
_err "Please create you key and try again."
|
_err "Please create the key and try again."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -94,8 +94,8 @@ dns_cf_rm() {
|
|||||||
if [ -z "$CF_Key" ] || [ -z "$CF_Email" ]; then
|
if [ -z "$CF_Key" ] || [ -z "$CF_Email" ]; then
|
||||||
CF_Key=""
|
CF_Key=""
|
||||||
CF_Email=""
|
CF_Email=""
|
||||||
_err "You don't specify cloudflare api key and email yet."
|
_err "You didn't specify a cloudflare api key and email yet."
|
||||||
_err "Please create you key and try again."
|
_err "Please create the key and try again."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
184
dnsapi/dns_da.sh
Executable file
184
dnsapi/dns_da.sh
Executable file
@ -0,0 +1,184 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
# -*- mode: sh; tab-width: 2; indent-tabs-mode: s; coding: utf-8 -*-
|
||||||
|
# vim: et ts=2 sw=2
|
||||||
|
#
|
||||||
|
# DirectAdmin 1.41.0 API
|
||||||
|
# The DirectAdmin interface has it's own Let's encrypt functionality, but this
|
||||||
|
# script can be used to generate certificates for names which are not hosted on
|
||||||
|
# DirectAdmin
|
||||||
|
#
|
||||||
|
# User must provide login data and URL to DirectAdmin incl. port.
|
||||||
|
# You can create login key, by using the Login Keys function
|
||||||
|
# ( https://da.example.com:8443/CMD_LOGIN_KEYS ), which only has access to
|
||||||
|
# - CMD_API_DNS_CONTROL
|
||||||
|
# - CMD_API_SHOW_DOMAINS
|
||||||
|
#
|
||||||
|
# See also https://www.directadmin.com/api.php and
|
||||||
|
# https://www.directadmin.com/features.php?id=1298
|
||||||
|
#
|
||||||
|
# Report bugs to https://github.com/TigerP/acme.sh/issues
|
||||||
|
#
|
||||||
|
# Values to export:
|
||||||
|
# export DA_Api="https://remoteUser:remotePassword@da.example.com:8443"
|
||||||
|
# export DA_Api_Insecure=1
|
||||||
|
#
|
||||||
|
# Set DA_Api_Insecure to 1 for insecure and 0 for secure -> difference is
|
||||||
|
# whether ssl cert is checked for validity (0) or whether it is just accepted
|
||||||
|
# (1)
|
||||||
|
#
|
||||||
|
######## Public functions #####################
|
||||||
|
|
||||||
|
# Usage: dns_myapi_add _acme-challenge.www.example.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||||
|
# Used to add txt record
|
||||||
|
dns_da_add() {
|
||||||
|
fulldomain="${1}"
|
||||||
|
txtvalue="${2}"
|
||||||
|
_debug "Calling: dns_da_add() '${fulldomain}' '${txtvalue}'"
|
||||||
|
_DA_credentials && _DA_getDomainInfo && _DA_addTxt
|
||||||
|
}
|
||||||
|
|
||||||
|
# Usage: dns_da_rm _acme-challenge.www.example.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||||
|
# Used to remove the txt record after validation
|
||||||
|
dns_da_rm() {
|
||||||
|
fulldomain="${1}"
|
||||||
|
txtvalue="${2}"
|
||||||
|
_debug "Calling: dns_da_rm() '${fulldomain}' '${txtvalue}'"
|
||||||
|
_DA_credentials && _DA_getDomainInfo && _DA_rmTxt
|
||||||
|
}
|
||||||
|
|
||||||
|
#################### Private functions below ##################################
|
||||||
|
# Usage: _DA_credentials
|
||||||
|
# It will check if the needed settings are available
|
||||||
|
_DA_credentials() {
|
||||||
|
DA_Api="${DA_Api:-$(_readaccountconf_mutable DA_Api)}"
|
||||||
|
DA_Api_Insecure="${DA_Api_Insecure:-$(_readaccountconf_mutable DA_Api_Insecure)}"
|
||||||
|
if [ -z "${DA_Api}" ] || [ -z "${DA_Api_Insecure}" ]; then
|
||||||
|
DA_Api=""
|
||||||
|
DA_Api_Insecure=""
|
||||||
|
_err "You haven't specified the DirectAdmin Login data, URL and whether you want check the DirectAdmin SSL cert. Please try again."
|
||||||
|
return 1
|
||||||
|
else
|
||||||
|
_saveaccountconf_mutable DA_Api "${DA_Api}"
|
||||||
|
_saveaccountconf_mutable DA_Api_Insecure "${DA_Api_Insecure}"
|
||||||
|
# Set whether curl should use secure or insecure mode
|
||||||
|
export HTTPS_INSECURE="${DA_Api_Insecure}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Usage: _get_root _acme-challenge.www.example.com
|
||||||
|
# Split the full domain to a domain and subdomain
|
||||||
|
#returns
|
||||||
|
# _sub_domain=_acme-challenge.www
|
||||||
|
# _domain=example.com
|
||||||
|
_get_root() {
|
||||||
|
domain=$1
|
||||||
|
i=2
|
||||||
|
p=1
|
||||||
|
# Get a list of all the domains
|
||||||
|
# response will contain "list[]=example.com&list[]=example.org"
|
||||||
|
_da_api CMD_API_SHOW_DOMAINS "" "${domain}"
|
||||||
|
while true; do
|
||||||
|
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
|
||||||
|
_debug h "$h"
|
||||||
|
if [ -z "$h" ]; then
|
||||||
|
# not valid
|
||||||
|
_debug "The given domain $h is not valid"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
if _contains "$response" "$h" >/dev/null; then
|
||||||
|
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
|
||||||
|
_domain=$h
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
p=$i
|
||||||
|
i=$(_math "$i" + 1)
|
||||||
|
done
|
||||||
|
_debug "Stop on 100"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Usage: _da_api CMD_API_* data example.com
|
||||||
|
# Use the DirectAdmin API and check the result
|
||||||
|
# returns
|
||||||
|
# response="error=0&text=Result text&details="
|
||||||
|
_da_api() {
|
||||||
|
cmd=$1
|
||||||
|
data=$2
|
||||||
|
domain=$3
|
||||||
|
_debug "$domain; $data"
|
||||||
|
response="$(_post "$data" "$DA_Api/$cmd" "" "POST")"
|
||||||
|
|
||||||
|
if [ "$?" != "0" ]; then
|
||||||
|
_err "error $cmd"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_debug response "$response"
|
||||||
|
|
||||||
|
case "${cmd}" in
|
||||||
|
CMD_API_DNS_CONTROL)
|
||||||
|
# Parse the result in general
|
||||||
|
# error=0&text=Records Deleted&details=
|
||||||
|
# error=1&text=Cannot View Dns Record&details=No domain provided
|
||||||
|
err_field="$(_getfield "$response" 1 '&')"
|
||||||
|
txt_field="$(_getfield "$response" 2 '&')"
|
||||||
|
details_field="$(_getfield "$response" 3 '&')"
|
||||||
|
error="$(_getfield "$err_field" 2 '=')"
|
||||||
|
text="$(_getfield "$txt_field" 2 '=')"
|
||||||
|
details="$(_getfield "$details_field" 2 '=')"
|
||||||
|
_debug "error: ${error}, text: ${text}, details: ${details}"
|
||||||
|
if [ "$error" != "0" ]; then
|
||||||
|
_err "error $response"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
CMD_API_SHOW_DOMAINS) ;;
|
||||||
|
esac
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Usage: _DA_getDomainInfo
|
||||||
|
# Get the root zone if possible
|
||||||
|
_DA_getDomainInfo() {
|
||||||
|
_debug "First detect the root zone"
|
||||||
|
if ! _get_root "$fulldomain"; then
|
||||||
|
_err "invalid domain"
|
||||||
|
return 1
|
||||||
|
else
|
||||||
|
_debug "The root domain: $_domain"
|
||||||
|
_debug "The sub domain: $_sub_domain"
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Usage: _DA_addTxt
|
||||||
|
# Use the API to add a record
|
||||||
|
_DA_addTxt() {
|
||||||
|
curData="domain=${_domain}&action=add&type=TXT&name=${_sub_domain}&value=\"${txtvalue}\""
|
||||||
|
_debug "Calling _DA_addTxt: '${curData}' '${DA_Api}/CMD_API_DNS_CONTROL'"
|
||||||
|
_da_api CMD_API_DNS_CONTROL "${curData}" "${_domain}"
|
||||||
|
_debug "Result of _DA_addTxt: '$response'"
|
||||||
|
if _contains "${response}" 'error=0'; then
|
||||||
|
_debug "Add TXT succeeded"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
_debug "Add TXT failed"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Usage: _DA_rmTxt
|
||||||
|
# Use the API to remove a record
|
||||||
|
_DA_rmTxt() {
|
||||||
|
curData="domain=${_domain}&action=select&txtrecs0=name=${_sub_domain}&value=\"${txtvalue}\""
|
||||||
|
_debug "Calling _DA_rmTxt: '${curData}' '${DA_Api}/CMD_API_DNS_CONTROL'"
|
||||||
|
if _da_api CMD_API_DNS_CONTROL "${curData}" "${_domain}"; then
|
||||||
|
_debug "Result of _DA_rmTxt: '$response'"
|
||||||
|
else
|
||||||
|
_err "Result of _DA_rmTxt: '$response'"
|
||||||
|
fi
|
||||||
|
if _contains "${response}" 'error=0'; then
|
||||||
|
_debug "RM TXT succeeded"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
_debug "RM TXT failed"
|
||||||
|
return 1
|
||||||
|
}
|
@ -20,12 +20,22 @@
|
|||||||
dns_dgon_add() {
|
dns_dgon_add() {
|
||||||
fulldomain="$(echo "$1" | _lower_case)"
|
fulldomain="$(echo "$1" | _lower_case)"
|
||||||
txtvalue=$2
|
txtvalue=$2
|
||||||
|
|
||||||
|
DO_API_KEY="${DO_API_KEY:-$(_readaccountconf_mutable DO_API_KEY)}"
|
||||||
|
# Check if API Key Exist
|
||||||
|
if [ -z "$DO_API_KEY" ]; then
|
||||||
|
DO_API_KEY=""
|
||||||
|
_err "You did not specify DigitalOcean API key."
|
||||||
|
_err "Please export DO_API_KEY and try again."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
_info "Using digitalocean dns validation - add record"
|
_info "Using digitalocean dns validation - add record"
|
||||||
_debug fulldomain "$fulldomain"
|
_debug fulldomain "$fulldomain"
|
||||||
_debug txtvalue "$txtvalue"
|
_debug txtvalue "$txtvalue"
|
||||||
|
|
||||||
## save the env vars (key and domain split location) for later automated use
|
## save the env vars (key and domain split location) for later automated use
|
||||||
_saveaccountconf DO_API_KEY "$DO_API_KEY"
|
_saveaccountconf_mutable DO_API_KEY "$DO_API_KEY"
|
||||||
|
|
||||||
## split the domain for DO API
|
## split the domain for DO API
|
||||||
if ! _get_base_domain "$fulldomain"; then
|
if ! _get_base_domain "$fulldomain"; then
|
||||||
@ -39,7 +49,7 @@ dns_dgon_add() {
|
|||||||
export _H1="Content-Type: application/json"
|
export _H1="Content-Type: application/json"
|
||||||
export _H2="Authorization: Bearer $DO_API_KEY"
|
export _H2="Authorization: Bearer $DO_API_KEY"
|
||||||
PURL='https://api.digitalocean.com/v2/domains/'$_domain'/records'
|
PURL='https://api.digitalocean.com/v2/domains/'$_domain'/records'
|
||||||
PBODY='{"type":"TXT","name":"'$_sub_domain'","data":"'$txtvalue'"}'
|
PBODY='{"type":"TXT","name":"'$_sub_domain'","data":"'$txtvalue'","ttl":120}'
|
||||||
|
|
||||||
_debug PURL "$PURL"
|
_debug PURL "$PURL"
|
||||||
_debug PBODY "$PBODY"
|
_debug PBODY "$PBODY"
|
||||||
@ -65,6 +75,16 @@ dns_dgon_add() {
|
|||||||
dns_dgon_rm() {
|
dns_dgon_rm() {
|
||||||
fulldomain="$(echo "$1" | _lower_case)"
|
fulldomain="$(echo "$1" | _lower_case)"
|
||||||
txtvalue=$2
|
txtvalue=$2
|
||||||
|
|
||||||
|
DO_API_KEY="${DO_API_KEY:-$(_readaccountconf_mutable DO_API_KEY)}"
|
||||||
|
# Check if API Key Exist
|
||||||
|
if [ -z "$DO_API_KEY" ]; then
|
||||||
|
DO_API_KEY=""
|
||||||
|
_err "You did not specify DigitalOcean API key."
|
||||||
|
_err "Please export DO_API_KEY and try again."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
_info "Using digitalocean dns validation - remove record"
|
_info "Using digitalocean dns validation - remove record"
|
||||||
_debug fulldomain "$fulldomain"
|
_debug fulldomain "$fulldomain"
|
||||||
_debug txtvalue "$txtvalue"
|
_debug txtvalue "$txtvalue"
|
||||||
@ -92,11 +112,11 @@ dns_dgon_rm() {
|
|||||||
domain_list="$(_get "$GURL")"
|
domain_list="$(_get "$GURL")"
|
||||||
## 2) find record
|
## 2) find record
|
||||||
## check for what we are looing for: "type":"A","name":"$_sub_domain"
|
## check for what we are looing for: "type":"A","name":"$_sub_domain"
|
||||||
record="$(echo "$domain_list" | _egrep_o "\"id\"\s*\:\s*\"*\d+\"*[^}]*\"name\"\s*\:\s*\"$_sub_domain\"[^}]*\"data\"\s*\:\s*\"$txtvalue\"")"
|
record="$(echo "$domain_list" | _egrep_o "\"id\"\s*\:\s*\"*[0-9]+\"*[^}]*\"name\"\s*\:\s*\"$_sub_domain\"[^}]*\"data\"\s*\:\s*\"$txtvalue\"")"
|
||||||
## 3) check record and get next page
|
## 3) check record and get next page
|
||||||
if [ -z "$record" ]; then
|
if [ -z "$record" ]; then
|
||||||
## find the next page if we dont have a match
|
## find the next page if we dont have a match
|
||||||
nextpage="$(echo "$domain_list" | _egrep_o "\"links\".*" | _egrep_o "\"next\".*" | _egrep_o "http.*page\=\d+")"
|
nextpage="$(echo "$domain_list" | _egrep_o "\"links\".*" | _egrep_o "\"next\".*" | _egrep_o "http.*page\=[0-9]+")"
|
||||||
if [ -z "$nextpage" ]; then
|
if [ -z "$nextpage" ]; then
|
||||||
_err "no record and no nextpage in digital ocean DNS removal"
|
_err "no record and no nextpage in digital ocean DNS removal"
|
||||||
return 1
|
return 1
|
||||||
@ -108,7 +128,7 @@ dns_dgon_rm() {
|
|||||||
done
|
done
|
||||||
|
|
||||||
## we found the record
|
## we found the record
|
||||||
rec_id="$(echo "$record" | _egrep_o "id\"\s*\:\s*\"*\d+" | _egrep_o "\d+")"
|
rec_id="$(echo "$record" | _egrep_o "id\"\s*\:\s*\"*[0-9]+" | _egrep_o "[0-9]+")"
|
||||||
_debug rec_id "$rec_id"
|
_debug rec_id "$rec_id"
|
||||||
|
|
||||||
## delete the record
|
## delete the record
|
||||||
|
@ -39,34 +39,17 @@ dns_dnsimple_add() {
|
|||||||
|
|
||||||
_get_records "$_account_id" "$_domain" "$_sub_domain"
|
_get_records "$_account_id" "$_domain" "$_sub_domain"
|
||||||
|
|
||||||
if [ "$_records_count" = "0" ]; then
|
_info "Adding record"
|
||||||
_info "Adding record"
|
if _dnsimple_rest POST "$_account_id/zones/$_domain/records" "{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"content\":\"$txtvalue\",\"ttl\":120}"; then
|
||||||
if _dnsimple_rest POST "$_account_id/zones/$_domain/records" "{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"content\":\"$txtvalue\",\"ttl\":120}"; then
|
if printf -- "%s" "$response" | grep "\"name\":\"$_sub_domain\"" >/dev/null; then
|
||||||
if printf -- "%s" "$response" | grep "\"name\":\"$_sub_domain\"" >/dev/null; then
|
_info "Added"
|
||||||
_info "Added"
|
|
||||||
return 0
|
|
||||||
else
|
|
||||||
_err "Unexpected response while adding text record."
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
_err "Add txt record error."
|
|
||||||
else
|
|
||||||
_info "Updating record"
|
|
||||||
_extract_record_id "$_records" "$_sub_domain"
|
|
||||||
|
|
||||||
if _dnsimple_rest \
|
|
||||||
PATCH \
|
|
||||||
"$_account_id/zones/$_domain/records/$_record_id" \
|
|
||||||
"{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"content\":\"$txtvalue\",\"ttl\":120}"; then
|
|
||||||
|
|
||||||
_info "Updated!"
|
|
||||||
return 0
|
return 0
|
||||||
|
else
|
||||||
|
_err "Unexpected response while adding text record."
|
||||||
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
_err "Update error"
|
|
||||||
return 1
|
|
||||||
fi
|
fi
|
||||||
|
_err "Add txt record error."
|
||||||
}
|
}
|
||||||
|
|
||||||
# fulldomain
|
# fulldomain
|
||||||
@ -84,19 +67,19 @@ dns_dnsimple_rm() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
_get_records "$_account_id" "$_domain" "$_sub_domain"
|
_get_records "$_account_id" "$_domain" "$_sub_domain"
|
||||||
|
|
||||||
_extract_record_id "$_records" "$_sub_domain"
|
_extract_record_id "$_records" "$_sub_domain"
|
||||||
|
|
||||||
if [ "$_record_id" ]; then
|
if [ "$_record_id" ]; then
|
||||||
|
echo "$_record_id" | while read -r item; do
|
||||||
if _dnsimple_rest DELETE "$_account_id/zones/$_domain/records/$_record_id"; then
|
if _dnsimple_rest DELETE "$_account_id/zones/$_domain/records/$item"; then
|
||||||
_info "removed record" "$_record_id"
|
_info "removed record" "$item"
|
||||||
return 0
|
return 0
|
||||||
fi
|
else
|
||||||
|
_err "failed to remove record" "$item"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
_err "failed to remove record" "$_record_id"
|
|
||||||
return 1
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#################### Private functions bellow ##################################
|
#################### Private functions bellow ##################################
|
||||||
|
@ -53,8 +53,9 @@ dns_freedns_add() {
|
|||||||
i="$(_math "$i" - 1)"
|
i="$(_math "$i" - 1)"
|
||||||
sub_domain="$(echo "$fulldomain" | cut -d. -f -"$i")"
|
sub_domain="$(echo "$fulldomain" | cut -d. -f -"$i")"
|
||||||
|
|
||||||
_debug top_domain "$top_domain"
|
_debug "top_domain: $top_domain"
|
||||||
_debug sub_domain "$sub_domain"
|
_debug "sub_domain: $sub_domain"
|
||||||
|
|
||||||
# Sometimes FreeDNS does not return the subdomain page but rather
|
# Sometimes FreeDNS does not return the subdomain page but rather
|
||||||
# returns a page regarding becoming a premium member. This usually
|
# returns a page regarding becoming a premium member. This usually
|
||||||
# happens after a period of inactivity. Immediately trying again
|
# happens after a period of inactivity. Immediately trying again
|
||||||
@ -63,6 +64,7 @@ dns_freedns_add() {
|
|||||||
attempts=2
|
attempts=2
|
||||||
while [ "$attempts" -gt "0" ]; do
|
while [ "$attempts" -gt "0" ]; do
|
||||||
attempts="$(_math "$attempts" - 1)"
|
attempts="$(_math "$attempts" - 1)"
|
||||||
|
|
||||||
htmlpage="$(_freedns_retrieve_subdomain_page "$FREEDNS_COOKIE")"
|
htmlpage="$(_freedns_retrieve_subdomain_page "$FREEDNS_COOKIE")"
|
||||||
if [ "$?" != "0" ]; then
|
if [ "$?" != "0" ]; then
|
||||||
if [ "$using_cached_cookies" = "true" ]; then
|
if [ "$using_cached_cookies" = "true" ]; then
|
||||||
@ -71,10 +73,9 @@ dns_freedns_add() {
|
|||||||
fi
|
fi
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
_debug2 htmlpage "$htmlpage"
|
|
||||||
|
|
||||||
subdomain_csv="$(echo "$htmlpage" | tr -d "\n\r" | _egrep_o '<form .*</form>' | sed 's/<tr>/@<tr>/g' | tr '@' '\n' | grep edit.php | grep "$top_domain")"
|
subdomain_csv="$(echo "$htmlpage" | tr -d "\n\r" | _egrep_o '<form .*</form>' | sed 's/<tr>/@<tr>/g' | tr '@' '\n' | grep edit.php | grep "$top_domain")"
|
||||||
_debug2 subdomain_csv "$subdomain_csv"
|
_debug3 "subdomain_csv: $subdomain_csv"
|
||||||
|
|
||||||
# The above beauty ends with striping out rows that do not have an
|
# The above beauty ends with striping out rows that do not have an
|
||||||
# href to edit.php and do not have the top domain we are looking for.
|
# href to edit.php and do not have the top domain we are looking for.
|
||||||
@ -85,55 +86,25 @@ dns_freedns_add() {
|
|||||||
lines="$(echo "$subdomain_csv" | wc -l)"
|
lines="$(echo "$subdomain_csv" | wc -l)"
|
||||||
i=0
|
i=0
|
||||||
found=0
|
found=0
|
||||||
|
DNSdomainid=""
|
||||||
while [ "$i" -lt "$lines" ]; do
|
while [ "$i" -lt "$lines" ]; do
|
||||||
i="$(_math "$i" + 1)"
|
i="$(_math "$i" + 1)"
|
||||||
line="$(echo "$subdomain_csv" | sed -n "${i}p")"
|
line="$(echo "$subdomain_csv" | sed -n "${i}p")"
|
||||||
_debug2 line "$line"
|
_debug2 "line: $line"
|
||||||
if [ $found = 0 ] && _contains "$line" "<td>$top_domain</td>"; then
|
if [ $found = 0 ] && _contains "$line" "<td>$top_domain</td>"; then
|
||||||
# this line will contain DNSdomainid for the top_domain
|
# this line will contain DNSdomainid for the top_domain
|
||||||
DNSdomainid="$(echo "$line" | _egrep_o "edit_domain_id *= *.*>" | cut -d = -f 2 | cut -d '>' -f 1)"
|
DNSdomainid="$(echo "$line" | _egrep_o "edit_domain_id *= *.*>" | cut -d = -f 2 | cut -d '>' -f 1)"
|
||||||
_debug2 DNSdomainid "$DNSdomainid"
|
_debug2 "DNSdomainid: $DNSdomainid"
|
||||||
found=1
|
found=1
|
||||||
else
|
break
|
||||||
# lines contain DNS records for all subdomains
|
|
||||||
DNSname="$(echo "$line" | _egrep_o 'edit.php.*</a>' | cut -d '>' -f 2 | cut -d '<' -f 1)"
|
|
||||||
_debug2 DNSname "$DNSname"
|
|
||||||
DNStype="$(echo "$line" | sed 's/<td/@<td/g' | tr '@' '\n' | sed -n '4p' | cut -d '>' -f 2 | cut -d '<' -f 1)"
|
|
||||||
_debug2 DNStype "$DNStype"
|
|
||||||
if [ "$DNSname" = "$fulldomain" ] && [ "$DNStype" = "TXT" ]; then
|
|
||||||
DNSdataid="$(echo "$line" | _egrep_o 'data_id=.*' | cut -d = -f 2 | cut -d '>' -f 1)"
|
|
||||||
# Now get current value for the TXT record. This method may
|
|
||||||
# not produce accurate results as the value field is truncated
|
|
||||||
# on this webpage. To get full value we would need to load
|
|
||||||
# another page. However we don't really need this so long as
|
|
||||||
# there is only one TXT record for the acme challenge subdomain.
|
|
||||||
DNSvalue="$(echo "$line" | sed 's/<td/@<td/g' | tr '@' '\n' | sed -n '5p' | cut -d '>' -f 2 | cut -d '<' -f 1)"
|
|
||||||
_debug2 DNSvalue "$DNSvalue"
|
|
||||||
if [ $found != 0 ]; then
|
|
||||||
break
|
|
||||||
# we are breaking out of the loop at the first match of DNS name
|
|
||||||
# and DNS type (if we are past finding the domainid). This assumes
|
|
||||||
# that there is only ever one TXT record for the LetsEncrypt/acme
|
|
||||||
# challenge subdomain. This seems to be a reasonable assumption
|
|
||||||
# as the acme client deletes the TXT record on successful validation.
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
DNSname=""
|
|
||||||
DNStype=""
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
_debug "DNSname: $DNSname DNStype: $DNStype DNSdomainid: $DNSdomainid DNSdataid: $DNSdataid"
|
|
||||||
_debug "DNSvalue: $DNSvalue"
|
|
||||||
|
|
||||||
if [ -z "$DNSdomainid" ]; then
|
if [ -z "$DNSdomainid" ]; then
|
||||||
# If domain ID is empty then something went wrong (top level
|
# If domain ID is empty then something went wrong (top level
|
||||||
# domain not found at FreeDNS).
|
# domain not found at FreeDNS).
|
||||||
if [ "$attempts" = "0" ]; then
|
if [ "$attempts" = "0" ]; then
|
||||||
# exhausted maximum retry attempts
|
# exhausted maximum retry attempts
|
||||||
_debug "$htmlpage"
|
|
||||||
_debug "$subdomain_csv"
|
|
||||||
_err "Domain $top_domain not found at FreeDNS"
|
_err "Domain $top_domain not found at FreeDNS"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
@ -145,33 +116,10 @@ dns_freedns_add() {
|
|||||||
_info "Retry loading subdomain page ($attempts attempts remaining)"
|
_info "Retry loading subdomain page ($attempts attempts remaining)"
|
||||||
done
|
done
|
||||||
|
|
||||||
if [ -z "$DNSdataid" ]; then
|
# Add in new TXT record with the value provided
|
||||||
# If data ID is empty then specific subdomain does not exist yet, need
|
_debug "Adding TXT record for $fulldomain, $txtvalue"
|
||||||
# to create it this should always be the case as the acme client
|
_freedns_add_txt_record "$FREEDNS_COOKIE" "$DNSdomainid" "$sub_domain" "$txtvalue"
|
||||||
# deletes the entry after domain is validated.
|
return $?
|
||||||
_freedns_add_txt_record "$FREEDNS_COOKIE" "$DNSdomainid" "$sub_domain" "$txtvalue"
|
|
||||||
return $?
|
|
||||||
else
|
|
||||||
if [ "$txtvalue" = "$DNSvalue" ]; then
|
|
||||||
# if value in TXT record matches value requested then DNS record
|
|
||||||
# does not need to be updated. But...
|
|
||||||
# Testing value match fails. Website is truncating the value field.
|
|
||||||
# So for now we will always go down the else path. Though in theory
|
|
||||||
# should never come here anyway as the acme client deletes
|
|
||||||
# the TXT record on successful validation, so we should not even
|
|
||||||
# have found a TXT record !!
|
|
||||||
_info "No update necessary for $fulldomain at FreeDNS"
|
|
||||||
return 0
|
|
||||||
else
|
|
||||||
# Delete the old TXT record (with the wrong value)
|
|
||||||
if _freedns_delete_txt_record "$FREEDNS_COOKIE" "$DNSdataid"; then
|
|
||||||
# And add in new TXT record with the value provided
|
|
||||||
_freedns_add_txt_record "$FREEDNS_COOKIE" "$DNSdomainid" "$sub_domain" "$txtvalue"
|
|
||||||
fi
|
|
||||||
return $?
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
return 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#Usage: fulldomain txtvalue
|
#Usage: fulldomain txtvalue
|
||||||
@ -205,7 +153,7 @@ dns_freedns_rm() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
subdomain_csv="$(echo "$htmlpage" | tr -d "\n\r" | _egrep_o '<form .*</form>' | sed 's/<tr>/@<tr>/g' | tr '@' '\n' | grep edit.php | grep "$fulldomain")"
|
subdomain_csv="$(echo "$htmlpage" | tr -d "\n\r" | _egrep_o '<form .*</form>' | sed 's/<tr>/@<tr>/g' | tr '@' '\n' | grep edit.php | grep "$fulldomain")"
|
||||||
_debug2 subdomain_csv "$subdomain_csv"
|
_debug3 "subdomain_csv: $subdomain_csv"
|
||||||
|
|
||||||
# The above beauty ends with striping out rows that do not have an
|
# The above beauty ends with striping out rows that do not have an
|
||||||
# href to edit.php and do not have the domain name we are looking for.
|
# href to edit.php and do not have the domain name we are looking for.
|
||||||
@ -216,35 +164,51 @@ dns_freedns_rm() {
|
|||||||
lines="$(echo "$subdomain_csv" | wc -l)"
|
lines="$(echo "$subdomain_csv" | wc -l)"
|
||||||
i=0
|
i=0
|
||||||
found=0
|
found=0
|
||||||
|
DNSdataid=""
|
||||||
while [ "$i" -lt "$lines" ]; do
|
while [ "$i" -lt "$lines" ]; do
|
||||||
i="$(_math "$i" + 1)"
|
i="$(_math "$i" + 1)"
|
||||||
line="$(echo "$subdomain_csv" | sed -n "${i}p")"
|
line="$(echo "$subdomain_csv" | sed -n "${i}p")"
|
||||||
_debug2 line "$line"
|
_debug3 "line: $line"
|
||||||
DNSname="$(echo "$line" | _egrep_o 'edit.php.*</a>' | cut -d '>' -f 2 | cut -d '<' -f 1)"
|
DNSname="$(echo "$line" | _egrep_o 'edit.php.*</a>' | cut -d '>' -f 2 | cut -d '<' -f 1)"
|
||||||
_debug2 DNSname "$DNSname"
|
_debug2 "DNSname: $DNSname"
|
||||||
DNStype="$(echo "$line" | sed 's/<td/@<td/g' | tr '@' '\n' | sed -n '4p' | cut -d '>' -f 2 | cut -d '<' -f 1)"
|
if [ "$DNSname" = "$fulldomain" ]; then
|
||||||
_debug2 DNStype "$DNStype"
|
DNStype="$(echo "$line" | sed 's/<td/@<td/g' | tr '@' '\n' | sed -n '4p' | cut -d '>' -f 2 | cut -d '<' -f 1)"
|
||||||
if [ "$DNSname" = "$fulldomain" ] && [ "$DNStype" = "TXT" ]; then
|
_debug2 "DNStype: $DNStype"
|
||||||
DNSdataid="$(echo "$line" | _egrep_o 'data_id=.*' | cut -d = -f 2 | cut -d '>' -f 1)"
|
if [ "$DNStype" = "TXT" ]; then
|
||||||
_debug2 DNSdataid "$DNSdataid"
|
DNSdataid="$(echo "$line" | _egrep_o 'data_id=.*' | cut -d = -f 2 | cut -d '>' -f 1)"
|
||||||
DNSvalue="$(echo "$line" | sed 's/<td/@<td/g' | tr '@' '\n' | sed -n '5p' | cut -d '>' -f 2 | cut -d '<' -f 1)"
|
_debug2 "DNSdataid: $DNSdataid"
|
||||||
_debug2 DNSvalue "$DNSvalue"
|
DNSvalue="$(echo "$line" | sed 's/<td/@<td/g' | tr '@' '\n' | sed -n '5p' | cut -d '>' -f 2 | cut -d '<' -f 1)"
|
||||||
# if [ "$DNSvalue" = "$txtvalue" ]; then
|
if _startswith "$DNSvalue" """; then
|
||||||
# Testing value match fails. Website is truncating the value
|
# remove the quotation from the start
|
||||||
# field. So for now we will assume that there is only one TXT
|
DNSvalue="$(echo "$DNSvalue" | cut -c 7-)"
|
||||||
# field for the sub domain and just delete it. Currently this
|
fi
|
||||||
# is a safe assumption.
|
if _endswith "$DNSvalue" "..."; then
|
||||||
_freedns_delete_txt_record "$FREEDNS_COOKIE" "$DNSdataid"
|
# value was truncated, remove the dot dot dot from the end
|
||||||
return $?
|
DNSvalue="$(echo "$DNSvalue" | sed 's/...$//')"
|
||||||
# fi
|
elif _endswith "$DNSvalue" """; then
|
||||||
|
# else remove the closing quotation from the end
|
||||||
|
DNSvalue="$(echo "$DNSvalue" | sed 's/......$//')"
|
||||||
|
fi
|
||||||
|
_debug2 "DNSvalue: $DNSvalue"
|
||||||
|
|
||||||
|
if [ -n "$DNSdataid" ] && _startswith "$txtvalue" "$DNSvalue"; then
|
||||||
|
# Found a match. But note... Website is truncating the
|
||||||
|
# value field so we are only testing that part that is not
|
||||||
|
# truncated. This should be accurate enough.
|
||||||
|
_debug "Deleting TXT record for $fulldomain, $txtvalue"
|
||||||
|
_freedns_delete_txt_record "$FREEDNS_COOKIE" "$DNSdataid"
|
||||||
|
return $?
|
||||||
|
fi
|
||||||
|
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
done
|
done
|
||||||
|
|
||||||
# If we get this far we did not find a match (after two attempts)
|
# If we get this far we did not find a match (after two attempts)
|
||||||
# Not necessarily an error, but log anyway.
|
# Not necessarily an error, but log anyway.
|
||||||
_debug2 "$subdomain_csv"
|
_debug3 "$subdomain_csv"
|
||||||
_info "Cannot delete TXT record for $fulldomain/$txtvalue. Does not exist at FreeDNS"
|
_info "Cannot delete TXT record for $fulldomain, $txtvalue. Does not exist at FreeDNS"
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -272,7 +236,7 @@ _freedns_login() {
|
|||||||
|
|
||||||
# if cookies is not empty then logon successful
|
# if cookies is not empty then logon successful
|
||||||
if [ -z "$cookies" ]; then
|
if [ -z "$cookies" ]; then
|
||||||
_debug "$htmlpage"
|
_debug3 "htmlpage: $htmlpage"
|
||||||
_err "FreeDNS login failed for user $username. Check $HTTP_HEADER file"
|
_err "FreeDNS login failed for user $username. Check $HTTP_HEADER file"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
@ -301,7 +265,7 @@ _freedns_retrieve_subdomain_page() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
_debug2 "$htmlpage"
|
_debug3 "htmlpage: $htmlpage"
|
||||||
|
|
||||||
printf "%s" "$htmlpage"
|
printf "%s" "$htmlpage"
|
||||||
return 0
|
return 0
|
||||||
@ -315,7 +279,7 @@ _freedns_add_txt_record() {
|
|||||||
domain_id="$2"
|
domain_id="$2"
|
||||||
subdomain="$3"
|
subdomain="$3"
|
||||||
value="$(printf '%s' "$4" | _url_encode)"
|
value="$(printf '%s' "$4" | _url_encode)"
|
||||||
url="http://freedns.afraid.org/subdomain/save.php?step=2"
|
url="https://freedns.afraid.org/subdomain/save.php?step=2"
|
||||||
|
|
||||||
htmlpage="$(_post "type=TXT&domain_id=$domain_id&subdomain=$subdomain&address=%22$value%22&send=Save%21" "$url")"
|
htmlpage="$(_post "type=TXT&domain_id=$domain_id&subdomain=$subdomain&address=%22$value%22&send=Save%21" "$url")"
|
||||||
|
|
||||||
@ -323,17 +287,17 @@ _freedns_add_txt_record() {
|
|||||||
_err "FreeDNS failed to add TXT record for $subdomain bad RC from _post"
|
_err "FreeDNS failed to add TXT record for $subdomain bad RC from _post"
|
||||||
return 1
|
return 1
|
||||||
elif ! grep "200 OK" "$HTTP_HEADER" >/dev/null; then
|
elif ! grep "200 OK" "$HTTP_HEADER" >/dev/null; then
|
||||||
_debug "$htmlpage"
|
_debug3 "htmlpage: $htmlpage"
|
||||||
_err "FreeDNS failed to add TXT record for $subdomain. Check $HTTP_HEADER file"
|
_err "FreeDNS failed to add TXT record for $subdomain. Check $HTTP_HEADER file"
|
||||||
return 1
|
return 1
|
||||||
elif _contains "$htmlpage" "security code was incorrect"; then
|
elif _contains "$htmlpage" "security code was incorrect"; then
|
||||||
_debug "$htmlpage"
|
_debug3 "htmlpage: $htmlpage"
|
||||||
_err "FreeDNS failed to add TXT record for $subdomain as FreeDNS requested security code"
|
_err "FreeDNS failed to add TXT record for $subdomain as FreeDNS requested security code"
|
||||||
_err "Note that you cannot use automatic DNS validation for FreeDNS public domains"
|
_err "Note that you cannot use automatic DNS validation for FreeDNS public domains"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
_debug2 "$htmlpage"
|
_debug3 "htmlpage: $htmlpage"
|
||||||
_info "Added acme challenge TXT record for $fulldomain at FreeDNS"
|
_info "Added acme challenge TXT record for $fulldomain at FreeDNS"
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
@ -352,7 +316,7 @@ _freedns_delete_txt_record() {
|
|||||||
_err "FreeDNS failed to delete TXT record for $data_id bad RC from _get"
|
_err "FreeDNS failed to delete TXT record for $data_id bad RC from _get"
|
||||||
return 1
|
return 1
|
||||||
elif ! _contains "$htmlheader" "200 OK"; then
|
elif ! _contains "$htmlheader" "200 OK"; then
|
||||||
_debug "$htmlheader"
|
_debug2 "htmlheader: $htmlheader"
|
||||||
_err "FreeDNS failed to delete TXT record $data_id"
|
_err "FreeDNS failed to delete TXT record $data_id"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
@ -59,19 +59,13 @@ dns_gd_add() {
|
|||||||
|
|
||||||
_info "Adding record"
|
_info "Adding record"
|
||||||
if _gd_rest PUT "domains/$_domain/records/TXT/$_sub_domain" "[$_add_data]"; then
|
if _gd_rest PUT "domains/$_domain/records/TXT/$_sub_domain" "[$_add_data]"; then
|
||||||
if [ "$response" = "{}" ]; then
|
_info "Added, sleeping 10 seconds"
|
||||||
_info "Added, sleeping 10 seconds"
|
_sleep 10
|
||||||
_sleep 10
|
#todo: check if the record takes effect
|
||||||
#todo: check if the record takes effect
|
return 0
|
||||||
return 0
|
|
||||||
else
|
|
||||||
_err "Add txt record error."
|
|
||||||
_err "$response"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
_err "Add txt record error."
|
_err "Add txt record error."
|
||||||
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
#fulldomain
|
#fulldomain
|
||||||
@ -174,5 +168,9 @@ _gd_rest() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
_debug2 response "$response"
|
_debug2 response "$response"
|
||||||
|
if _contains "$response" "UNABLE_TO_AUTHENTICATE"; then
|
||||||
|
_err "It seems that your api key or secret is not correct."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
@ -33,8 +33,9 @@ dns_he_add() {
|
|||||||
# 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."
|
||||||
|
username_encoded="$(printf "%s" "${HE_Username}" | _url_encode)"
|
||||||
body="email=${HE_Username}&pass=${HE_Password}"
|
password_encoded="$(printf "%s" "${HE_Password}" | _url_encode)"
|
||||||
|
body="email=${username_encoded}&pass=${password_encoded}"
|
||||||
body="$body&account="
|
body="$body&account="
|
||||||
body="$body&menu=edit_zone"
|
body="$body&menu=edit_zone"
|
||||||
body="$body&Type=TXT"
|
body="$body&Type=TXT"
|
||||||
@ -71,7 +72,9 @@ dns_he_rm() {
|
|||||||
_debug "Zone id \"$_zone_id\" will be used."
|
_debug "Zone id \"$_zone_id\" will be used."
|
||||||
|
|
||||||
# Find the record id to clean
|
# Find the record id to clean
|
||||||
body="email=${HE_Username}&pass=${HE_Password}"
|
username_encoded="$(printf "%s" "${HE_Username}" | _url_encode)"
|
||||||
|
password_encoded="$(printf "%s" "${HE_Password}" | _url_encode)"
|
||||||
|
body="email=${username_encoded}&pass=${password_encoded}"
|
||||||
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="
|
||||||
@ -112,9 +115,15 @@ dns_he_rm() {
|
|||||||
|
|
||||||
_find_zone() {
|
_find_zone() {
|
||||||
_domain="$1"
|
_domain="$1"
|
||||||
body="email=${HE_Username}&pass=${HE_Password}"
|
username_encoded="$(printf "%s" "${HE_Username}" | _url_encode)"
|
||||||
|
password_encoded="$(printf "%s" "${HE_Password}" | _url_encode)"
|
||||||
|
body="email=${username_encoded}&pass=${password_encoded}"
|
||||||
response="$(_post "$body" "https://dns.he.net/")"
|
response="$(_post "$body" "https://dns.he.net/")"
|
||||||
_debug2 response "$response"
|
_debug2 response "$response"
|
||||||
|
if _contains "$response" '>Incorrect<'; then
|
||||||
|
_err "Unable to login to dns.he.net please check username and password"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
_table="$(echo "$response" | tr -d "#" | sed "s/<table/#<table/g" | tr -d "\n" | tr "#" "\n" | grep 'id="domains_table"')"
|
_table="$(echo "$response" | tr -d "#" | sed "s/<table/#<table/g" | tr -d "\n" | tr "#" "\n" | grep 'id="domains_table"')"
|
||||||
_debug2 _table "$_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" | grep 'hosted_dns_zoneid')"
|
_matches="$(echo "$_table" | sed "s/<tr/#<tr/g" | tr "#" "\n" | grep 'alt="edit"' | tr -d " " | sed "s/<td/#<td/g" | tr "#" "\n" | grep 'hosted_dns_zoneid')"
|
||||||
@ -143,7 +152,7 @@ _find_zone() {
|
|||||||
|
|
||||||
_debug "Looking for zone \"${_attempted_zone}\""
|
_debug "Looking for zone \"${_attempted_zone}\""
|
||||||
|
|
||||||
line_num="$(echo "$_zone_names" | grep -n "$_attempted_zone" | cut -d : -f 1)"
|
line_num="$(echo "$_zone_names" | grep -n "^$_attempted_zone" | cut -d : -f 1)"
|
||||||
|
|
||||||
if [ "$line_num" ]; then
|
if [ "$line_num" ]; then
|
||||||
_zone_id=$(echo "$_zone_ids" | sed -n "${line_num}p")
|
_zone_id=$(echo "$_zone_ids" | sed -n "${line_num}p")
|
||||||
|
@ -4,6 +4,10 @@
|
|||||||
#INWX_User="username"
|
#INWX_User="username"
|
||||||
#
|
#
|
||||||
#INWX_Password="password"
|
#INWX_Password="password"
|
||||||
|
#
|
||||||
|
# Dependencies:
|
||||||
|
# -------------
|
||||||
|
# - oathtool (When using 2 Factor Authentication)
|
||||||
|
|
||||||
INWX_Api="https://api.domrobot.com/xmlrpc/"
|
INWX_Api="https://api.domrobot.com/xmlrpc/"
|
||||||
|
|
||||||
@ -16,6 +20,7 @@ dns_inwx_add() {
|
|||||||
|
|
||||||
INWX_User="${INWX_User:-$(_readaccountconf_mutable INWX_User)}"
|
INWX_User="${INWX_User:-$(_readaccountconf_mutable INWX_User)}"
|
||||||
INWX_Password="${INWX_Password:-$(_readaccountconf_mutable INWX_Password)}"
|
INWX_Password="${INWX_Password:-$(_readaccountconf_mutable INWX_Password)}"
|
||||||
|
INWX_Shared_Secret="${INWX_Shared_Secret:-$(_readaccountconf_mutable INWX_Shared_Secret)}"
|
||||||
if [ -z "$INWX_User" ] || [ -z "$INWX_Password" ]; then
|
if [ -z "$INWX_User" ] || [ -z "$INWX_Password" ]; then
|
||||||
INWX_User=""
|
INWX_User=""
|
||||||
INWX_Password=""
|
INWX_Password=""
|
||||||
@ -27,6 +32,7 @@ dns_inwx_add() {
|
|||||||
#save the api key and email to the account conf file.
|
#save the api key and email to the account conf file.
|
||||||
_saveaccountconf_mutable INWX_User "$INWX_User"
|
_saveaccountconf_mutable INWX_User "$INWX_User"
|
||||||
_saveaccountconf_mutable INWX_Password "$INWX_Password"
|
_saveaccountconf_mutable INWX_Password "$INWX_Password"
|
||||||
|
_saveaccountconf_mutable INWX_Shared_Secret "$INWX_Shared_Secret"
|
||||||
|
|
||||||
_debug "First detect the root zone"
|
_debug "First detect the root zone"
|
||||||
if ! _get_root "$fulldomain"; then
|
if ! _get_root "$fulldomain"; then
|
||||||
@ -148,8 +154,46 @@ _inwx_login() {
|
|||||||
</methodCall>' $INWX_User $INWX_Password)
|
</methodCall>' $INWX_User $INWX_Password)
|
||||||
|
|
||||||
response="$(_post "$xml_content" "$INWX_Api" "" "POST")"
|
response="$(_post "$xml_content" "$INWX_Api" "" "POST")"
|
||||||
|
_H1=$(printf "Cookie: %s" "$(grep "domrobot=" "$HTTP_HEADER" | grep "^Set-Cookie:" | _tail_n 1 | _egrep_o 'domrobot=[^;]*;' | tr -d ';')")
|
||||||
|
export _H1
|
||||||
|
|
||||||
printf "Cookie: %s" "$(grep "domrobot=" "$HTTP_HEADER" | grep "^Set-Cookie:" | _tail_n 1 | _egrep_o 'domrobot=[^;]*;' | tr -d ';')"
|
#https://github.com/inwx/php-client/blob/master/INWX/Domrobot.php#L71
|
||||||
|
if _contains "$response" "tfa"; then
|
||||||
|
if [ -z "$INWX_Shared_Secret" ]; then
|
||||||
|
_err "Mobile TAN detected."
|
||||||
|
_err "Please define a shared secret."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! _exists oathtool; then
|
||||||
|
_err "Please install oathtool to use 2 Factor Authentication."
|
||||||
|
_err ""
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
tan="$(oathtool --base32 --totp "${INWX_Shared_Secret}" 2>/dev/null)"
|
||||||
|
|
||||||
|
xml_content=$(printf '<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<methodCall>
|
||||||
|
<methodName>account.unlock</methodName>
|
||||||
|
<params>
|
||||||
|
<param>
|
||||||
|
<value>
|
||||||
|
<struct>
|
||||||
|
<member>
|
||||||
|
<name>tan</name>
|
||||||
|
<value>
|
||||||
|
<string>%s</string>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
</struct>
|
||||||
|
</value>
|
||||||
|
</param>
|
||||||
|
</params>
|
||||||
|
</methodCall>' "$tan")
|
||||||
|
|
||||||
|
response="$(_post "$xml_content" "$INWX_Api" "" "POST")"
|
||||||
|
fi
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,8 +205,8 @@ _get_root() {
|
|||||||
i=2
|
i=2
|
||||||
p=1
|
p=1
|
||||||
|
|
||||||
_H1=$(_inwx_login)
|
_inwx_login
|
||||||
export _H1
|
|
||||||
xml_content='<?xml version="1.0" encoding="UTF-8"?>
|
xml_content='<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<methodCall>
|
<methodCall>
|
||||||
<methodName>nameserver.list</methodName>
|
<methodName>nameserver.list</methodName>
|
||||||
|
@ -128,7 +128,7 @@ _ISPC_addTxt() {
|
|||||||
curSerial="$(date +%s)"
|
curSerial="$(date +%s)"
|
||||||
curStamp="$(date +'%F %T')"
|
curStamp="$(date +'%F %T')"
|
||||||
params="\"server_id\":\"${server_id}\",\"zone\":\"${zone}\",\"name\":\"${fulldomain}.\",\"type\":\"txt\",\"data\":\"${txtvalue}\",\"aux\":\"0\",\"ttl\":\"3600\",\"active\":\"y\",\"stamp\":\"${curStamp}\",\"serial\":\"${curSerial}\""
|
params="\"server_id\":\"${server_id}\",\"zone\":\"${zone}\",\"name\":\"${fulldomain}.\",\"type\":\"txt\",\"data\":\"${txtvalue}\",\"aux\":\"0\",\"ttl\":\"3600\",\"active\":\"y\",\"stamp\":\"${curStamp}\",\"serial\":\"${curSerial}\""
|
||||||
curData="{\"session_id\":\"${sessionID}\",\"client_id\":\"${client_id}\",\"params\":{${params}}}"
|
curData="{\"session_id\":\"${sessionID}\",\"client_id\":\"${client_id}\",\"params\":{${params}},\"update_serial\":true}"
|
||||||
curResult="$(_post "${curData}" "${ISPC_Api}?dns_txt_add")"
|
curResult="$(_post "${curData}" "${ISPC_Api}?dns_txt_add")"
|
||||||
_debug "Calling _ISPC_addTxt: '${curData}' '${ISPC_Api}?dns_txt_add'"
|
_debug "Calling _ISPC_addTxt: '${curData}' '${ISPC_Api}?dns_txt_add'"
|
||||||
_debug "Result of _ISPC_addTxt: '$curResult'"
|
_debug "Result of _ISPC_addTxt: '$curResult'"
|
||||||
@ -160,7 +160,7 @@ _ISPC_rmTxt() {
|
|||||||
*)
|
*)
|
||||||
unset IFS
|
unset IFS
|
||||||
_info "Retrieved Record ID."
|
_info "Retrieved Record ID."
|
||||||
curData="{\"session_id\":\"${sessionID}\",\"primary_id\":\"${record_id}\"}"
|
curData="{\"session_id\":\"${sessionID}\",\"primary_id\":\"${record_id}\",\"update_serial\":true}"
|
||||||
curResult="$(_post "${curData}" "${ISPC_Api}?dns_txt_delete")"
|
curResult="$(_post "${curData}" "${ISPC_Api}?dns_txt_delete")"
|
||||||
_debug "Calling _ISPC_rmTxt: '${curData}' '${ISPC_Api}?dns_txt_delete'"
|
_debug "Calling _ISPC_rmTxt: '${curData}' '${ISPC_Api}?dns_txt_delete'"
|
||||||
_debug "Result of _ISPC_rmTxt: '$curResult'"
|
_debug "Result of _ISPC_rmTxt: '$curResult'"
|
||||||
|
107
dnsapi/dns_kinghost.sh
Normal file
107
dnsapi/dns_kinghost.sh
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
############################################################
|
||||||
|
# KingHost API support #
|
||||||
|
# http://api.kinghost.net/doc/ #
|
||||||
|
# #
|
||||||
|
# Author: Felipe Keller Braz <felipebraz@kinghost.com.br> #
|
||||||
|
# Report Bugs here: https://github.com/kinghost/acme.sh #
|
||||||
|
# #
|
||||||
|
# Values to export: #
|
||||||
|
# export KINGHOST_Username="email@provider.com" #
|
||||||
|
# export KINGHOST_Password="xxxxxxxxxx" #
|
||||||
|
############################################################
|
||||||
|
|
||||||
|
KING_Api="https://api.kinghost.net/acme"
|
||||||
|
|
||||||
|
# Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||||
|
# Used to add txt record
|
||||||
|
dns_kinghost_add() {
|
||||||
|
fulldomain=$1
|
||||||
|
txtvalue=$2
|
||||||
|
|
||||||
|
KINGHOST_Username="${KINGHOST_Username:-$(_readaccountconf_mutable KINGHOST_Username)}"
|
||||||
|
KINGHOST_Password="${KINGHOST_Password:-$(_readaccountconf_mutable KINGHOST_Password)}"
|
||||||
|
if [ -z "$KINGHOST_Username" ] || [ -z "$KINGHOST_Password" ]; then
|
||||||
|
KINGHOST_Username=""
|
||||||
|
KINGHOST_Password=""
|
||||||
|
_err "You don't specify KingHost api password and email yet."
|
||||||
|
_err "Please create you key and try again."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
#save the credentials to the account conf file.
|
||||||
|
_saveaccountconf_mutable KINGHOST_Username "$KINGHOST_Username"
|
||||||
|
_saveaccountconf_mutable KINGHOST_Password "$KINGHOST_Password"
|
||||||
|
|
||||||
|
_debug "Getting txt records"
|
||||||
|
_kinghost_rest GET "dns" "name=$fulldomain&content=$txtvalue"
|
||||||
|
|
||||||
|
#This API call returns "status":"ok" if dns record does not exists
|
||||||
|
#We are creating a new txt record here, so we expect the "ok" status
|
||||||
|
if ! echo "$response" | grep '"status":"ok"' >/dev/null; then
|
||||||
|
_err "Error"
|
||||||
|
_err "$response"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_kinghost_rest POST "dns" "name=$fulldomain&content=$txtvalue"
|
||||||
|
if ! echo "$response" | grep '"status":"ok"' >/dev/null; then
|
||||||
|
_err "Error"
|
||||||
|
_err "$response"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Usage: fulldomain txtvalue
|
||||||
|
# Used to remove the txt record after validation
|
||||||
|
dns_kinghost_rm() {
|
||||||
|
fulldomain=$1
|
||||||
|
txtvalue=$2
|
||||||
|
|
||||||
|
KINGHOST_Password="${KINGHOST_Password:-$(_readaccountconf_mutable KINGHOST_Password)}"
|
||||||
|
KINGHOST_Username="${KINGHOST_Username:-$(_readaccountconf_mutable KINGHOST_Username)}"
|
||||||
|
if [ -z "$KINGHOST_Password" ] || [ -z "$KINGHOST_Username" ]; then
|
||||||
|
KINGHOST_Password=""
|
||||||
|
KINGHOST_Username=""
|
||||||
|
_err "You don't specify KingHost api key and email yet."
|
||||||
|
_err "Please create you key and try again."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_kinghost_rest DELETE "dns" "name=$fulldomain&content=$txtvalue"
|
||||||
|
if ! echo "$response" | grep '"status":"ok"' >/dev/null; then
|
||||||
|
_err "Error"
|
||||||
|
_err "$response"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
#################### Private functions below ##################################
|
||||||
|
_kinghost_rest() {
|
||||||
|
method=$1
|
||||||
|
uri="$2"
|
||||||
|
data="$3"
|
||||||
|
_debug "$uri"
|
||||||
|
|
||||||
|
export _H1="X-Auth-Email: $KINGHOST_Username"
|
||||||
|
export _H2="X-Auth-Key: $KINGHOST_Password"
|
||||||
|
|
||||||
|
if [ "$method" != "GET" ]; then
|
||||||
|
_debug data "$data"
|
||||||
|
response="$(_post "$data" "$KING_Api/$uri.json" "" "$method")"
|
||||||
|
else
|
||||||
|
response="$(_get "$KING_Api/$uri.json?$data")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$?" != "0" ]; then
|
||||||
|
_err "error $uri"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_debug2 response "$response"
|
||||||
|
return 0
|
||||||
|
}
|
227
dnsapi/dns_loopia.sh
Normal file
227
dnsapi/dns_loopia.sh
Normal file
@ -0,0 +1,227 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
#
|
||||||
|
#LOOPIA_User="username"
|
||||||
|
#
|
||||||
|
#LOOPIA_Password="password"
|
||||||
|
|
||||||
|
LOOPIA_Api="https://api.loopia.se/RPCSERV"
|
||||||
|
|
||||||
|
######## Public functions #####################
|
||||||
|
|
||||||
|
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||||
|
dns_loopia_add() {
|
||||||
|
fulldomain=$1
|
||||||
|
txtvalue=$2
|
||||||
|
|
||||||
|
LOOPIA_User="${LOOPIA_User:-$(_readaccountconf_mutable LOOPIA_User)}"
|
||||||
|
LOOPIA_Password="${LOOPIA_Password:-$(_readaccountconf_mutable LOOPIA_Password)}"
|
||||||
|
if [ -z "$LOOPIA_User" ] || [ -z "$LOOPIA_Password" ]; then
|
||||||
|
LOOPIA_User=""
|
||||||
|
LOOPIA_Password=""
|
||||||
|
_err "You don't specify loopia user and password yet."
|
||||||
|
_err "Please create you key and try again."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
#save the api key and email to the account conf file.
|
||||||
|
_saveaccountconf_mutable LOOPIA_User "$LOOPIA_User"
|
||||||
|
_saveaccountconf_mutable LOOPIA_Password "$LOOPIA_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"
|
||||||
|
|
||||||
|
_info "Adding record"
|
||||||
|
|
||||||
|
_loopia_add_record "$_domain" "$_sub_domain"
|
||||||
|
_loopia_update_record "$_domain" "$_sub_domain" "$txtvalue"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
dns_loopia_rm() {
|
||||||
|
fulldomain=$1
|
||||||
|
txtvalue=$2
|
||||||
|
|
||||||
|
LOOPIA_User="${LOOPIA_User:-$(_readaccountconf_mutable LOOPIA_User)}"
|
||||||
|
LOOPIA_Password="${LOOPIA_Password:-$(_readaccountconf_mutable LOOPIA_Password)}"
|
||||||
|
if [ -z "$LOOPIA_User" ] || [ -z "$LOOPIA_Password" ]; then
|
||||||
|
LOOPIA_User=""
|
||||||
|
LOOPIA_Password=""
|
||||||
|
_err "You don't specify LOOPIA user and password yet."
|
||||||
|
_err "Please create you key and try again."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
#save the api key and email to the account conf file.
|
||||||
|
_saveaccountconf_mutable LOOPIA_User "$LOOPIA_User"
|
||||||
|
_saveaccountconf_mutable LOOPIA_Password "$LOOPIA_Password"
|
||||||
|
|
||||||
|
_debug "First detect the root zone"
|
||||||
|
if ! _get_root "$fulldomain"; then
|
||||||
|
_err "invalid domain"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
xml_content=$(printf '<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<methodCall>
|
||||||
|
<methodName>removeSubdomain</methodName>
|
||||||
|
<params>
|
||||||
|
<param>
|
||||||
|
<value><string>%s</string></value>
|
||||||
|
</param>
|
||||||
|
<param>
|
||||||
|
<value><string>%s</string></value>
|
||||||
|
</param>
|
||||||
|
<param>
|
||||||
|
<value><string>%s</string></value>
|
||||||
|
</param>
|
||||||
|
<param>
|
||||||
|
<value><string>%s</string></value>
|
||||||
|
</param>
|
||||||
|
</params>
|
||||||
|
</methodCall>' $LOOPIA_User $LOOPIA_Password "$_domain" "$_sub_domain")
|
||||||
|
|
||||||
|
response="$(_post "$xml_content" "$LOOPIA_Api" "" "POST")"
|
||||||
|
|
||||||
|
if ! _contains "$response" "OK"; then
|
||||||
|
_err "Error could not get txt records"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
#################### Private functions below ##################################
|
||||||
|
|
||||||
|
_get_root() {
|
||||||
|
domain=$1
|
||||||
|
_debug "get root"
|
||||||
|
|
||||||
|
domain=$1
|
||||||
|
i=2
|
||||||
|
p=1
|
||||||
|
|
||||||
|
xml_content=$(printf '<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<methodCall>
|
||||||
|
<methodName>getDomains</methodName>
|
||||||
|
<params>
|
||||||
|
<param>
|
||||||
|
<value><string>%s</string></value>
|
||||||
|
</param>
|
||||||
|
<param>
|
||||||
|
<value><string>%s</string></value>
|
||||||
|
</param>
|
||||||
|
</params>
|
||||||
|
</methodCall>' $LOOPIA_User $LOOPIA_Password)
|
||||||
|
|
||||||
|
response="$(_post "$xml_content" "$LOOPIA_Api" "" "POST")"
|
||||||
|
while true; do
|
||||||
|
h=$(echo "$domain" | cut -d . -f $i-100)
|
||||||
|
if [ -z "$h" ]; then
|
||||||
|
#not valid
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if _contains "$response" "$h"; then
|
||||||
|
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
|
||||||
|
_domain="$h"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
p=$i
|
||||||
|
i=$(_math "$i" + 1)
|
||||||
|
done
|
||||||
|
return 1
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
_loopia_update_record() {
|
||||||
|
domain=$1
|
||||||
|
sub_domain=$2
|
||||||
|
txtval=$3
|
||||||
|
|
||||||
|
xml_content=$(printf '<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<methodCall>
|
||||||
|
<methodName>updateZoneRecord</methodName>
|
||||||
|
<params>
|
||||||
|
<param>
|
||||||
|
<value><string>%s</string></value>
|
||||||
|
</param>
|
||||||
|
<param>
|
||||||
|
<value><string>%s</string></value>
|
||||||
|
</param>
|
||||||
|
<param>
|
||||||
|
<value><string>%s</string></value>
|
||||||
|
</param>
|
||||||
|
<param>
|
||||||
|
<value><string>%s</string></value>
|
||||||
|
</param>
|
||||||
|
<param>
|
||||||
|
<struct>
|
||||||
|
<member>
|
||||||
|
<name>type</name>
|
||||||
|
<value><string>TXT</string></value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>priority</name>
|
||||||
|
<value><int>0</int></value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>ttl</name>
|
||||||
|
<value><int>60</int></value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>rdata</name>
|
||||||
|
<value><string>%s</string></value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>record_id</name>
|
||||||
|
<value><int>0</int></value>
|
||||||
|
</member>
|
||||||
|
</struct>
|
||||||
|
</param>
|
||||||
|
</params>
|
||||||
|
</methodCall>' $LOOPIA_User $LOOPIA_Password "$domain" "$sub_domain" "$txtval")
|
||||||
|
|
||||||
|
response="$(_post "$xml_content" "$LOOPIA_Api" "" "POST")"
|
||||||
|
|
||||||
|
if ! _contains "$response" "OK"; then
|
||||||
|
_err "Error"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
_loopia_add_record() {
|
||||||
|
domain=$1
|
||||||
|
sub_domain=$2
|
||||||
|
|
||||||
|
xml_content=$(printf '<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<methodCall>
|
||||||
|
<methodName>addSubdomain</methodName>
|
||||||
|
<params>
|
||||||
|
<param>
|
||||||
|
<value><string>%s</string></value>
|
||||||
|
</param>
|
||||||
|
<param>
|
||||||
|
<value><string>%s</string></value>
|
||||||
|
</param>
|
||||||
|
<param>
|
||||||
|
<value><string>%s</string></value>
|
||||||
|
</param>
|
||||||
|
<param>
|
||||||
|
<value><string>%s</string></value>
|
||||||
|
</param>
|
||||||
|
</params>
|
||||||
|
</methodCall>' $LOOPIA_User $LOOPIA_Password "$domain" "$sub_domain")
|
||||||
|
|
||||||
|
response="$(_post "$xml_content" "$LOOPIA_Api" "" "POST")"
|
||||||
|
|
||||||
|
if ! _contains "$response" "OK"; then
|
||||||
|
_err "Error"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
}
|
@ -1,11 +1,12 @@
|
|||||||
#!/usr/bin/env sh
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
#Author: RaidneII
|
#Author: RaidenII
|
||||||
#Created 06/28/2017
|
#Created 06/28/2017
|
||||||
|
#Updated 03/01/2018, rewrote to support name.com API v4
|
||||||
#Utilize name.com API to finish dns-01 verifications.
|
#Utilize name.com API to finish dns-01 verifications.
|
||||||
######## Public functions #####################
|
######## Public functions #####################
|
||||||
|
|
||||||
Namecom_API="https://api.name.com/api"
|
Namecom_API="https://api.name.com/v4"
|
||||||
|
|
||||||
#Usage: dns_namecom_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
#Usage: dns_namecom_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||||
dns_namecom_add() {
|
dns_namecom_add() {
|
||||||
@ -39,21 +40,18 @@ dns_namecom_add() {
|
|||||||
# Find domain in domain list.
|
# Find domain in domain list.
|
||||||
if ! _namecom_get_root "$fulldomain"; then
|
if ! _namecom_get_root "$fulldomain"; then
|
||||||
_err "Unable to find domain specified."
|
_err "Unable to find domain specified."
|
||||||
_namecom_logout
|
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Add TXT record.
|
# Add TXT record.
|
||||||
_namecom_addtxt_json="{\"hostname\":\"$_sub_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"ttl\":\"300\",\"priority\":\"10\"}"
|
_namecom_addtxt_json="{\"host\":\"$_sub_domain\",\"type\":\"TXT\",\"answer\":\"$txtvalue\",\"ttl\":\"300\"}"
|
||||||
if _namecom_rest POST "dns/create/$_domain" "$_namecom_addtxt_json"; then
|
if _namecom_rest POST "domains/$_domain/records" "$_namecom_addtxt_json"; then
|
||||||
retcode=$(printf "%s\n" "$response" | _egrep_o "\"code\":100")
|
_retvalue=$(printf "%s\n" "$response" | _egrep_o "\"$_sub_domain\"")
|
||||||
if [ "$retcode" ]; then
|
if [ "$_retvalue" ]; then
|
||||||
_info "Successfully added TXT record, ready for validation."
|
_info "Successfully added TXT record, ready for validation."
|
||||||
_namecom_logout
|
|
||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
_err "Unable to add the DNS record."
|
_err "Unable to add the DNS record."
|
||||||
_namecom_logout
|
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
@ -72,37 +70,28 @@ dns_namecom_rm() {
|
|||||||
# Find domain in domain list.
|
# Find domain in domain list.
|
||||||
if ! _namecom_get_root "$fulldomain"; then
|
if ! _namecom_get_root "$fulldomain"; then
|
||||||
_err "Unable to find domain specified."
|
_err "Unable to find domain specified."
|
||||||
_namecom_logout
|
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Get the record id.
|
# Get the record id.
|
||||||
if _namecom_rest GET "dns/list/$_domain"; then
|
if _namecom_rest GET "domains/$_domain/records"; then
|
||||||
retcode=$(printf "%s\n" "$response" | _egrep_o "\"code\":100")
|
_record_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[0-9]+,\"domainName\":\"$_domain\",\"host\":\"$_sub_domain\",\"fqdn\":\"$fulldomain.\",\"type\":\"TXT\",\"answer\":\"$txtvalue\"" | cut -d \" -f 3 | _egrep_o [0-9]+)
|
||||||
if [ "$retcode" ]; then
|
_debug record_id "$_record_id"
|
||||||
_record_id=$(printf "%s\n" "$response" | _egrep_o "\"record_id\":\"[0-9]+\",\"name\":\"$fulldomain\",\"type\":\"TXT\"" | cut -d \" -f 4)
|
if [ "$_record_id" ]; then
|
||||||
_debug record_id "$_record_id"
|
|
||||||
_info "Successfully retrieved the record id for ACME challenge."
|
_info "Successfully retrieved the record id for ACME challenge."
|
||||||
else
|
else
|
||||||
_err "Unable to retrieve the record id."
|
_err "Unable to retrieve the record id."
|
||||||
_namecom_logout
|
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Remove the DNS record using record id.
|
# Remove the DNS record using record id.
|
||||||
_namecom_rmtxt_json="{\"record_id\":\"$_record_id\"}"
|
if _namecom_rest DELETE "domains/$_domain/records/$_record_id"; then
|
||||||
if _namecom_rest POST "dns/delete/$_domain" "$_namecom_rmtxt_json"; then
|
_info "Successfully removed the TXT record."
|
||||||
retcode=$(printf "%s\n" "$response" | _egrep_o "\"code\":100")
|
return 0
|
||||||
if [ "$retcode" ]; then
|
else
|
||||||
_info "Successfully removed the TXT record."
|
_err "Unable to delete record id."
|
||||||
_namecom_logout
|
return 1
|
||||||
return 0
|
|
||||||
else
|
|
||||||
_err "Unable to remove the DNS record."
|
|
||||||
_namecom_logout
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,8 +101,9 @@ _namecom_rest() {
|
|||||||
param=$2
|
param=$2
|
||||||
data=$3
|
data=$3
|
||||||
|
|
||||||
export _H1="Content-Type: application/json"
|
export _H1="Authorization: Basic $_namecom_auth"
|
||||||
export _H2="Api-Session-Token: $sessionkey"
|
export _H2="Content-Type: application/json"
|
||||||
|
|
||||||
if [ "$method" != "GET" ]; then
|
if [ "$method" != "GET" ]; then
|
||||||
response="$(_post "$data" "$Namecom_API/$param" "" "$method")"
|
response="$(_post "$data" "$Namecom_API/$param" "" "$method")"
|
||||||
else
|
else
|
||||||
@ -130,20 +120,15 @@ _namecom_rest() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_namecom_login() {
|
_namecom_login() {
|
||||||
namecom_login_json="{\"username\":\"$Namecom_Username\",\"api_token\":\"$Namecom_Token\"}"
|
# Auth string
|
||||||
|
# Name.com API v4 uses http basic auth to authenticate
|
||||||
|
# need to convert the token for http auth
|
||||||
|
_namecom_auth=$(printf "%s:%s" "$Namecom_Username" "$Namecom_Token" | _base64)
|
||||||
|
|
||||||
if _namecom_rest POST "login" "$namecom_login_json"; then
|
if _namecom_rest GET "hello"; then
|
||||||
retcode=$(printf "%s\n" "$response" | _egrep_o "\"code\":100")
|
retcode=$(printf "%s\n" "$response" | _egrep_o "\"username\"\:\"$Namecom_Username\"")
|
||||||
if [ "$retcode" ]; then
|
if [ "$retcode" ]; then
|
||||||
_info "Successfully logged in. Fetching session token..."
|
_info "Successfully logged in."
|
||||||
sessionkey=$(printf "%s\n" "$response" | _egrep_o "\"session_token\":\".+" | cut -d \" -f 4)
|
|
||||||
if [ ! -z "$sessionkey" ]; then
|
|
||||||
_debug sessionkey "$sessionkey"
|
|
||||||
_info "Session key obtained."
|
|
||||||
else
|
|
||||||
_err "Unable to get session key."
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
else
|
else
|
||||||
_err "Logging in failed."
|
_err "Logging in failed."
|
||||||
return 1
|
return 1
|
||||||
@ -151,24 +136,12 @@ _namecom_login() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
_namecom_logout() {
|
|
||||||
if _namecom_rest GET "logout"; then
|
|
||||||
retcode=$(printf "%s\n" "$response" | _egrep_o "\"code\":100")
|
|
||||||
if [ "$retcode" ]; then
|
|
||||||
_info "Successfully logged out."
|
|
||||||
else
|
|
||||||
_err "Error logging out."
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
_namecom_get_root() {
|
_namecom_get_root() {
|
||||||
domain=$1
|
domain=$1
|
||||||
i=2
|
i=2
|
||||||
p=1
|
p=1
|
||||||
|
|
||||||
if ! _namecom_rest GET "domain/list"; then
|
if ! _namecom_rest GET "domains"; then
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -8,12 +8,14 @@ dns_nsupdate_add() {
|
|||||||
txtvalue=$2
|
txtvalue=$2
|
||||||
_checkKeyFile || return 1
|
_checkKeyFile || return 1
|
||||||
[ -n "${NSUPDATE_SERVER}" ] || NSUPDATE_SERVER="localhost"
|
[ -n "${NSUPDATE_SERVER}" ] || NSUPDATE_SERVER="localhost"
|
||||||
|
[ -n "${NSUPDATE_SERVER_PORT}" ] || NSUPDATE_SERVER_PORT=53
|
||||||
# save the dns server and key to the account conf file.
|
# save the dns server and key to the account conf file.
|
||||||
_saveaccountconf NSUPDATE_SERVER "${NSUPDATE_SERVER}"
|
_saveaccountconf NSUPDATE_SERVER "${NSUPDATE_SERVER}"
|
||||||
|
_saveaccountconf NSUPDATE_SERVER_PORT "${NSUPDATE_SERVER_PORT}"
|
||||||
_saveaccountconf NSUPDATE_KEY "${NSUPDATE_KEY}"
|
_saveaccountconf NSUPDATE_KEY "${NSUPDATE_KEY}"
|
||||||
_info "adding ${fulldomain}. 60 in txt \"${txtvalue}\""
|
_info "adding ${fulldomain}. 60 in txt \"${txtvalue}\""
|
||||||
nsupdate -k "${NSUPDATE_KEY}" <<EOF
|
nsupdate -k "${NSUPDATE_KEY}" <<EOF
|
||||||
server ${NSUPDATE_SERVER}
|
server ${NSUPDATE_SERVER} ${NSUPDATE_SERVER_PORT}
|
||||||
update add ${fulldomain}. 60 in txt "${txtvalue}"
|
update add ${fulldomain}. 60 in txt "${txtvalue}"
|
||||||
send
|
send
|
||||||
EOF
|
EOF
|
||||||
@ -30,9 +32,10 @@ dns_nsupdate_rm() {
|
|||||||
fulldomain=$1
|
fulldomain=$1
|
||||||
_checkKeyFile || return 1
|
_checkKeyFile || return 1
|
||||||
[ -n "${NSUPDATE_SERVER}" ] || NSUPDATE_SERVER="localhost"
|
[ -n "${NSUPDATE_SERVER}" ] || NSUPDATE_SERVER="localhost"
|
||||||
|
[ -n "${NSUPDATE_SERVER_PORT}" ] || NSUPDATE_SERVER_PORT=53
|
||||||
_info "removing ${fulldomain}. txt"
|
_info "removing ${fulldomain}. txt"
|
||||||
nsupdate -k "${NSUPDATE_KEY}" <<EOF
|
nsupdate -k "${NSUPDATE_KEY}" <<EOF
|
||||||
server ${NSUPDATE_SERVER}
|
server ${NSUPDATE_SERVER} ${NSUPDATE_SERVER_PORT}
|
||||||
update delete ${fulldomain}. txt
|
update delete ${fulldomain}. txt
|
||||||
send
|
send
|
||||||
EOF
|
EOF
|
||||||
|
@ -69,15 +69,21 @@ dns_pdns_add() {
|
|||||||
#fulldomain
|
#fulldomain
|
||||||
dns_pdns_rm() {
|
dns_pdns_rm() {
|
||||||
fulldomain=$1
|
fulldomain=$1
|
||||||
|
txtvalue=$2
|
||||||
|
|
||||||
|
if [ -z "$PDNS_Ttl" ]; then
|
||||||
|
PDNS_Ttl="$DEFAULT_PDNS_TTL"
|
||||||
|
fi
|
||||||
|
|
||||||
_debug "Detect root zone"
|
_debug "Detect root zone"
|
||||||
if ! _get_root "$fulldomain"; then
|
if ! _get_root "$fulldomain"; then
|
||||||
_err "invalid domain"
|
_err "invalid domain"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
_debug _domain "$_domain"
|
_debug _domain "$_domain"
|
||||||
|
|
||||||
if ! rm_record "$_domain" "$fulldomain"; then
|
if ! rm_record "$_domain" "$fulldomain" "$txtvalue"; then
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -88,9 +94,16 @@ set_record() {
|
|||||||
_info "Adding record"
|
_info "Adding record"
|
||||||
root=$1
|
root=$1
|
||||||
full=$2
|
full=$2
|
||||||
txtvalue=$3
|
new_challenge=$3
|
||||||
|
|
||||||
if ! _pdns_rest "PATCH" "/api/v1/servers/$PDNS_ServerId/zones/$root." "{\"rrsets\": [{\"changetype\": \"REPLACE\", \"name\": \"$full.\", \"type\": \"TXT\", \"ttl\": $PDNS_Ttl, \"records\": [{\"name\": \"$full.\", \"type\": \"TXT\", \"content\": \"\\\"$txtvalue\\\"\", \"disabled\": false, \"ttl\": $PDNS_Ttl}]}]}"; then
|
_record_string=""
|
||||||
|
_build_record_string "$new_challenge"
|
||||||
|
_list_existingchallenges
|
||||||
|
for oldchallenge in $_existing_challenges; do
|
||||||
|
_build_record_string "$oldchallenge"
|
||||||
|
done
|
||||||
|
|
||||||
|
if ! _pdns_rest "PATCH" "/api/v1/servers/$PDNS_ServerId/zones/$root" "{\"rrsets\": [{\"changetype\": \"REPLACE\", \"name\": \"$full.\", \"type\": \"TXT\", \"ttl\": $PDNS_Ttl, \"records\": [$_record_string]}]}"; then
|
||||||
_err "Set txt record error."
|
_err "Set txt record error."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
@ -106,14 +119,37 @@ rm_record() {
|
|||||||
_info "Remove record"
|
_info "Remove record"
|
||||||
root=$1
|
root=$1
|
||||||
full=$2
|
full=$2
|
||||||
|
txtvalue=$3
|
||||||
|
|
||||||
if ! _pdns_rest "PATCH" "/api/v1/servers/$PDNS_ServerId/zones/$root." "{\"rrsets\": [{\"changetype\": \"DELETE\", \"name\": \"$full.\", \"type\": \"TXT\"}]}"; then
|
#Enumerate existing acme challenges
|
||||||
_err "Delete txt record error."
|
_list_existingchallenges
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! notify_slaves "$root"; then
|
if _contains "$_existing_challenges" "$txtvalue"; then
|
||||||
return 1
|
#Delete all challenges (PowerDNS API does not allow to delete content)
|
||||||
|
if ! _pdns_rest "PATCH" "/api/v1/servers/$PDNS_ServerId/zones/$root" "{\"rrsets\": [{\"changetype\": \"DELETE\", \"name\": \"$full.\", \"type\": \"TXT\"}]}"; then
|
||||||
|
_err "Delete txt record error."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_record_string=""
|
||||||
|
#If the only existing challenge was the challenge to delete: nothing to do
|
||||||
|
if ! [ "$_existing_challenges" = "$txtvalue" ]; then
|
||||||
|
for oldchallenge in $_existing_challenges; do
|
||||||
|
#Build up the challenges to re-add, ommitting the one what should be deleted
|
||||||
|
if ! [ "$oldchallenge" = "$txtvalue" ]; then
|
||||||
|
_build_record_string "$oldchallenge"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
#Recreate the existing challenges
|
||||||
|
if ! _pdns_rest "PATCH" "/api/v1/servers/$PDNS_ServerId/zones/$root" "{\"rrsets\": [{\"changetype\": \"REPLACE\", \"name\": \"$full.\", \"type\": \"TXT\", \"ttl\": $PDNS_Ttl, \"records\": [$_record_string]}]}"; then
|
||||||
|
_err "Set txt record error."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if ! notify_slaves "$root"; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
_info "Record not found, nothing to remove"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
@ -122,7 +158,7 @@ rm_record() {
|
|||||||
notify_slaves() {
|
notify_slaves() {
|
||||||
root=$1
|
root=$1
|
||||||
|
|
||||||
if ! _pdns_rest "PUT" "/api/v1/servers/$PDNS_ServerId/zones/$root./notify"; then
|
if ! _pdns_rest "PUT" "/api/v1/servers/$PDNS_ServerId/zones/$root/notify"; then
|
||||||
_err "Notify slaves error."
|
_err "Notify slaves error."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
@ -144,15 +180,18 @@ _get_root() {
|
|||||||
|
|
||||||
while true; do
|
while true; do
|
||||||
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
|
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
|
||||||
if [ -z "$h" ]; then
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if _contains "$_zones_response" "\"name\": \"$h.\""; then
|
if _contains "$_zones_response" "\"name\": \"$h.\""; then
|
||||||
_domain="$h"
|
_domain="$h."
|
||||||
|
if [ -z "$h" ]; then
|
||||||
|
_domain="=2E"
|
||||||
|
fi
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ -z "$h" ]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
i=$(_math $i + 1)
|
i=$(_math $i + 1)
|
||||||
done
|
done
|
||||||
_debug "$domain not found"
|
_debug "$domain not found"
|
||||||
@ -182,3 +221,12 @@ _pdns_rest() {
|
|||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_build_record_string() {
|
||||||
|
_record_string="${_record_string:+${_record_string}, }{\"content\": \"\\\"${1}\\\"\", \"disabled\": false}"
|
||||||
|
}
|
||||||
|
|
||||||
|
_list_existingchallenges() {
|
||||||
|
_pdns_rest "GET" "/api/v1/servers/$PDNS_ServerId/zones/$root"
|
||||||
|
_existing_challenges=$(echo "$response" | _normalizeJson | _egrep_o "\"name\":\"${fulldomain}[^]]*}" | _egrep_o 'content\":\"\\"[^\\]*' | sed -n 's/^content":"\\"//p')
|
||||||
|
}
|
||||||
|
69
dnsapi/dns_tele3.sh
Normal file
69
dnsapi/dns_tele3.sh
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
#
|
||||||
|
# tele3.cz DNS API
|
||||||
|
#
|
||||||
|
# Author: Roman Blizik
|
||||||
|
# Report Bugs here: https://github.com/par-pa/acme.sh
|
||||||
|
#
|
||||||
|
# --
|
||||||
|
# export TELE3_Key="MS2I4uPPaI..."
|
||||||
|
# export TELE3_Secret="kjhOIHGJKHg"
|
||||||
|
# --
|
||||||
|
|
||||||
|
TELE3_API="https://www.tele3.cz/acme/"
|
||||||
|
|
||||||
|
######## Public functions #####################
|
||||||
|
|
||||||
|
dns_tele3_add() {
|
||||||
|
_info "Using TELE3 DNS"
|
||||||
|
data="\"ope\":\"add\", \"domain\":\"$1\", \"value\":\"$2\""
|
||||||
|
if ! _tele3_call; then
|
||||||
|
_err "Publish zone failed"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_info "Zone published"
|
||||||
|
}
|
||||||
|
|
||||||
|
dns_tele3_rm() {
|
||||||
|
_info "Using TELE3 DNS"
|
||||||
|
data="\"ope\":\"rm\", \"domain\":\"$1\", \"value\":\"$2\""
|
||||||
|
if ! _tele3_call; then
|
||||||
|
_err "delete TXT record failed"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_info "TXT record successfully deleted"
|
||||||
|
}
|
||||||
|
|
||||||
|
#################### Private functions below ##################################
|
||||||
|
|
||||||
|
_tele3_init() {
|
||||||
|
TELE3_Key="${TELE3_Key:-$(_readaccountconf_mutable TELE3_Key)}"
|
||||||
|
TELE3_Secret="${TELE3_Secret:-$(_readaccountconf_mutable TELE3_Secret)}"
|
||||||
|
if [ -z "$TELE3_Key" ] || [ -z "$TELE3_Secret" ]; then
|
||||||
|
TELE3_Key=""
|
||||||
|
TELE3_Secret=""
|
||||||
|
_err "You must export variables: TELE3_Key and TELE3_Secret"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
#save the config variables to the account conf file.
|
||||||
|
_saveaccountconf_mutable TELE3_Key "$TELE3_Key"
|
||||||
|
_saveaccountconf_mutable TELE3_Secret "$TELE3_Secret"
|
||||||
|
}
|
||||||
|
|
||||||
|
_tele3_call() {
|
||||||
|
_tele3_init
|
||||||
|
data="{\"key\":\"$TELE3_Key\", \"secret\":\"$TELE3_Secret\", $data}"
|
||||||
|
|
||||||
|
_debug data "$data"
|
||||||
|
|
||||||
|
response="$(_post "$data" "$TELE3_API" "" "POST")"
|
||||||
|
_debug response "$response"
|
||||||
|
|
||||||
|
if [ "$response" != "success" ]; then
|
||||||
|
_err "$response"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
@ -50,9 +50,9 @@ _PDD_get_domain() {
|
|||||||
__last=0
|
__last=0
|
||||||
while [ $__last -eq 0 ]; do
|
while [ $__last -eq 0 ]; do
|
||||||
uri1="https://pddimp.yandex.ru/api2/admin/domain/domains?page=${__page}&on_page=20"
|
uri1="https://pddimp.yandex.ru/api2/admin/domain/domains?page=${__page}&on_page=20"
|
||||||
res1=$(_get "$uri1" | _normalizeJson)
|
res1="$(_get "$uri1" | _normalizeJson)"
|
||||||
#_debug "$res1"
|
_debug2 "res1" "$res1"
|
||||||
__found=$(echo "$res1" | sed -n -e 's#.* "found": \([^,]*\),.*#\1#p')
|
__found="$(echo "$res1" | sed -n -e 's#.* "found": \([^,]*\),.*#\1#p')"
|
||||||
_debug "found: $__found results on page"
|
_debug "found: $__found results on page"
|
||||||
if [ "$__found" -lt 20 ]; then
|
if [ "$__found" -lt 20 ]; then
|
||||||
_debug "last page: $__page"
|
_debug "last page: $__page"
|
||||||
|
139
dnsapi/dns_zilore.sh
Normal file
139
dnsapi/dns_zilore.sh
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
Zilore_API="https://api.zilore.com/dns/v1"
|
||||||
|
# Zilore_Key="YOUR-ZILORE-API-KEY"
|
||||||
|
|
||||||
|
######## Public functions #####################
|
||||||
|
|
||||||
|
dns_zilore_add() {
|
||||||
|
fulldomain=$1
|
||||||
|
txtvalue=$2
|
||||||
|
|
||||||
|
_info "Using Zilore"
|
||||||
|
_debug fulldomain "$fulldomain"
|
||||||
|
_debug txtvalue "$txtvalue"
|
||||||
|
|
||||||
|
Zilore_Key="${Zilore_Key:-$(_readaccountconf_mutable Zilore_Key)}"
|
||||||
|
if [ -z "$Zilore_Key" ]; then
|
||||||
|
Zilore_Key=""
|
||||||
|
_err "Please define Zilore API key"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_saveaccountconf_mutable Zilore_Key "$Zilore_Key"
|
||||||
|
|
||||||
|
if ! _get_root "$fulldomain"; then
|
||||||
|
_err "Unable to determine root domain"
|
||||||
|
return 1
|
||||||
|
else
|
||||||
|
_debug _domain "$_domain"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if _zilore_rest POST "domains/$_domain/records?record_type=TXT&record_ttl=600&record_name=$fulldomain&record_value=\"$txtvalue\""; then
|
||||||
|
if _contains "$response" '"added"' >/dev/null; then
|
||||||
|
_info "Added TXT record, waiting for validation"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
_debug response "$response"
|
||||||
|
_err "Error while adding DNS records"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
dns_zilore_rm() {
|
||||||
|
fulldomain=$1
|
||||||
|
txtvalue=$2
|
||||||
|
|
||||||
|
_info "Using Zilore"
|
||||||
|
_debug fulldomain "$fulldomain"
|
||||||
|
_debug txtvalue "$txtvalue"
|
||||||
|
|
||||||
|
Zilore_Key="${Zilore_Key:-$(_readaccountconf_mutable Zilore_Key)}"
|
||||||
|
if [ -z "$Zilore_Key" ]; then
|
||||||
|
Zilore_Key=""
|
||||||
|
_err "Please define Zilore API key"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_saveaccountconf_mutable Zilore_Key "$Zilore_Key"
|
||||||
|
|
||||||
|
if ! _get_root "$fulldomain"; then
|
||||||
|
_err "Unable to determine root domain"
|
||||||
|
return 1
|
||||||
|
else
|
||||||
|
_debug _domain "$_domain"
|
||||||
|
fi
|
||||||
|
|
||||||
|
_debug "Getting TXT records"
|
||||||
|
_zilore_rest GET "domains/${_domain}/records?search_text=$txtvalue&search_record_type=TXT"
|
||||||
|
_debug response "$response"
|
||||||
|
|
||||||
|
if ! _contains "$response" '"ok"' >/dev/null; then
|
||||||
|
_err "Error while getting records list"
|
||||||
|
return 1
|
||||||
|
else
|
||||||
|
_record_id=$(printf "%s\n" "$response" | _egrep_o "\"record_id\":\"[^\"]+\"" | cut -d : -f 2 | tr -d \" | _head_n 1)
|
||||||
|
if [ -z "$_record_id" ]; then
|
||||||
|
_err "Cannot determine _record_id"
|
||||||
|
return 1
|
||||||
|
else
|
||||||
|
_debug _record_id "$_record_id"
|
||||||
|
fi
|
||||||
|
if ! _zilore_rest DELETE "domains/${_domain}/records?record_id=$_record_id"; then
|
||||||
|
_err "Error while deleting chosen record"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_contains "$response" '"ok"'
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
#################### Private functions below ##################################
|
||||||
|
|
||||||
|
_get_root() {
|
||||||
|
domain=$1
|
||||||
|
i=2
|
||||||
|
while true; do
|
||||||
|
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
|
||||||
|
_debug h "$h"
|
||||||
|
if [ -z "$h" ]; then
|
||||||
|
#not valid
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! _zilore_rest GET "domains?search_text=$h"; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if _contains "$response" "\"$h\"" >/dev/null; then
|
||||||
|
_domain=$h
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
_debug "$h not found"
|
||||||
|
fi
|
||||||
|
i=$(_math "$i" + 1)
|
||||||
|
done
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
_zilore_rest() {
|
||||||
|
method=$1
|
||||||
|
param=$2
|
||||||
|
data=$3
|
||||||
|
|
||||||
|
export _H1="X-Auth-Key: $Zilore_Key"
|
||||||
|
|
||||||
|
if [ "$method" != "GET" ]; then
|
||||||
|
response="$(_post "$data" "$Zilore_API/$param" "" "$method")"
|
||||||
|
else
|
||||||
|
response="$(_get "$Zilore_API/$param")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$?" != "0" ]; then
|
||||||
|
_err "error $param"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_debug2 response "$response"
|
||||||
|
return 0
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user