Merge branch 'dev' into WETOOP-patch-alicdn
This commit is contained in:
commit
3546e60737
11
.travis.yml
11
.travis.yml
@ -13,12 +13,6 @@ env:
|
||||
global:
|
||||
- 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:
|
||||
- if [ "$TRAVIS_OS_NAME" = 'osx' ]; then
|
||||
@ -29,9 +23,7 @@ install:
|
||||
script:
|
||||
- echo "NGROK_TOKEN=$(echo "$NGROK_TOKEN" | wc -c)"
|
||||
- command -V openssl && openssl version
|
||||
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then curl -sSL $SHFMT_URL -o ~/shfmt ; 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 curl -sSL $SHFMT_URL -o ~/shfmt && chmod +x ~/shfmt && ~/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 shellcheck -V ; 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" = "osx" -a "$NGROK_TOKEN" ]; then sudo TEST_LOCAL="$TEST_LOCAL" NGROK_TOKEN="$NGROK_TOKEN" ACME_OPENSSL_BIN="$ACME_OPENSSL_BIN" ./letest.sh ; fi
|
||||
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
|
||||
|
||||
@ -3,6 +3,7 @@ FROM alpine:3.6
|
||||
RUN apk update -f \
|
||||
&& apk --no-cache add -f \
|
||||
openssl \
|
||||
coreutils \
|
||||
curl \
|
||||
socat \
|
||||
&& rm -rf /var/cache/apk/*
|
||||
|
||||
13
README.md
13
README.md
@ -33,7 +33,7 @@ Twitter: [@neilpangxa](https://twitter.com/neilpangxa)
|
||||
- [webfaction](https://community.webfaction.com/questions/19988/using-letsencrypt)
|
||||
- [Loadbalancer.org](https://www.loadbalancer.org/blog/loadbalancer-org-with-lets-encrypt-quick-and-dirty)
|
||||
- [discourse.org](https://meta.discourse.org/t/setting-up-lets-encrypt/40709)
|
||||
- [Centminmod](http://centminmod.com/letsencrypt-acmetool-https.html)
|
||||
- [Centminmod](https://centminmod.com/letsencrypt-acmetool-https.html)
|
||||
- [splynx](https://forum.splynx.com/t/free-ssl-cert-for-splynx-lets-encrypt/297)
|
||||
- [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)
|
||||
@ -317,7 +317,16 @@ You don't have to do anything manually!
|
||||
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. EUSERV.EU (https://www.euserv.eu)
|
||||
1. DNSPod.com API (https://www.dnspod.com)
|
||||
1. Google Cloud DNS API
|
||||
1. ConoHa (https://www.conoha.jp)
|
||||
1. netcup DNS API (https://www.netcup.de)
|
||||
1. GratisDNS.dk (https://gratisdns.dk)
|
||||
1. Namecheap API (https://www.namecheap.com/)
|
||||
|
||||
And:
|
||||
|
||||
|
||||
88
acme.sh
88
acme.sh
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
VER=2.7.8
|
||||
VER=2.8.0
|
||||
|
||||
PROJECT_NAME="acme.sh"
|
||||
|
||||
@ -124,21 +124,21 @@ if [ -t 1 ]; then
|
||||
fi
|
||||
|
||||
__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'
|
||||
fi
|
||||
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'
|
||||
fi
|
||||
}
|
||||
|
||||
__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'
|
||||
fi
|
||||
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'
|
||||
fi
|
||||
}
|
||||
@ -1327,6 +1327,7 @@ createDomainKey() {
|
||||
if _createkey "$_cdl" "$CERT_KEY_PATH"; then
|
||||
_savedomainconf Le_Keylength "$_cdl"
|
||||
_info "The domain key is here: $(__green $CERT_KEY_PATH)"
|
||||
return 0
|
||||
fi
|
||||
else
|
||||
if [ "$IS_RENEW" ]; then
|
||||
@ -1374,17 +1375,17 @@ _url_replace() {
|
||||
}
|
||||
|
||||
_time2str() {
|
||||
#Linux
|
||||
if date -u -d@"$1" 2>/dev/null; then
|
||||
return
|
||||
fi
|
||||
|
||||
#BSD
|
||||
if date -u -r "$1" 2>/dev/null; then
|
||||
return
|
||||
fi
|
||||
|
||||
#Soaris
|
||||
#Linux
|
||||
if date -u -d@"$1" 2>/dev/null; then
|
||||
return
|
||||
fi
|
||||
|
||||
#Solaris
|
||||
if _exists adb; then
|
||||
_t_s_a=$(echo "0t${1}=Y" | adb)
|
||||
echo "$_t_s_a"
|
||||
@ -1607,7 +1608,7 @@ _inithttp() {
|
||||
|
||||
}
|
||||
|
||||
# body url [needbase64] [POST|PUT] [ContentType]
|
||||
# body url [needbase64] [POST|PUT|DELETE] [ContentType]
|
||||
_post() {
|
||||
body="$1"
|
||||
_post_url="$2"
|
||||
@ -1795,15 +1796,13 @@ _send_signed_request() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ "$ACME_VERSION" = "2" ]; then
|
||||
__request_conent_type="$CONTENT_TYPE_JSON"
|
||||
else
|
||||
__request_conent_type=""
|
||||
fi
|
||||
__request_conent_type="$CONTENT_TYPE_JSON"
|
||||
|
||||
payload64=$(printf "%s" "$payload" | _base64 | _url_replace)
|
||||
_debug3 payload64 "$payload64"
|
||||
|
||||
MAX_REQUEST_RETRY_TIMES=5
|
||||
MAX_REQUEST_RETRY_TIMES=20
|
||||
_sleep_retry_sec=1
|
||||
_request_retry_times=0
|
||||
while [ "${_request_retry_times}" -lt "$MAX_REQUEST_RETRY_TIMES" ]; do
|
||||
_request_retry_times=$(_math "$_request_retry_times" + 1)
|
||||
@ -1811,14 +1810,14 @@ _send_signed_request() {
|
||||
if [ -z "$_CACHED_NONCE" ]; then
|
||||
_headers=""
|
||||
if [ "$ACME_NEW_NONCE" ]; then
|
||||
_debug2 "Get nonce. ACME_NEW_NONCE" "$ACME_NEW_NONCE"
|
||||
_debug2 "Get nonce with HEAD. ACME_NEW_NONCE" "$ACME_NEW_NONCE"
|
||||
nonceurl="$ACME_NEW_NONCE"
|
||||
if _post "" "$nonceurl" "" "HEAD" "$__request_conent_type"; then
|
||||
_headers="$(cat "$HTTP_HEADER")"
|
||||
fi
|
||||
fi
|
||||
if [ -z "$_headers" ]; then
|
||||
_debug2 "Get nonce. ACME_DIRECTORY" "$ACME_DIRECTORY"
|
||||
_debug2 "Get nonce with GET. ACME_DIRECTORY" "$ACME_DIRECTORY"
|
||||
nonceurl="$ACME_DIRECTORY"
|
||||
_headers="$(_get "$nonceurl" "onlyheader")"
|
||||
fi
|
||||
@ -1897,9 +1896,10 @@ _send_signed_request() {
|
||||
_debug3 _body "$_body"
|
||||
fi
|
||||
|
||||
if _contains "$_body" "JWS has invalid anti-replay nonce"; then
|
||||
_info "It seems the CA server is busy now, let's wait and retry."
|
||||
_sleep 5
|
||||
if _contains "$_body" "JWS has invalid anti-replay nonce" || _contains "$_body" "JWS has an invalid anti-replay nonce"; then
|
||||
_info "It seems the CA server is busy now, let's wait and retry. Sleeping $_sleep_retry_sec seconds."
|
||||
_CACHED_NONCE=""
|
||||
_sleep $_sleep_retry_sec
|
||||
continue
|
||||
fi
|
||||
break
|
||||
@ -4287,20 +4287,21 @@ $_authorizations_map"
|
||||
Le_NextRenewTime=$(_math "$Le_NextRenewTime" - 86400)
|
||||
_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
|
||||
_savedomainconf "Le_RealCertPath" "$_real_cert"
|
||||
_savedomainconf "Le_RealCACertPath" "$_real_ca"
|
||||
_savedomainconf "Le_RealKeyPath" "$_real_key"
|
||||
_savedomainconf "Le_ReloadCmd" "$_reload_cmd"
|
||||
_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
|
||||
|
||||
if ! _on_issue_success "$_post_hook" "$_renew_hook"; then
|
||||
_err "Call hook error."
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
#domain [isEcc]
|
||||
@ -4601,7 +4602,8 @@ deploy() {
|
||||
|
||||
_initpath "$_d" "$_isEcc"
|
||||
if [ ! -d "$DOMAIN_PATH" ]; then
|
||||
_err "Domain is not valid:'$_d'"
|
||||
_err "The domain '$_d' is not a cert name. You must use the cert name to specify the cert to install."
|
||||
_err "Can not find path:'$DOMAIN_PATH'"
|
||||
return 1
|
||||
fi
|
||||
|
||||
@ -4628,7 +4630,8 @@ installcert() {
|
||||
|
||||
_initpath "$_main_domain" "$_isEcc"
|
||||
if [ ! -d "$DOMAIN_PATH" ]; then
|
||||
_err "Domain is not valid:'$_main_domain'"
|
||||
_err "The domain '$_main_domain' is not a cert name. You must use the cert name to specify the cert to install."
|
||||
_err "Can not find path:'$DOMAIN_PATH'"
|
||||
return 1
|
||||
fi
|
||||
|
||||
@ -4675,19 +4678,19 @@ _installcert() {
|
||||
if [ -f "$_real_cert" ] && [ ! "$IS_RENEW" ]; then
|
||||
cp "$_real_cert" "$_backup_path/cert.bak"
|
||||
fi
|
||||
cat "$CERT_PATH" >"$_real_cert"
|
||||
cat "$CERT_PATH" >"$_real_cert" || return 1
|
||||
fi
|
||||
|
||||
if [ "$_real_ca" ]; then
|
||||
_info "Installing CA to:$_real_ca"
|
||||
if [ "$_real_ca" = "$_real_cert" ]; then
|
||||
echo "" >>"$_real_ca"
|
||||
cat "$CA_CERT_PATH" >>"$_real_ca"
|
||||
cat "$CA_CERT_PATH" >>"$_real_ca" || return 1
|
||||
else
|
||||
if [ -f "$_real_ca" ] && [ ! "$IS_RENEW" ]; then
|
||||
cp "$_real_ca" "$_backup_path/ca.bak"
|
||||
fi
|
||||
cat "$CA_CERT_PATH" >"$_real_ca"
|
||||
cat "$CA_CERT_PATH" >"$_real_ca" || return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
@ -4697,9 +4700,9 @@ _installcert() {
|
||||
cp "$_real_key" "$_backup_path/key.bak"
|
||||
fi
|
||||
if [ -f "$_real_key" ]; then
|
||||
cat "$CERT_KEY_PATH" >"$_real_key"
|
||||
cat "$CERT_KEY_PATH" >"$_real_key" || return 1
|
||||
else
|
||||
cat "$CERT_KEY_PATH" >"$_real_key"
|
||||
cat "$CERT_KEY_PATH" >"$_real_key" || return 1
|
||||
chmod 600 "$_real_key"
|
||||
fi
|
||||
fi
|
||||
@ -4709,7 +4712,7 @@ _installcert() {
|
||||
if [ -f "$_real_fullchain" ] && [ ! "$IS_RENEW" ]; then
|
||||
cp "$_real_fullchain" "$_backup_path/fullchain.bak"
|
||||
fi
|
||||
cat "$CERT_FULLCHAIN_PATH" >"$_real_fullchain"
|
||||
cat "$CERT_FULLCHAIN_PATH" >"$_real_fullchain" || return 1
|
||||
fi
|
||||
|
||||
if [ "$_reload_cmd" ]; then
|
||||
@ -5473,7 +5476,7 @@ Parameters:
|
||||
--log-level 1|2 Specifies the log level, default is 1.
|
||||
--syslog [0|3|6|7] Syslog level, 0: disable syslog, 3: error, 6: info, 7: debug.
|
||||
|
||||
These parameters are to install the cert to nginx/apache or anyother server after issue/renew a cert:
|
||||
These parameters are to install the cert to nginx/apache or any other server after issue/renew a cert:
|
||||
|
||||
--cert-file After issue/renew, the cert will be copied to this path.
|
||||
--key-file After issue/renew, the key will be copied to this path.
|
||||
@ -5500,6 +5503,7 @@ Parameters:
|
||||
--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.
|
||||
--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'
|
||||
--csr Specifies the input csr.
|
||||
--pre-hook Command to be run before obtaining any certificates.
|
||||
@ -5514,6 +5518,7 @@ Parameters:
|
||||
--openssl-bin Specifies a custom openssl bin location.
|
||||
--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.
|
||||
"
|
||||
}
|
||||
|
||||
@ -5964,6 +5969,9 @@ _process() {
|
||||
--no-color)
|
||||
export ACME_NO_COLOR=1
|
||||
;;
|
||||
--force-color)
|
||||
export ACME_FORCE_COLOR=1
|
||||
;;
|
||||
--ecc)
|
||||
_ecc="isEcc"
|
||||
;;
|
||||
@ -6058,6 +6066,10 @@ _process() {
|
||||
_use_wget="1"
|
||||
ACME_USE_WGET="1"
|
||||
;;
|
||||
--branch | -b)
|
||||
export BRANCH="$2"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
_err "Unknown parameter : $1"
|
||||
return 1
|
||||
|
||||
@ -256,7 +256,48 @@ acme.sh --deploy -d fritzbox.example.com --deploy-hook fritzbox
|
||||
acme.sh --deploy -d ftp.example.com --deploy-hook strongswan
|
||||
```
|
||||
|
||||
## 10. Deploy the cert to your AliCDN account
|
||||
## 10. Deploy the cert to HAProxy
|
||||
|
||||
You must specify the path where you want the concatenated key and certificate chain written.
|
||||
```sh
|
||||
export DEPLOY_HAPROXY_PEM_PATH=/etc/haproxy
|
||||
```
|
||||
|
||||
You may optionally define the command to reload HAProxy. The value shown below will be used as the default if you don't set this environment variable.
|
||||
|
||||
```sh
|
||||
export DEPLOY_HAPROXY_RELOAD="/usr/sbin/service haproxy restart"
|
||||
```
|
||||
|
||||
You can then deploy the certificate as follows
|
||||
```sh
|
||||
acme.sh --deploy -d haproxy.example.com --deploy-hook haproxy
|
||||
```
|
||||
|
||||
The path for the PEM file will be stored with the domain configuration and will be available when renewing, so that deploy will happen automatically when renewed.
|
||||
|
||||
## 11. Deploy your cert to Gitlab pages
|
||||
|
||||
You must define the API key and the informations for the project and Gitlab page you are updating the certificate for.
|
||||
|
||||
```sh
|
||||
# The token can be created in your user settings under "Access Tokens"
|
||||
export GITLAB_TOKEN="xxxxxxxxxxx"
|
||||
|
||||
# The project ID is displayed on the home page of the project
|
||||
export GITLAB_PROJECT_ID=12345678
|
||||
|
||||
# The domain must match the one defined for the Gitlab page, without "https://"
|
||||
export GITLAB_DOMAIN="www.mydomain.com"
|
||||
```
|
||||
|
||||
You can then deploy the certificate as follows
|
||||
|
||||
```sh
|
||||
acme.sh --deploy -d www.mydomain.com --deploy-hook gitlab
|
||||
```
|
||||
|
||||
## 12. Deploy the cert to your AliCDN account
|
||||
|
||||
You must specify the aliyun account credentials in order to deploy the certificate, optionally specify the prefix of your domain if you use wildcard in cdn domain, through the following environment variables:
|
||||
```sh
|
||||
@ -276,7 +317,7 @@ If your cdn domain is cdn.example.com and cert domain is also cdn.example.com, y
|
||||
export DEPLOY_CDN_Ali_Key="AK"
|
||||
export DEPLOY_CDN_Ali_Secret="SK"
|
||||
export DEPLOY_CDN_Ali_Prefix=""
|
||||
acme.sh --deploy -d example.com --deploy-hook cdn_ali
|
||||
acme.sh --deploy -d cdn.example.com --deploy-hook cdn_ali
|
||||
```
|
||||
|
||||
If your cdn domain is cdn.example.com but cert domain is example.com(subject alternative names: example.com,\*.example.com), you must specify the prefix in deployment:
|
||||
|
||||
@ -2,8 +2,12 @@
|
||||
# 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.
|
||||
# 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
|
||||
|
||||
@ -28,15 +32,9 @@ cpanel_uapi_deploy() {
|
||||
_err "The command uapi is not found."
|
||||
return 1
|
||||
fi
|
||||
if ! _exists php; then
|
||||
_err "The command php is not found."
|
||||
return 1
|
||||
fi
|
||||
# read cert and key files and urlencode both
|
||||
_certstr=$(cat "$_ccert")
|
||||
_keystr=$(cat "$_ckey")
|
||||
_cert=$(php -r "echo urlencode(\"$_certstr\");")
|
||||
_key=$(php -r "echo urlencode(\"$_keystr\");")
|
||||
_cert=$(_url_encode <"$_ccert")
|
||||
_key=$(_url_encode <"$_ckey")
|
||||
|
||||
_debug _cert "$_cert"
|
||||
_debug _key "$_key"
|
||||
|
||||
@ -28,8 +28,10 @@ fritzbox_deploy() {
|
||||
_debug _cfullchain "$_cfullchain"
|
||||
|
||||
if ! _exists iconv; then
|
||||
_err "iconv not found"
|
||||
return 1
|
||||
if ! _exists perl; then
|
||||
_err "iconv or perl not found"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
_fritzbox_username="${DEPLOY_FRITZBOX_USERNAME}"
|
||||
@ -61,7 +63,11 @@ fritzbox_deploy() {
|
||||
|
||||
_info "Log in to the FRITZ!Box"
|
||||
_fritzbox_challenge="$(_get "${_fritzbox_url}/login_sid.lua" | sed -e 's/^.*<Challenge>//' -e 's/<\/Challenge>.*$//')"
|
||||
_fritzbox_hash="$(printf "%s-%s" "${_fritzbox_challenge}" "${_fritzbox_password}" | iconv -f ASCII -t UTF16LE | md5sum | awk '{print $1}')"
|
||||
if _exists iconv; then
|
||||
_fritzbox_hash="$(printf "%s-%s" "${_fritzbox_challenge}" "${_fritzbox_password}" | iconv -f ASCII -t UTF16LE | md5sum | awk '{print $1}')"
|
||||
else
|
||||
_fritzbox_hash="$(printf "%s-%s" "${_fritzbox_challenge}" "${_fritzbox_password}" | perl -p -e 'use Encode qw/encode/; print encode("UTF-16LE","$_"); $_="";' | md5sum | awk '{print $1}')"
|
||||
fi
|
||||
_fritzbox_sid="$(_get "${_fritzbox_url}/login_sid.lua?sid=0000000000000000&username=${_fritzbox_username}&response=${_fritzbox_challenge}-${_fritzbox_hash}" | sed -e 's/^.*<SID>//' -e 's/<\/SID>.*$//')"
|
||||
|
||||
if [ -z "${_fritzbox_sid}" ] || [ "${_fritzbox_sid}" = "0000000000000000" ]; then
|
||||
|
||||
80
deploy/gitlab.sh
Normal file
80
deploy/gitlab.sh
Normal file
@ -0,0 +1,80 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
# Script to deploy certificate to a Gitlab hosted page
|
||||
|
||||
# The following variables exported from environment will be used.
|
||||
# If not set then values previously saved in domain.conf file are used.
|
||||
|
||||
# All the variables are required
|
||||
|
||||
# export GITLAB_TOKEN="xxxxxxx"
|
||||
# export GITLAB_PROJECT_ID=012345
|
||||
# export GITLAB_DOMAIN="mydomain.com"
|
||||
|
||||
gitlab_deploy() {
|
||||
_cdomain="$1"
|
||||
_ckey="$2"
|
||||
_ccert="$3"
|
||||
_cca="$4"
|
||||
_cfullchain="$5"
|
||||
|
||||
_debug _cdomain "$_cdomain"
|
||||
_debug _ckey "$_ckey"
|
||||
_debug _ccert "$_ccert"
|
||||
_debug _cca "$_cca"
|
||||
_debug _cfullchain "$_cfullchain"
|
||||
|
||||
if [ -z "$GITLAB_TOKEN" ]; then
|
||||
if [ -z "$Le_Deploy_gitlab_token" ]; then
|
||||
_err "GITLAB_TOKEN not defined."
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
Le_Deploy_gitlab_token="$GITLAB_TOKEN"
|
||||
_savedomainconf Le_Deploy_gitlab_token "$Le_Deploy_gitlab_token"
|
||||
fi
|
||||
|
||||
if [ -z "$GITLAB_PROJECT_ID" ]; then
|
||||
if [ -z "$Le_Deploy_gitlab_project_id" ]; then
|
||||
_err "GITLAB_PROJECT_ID not defined."
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
Le_Deploy_gitlab_project_id="$GITLAB_PROJECT_ID"
|
||||
_savedomainconf Le_Deploy_gitlab_project_id "$Le_Deploy_gitlab_project_id"
|
||||
fi
|
||||
|
||||
if [ -z "$GITLAB_DOMAIN" ]; then
|
||||
if [ -z "$Le_Deploy_gitlab_domain" ]; then
|
||||
_err "GITLAB_DOMAIN not defined."
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
Le_Deploy_gitlab_domain="$GITLAB_DOMAIN"
|
||||
_savedomainconf Le_Deploy_gitlab_domain "$Le_Deploy_gitlab_domain"
|
||||
fi
|
||||
|
||||
string_fullchain=$(_url_encode <"$_cfullchain")
|
||||
string_key=$(_url_encode <"$_ckey")
|
||||
|
||||
body="certificate=$string_fullchain&key=$string_key"
|
||||
|
||||
export _H1="PRIVATE-TOKEN: $Le_Deploy_gitlab_token"
|
||||
|
||||
gitlab_url="https://gitlab.com/api/v4/projects/$Le_Deploy_gitlab_project_id/pages/domains/$Le_Deploy_gitlab_domain"
|
||||
|
||||
_response=$(_post "$body" "$gitlab_url" 0 PUT | _dbase64 "multiline")
|
||||
|
||||
error_response="error"
|
||||
|
||||
if test "${_response#*$error_response}" != "$_response"; then
|
||||
_err "Error in deploying certificate:"
|
||||
_err "$_response"
|
||||
return 1
|
||||
fi
|
||||
|
||||
_debug response "$_response"
|
||||
_info "Certificate successfully deployed"
|
||||
|
||||
return 0
|
||||
}
|
||||
@ -20,7 +20,39 @@ haproxy_deploy() {
|
||||
_debug _cca "$_cca"
|
||||
_debug _cfullchain "$_cfullchain"
|
||||
|
||||
_err "deploy cert to haproxy server, Not implemented yet"
|
||||
return 1
|
||||
# handle reload preference
|
||||
DEFAULT_HAPROXY_RELOAD="/usr/sbin/service haproxy restart"
|
||||
if [ -z "${DEPLOY_HAPROXY_RELOAD}" ]; then
|
||||
_reload="${DEFAULT_HAPROXY_RELOAD}"
|
||||
_cleardomainconf DEPLOY_HAPROXY_RELOAD
|
||||
else
|
||||
_reload="${DEPLOY_HAPROXY_RELOAD}"
|
||||
_savedomainconf DEPLOY_HAPROXY_RELOAD "$DEPLOY_HAPROXY_RELOAD"
|
||||
fi
|
||||
_savedomainconf DEPLOY_HAPROXY_PEM_PATH "$DEPLOY_HAPROXY_PEM_PATH"
|
||||
|
||||
# work out the path where the PEM file should go
|
||||
_pem_path="${DEPLOY_HAPROXY_PEM_PATH}"
|
||||
if [ -z "$_pem_path" ]; then
|
||||
_err "Path to save PEM file not found. Please define DEPLOY_HAPROXY_PEM_PATH."
|
||||
return 1
|
||||
fi
|
||||
_pem_full_path="$_pem_path/$_cdomain.pem"
|
||||
_info "Full path to PEM $_pem_full_path"
|
||||
|
||||
# combine the key and fullchain into a single pem and install
|
||||
cat "$_cfullchain" "$_ckey" >"$_pem_full_path"
|
||||
chmod 600 "$_pem_full_path"
|
||||
_info "Certificate successfully deployed"
|
||||
|
||||
# restart HAProxy
|
||||
_info "Run reload: $_reload"
|
||||
if eval "$_reload"; then
|
||||
_info "Reload success!"
|
||||
return 0
|
||||
else
|
||||
_err "Reload error"
|
||||
return 1
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
#
|
||||
# Only a username is required. All others are optional.
|
||||
#
|
||||
# The following examples are for QNAP NAS running QTS 4.2
|
||||
# The following examples are for QNAP NAS running QTS 4.2
|
||||
# export DEPLOY_SSH_CMD="" # defaults to ssh
|
||||
# export DEPLOY_SSH_USER="admin" # required
|
||||
# export DEPLOY_SSH_SERVER="qnap" # defaults to domain name
|
||||
@ -101,7 +101,7 @@ ssh_deploy() {
|
||||
fi
|
||||
|
||||
# CERTFILE is optional.
|
||||
# If provided then private key will be copied or appended to provided filename.
|
||||
# If provided then certificate will be copied or appended to provided filename.
|
||||
if [ -n "$DEPLOY_SSH_CERTFILE" ]; then
|
||||
Le_Deploy_ssh_certfile="$DEPLOY_SSH_CERTFILE"
|
||||
_savedomainconf Le_Deploy_ssh_certfile "$Le_Deploy_ssh_certfile"
|
||||
@ -190,7 +190,7 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d
|
||||
_info "Backup directories erased after 180 days."
|
||||
fi
|
||||
|
||||
_debug "Remote commands to execute: $_cmdstr"
|
||||
_secure_debug "Remote commands to execute: " "$_cmdstr"
|
||||
_info "Submitting sequence of commands to remote server by ssh"
|
||||
# quotations in bash cmd below intended. Squash travis spellcheck error
|
||||
# shellcheck disable=SC2029
|
||||
|
||||
202
dnsapi/README.md
202
dnsapi/README.md
@ -1,5 +1,9 @@
|
||||
# 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
|
||||
|
||||
First you need to login to your CloudFlare account to get your API key.
|
||||
@ -641,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.
|
||||
|
||||
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
|
||||
|
||||
Create a new user from the servercow control center. Don't forget to activate **DNS API** for this user.
|
||||
@ -753,7 +765,7 @@ DNS API keys may be created at https://panel.dreamhost.com/?tree=home.api.
|
||||
Ensure the created key has add and remove privelages.
|
||||
|
||||
```
|
||||
export DH_API_Key="<api key>"
|
||||
export DH_API_KEY="<api key>"
|
||||
acme.sh --issue --dns dns_dreamhost -d example.com -d www.example.com
|
||||
```
|
||||
|
||||
@ -814,6 +826,194 @@ 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 Euserv.eu API
|
||||
|
||||
First you need to login to your euserv.eu account and activate your API Administration (API Verwaltung).
|
||||
[https://support.euserv.com](https://support.euserv.com)
|
||||
|
||||
Once you've activate, login to your API Admin Interface and create an API account.
|
||||
Please specify the scope (active groups: domain) and assign the allowed IPs.
|
||||
|
||||
```
|
||||
export EUSERV_Username="99999.user123"
|
||||
export EUSERV_Password="Asbe54gHde"
|
||||
```
|
||||
|
||||
Ok, let's issue a cert now: (Be aware to use the `--insecure` flag, cause euserv.eu is still using self-signed certificates!)
|
||||
```
|
||||
acme.sh --issue --dns dns_euserv -d example.com -d *.example.com --insecure
|
||||
```
|
||||
|
||||
The `EUSERV_Username` and `EUSERV_Password` will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
|
||||
|
||||
Please report any issues to https://github.com/initit/acme.sh or to <github@initit.de>
|
||||
|
||||
## 48. Use DNSPod.com domain API to automatically issue cert
|
||||
|
||||
First you need to get your API Key and ID by this [get-the-user-token](https://www.dnspod.com/docs/info.html#get-the-user-token).
|
||||
|
||||
```
|
||||
export DPI_Id="1234"
|
||||
export DPI_Key="sADDsdasdgdsf"
|
||||
```
|
||||
|
||||
Ok, let's issue a cert now:
|
||||
```
|
||||
acme.sh --issue --dns dns_dpi -d example.com -d www.example.com
|
||||
```
|
||||
|
||||
The `DPI_Id` and `DPI_Key` will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
|
||||
|
||||
## 49. Use Google Cloud DNS API to automatically issue cert
|
||||
|
||||
First you need to authenticate to gcloud.
|
||||
|
||||
```
|
||||
gcloud init
|
||||
```
|
||||
|
||||
**The `dns_gcloud` script uses the active gcloud configuration and credentials.**
|
||||
There is no logic inside `dns_gcloud` to override the project and other settings.
|
||||
If needed, create additional [gcloud configurations](https://cloud.google.com/sdk/gcloud/reference/topic/configurations).
|
||||
You can change the configuration being used without *activating* it; simply set the `CLOUDSDK_ACTIVE_CONFIG_NAME` environment variable.
|
||||
|
||||
To issue a certificate you can:
|
||||
```
|
||||
export CLOUDSDK_ACTIVE_CONFIG_NAME=default # see the note above
|
||||
acme.sh --issue --dns dns_gcloud -d example.com -d '*.example.com'
|
||||
```
|
||||
|
||||
`dns_gcloud` also supports [DNS alias mode](https://github.com/Neilpang/acme.sh/wiki/DNS-alias-mode).
|
||||
|
||||
## 50. Use ConoHa API
|
||||
|
||||
First you need to login to your ConoHa account to get your API credentials.
|
||||
|
||||
```
|
||||
export CONOHA_Username="xxxxxx"
|
||||
export CONOHA_Password="xxxxxx"
|
||||
export CONOHA_TenantId="xxxxxx"
|
||||
export CONOHA_IdentityServiceApi="https://identity.xxxx.conoha.io/v2.0"
|
||||
```
|
||||
|
||||
To issue a cert:
|
||||
```
|
||||
acme.sh --issue --dns dns_conoha -d example.com -d www.example.com
|
||||
```
|
||||
|
||||
The `CONOHA_Username`, `CONOHA_Password`, `CONOHA_TenantId` and `CONOHA_IdentityServiceApi` will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
|
||||
|
||||
## 51. Use netcup DNS API to automatically issue cert
|
||||
|
||||
First you need to login in your CCP account to get your API Key and API Password.
|
||||
```
|
||||
export NC_Apikey="<Apikey>"
|
||||
export NC_Apipw="<Apipassword>"
|
||||
export NC_CID="<Customernumber>"
|
||||
```
|
||||
|
||||
Now, let's issue a cert:
|
||||
```
|
||||
acme.sh --issue --dns dns_netcup -d example.com -d www.example.com
|
||||
```
|
||||
|
||||
The `NC_Apikey`,`NC_Apipw` and `NC_CID` will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
|
||||
|
||||
## 52. Use GratisDNS.dk
|
||||
|
||||
GratisDNS.dk (https://gratisdns.dk/) does not provide an API to update DNS records (other than IPv4 and IPv6
|
||||
dynamic DNS addresses). The acme.sh plugin therefore retrieves and updates domain TXT records by logging
|
||||
into the GratisDNS website to read the HTML and posting updates as HTTP. The plugin needs to know your
|
||||
userid and password for the GratisDNS website.
|
||||
|
||||
```sh
|
||||
export GDNSDK_Username="..."
|
||||
export GDNSDK_Password="..."
|
||||
```
|
||||
The username and password will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
|
||||
|
||||
|
||||
Now you can issue a certificate.
|
||||
|
||||
Note: It usually takes a few minutes (usually 3-4 minutes) before the changes propagates to gratisdns.dk nameservers (ns3.gratisdns.dk often are slow),
|
||||
and in rare cases I have seen over 5 minutes before google DNS catches it. Therefor a DNS sleep of at least 300 seconds are recommended-
|
||||
|
||||
```sh
|
||||
acme.sh --issue --dns dns_gdnsdk --dnssleep 300 -d example.com -d *.example.com
|
||||
```
|
||||
|
||||
## 53. Use Namecheap
|
||||
|
||||
You will need your namecheap username, API KEY (https://www.namecheap.com/support/api/intro.aspx) and your external IP address (or an URL to get it), this IP will need to be whitelisted at Namecheap.
|
||||
Due to Namecheap's API limitation all the records of your domain will be read and re applied, make sure to have a backup of your records you could apply if any issue would arise.
|
||||
|
||||
```sh
|
||||
export NAMECHEAP_USERNAME="..."
|
||||
export NAMECHEAP_API_KEY="..."
|
||||
export NAMECHEAP_SOURCEIP="..."
|
||||
```
|
||||
|
||||
NAMECHEAP_SOURCEIP can either be an IP address or an URL to provide it (e.g. https://ifconfig.co/ip).
|
||||
|
||||
The username and password will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
|
||||
|
||||
Now you can issue a certificate.
|
||||
|
||||
```sh
|
||||
acme.sh --issue --dns dns_namecheap -d example.com -d *.example.com
|
||||
```
|
||||
|
||||
# Use custom API
|
||||
|
||||
If your API is not supported yet, you can write your own DNS API.
|
||||
|
||||
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 ##################################
|
||||
@ -29,7 +29,7 @@ dns_aws_add() {
|
||||
if [ -z "$AWS_ACCESS_KEY_ID" ] || [ -z "$AWS_SECRET_ACCESS_KEY" ]; then
|
||||
AWS_ACCESS_KEY_ID=""
|
||||
AWS_SECRET_ACCESS_KEY=""
|
||||
_err "You don't specify aws route53 api key id and and api key secret yet."
|
||||
_err "You haven't specifed the aws route53 api key id and and api key secret yet."
|
||||
_err "Please create your key and try again. see $(__green $AWS_WIKI)"
|
||||
return 1
|
||||
fi
|
||||
@ -62,7 +62,7 @@ dns_aws_add() {
|
||||
fi
|
||||
|
||||
if [ "$_resource_record" ] && _contains "$response" "$txtvalue"; then
|
||||
_info "The txt record already exists, skip"
|
||||
_info "The TXT record already exists. Skipping."
|
||||
return 0
|
||||
fi
|
||||
|
||||
@ -71,7 +71,7 @@ dns_aws_add() {
|
||||
_aws_tmpl_xml="<ChangeResourceRecordSetsRequest xmlns=\"https://route53.amazonaws.com/doc/2013-04-01/\"><ChangeBatch><Changes><Change><Action>UPSERT</Action><ResourceRecordSet><Name>$fulldomain</Name><Type>TXT</Type><TTL>300</TTL><ResourceRecords>$_resource_record<ResourceRecord><Value>\"$txtvalue\"</Value></ResourceRecord></ResourceRecords></ResourceRecordSet></Change></Changes></ChangeBatch></ChangeResourceRecordSetsRequest>"
|
||||
|
||||
if aws_rest POST "2013-04-01$_domain_id/rrset/" "" "$_aws_tmpl_xml" && _contains "$response" "ChangeResourceRecordSetsResponse"; then
|
||||
_info "txt record updated success."
|
||||
_info "TXT record updated successfully."
|
||||
return 0
|
||||
fi
|
||||
|
||||
@ -99,7 +99,7 @@ dns_aws_rm() {
|
||||
_debug _sub_domain "$_sub_domain"
|
||||
_debug _domain "$_domain"
|
||||
|
||||
_info "Geting existing records for $fulldomain"
|
||||
_info "Getting existing records for $fulldomain"
|
||||
if ! aws_rest GET "2013-04-01$_domain_id/rrset" "name=$fulldomain&type=TXT"; then
|
||||
return 1
|
||||
fi
|
||||
@ -108,14 +108,14 @@ dns_aws_rm() {
|
||||
_resource_record="$(echo "$response" | sed 's/<ResourceRecordSet>/"/g' | tr '"' "\n" | grep "<Name>$fulldomain.</Name>" | _egrep_o "<ResourceRecords.*</ResourceRecords>" | sed "s/<ResourceRecords>//" | sed "s#</ResourceRecords>##")"
|
||||
_debug "_resource_record" "$_resource_record"
|
||||
else
|
||||
_debug "no records exists, skip"
|
||||
_debug "no records exist, skip"
|
||||
return 0
|
||||
fi
|
||||
|
||||
_aws_tmpl_xml="<ChangeResourceRecordSetsRequest xmlns=\"https://route53.amazonaws.com/doc/2013-04-01/\"><ChangeBatch><Changes><Change><Action>DELETE</Action><ResourceRecordSet><ResourceRecords>$_resource_record</ResourceRecords><Name>$fulldomain.</Name><Type>TXT</Type><TTL>300</TTL></ResourceRecordSet></Change></Changes></ChangeBatch></ChangeResourceRecordSetsRequest>"
|
||||
|
||||
if aws_rest POST "2013-04-01$_domain_id/rrset/" "" "$_aws_tmpl_xml" && _contains "$response" "ChangeResourceRecordSetsResponse"; then
|
||||
_info "txt record deleted success."
|
||||
_info "TXT record deleted successfully."
|
||||
return 0
|
||||
fi
|
||||
|
||||
@ -163,7 +163,7 @@ _get_root() {
|
||||
_domain=$h
|
||||
return 0
|
||||
fi
|
||||
_err "Can not find domain id: $h"
|
||||
_err "Can't find domain with id: $h"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
@ -76,10 +76,10 @@ dns_azure_add() {
|
||||
values="{\"value\":[\"$txtvalue\"]}"
|
||||
timestamp="$(_time)"
|
||||
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 "$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
|
||||
# the record was not created by acme.sh. Copy the exisiting entires
|
||||
existingts=$timestamp
|
||||
@ -172,7 +172,7 @@ dns_azure_rm() {
|
||||
_azure_rest GET "$acmeRecordURI" "" "$accesstoken"
|
||||
timestamp="$(_time)"
|
||||
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=""
|
||||
comma=""
|
||||
for v in $vlist; do
|
||||
@ -230,7 +230,7 @@ _azure_rest() {
|
||||
fi
|
||||
_ret="$?"
|
||||
_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"
|
||||
if [ "$_code" = "401" ]; then
|
||||
# we have an invalid access token set to expired
|
||||
@ -308,7 +308,7 @@ _get_root() {
|
||||
domain=$1
|
||||
subscriptionId=$2
|
||||
accesstoken=$3
|
||||
i=2
|
||||
i=1
|
||||
p=1
|
||||
|
||||
## Ref: https://docs.microsoft.com/en-us/rest/api/dns/zones/list
|
||||
@ -328,9 +328,14 @@ _get_root() {
|
||||
fi
|
||||
|
||||
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
|
||||
_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
|
||||
return 0
|
||||
fi
|
||||
|
||||
253
dnsapi/dns_conoha.sh
Executable file
253
dnsapi/dns_conoha.sh
Executable file
@ -0,0 +1,253 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
CONOHA_DNS_EP_PREFIX_REGEXP="https://dns-service\."
|
||||
|
||||
######## Public functions #####################
|
||||
|
||||
#Usage: dns_conoha_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||
dns_conoha_add() {
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
_info "Using conoha"
|
||||
_debug fulldomain "$fulldomain"
|
||||
_debug txtvalue "$txtvalue"
|
||||
|
||||
_debug "Check uesrname and password"
|
||||
CONOHA_Username="${CONOHA_Username:-$(_readaccountconf_mutable CONOHA_Username)}"
|
||||
CONOHA_Password="${CONOHA_Password:-$(_readaccountconf_mutable CONOHA_Password)}"
|
||||
CONOHA_TenantId="${CONOHA_TenantId:-$(_readaccountconf_mutable CONOHA_TenantId)}"
|
||||
CONOHA_IdentityServiceApi="${CONOHA_IdentityServiceApi:-$(_readaccountconf_mutable CONOHA_IdentityServiceApi)}"
|
||||
if [ -z "$CONOHA_Username" ] || [ -z "$CONOHA_Password" ] || [ -z "$CONOHA_TenantId" ] || [ -z "$CONOHA_IdentityServiceApi" ]; then
|
||||
CONOHA_Username=""
|
||||
CONOHA_Password=""
|
||||
CONOHA_TenantId=""
|
||||
CONOHA_IdentityServiceApi=""
|
||||
_err "You didn't specify a conoha api username and password yet."
|
||||
_err "Please create the user and try again."
|
||||
return 1
|
||||
fi
|
||||
|
||||
_saveaccountconf_mutable CONOHA_Username "$CONOHA_Username"
|
||||
_saveaccountconf_mutable CONOHA_Password "$CONOHA_Password"
|
||||
_saveaccountconf_mutable CONOHA_TenantId "$CONOHA_TenantId"
|
||||
_saveaccountconf_mutable CONOHA_IdentityServiceApi "$CONOHA_IdentityServiceApi"
|
||||
|
||||
if token="$(_conoha_get_accesstoken "$CONOHA_IdentityServiceApi/tokens" "$CONOHA_Username" "$CONOHA_Password" "$CONOHA_TenantId")"; then
|
||||
accesstoken="$(printf "%s" "$token" | sed -n 1p)"
|
||||
CONOHA_Api="$(printf "%s" "$token" | sed -n 2p)"
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
|
||||
_debug "First detect the root zone"
|
||||
if ! _get_root "$fulldomain" "$CONOHA_Api" "$accesstoken"; then
|
||||
_err "invalid domain"
|
||||
return 1
|
||||
fi
|
||||
_debug _domain_id "$_domain_id"
|
||||
_debug _sub_domain "$_sub_domain"
|
||||
_debug _domain "$_domain"
|
||||
|
||||
_info "Adding record"
|
||||
body="{\"type\":\"TXT\",\"name\":\"$fulldomain.\",\"data\":\"$txtvalue\",\"ttl\":60}"
|
||||
if _conoha_rest POST "$CONOHA_Api/v1/domains/$_domain_id/records" "$body" "$accesstoken"; then
|
||||
if _contains "$response" '"data":"'"$txtvalue"'"'; then
|
||||
_info "Added, OK"
|
||||
return 0
|
||||
else
|
||||
_err "Add txt record error."
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
_err "Add txt record error."
|
||||
return 1
|
||||
}
|
||||
|
||||
#Usage: fulldomain txtvalue
|
||||
#Remove the txt record after validation.
|
||||
dns_conoha_rm() {
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
_info "Using conoha"
|
||||
_debug fulldomain "$fulldomain"
|
||||
_debug txtvalue "$txtvalue"
|
||||
|
||||
_debug "Check uesrname and password"
|
||||
CONOHA_Username="${CONOHA_Username:-$(_readaccountconf_mutable CONOHA_Username)}"
|
||||
CONOHA_Password="${CONOHA_Password:-$(_readaccountconf_mutable CONOHA_Password)}"
|
||||
CONOHA_TenantId="${CONOHA_TenantId:-$(_readaccountconf_mutable CONOHA_TenantId)}"
|
||||
CONOHA_IdentityServiceApi="${CONOHA_IdentityServiceApi:-$(_readaccountconf_mutable CONOHA_IdentityServiceApi)}"
|
||||
if [ -z "$CONOHA_Username" ] || [ -z "$CONOHA_Password" ] || [ -z "$CONOHA_TenantId" ] || [ -z "$CONOHA_IdentityServiceApi" ]; then
|
||||
CONOHA_Username=""
|
||||
CONOHA_Password=""
|
||||
CONOHA_TenantId=""
|
||||
CONOHA_IdentityServiceApi=""
|
||||
_err "You didn't specify a conoha api username and password yet."
|
||||
_err "Please create the user and try again."
|
||||
return 1
|
||||
fi
|
||||
|
||||
_saveaccountconf_mutable CONOHA_Username "$CONOHA_Username"
|
||||
_saveaccountconf_mutable CONOHA_Password "$CONOHA_Password"
|
||||
_saveaccountconf_mutable CONOHA_TenantId "$CONOHA_TenantId"
|
||||
_saveaccountconf_mutable CONOHA_IdentityServiceApi "$CONOHA_IdentityServiceApi"
|
||||
|
||||
if token="$(_conoha_get_accesstoken "$CONOHA_IdentityServiceApi/tokens" "$CONOHA_Username" "$CONOHA_Password" "$CONOHA_TenantId")"; then
|
||||
accesstoken="$(printf "%s" "$token" | sed -n 1p)"
|
||||
CONOHA_Api="$(printf "%s" "$token" | sed -n 2p)"
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
|
||||
_debug "First detect the root zone"
|
||||
if ! _get_root "$fulldomain" "$CONOHA_Api" "$accesstoken"; then
|
||||
_err "invalid domain"
|
||||
return 1
|
||||
fi
|
||||
_debug _domain_id "$_domain_id"
|
||||
_debug _sub_domain "$_sub_domain"
|
||||
_debug _domain "$_domain"
|
||||
|
||||
_debug "Getting txt records"
|
||||
if ! _conoha_rest GET "$CONOHA_Api/v1/domains/$_domain_id/records" "" "$accesstoken"; then
|
||||
_err "Error"
|
||||
return 1
|
||||
fi
|
||||
|
||||
record_id=$(printf "%s" "$response" | _egrep_o '{[^}]*}' \
|
||||
| grep '"type":"TXT"' | grep "\"data\":\"$txtvalue\"" | _egrep_o "\"id\":\"[^\"]*\"" \
|
||||
| _head_n 1 | cut -d : -f 2 | tr -d \")
|
||||
if [ -z "$record_id" ]; then
|
||||
_err "Can not get record id to remove."
|
||||
return 1
|
||||
fi
|
||||
_debug record_id "$record_id"
|
||||
|
||||
_info "Removing the txt record"
|
||||
if ! _conoha_rest DELETE "$CONOHA_Api/v1/domains/$_domain_id/records/$record_id" "" "$accesstoken"; then
|
||||
_err "Delete record error."
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
#################### Private functions below ##################################
|
||||
|
||||
_conoha_rest() {
|
||||
m="$1"
|
||||
ep="$2"
|
||||
data="$3"
|
||||
accesstoken="$4"
|
||||
|
||||
export _H1="Accept: application/json"
|
||||
export _H2="Content-Type: application/json"
|
||||
if [ -n "$accesstoken" ]; then
|
||||
export _H3="X-Auth-Token: $accesstoken"
|
||||
fi
|
||||
|
||||
_debug "$ep"
|
||||
if [ "$m" != "GET" ]; then
|
||||
_secure_debug2 data "$data"
|
||||
response="$(_post "$data" "$ep" "" "$m")"
|
||||
else
|
||||
response="$(_get "$ep")"
|
||||
fi
|
||||
_ret="$?"
|
||||
_secure_debug2 response "$response"
|
||||
if [ "$_ret" != "0" ]; then
|
||||
_err "error $ep"
|
||||
return 1
|
||||
fi
|
||||
|
||||
response="$(printf "%s" "$response" | _normalizeJson)"
|
||||
return 0
|
||||
}
|
||||
|
||||
_conoha_get_accesstoken() {
|
||||
ep="$1"
|
||||
username="$2"
|
||||
password="$3"
|
||||
tenantId="$4"
|
||||
|
||||
accesstoken="$(_readaccountconf_mutable conoha_accesstoken)"
|
||||
expires="$(_readaccountconf_mutable conoha_tokenvalidto)"
|
||||
CONOHA_Api="$(_readaccountconf_mutable conoha_dns_ep)"
|
||||
|
||||
# can we reuse the access token?
|
||||
if [ -n "$accesstoken" ] && [ -n "$expires" ] && [ -n "$CONOHA_Api" ]; then
|
||||
utc_date="$(_utc_date | sed "s/ /T/")"
|
||||
if expr "$utc_date" "<" "$expires" >/dev/null; then
|
||||
# access token is still valid - reuse it
|
||||
_debug "reusing access token"
|
||||
printf "%s\n%s\n" "$accesstoken" "$CONOHA_Api"
|
||||
return 0
|
||||
else
|
||||
_debug "access token expired"
|
||||
fi
|
||||
fi
|
||||
_debug "getting new access token"
|
||||
|
||||
body="$(printf '{"auth":{"passwordCredentials":{"username":"%s","password":"%s"},"tenantId":"%s"}}' "$username" "$password" "$tenantId")"
|
||||
if ! _conoha_rest POST "$ep" "$body" ""; then
|
||||
_err error "$response"
|
||||
return 1
|
||||
fi
|
||||
accesstoken=$(printf "%s" "$response" | _egrep_o "\"id\":\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \")
|
||||
expires=$(printf "%s" "$response" | _egrep_o "\"expires\":\"[^\"]*\"" | _head_n 1 | cut -d : -f 2-4 | tr -d \" | tr -d Z) #expect UTC
|
||||
if [ -z "$accesstoken" ] || [ -z "$expires" ]; then
|
||||
_err "no acccess token received. Check your Conoha settings see $WIKI"
|
||||
return 1
|
||||
fi
|
||||
_saveaccountconf_mutable conoha_accesstoken "$accesstoken"
|
||||
_saveaccountconf_mutable conoha_tokenvalidto "$expires"
|
||||
|
||||
CONOHA_Api=$(printf "%s" "$response" | _egrep_o 'publicURL":"'"$CONOHA_DNS_EP_PREFIX_REGEXP"'[^"]*"' | _head_n 1 | cut -d : -f 2-3 | tr -d \")
|
||||
if [ -z "$CONOHA_Api" ]; then
|
||||
_err "failed to get conoha dns endpoint url"
|
||||
return 1
|
||||
fi
|
||||
_saveaccountconf_mutable conoha_dns_ep "$CONOHA_Api"
|
||||
|
||||
printf "%s\n%s\n" "$accesstoken" "$CONOHA_Api"
|
||||
return 0
|
||||
}
|
||||
|
||||
#_acme-challenge.www.domain.com
|
||||
#returns
|
||||
# _sub_domain=_acme-challenge.www
|
||||
# _domain=domain.com
|
||||
# _domain_id=sdjkglgdfewsdfg
|
||||
_get_root() {
|
||||
domain="$1"
|
||||
ep="$2"
|
||||
accesstoken="$3"
|
||||
i=2
|
||||
p=1
|
||||
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 ! _conoha_rest GET "$ep/v1/domains?name=$h" "" "$accesstoken"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
if _contains "$response" "\"name\":\"$h\"" >/dev/null; then
|
||||
_domain_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":\"[^\"]*\"" | head -n 1 | cut -d : -f 2 | tr -d \")
|
||||
if [ "$_domain_id" ]; then
|
||||
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
|
||||
_domain=$h
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
fi
|
||||
p=$i
|
||||
i=$(_math "$i" + 1)
|
||||
done
|
||||
return 1
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
# Cloudxns.com Domain api
|
||||
# CloudXNS Domain api
|
||||
#
|
||||
#CX_Key="1234"
|
||||
#
|
||||
@ -19,7 +19,7 @@ dns_cx_add() {
|
||||
if [ -z "$CX_Key" ] || [ -z "$CX_Secret" ]; then
|
||||
CX_Key=""
|
||||
CX_Secret=""
|
||||
_err "You don't specify cloudxns.com api key or secret yet."
|
||||
_err "You don't specify cloudxns.net api key or secret yet."
|
||||
_err "Please create you key and try again."
|
||||
return 1
|
||||
fi
|
||||
|
||||
161
dnsapi/dns_dpi.sh
Executable file
161
dnsapi/dns_dpi.sh
Executable file
@ -0,0 +1,161 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
# Dnspod.com Domain api
|
||||
#
|
||||
#DPI_Id="1234"
|
||||
#
|
||||
#DPI_Key="sADDsdasdgdsf"
|
||||
|
||||
REST_API="https://api.dnspod.com"
|
||||
|
||||
######## Public functions #####################
|
||||
|
||||
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||
dns_dpi_add() {
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
|
||||
DPI_Id="${DPI_Id:-$(_readaccountconf_mutable DPI_Id)}"
|
||||
DPI_Key="${DPI_Key:-$(_readaccountconf_mutable DPI_Key)}"
|
||||
if [ -z "$DPI_Id" ] || [ -z "$DPI_Key" ]; then
|
||||
DPI_Id=""
|
||||
DPI_Key=""
|
||||
_err "You don't specify dnspod api key and key id 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 DPI_Id "$DPI_Id"
|
||||
_saveaccountconf_mutable DPI_Key "$DPI_Key"
|
||||
|
||||
_debug "First detect the root zone"
|
||||
if ! _get_root "$fulldomain"; then
|
||||
_err "invalid domain"
|
||||
return 1
|
||||
fi
|
||||
|
||||
add_record "$_domain" "$_sub_domain" "$txtvalue"
|
||||
|
||||
}
|
||||
|
||||
#fulldomain txtvalue
|
||||
dns_dpi_rm() {
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
|
||||
DPI_Id="${DPI_Id:-$(_readaccountconf_mutable DPI_Id)}"
|
||||
DPI_Key="${DPI_Key:-$(_readaccountconf_mutable DPI_Key)}"
|
||||
|
||||
_debug "First detect the root zone"
|
||||
if ! _get_root "$fulldomain"; then
|
||||
_err "invalid domain"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! _rest POST "Record.List" "user_token=$DPI_Id,$DPI_Key&format=json&domain_id=$_domain_id&sub_domain=$_sub_domain"; then
|
||||
_err "Record.Lis error."
|
||||
return 1
|
||||
fi
|
||||
|
||||
if _contains "$response" 'No records'; then
|
||||
_info "Don't need to remove."
|
||||
return 0
|
||||
fi
|
||||
|
||||
record_id=$(echo "$response" | _egrep_o '{[^{]*"value":"'"$txtvalue"'"' | cut -d , -f 1 | cut -d : -f 2 | tr -d \")
|
||||
_debug record_id "$record_id"
|
||||
if [ -z "$record_id" ]; then
|
||||
_err "Can not get record id."
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! _rest POST "Record.Remove" "user_token=$DPI_Id,$DPI_Key&format=json&domain_id=$_domain_id&record_id=$record_id"; then
|
||||
_err "Record.Remove error."
|
||||
return 1
|
||||
fi
|
||||
|
||||
_contains "$response" "Action completed successful"
|
||||
|
||||
}
|
||||
|
||||
#add the txt record.
|
||||
#usage: root sub txtvalue
|
||||
add_record() {
|
||||
root=$1
|
||||
sub=$2
|
||||
txtvalue=$3
|
||||
fulldomain="$sub.$root"
|
||||
|
||||
_info "Adding record"
|
||||
|
||||
if ! _rest POST "Record.Create" "user_token=$DPI_Id,$DPI_Key&format=json&domain_id=$_domain_id&sub_domain=$_sub_domain&record_type=TXT&value=$txtvalue&record_line=default"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
_contains "$response" "Action completed successful" || _contains "$response" "Domain record already exists"
|
||||
}
|
||||
|
||||
#################### Private functions below ##################################
|
||||
#_acme-challenge.www.domain.com
|
||||
#returns
|
||||
# _sub_domain=_acme-challenge.www
|
||||
# _domain=domain.com
|
||||
# _domain_id=sdjkglgdfewsdfg
|
||||
_get_root() {
|
||||
domain=$1
|
||||
i=2
|
||||
p=1
|
||||
while true; do
|
||||
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
|
||||
if [ -z "$h" ]; then
|
||||
#not valid
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! _rest POST "Domain.Info" "user_token=$DPI_Id,$DPI_Key&format=json&domain=$h"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
if _contains "$response" "Action completed successful"; then
|
||||
_domain_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \")
|
||||
_debug _domain_id "$_domain_id"
|
||||
if [ "$_domain_id" ]; then
|
||||
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
|
||||
_debug _sub_domain "$_sub_domain"
|
||||
_domain="$h"
|
||||
_debug _domain "$_domain"
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
fi
|
||||
p="$i"
|
||||
i=$(_math "$i" + 1)
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
#Usage: method URI data
|
||||
_rest() {
|
||||
m="$1"
|
||||
ep="$2"
|
||||
data="$3"
|
||||
_debug "$ep"
|
||||
url="$REST_API/$ep"
|
||||
|
||||
_debug url "$url"
|
||||
|
||||
if [ "$m" = "GET" ]; then
|
||||
response="$(_get "$url" | tr -d '\r')"
|
||||
else
|
||||
_debug2 data "$data"
|
||||
response="$(_post "$data" "$url" | tr -d '\r')"
|
||||
fi
|
||||
|
||||
if [ "$?" != "0" ]; then
|
||||
_err "error $ep"
|
||||
return 1
|
||||
fi
|
||||
_debug2 response "$response"
|
||||
return 0
|
||||
}
|
||||
358
dnsapi/dns_euserv.sh
Normal file
358
dnsapi/dns_euserv.sh
Normal file
@ -0,0 +1,358 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
#This is the euserv.eu api wrapper for acme.sh
|
||||
#
|
||||
#Author: Michael Brueckner
|
||||
#Report Bugs: https://www.github.com/initit/acme.sh or mbr@initit.de
|
||||
|
||||
#
|
||||
#EUSERV_Username="username"
|
||||
#
|
||||
#EUSERV_Password="password"
|
||||
#
|
||||
# Dependencies:
|
||||
# -------------
|
||||
# - none -
|
||||
|
||||
EUSERV_Api="https://api.euserv.net"
|
||||
|
||||
######## Public functions #####################
|
||||
|
||||
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||
dns_euserv_add() {
|
||||
fulldomain="$(echo "$1" | _lower_case)"
|
||||
txtvalue=$2
|
||||
|
||||
EUSERV_Username="${EUSERV_Username:-$(_readaccountconf_mutable EUSERV_Username)}"
|
||||
EUSERV_Password="${EUSERV_Password:-$(_readaccountconf_mutable EUSERV_Password)}"
|
||||
if [ -z "$EUSERV_Username" ] || [ -z "$EUSERV_Password" ]; then
|
||||
EUSERV_Username=""
|
||||
EUSERV_Password=""
|
||||
_err "You don't specify euserv user and password yet."
|
||||
_err "Please create your key and try again."
|
||||
return 1
|
||||
fi
|
||||
|
||||
#save the user and email to the account conf file.
|
||||
_saveaccountconf_mutable EUSERV_Username "$EUSERV_Username"
|
||||
_saveaccountconf_mutable EUSERV_Password "$EUSERV_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"
|
||||
if ! _euserv_add_record "$_domain" "$_sub_domain" "$txtvalue"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
#fulldomain txtvalue
|
||||
dns_euserv_rm() {
|
||||
|
||||
fulldomain="$(echo "$1" | _lower_case)"
|
||||
txtvalue=$2
|
||||
|
||||
EUSERV_Username="${EUSERV_Username:-$(_readaccountconf_mutable EUSERV_Username)}"
|
||||
EUSERV_Password="${EUSERV_Password:-$(_readaccountconf_mutable EUSERV_Password)}"
|
||||
if [ -z "$EUSERV_Username" ] || [ -z "$EUSERV_Password" ]; then
|
||||
EUSERV_Username=""
|
||||
EUSERV_Password=""
|
||||
_err "You don't specify euserv user and password yet."
|
||||
_err "Please create your key and try again."
|
||||
return 1
|
||||
fi
|
||||
|
||||
#save the user and email to the account conf file.
|
||||
_saveaccountconf_mutable EUSERV_Username "$EUSERV_Username"
|
||||
_saveaccountconf_mutable EUSERV_Password "$EUSERV_Password"
|
||||
|
||||
_debug "First detect the root zone"
|
||||
if ! _get_root "$fulldomain"; then
|
||||
_err "invalid domain"
|
||||
return 1
|
||||
fi
|
||||
_debug "_sub_domain" "$_sub_domain"
|
||||
_debug "_domain" "$_domain"
|
||||
|
||||
_debug "Getting txt records"
|
||||
|
||||
xml_content=$(printf '<?xml version="1.0" encoding="UTF-8"?>
|
||||
<methodCall>
|
||||
<methodName>domain.dns_get_active_records</methodName>
|
||||
<params>
|
||||
<param>
|
||||
<value>
|
||||
<struct>
|
||||
<member>
|
||||
<name>login</name>
|
||||
<value>
|
||||
<string>%s</string>
|
||||
</value>
|
||||
</member>
|
||||
<member>
|
||||
<name>password</name>
|
||||
<value>
|
||||
<string>%s</string>
|
||||
</value>
|
||||
</member>
|
||||
<member>
|
||||
<name>domain_id</name>
|
||||
<value>
|
||||
<int>%s</int>
|
||||
</value>
|
||||
</member>
|
||||
</struct>
|
||||
</value>
|
||||
</param>
|
||||
</params>
|
||||
</methodCall>' "$EUSERV_Username" "$EUSERV_Password" "$_euserv_domain_id")
|
||||
|
||||
export _H1="Content-Type: text/xml"
|
||||
response="$(_post "$xml_content" "$EUSERV_Api" "" "POST")"
|
||||
|
||||
if ! _contains "$response" "<member><name>status</name><value><i4>100</i4></value></member>"; then
|
||||
_err "Error could not get txt records"
|
||||
_debug "xml_content" "$xml_content"
|
||||
_debug "response" "$response"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! echo "$response" | grep '>dns_record_content<.*>'"$txtvalue"'<' >/dev/null; then
|
||||
_info "Do not need to delete record"
|
||||
else
|
||||
# find XML block where txtvalue is in. The record_id is allways prior this line!
|
||||
_endLine=$(echo "$response" | grep -n '>dns_record_content<.*>'"$txtvalue"'<' | cut -d ':' -f 1)
|
||||
# record_id is the last <name> Tag with a number before the row _endLine, identified by </name><value><struct>
|
||||
_record_id=$(echo "$response" | sed -n '1,'"$_endLine"'p' | grep '</name><value><struct>' | _tail_n 1 | sed 's/.*<name>\([0-9]*\)<\/name>.*/\1/')
|
||||
_info "Deleting record"
|
||||
_euserv_delete_record "$_record_id"
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
#################### Private functions below ##################################
|
||||
|
||||
_get_root() {
|
||||
domain=$1
|
||||
_debug "get root"
|
||||
|
||||
# Just to read the domain_orders once
|
||||
|
||||
domain=$1
|
||||
i=2
|
||||
p=1
|
||||
|
||||
if ! _euserv_get_domain_orders; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Get saved response with domain_orders
|
||||
response="$_euserv_domain_orders"
|
||||
|
||||
while true; do
|
||||
h=$(echo "$domain" | cut -d . -f $i-100)
|
||||
_debug h "$h"
|
||||
if [ -z "$h" ]; then
|
||||
#not valid
|
||||
return 1
|
||||
fi
|
||||
|
||||
if _contains "$response" "$h"; then
|
||||
_sub_domain=$(echo "$domain" | cut -d . -f 1-$p)
|
||||
_domain="$h"
|
||||
if ! _euserv_get_domain_id "$_domain"; then
|
||||
_err "invalid domain"
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
p=$i
|
||||
i=$(_math "$i" + 1)
|
||||
done
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
_euserv_get_domain_orders() {
|
||||
# returns: _euserv_domain_orders
|
||||
|
||||
_debug "get domain_orders"
|
||||
|
||||
xml_content=$(printf '<?xml version="1.0" encoding="UTF-8"?>
|
||||
<methodCall>
|
||||
<methodName>domain.get_domain_orders</methodName>
|
||||
<params>
|
||||
<param>
|
||||
<value>
|
||||
<struct>
|
||||
<member>
|
||||
<name>login</name>
|
||||
<value><string>%s</string></value>
|
||||
</member>
|
||||
<member>
|
||||
<name>password</name>
|
||||
<value><string>%s</string></value>
|
||||
</member>
|
||||
</struct>
|
||||
</value>
|
||||
</param>
|
||||
</params>
|
||||
</methodCall>' "$EUSERV_Username" "$EUSERV_Password")
|
||||
|
||||
export _H1="Content-Type: text/xml"
|
||||
response="$(_post "$xml_content" "$EUSERV_Api" "" "POST")"
|
||||
|
||||
if ! _contains "$response" "<member><name>status</name><value><i4>100</i4></value></member>"; then
|
||||
_err "Error could not get domain orders"
|
||||
_debug "xml_content" "$xml_content"
|
||||
_debug "response" "$response"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# save response to reduce API calls
|
||||
_euserv_domain_orders="$response"
|
||||
return 0
|
||||
}
|
||||
|
||||
_euserv_get_domain_id() {
|
||||
# returns: _euserv_domain_id
|
||||
domain=$1
|
||||
_debug "get domain_id"
|
||||
|
||||
# find line where the domain name is within the $response
|
||||
_startLine=$(echo "$_euserv_domain_orders" | grep -n '>domain_name<.*>'"$domain"'<' | cut -d ':' -f 1)
|
||||
# next occurency of domain_id after the domain_name is the correct one
|
||||
_euserv_domain_id=$(echo "$_euserv_domain_orders" | sed -n "$_startLine"',$p' | grep '>domain_id<' | _head_n 1 | sed 's/.*<i4>\([0-9]*\)<\/i4>.*/\1/')
|
||||
|
||||
if [ -z "$_euserv_domain_id" ]; then
|
||||
_err "Could not find domain_id for domain $domain"
|
||||
_debug "_euserv_domain_orders" "$_euserv_domain_orders"
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
_euserv_delete_record() {
|
||||
record_id=$1
|
||||
xml_content=$(printf '<?xml version="1.0" encoding="UTF-8"?>
|
||||
<methodCall>
|
||||
<methodName>domain.dns_delete_record</methodName>
|
||||
<params>
|
||||
<param>
|
||||
<value>
|
||||
<struct>
|
||||
<member>
|
||||
<name>login</name>
|
||||
<value>
|
||||
<string>%s</string>
|
||||
</value>
|
||||
</member>
|
||||
<member>
|
||||
<name>password</name>
|
||||
<value>
|
||||
<string>%s</string>
|
||||
</value>
|
||||
</member>
|
||||
<member>
|
||||
<name>dns_record_id</name>
|
||||
<value>
|
||||
<int>%s</int>
|
||||
</value>
|
||||
</member>
|
||||
</struct>
|
||||
</value>
|
||||
</param>
|
||||
</params>
|
||||
</methodCall>' "$EUSERV_Username" "$EUSERV_Password" "$record_id")
|
||||
|
||||
export _H1="Content-Type: text/xml"
|
||||
response="$(_post "$xml_content" "$EUSERV_Api" "" "POST")"
|
||||
|
||||
if ! _contains "$response" "<member><name>status</name><value><i4>100</i4></value></member>"; then
|
||||
_err "Error deleting record"
|
||||
_debug "xml_content" "$xml_content"
|
||||
_debug "response" "$response"
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
|
||||
}
|
||||
|
||||
_euserv_add_record() {
|
||||
domain=$1
|
||||
sub_domain=$2
|
||||
txtval=$3
|
||||
|
||||
xml_content=$(printf '<?xml version="1.0" encoding="UTF-8"?>
|
||||
<methodCall>
|
||||
<methodName>domain.dns_create_record</methodName>
|
||||
<params>
|
||||
<param>
|
||||
<value>
|
||||
<struct>
|
||||
<member>
|
||||
<name>login</name>
|
||||
<value>
|
||||
<string>%s</string>
|
||||
</value>
|
||||
</member>
|
||||
<member>
|
||||
<name>password</name>
|
||||
<value>
|
||||
<string>%s</string></value>
|
||||
</member>
|
||||
<member>
|
||||
<name>domain_id</name>
|
||||
<value>
|
||||
<int>%s</int>
|
||||
</value>
|
||||
</member>
|
||||
<member>
|
||||
<name>dns_record_subdomain</name>
|
||||
<value>
|
||||
<string>%s</string>
|
||||
</value>
|
||||
</member>
|
||||
<member>
|
||||
<name>dns_record_type</name>
|
||||
<value>
|
||||
<string>TXT</string>
|
||||
</value>
|
||||
</member>
|
||||
<member>
|
||||
<name>dns_record_value</name>
|
||||
<value>
|
||||
<string>%s</string>
|
||||
</value>
|
||||
</member>
|
||||
<member>
|
||||
<name>dns_record_ttl</name>
|
||||
<value>
|
||||
<int>300</int>
|
||||
</value>
|
||||
</member>
|
||||
</struct>
|
||||
</value>
|
||||
</param>
|
||||
</params>
|
||||
</methodCall>' "$EUSERV_Username" "$EUSERV_Password" "$_euserv_domain_id" "$sub_domain" "$txtval")
|
||||
|
||||
export _H1="Content-Type: text/xml"
|
||||
response="$(_post "$xml_content" "$EUSERV_Api" "" "POST")"
|
||||
|
||||
if ! _contains "$response" "<member><name>status</name><value><i4>100</i4></value></member>"; then
|
||||
_err "Error could not create record"
|
||||
_debug "xml_content" "$xml_content"
|
||||
_debug "response" "$response"
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
167
dnsapi/dns_gcloud.sh
Executable file
167
dnsapi/dns_gcloud.sh
Executable file
@ -0,0 +1,167 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
# Author: Janos Lenart <janos@lenart.io>
|
||||
|
||||
######## Public functions #####################
|
||||
|
||||
# Usage: dns_gcloud_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||
dns_gcloud_add() {
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
_info "Using gcloud"
|
||||
_debug fulldomain "$fulldomain"
|
||||
_debug txtvalue "$txtvalue"
|
||||
|
||||
_dns_gcloud_find_zone || return $?
|
||||
|
||||
# Add an extra RR
|
||||
_dns_gcloud_start_tr || return $?
|
||||
_dns_gcloud_get_rrdatas || return $?
|
||||
echo "$rrdatas" | _dns_gcloud_remove_rrs || return $?
|
||||
printf "%s\n%s\n" "$rrdatas" "\"$txtvalue\"" | grep -v '^$' | _dns_gcloud_add_rrs || return $?
|
||||
_dns_gcloud_execute_tr || return $?
|
||||
|
||||
_info "$fulldomain record added"
|
||||
}
|
||||
|
||||
# Usage: dns_gcloud_rm _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||
# Remove the txt record after validation.
|
||||
dns_gcloud_rm() {
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
_info "Using gcloud"
|
||||
_debug fulldomain "$fulldomain"
|
||||
_debug txtvalue "$txtvalue"
|
||||
|
||||
_dns_gcloud_find_zone || return $?
|
||||
|
||||
# Remove one RR
|
||||
_dns_gcloud_start_tr || return $?
|
||||
_dns_gcloud_get_rrdatas || return $?
|
||||
echo "$rrdatas" | _dns_gcloud_remove_rrs || return $?
|
||||
echo "$rrdatas" | grep -F -v "\"$txtvalue\"" | _dns_gcloud_add_rrs || return $?
|
||||
_dns_gcloud_execute_tr || return $?
|
||||
|
||||
_info "$fulldomain record added"
|
||||
}
|
||||
|
||||
#################### Private functions below ##################################
|
||||
|
||||
_dns_gcloud_start_tr() {
|
||||
if ! trd=$(mktemp -d); then
|
||||
_err "_dns_gcloud_start_tr: failed to create temporary directory"
|
||||
return 1
|
||||
fi
|
||||
tr="$trd/tr.yaml"
|
||||
_debug tr "$tr"
|
||||
|
||||
if ! gcloud dns record-sets transaction start \
|
||||
--transaction-file="$tr" \
|
||||
--zone="$managedZone"; then
|
||||
rm -r "$trd"
|
||||
_err "_dns_gcloud_start_tr: failed to execute transaction"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
_dns_gcloud_execute_tr() {
|
||||
if ! gcloud dns record-sets transaction execute \
|
||||
--transaction-file="$tr" \
|
||||
--zone="$managedZone"; then
|
||||
_debug tr "$(cat "$tr")"
|
||||
rm -r "$trd"
|
||||
_err "_dns_gcloud_execute_tr: failed to execute transaction"
|
||||
return 1
|
||||
fi
|
||||
rm -r "$trd"
|
||||
|
||||
for i in $(seq 1 120); do
|
||||
if gcloud dns record-sets changes list \
|
||||
--zone="$managedZone" \
|
||||
--filter='status != done' \
|
||||
| grep -q '^.*'; then
|
||||
_info "_dns_gcloud_execute_tr: waiting for transaction to be comitted ($i/120)..."
|
||||
sleep 5
|
||||
else
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
|
||||
_err "_dns_gcloud_execute_tr: transaction is still pending after 10 minutes"
|
||||
rm -r "$trd"
|
||||
return 1
|
||||
}
|
||||
|
||||
_dns_gcloud_remove_rrs() {
|
||||
if ! xargs --no-run-if-empty gcloud dns record-sets transaction remove \
|
||||
--name="$fulldomain." \
|
||||
--ttl="$ttl" \
|
||||
--type=TXT \
|
||||
--zone="$managedZone" \
|
||||
--transaction-file="$tr"; then
|
||||
_debug tr "$(cat "$tr")"
|
||||
rm -r "$trd"
|
||||
_err "_dns_gcloud_remove_rrs: failed to remove RRs"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
_dns_gcloud_add_rrs() {
|
||||
ttl=60
|
||||
if ! xargs --no-run-if-empty gcloud dns record-sets transaction add \
|
||||
--name="$fulldomain." \
|
||||
--ttl="$ttl" \
|
||||
--type=TXT \
|
||||
--zone="$managedZone" \
|
||||
--transaction-file="$tr"; then
|
||||
_debug tr "$(cat "$tr")"
|
||||
rm -r "$trd"
|
||||
_err "_dns_gcloud_add_rrs: failed to add RRs"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
_dns_gcloud_find_zone() {
|
||||
# Prepare a filter that matches zones that are suiteable for this entry.
|
||||
# For example, _acme-challenge.something.domain.com might need to go into something.domain.com or domain.com;
|
||||
# this function finds the longest postfix that has a managed zone.
|
||||
part="$fulldomain"
|
||||
filter="dnsName=( "
|
||||
while [ "$part" != "" ]; do
|
||||
filter="$filter$part. "
|
||||
part="$(echo "$part" | sed 's/[^.]*\.*//')"
|
||||
done
|
||||
filter="$filter)"
|
||||
_debug filter "$filter"
|
||||
|
||||
# List domains and find the longest match (in case of some levels of delegation)
|
||||
if ! match=$(gcloud dns managed-zones list \
|
||||
--format="value(name, dnsName)" \
|
||||
--filter="$filter" \
|
||||
| while read -r dnsName name; do
|
||||
printf "%s\t%s\t%s\n" "${#dnsName}" "$dnsName" "$name"
|
||||
done \
|
||||
| sort -n -r | _head_n 1 | cut -f2,3 | grep '^.*'); then
|
||||
_err "_dns_gcloud_find_zone: Can't find a matching managed zone! Perhaps wrong project or gcloud credentials?"
|
||||
return 1
|
||||
fi
|
||||
|
||||
dnsName=$(echo "$match" | cut -f2)
|
||||
_debug dnsName "$dnsName"
|
||||
managedZone=$(echo "$match" | cut -f1)
|
||||
_debug managedZone "$managedZone"
|
||||
}
|
||||
|
||||
_dns_gcloud_get_rrdatas() {
|
||||
if ! rrdatas=$(gcloud dns record-sets list \
|
||||
--zone="$managedZone" \
|
||||
--name="$fulldomain." \
|
||||
--type=TXT \
|
||||
--format="value(ttl,rrdatas)"); then
|
||||
_err "_dns_gcloud_get_rrdatas: Failed to list record-sets"
|
||||
rm -r "$trd"
|
||||
return 1
|
||||
fi
|
||||
ttl=$(echo "$rrdatas" | cut -f1)
|
||||
rrdatas=$(echo "$rrdatas" | cut -f2 | sed 's/","/"\n"/g')
|
||||
}
|
||||
@ -59,19 +59,13 @@ dns_gd_add() {
|
||||
|
||||
_info "Adding record"
|
||||
if _gd_rest PUT "domains/$_domain/records/TXT/$_sub_domain" "[$_add_data]"; then
|
||||
if [ "$response" = "{}" ]; then
|
||||
_info "Added, sleeping 10 seconds"
|
||||
_sleep 10
|
||||
#todo: check if the record takes effect
|
||||
return 0
|
||||
else
|
||||
_err "Add txt record error."
|
||||
_err "$response"
|
||||
return 1
|
||||
fi
|
||||
_info "Added, sleeping 10 seconds"
|
||||
_sleep 10
|
||||
#todo: check if the record takes effect
|
||||
return 0
|
||||
fi
|
||||
_err "Add txt record error."
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
#fulldomain
|
||||
@ -174,5 +168,9 @@ _gd_rest() {
|
||||
return 1
|
||||
fi
|
||||
_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
|
||||
}
|
||||
|
||||
168
dnsapi/dns_gdnsdk.sh
Executable file
168
dnsapi/dns_gdnsdk.sh
Executable file
@ -0,0 +1,168 @@
|
||||
#!/usr/bin/env sh
|
||||
#Author: Herman Sletteng
|
||||
#Report Bugs here: https://github.com/loial/acme.sh
|
||||
#
|
||||
#
|
||||
# Note, gratisdns requires a login first, so the script needs to handle
|
||||
# temporary cookies. Since acme.sh _get/_post currently don't directly support
|
||||
# cookies, I've defined wrapper functions _myget/_mypost to set the headers
|
||||
|
||||
GDNSDK_API="https://admin.gratisdns.com"
|
||||
######## Public functions #####################
|
||||
#Usage: dns_gdnsdk_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||
dns_gdnsdk_add() {
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
_info "Using gratisdns.dk"
|
||||
_debug fulldomain "$fulldomain"
|
||||
_debug txtvalue "$txtvalue"
|
||||
if ! _gratisdns_login; then
|
||||
_err "Login failed!"
|
||||
return 1
|
||||
fi
|
||||
#finding domain zone
|
||||
if ! _get_domain; then
|
||||
_err "No matching root domain for $fulldomain found"
|
||||
return 1
|
||||
fi
|
||||
# adding entry
|
||||
_info "Adding the entry"
|
||||
_mypost "action=dns_primary_record_added_txt&user_domain=$_domain&name=$fulldomain&txtdata=$txtvalue&ttl=1"
|
||||
if _successful_update; then return 0; fi
|
||||
_err "Couldn't create entry!"
|
||||
return 1
|
||||
}
|
||||
|
||||
#Usage: fulldomain txtvalue
|
||||
#Remove the txt record after validation.
|
||||
dns_gdnsdk_rm() {
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
_info "Using gratisdns.dk"
|
||||
_debug fulldomain "$fulldomain"
|
||||
_debug txtvalue "$txtvalue"
|
||||
if ! _gratisdns_login; then
|
||||
_err "Login failed!"
|
||||
return 1
|
||||
fi
|
||||
if ! _get_domain; then
|
||||
_err "No matching root domain for $fulldomain found"
|
||||
return 1
|
||||
fi
|
||||
_findentry "$fulldomain" "$txtvalue"
|
||||
if [ -z "$_id" ]; then
|
||||
_info "Entry doesn't exist, nothing to delete"
|
||||
return 0
|
||||
fi
|
||||
_debug "Deleting record..."
|
||||
_mypost "action=dns_primary_delete_txt&user_domain=$_domain&id=$_id"
|
||||
# removing entry
|
||||
|
||||
if _successful_update; then return 0; fi
|
||||
_err "Couldn't delete entry!"
|
||||
return 1
|
||||
}
|
||||
|
||||
#################### Private functions below ##################################
|
||||
|
||||
_checkcredentials() {
|
||||
GDNSDK_Username="${GDNSDK_Username:-$(_readaccountconf_mutable GDNSDK_Username)}"
|
||||
GDNSDK_Password="${GDNSDK_Password:-$(_readaccountconf_mutable GDNSDK_Password)}"
|
||||
|
||||
if [ -z "$GDNSDK_Username" ] || [ -z "$GDNSDK_Password" ]; then
|
||||
GDNSDK_Username=""
|
||||
GDNSDK_Password=""
|
||||
_err "You haven't specified gratisdns.dk username and password yet."
|
||||
_err "Please add credentials and try again."
|
||||
return 1
|
||||
fi
|
||||
#save the credentials to the account conf file.
|
||||
_saveaccountconf_mutable GDNSDK_Username "$GDNSDK_Username"
|
||||
_saveaccountconf_mutable GDNSDK_Password "$GDNSDK_Password"
|
||||
return 0
|
||||
}
|
||||
|
||||
_checkcookie() {
|
||||
GDNSDK_Cookie="${GDNSDK_Cookie:-$(_readaccountconf_mutable GDNSDK_Cookie)}"
|
||||
if [ -z "$GDNSDK_Cookie" ]; then
|
||||
_debug "No cached cookie found"
|
||||
return 1
|
||||
fi
|
||||
_myget "action="
|
||||
if (echo "$_result" | grep -q "logmeout"); then
|
||||
_debug "Cached cookie still valid"
|
||||
return 0
|
||||
fi
|
||||
_debug "Cached cookie no longer valid"
|
||||
GDNSDK_Cookie=""
|
||||
_saveaccountconf_mutable GDNSDK_Cookie "$GDNSDK_Cookie"
|
||||
return 1
|
||||
}
|
||||
|
||||
_gratisdns_login() {
|
||||
if ! _checkcredentials; then return 1; fi
|
||||
|
||||
if _checkcookie; then
|
||||
_debug "Already logged in"
|
||||
return 0
|
||||
fi
|
||||
_debug "Logging into GratisDNS with user $GDNSDK_Username"
|
||||
|
||||
if ! _mypost "login=$GDNSDK_Username&password=$GDNSDK_Password&action=logmein"; then
|
||||
_err "GratisDNS login failed for user $GDNSDK_Username bad RC from _post"
|
||||
return 1
|
||||
fi
|
||||
|
||||
GDNSDK_Cookie="$(grep -A 15 '302 Found' "$HTTP_HEADER" | _egrep_o 'Cookie: [^;]*' | _head_n 1 | cut -d ' ' -f2)"
|
||||
|
||||
if [ -z "$GDNSDK_Cookie" ]; then
|
||||
_err "GratisDNS login failed for user $GDNSDK_Username. Check $HTTP_HEADER file"
|
||||
return 1
|
||||
fi
|
||||
export GDNSDK_Cookie
|
||||
_saveaccountconf_mutable GDNSDK_Cookie "$GDNSDK_Cookie"
|
||||
return 0
|
||||
}
|
||||
|
||||
_myget() {
|
||||
#Adds cookie to request
|
||||
export _H1="Cookie: $GDNSDK_Cookie"
|
||||
_result=$(_get "$GDNSDK_API?$1")
|
||||
}
|
||||
_mypost() {
|
||||
#Adds cookie to request
|
||||
export _H1="Cookie: $GDNSDK_Cookie"
|
||||
_result=$(_post "$1" "$GDNSDK_API")
|
||||
}
|
||||
|
||||
_get_domain() {
|
||||
_myget 'action=dns_primarydns'
|
||||
_domains=$(echo "$_result" | _egrep_o ' domain="[[:alnum:].-_]+' | sed 's/^.*"//')
|
||||
if [ -z "$_domains" ]; then
|
||||
_err "Primary domain list not found!"
|
||||
return 1
|
||||
fi
|
||||
for _domain in $_domains; do
|
||||
if (_endswith "$fulldomain" "$_domain"); then
|
||||
_debug "Root domain: $_domain"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
_successful_update() {
|
||||
if (echo "$_result" | grep -q 'table-success'); then return 0; fi
|
||||
return 1
|
||||
}
|
||||
|
||||
_findentry() {
|
||||
#returns id of dns entry, if it exists
|
||||
_myget "action=dns_primary_changeDNSsetup&user_domain=$_domain"
|
||||
_id=$(echo "$_result" | _egrep_o "<td>$1</td>\s*<td>$2</td>[^?]*[^&]*&id=[^&]*" | sed 's/^.*=//')
|
||||
if [ -n "$_id" ]; then
|
||||
_debug "Entry found with _id=$_id"
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
@ -33,8 +33,9 @@ dns_he_add() {
|
||||
# Fills in the $_zone_id
|
||||
_find_zone "$_full_domain" || return 1
|
||||
_debug "Zone id \"$_zone_id\" will be used."
|
||||
|
||||
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&account="
|
||||
body="$body&menu=edit_zone"
|
||||
body="$body&Type=TXT"
|
||||
@ -71,7 +72,9 @@ dns_he_rm() {
|
||||
_debug "Zone id \"$_zone_id\" will be used."
|
||||
|
||||
# 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&menu=edit_zone"
|
||||
body="$body&hosted_dns_editzone="
|
||||
@ -89,7 +92,9 @@ dns_he_rm() {
|
||||
return 1
|
||||
fi
|
||||
# Remove the record
|
||||
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&menu=edit_zone"
|
||||
body="$body&hosted_dns_zoneid=$_zone_id"
|
||||
body="$body&hosted_dns_recordid=$_record_id"
|
||||
@ -112,9 +117,15 @@ dns_he_rm() {
|
||||
|
||||
_find_zone() {
|
||||
_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/")"
|
||||
_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"')"
|
||||
_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')"
|
||||
|
||||
@ -4,6 +4,10 @@
|
||||
#INWX_User="username"
|
||||
#
|
||||
#INWX_Password="password"
|
||||
#
|
||||
# Dependencies:
|
||||
# -------------
|
||||
# - oathtool (When using 2 Factor Authentication)
|
||||
|
||||
INWX_Api="https://api.domrobot.com/xmlrpc/"
|
||||
|
||||
@ -16,6 +20,7 @@ dns_inwx_add() {
|
||||
|
||||
INWX_User="${INWX_User:-$(_readaccountconf_mutable INWX_User)}"
|
||||
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
|
||||
INWX_User=""
|
||||
INWX_Password=""
|
||||
@ -27,6 +32,7 @@ dns_inwx_add() {
|
||||
#save the api key and email to the account conf file.
|
||||
_saveaccountconf_mutable INWX_User "$INWX_User"
|
||||
_saveaccountconf_mutable INWX_Password "$INWX_Password"
|
||||
_saveaccountconf_mutable INWX_Shared_Secret "$INWX_Shared_Secret"
|
||||
|
||||
_debug "First detect the root zone"
|
||||
if ! _get_root "$fulldomain"; then
|
||||
@ -148,8 +154,46 @@ _inwx_login() {
|
||||
</methodCall>' $INWX_User $INWX_Password)
|
||||
|
||||
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
|
||||
p=1
|
||||
|
||||
_H1=$(_inwx_login)
|
||||
export _H1
|
||||
_inwx_login
|
||||
|
||||
xml_content='<?xml version="1.0" encoding="UTF-8"?>
|
||||
<methodCall>
|
||||
<methodName>nameserver.list</methodName>
|
||||
|
||||
@ -128,7 +128,7 @@ _ISPC_addTxt() {
|
||||
curSerial="$(date +%s)"
|
||||
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}\""
|
||||
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")"
|
||||
_debug "Calling _ISPC_addTxt: '${curData}' '${ISPC_Api}?dns_txt_add'"
|
||||
_debug "Result of _ISPC_addTxt: '$curResult'"
|
||||
@ -160,7 +160,7 @@ _ISPC_rmTxt() {
|
||||
*)
|
||||
unset IFS
|
||||
_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")"
|
||||
_debug "Calling _ISPC_rmTxt: '${curData}' '${ISPC_Api}?dns_txt_delete'"
|
||||
_debug "Result of _ISPC_rmTxt: '$curResult'"
|
||||
|
||||
@ -7,20 +7,13 @@ lexicon_cmd="lexicon"
|
||||
|
||||
wiki="https://github.com/Neilpang/acme.sh/wiki/How-to-use-lexicon-dns-api"
|
||||
|
||||
######## Public functions #####################
|
||||
|
||||
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||
dns_lexicon_add() {
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
|
||||
domain=$(printf "%s" "$fulldomain" | cut -d . -f 2-999)
|
||||
|
||||
_lexicon_init() {
|
||||
if ! _exists "$lexicon_cmd"; then
|
||||
_err "Please install $lexicon_cmd first: $wiki"
|
||||
return 1
|
||||
fi
|
||||
|
||||
PROVIDER="${PROVIDER:-$(_readdomainconf PROVIDER)}"
|
||||
if [ -z "$PROVIDER" ]; then
|
||||
PROVIDER=""
|
||||
_err "Please define env PROVIDER first: $wiki"
|
||||
@ -33,46 +26,78 @@ dns_lexicon_add() {
|
||||
# e.g. busybox-ash does not know [:upper:]
|
||||
# shellcheck disable=SC2018,SC2019
|
||||
Lx_name=$(echo LEXICON_"${PROVIDER}"_USERNAME | tr 'a-z' 'A-Z')
|
||||
eval "$Lx_name=\${$Lx_name:-$(_readaccountconf_mutable "$Lx_name")}"
|
||||
Lx_name_v=$(eval echo \$"$Lx_name")
|
||||
_secure_debug "$Lx_name" "$Lx_name_v"
|
||||
if [ "$Lx_name_v" ]; then
|
||||
_saveaccountconf "$Lx_name" "$Lx_name_v"
|
||||
_saveaccountconf_mutable "$Lx_name" "$Lx_name_v"
|
||||
eval export "$Lx_name"
|
||||
fi
|
||||
|
||||
# shellcheck disable=SC2018,SC2019
|
||||
Lx_token=$(echo LEXICON_"${PROVIDER}"_TOKEN | tr 'a-z' 'A-Z')
|
||||
eval "$Lx_token=\${$Lx_token:-$(_readaccountconf_mutable "$Lx_token")}"
|
||||
Lx_token_v=$(eval echo \$"$Lx_token")
|
||||
_secure_debug "$Lx_token" "$Lx_token_v"
|
||||
if [ "$Lx_token_v" ]; then
|
||||
_saveaccountconf "$Lx_token" "$Lx_token_v"
|
||||
_saveaccountconf_mutable "$Lx_token" "$Lx_token_v"
|
||||
eval export "$Lx_token"
|
||||
fi
|
||||
|
||||
# shellcheck disable=SC2018,SC2019
|
||||
Lx_password=$(echo LEXICON_"${PROVIDER}"_PASSWORD | tr 'a-z' 'A-Z')
|
||||
eval "$Lx_password=\${$Lx_password:-$(_readaccountconf_mutable "$Lx_password")}"
|
||||
Lx_password_v=$(eval echo \$"$Lx_password")
|
||||
_secure_debug "$Lx_password" "$Lx_password_v"
|
||||
if [ "$Lx_password_v" ]; then
|
||||
_saveaccountconf "$Lx_password" "$Lx_password_v"
|
||||
_saveaccountconf_mutable "$Lx_password" "$Lx_password_v"
|
||||
eval export "$Lx_password"
|
||||
fi
|
||||
|
||||
# shellcheck disable=SC2018,SC2019
|
||||
Lx_domaintoken=$(echo LEXICON_"${PROVIDER}"_DOMAINTOKEN | tr 'a-z' 'A-Z')
|
||||
eval "$Lx_domaintoken=\${$Lx_domaintoken:-$(_readaccountconf_mutable "$Lx_domaintoken")}"
|
||||
Lx_domaintoken_v=$(eval echo \$"$Lx_domaintoken")
|
||||
_secure_debug "$Lx_domaintoken" "$Lx_domaintoken_v"
|
||||
if [ "$Lx_domaintoken_v" ]; then
|
||||
_saveaccountconf_mutable "$Lx_domaintoken" "$Lx_domaintoken_v"
|
||||
eval export "$Lx_domaintoken"
|
||||
_saveaccountconf "$Lx_domaintoken" "$Lx_domaintoken_v"
|
||||
fi
|
||||
}
|
||||
|
||||
######## Public functions #####################
|
||||
|
||||
#Usage: dns_lexicon_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||
dns_lexicon_add() {
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
|
||||
if ! _lexicon_init; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
$lexicon_cmd "$PROVIDER" create "${domain}" TXT --name="_acme-challenge.${domain}." --content="${txtvalue}"
|
||||
domain=$(printf "%s" "$fulldomain" | cut -d . -f 2-999)
|
||||
|
||||
_secure_debug LEXICON_OPTS "$LEXICON_OPTS"
|
||||
_savedomainconf LEXICON_OPTS "$LEXICON_OPTS"
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
$lexicon_cmd "$PROVIDER" $LEXICON_OPTS create "${domain}" TXT --name="_acme-challenge.${domain}." --content="${txtvalue}"
|
||||
|
||||
}
|
||||
|
||||
#fulldomain
|
||||
#Usage: dns_lexicon_rm _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||
dns_lexicon_rm() {
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
|
||||
if ! _lexicon_init; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
domain=$(printf "%s" "$fulldomain" | cut -d . -f 2-999)
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
$lexicon_cmd "$PROVIDER" $LEXICON_OPTS delete "${domain}" TXT --name="_acme-challenge.${domain}." --content="${txtvalue}"
|
||||
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
308
dnsapi/dns_namecheap.sh
Executable file
308
dnsapi/dns_namecheap.sh
Executable file
@ -0,0 +1,308 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
# Namecheap API
|
||||
# https://www.namecheap.com/support/api/intro.aspx
|
||||
#
|
||||
# Requires Namecheap API key set in NAMECHEAP_API_KEY, NAMECHEAP_SOURCEIP and NAMECHEAP_USERNAME set as environment variable
|
||||
# Due to Namecheap's API limitation all the records of your domain will be read and re applied, make sure to have a backup of your records you could apply if any issue would arise.
|
||||
|
||||
######## Public functions #####################
|
||||
|
||||
if [ "$STAGE" -eq 1 ]; then
|
||||
NAMECHEAP_API="https://api.sandbox.namecheap.com/xml.response"
|
||||
else
|
||||
NAMECHEAP_API="https://api.namecheap.com/xml.response"
|
||||
fi
|
||||
|
||||
#Usage: dns_namecheap_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||
dns_namecheap_add() {
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
|
||||
if ! _namecheap_check_config; then
|
||||
_err "$error"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! _namecheap_set_publicip; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
_debug "First detect the root zone"
|
||||
if ! _get_root "$fulldomain"; then
|
||||
_err "invalid domain"
|
||||
return 1
|
||||
fi
|
||||
|
||||
_debug fulldomain "$fulldomain"
|
||||
_debug txtvalue "$txtvalue"
|
||||
_debug domain "$_domain"
|
||||
_debug sub_domain "$_sub_domain"
|
||||
|
||||
_set_namecheap_TXT "$_domain" "$_sub_domain" "$txtvalue"
|
||||
}
|
||||
|
||||
#Usage: fulldomain txtvalue
|
||||
#Remove the txt record after validation.
|
||||
dns_namecheap_rm() {
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
|
||||
if ! _namecheap_set_publicip; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! _namecheap_check_config; then
|
||||
_err "$error"
|
||||
return 1
|
||||
fi
|
||||
|
||||
_debug "First detect the root zone"
|
||||
if ! _get_root "$fulldomain"; then
|
||||
_err "invalid domain"
|
||||
return 1
|
||||
fi
|
||||
|
||||
_debug fulldomain "$fulldomain"
|
||||
_debug txtvalue "$txtvalue"
|
||||
_debug domain "$_domain"
|
||||
_debug sub_domain "$_sub_domain"
|
||||
|
||||
_del_namecheap_TXT "$_domain" "$_sub_domain" "$txtvalue"
|
||||
}
|
||||
|
||||
#################### Private functions below ##################################
|
||||
#_acme-challenge.www.domain.com
|
||||
#returns
|
||||
# _sub_domain=_acme-challenge.www
|
||||
# _domain=domain.com
|
||||
_get_root() {
|
||||
domain=$1
|
||||
|
||||
if ! _namecheap_post "namecheap.domains.getList"; then
|
||||
_err "$error"
|
||||
return 1
|
||||
fi
|
||||
|
||||
i=2
|
||||
p=1
|
||||
|
||||
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 ! _contains "$response" "$h"; then
|
||||
_debug "$h not found"
|
||||
else
|
||||
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
|
||||
_domain="$h"
|
||||
return 0
|
||||
fi
|
||||
p="$i"
|
||||
i=$(_math "$i" + 1)
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
_namecheap_set_publicip() {
|
||||
|
||||
if [ -z "$NAMECHEAP_SOURCEIP" ]; then
|
||||
_err "No Source IP specified for Namecheap API."
|
||||
_err "Use your public ip address or an url to retrieve it (e.g. https://ipconfig.co/ip) and export it as NAMECHEAP_SOURCEIP"
|
||||
return 1
|
||||
else
|
||||
_saveaccountconf NAMECHEAP_SOURCEIP "$NAMECHEAP_SOURCEIP"
|
||||
_debug sourceip "$NAMECHEAP_SOURCEIP"
|
||||
|
||||
ip=$(echo "$NAMECHEAP_SOURCEIP" | _egrep_o '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}')
|
||||
addr=$(echo "$NAMECHEAP_SOURCEIP" | _egrep_o '(http|https)://.*')
|
||||
|
||||
_debug2 ip "$ip"
|
||||
_debug2 addr "$addr"
|
||||
|
||||
if [ -n "$ip" ]; then
|
||||
_publicip="$ip"
|
||||
elif [ -n "$addr" ]; then
|
||||
_publicip=$(_get "$addr")
|
||||
else
|
||||
_err "No Source IP specified for Namecheap API."
|
||||
_err "Use your public ip address or an url to retrieve it (e.g. https://ipconfig.co/ip) and export it as NAMECHEAP_SOURCEIP"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
_debug publicip "$_publicip"
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
_namecheap_post() {
|
||||
command=$1
|
||||
data="ApiUser=${NAMECHEAP_USERNAME}&ApiKey=${NAMECHEAP_API_KEY}&ClientIp=${_publicip}&UserName=${NAMECHEAP_USERNAME}&Command=${command}"
|
||||
|
||||
response="$(_post "$data" "$NAMECHEAP_API" "" "POST")"
|
||||
_debug2 response "$response"
|
||||
|
||||
if _contains "$response" "Status=\"ERROR\"" >/dev/null; then
|
||||
error=$(echo "$response" | _egrep_o ">.*<\\/Error>" | cut -d '<' -f 1 | tr -d '>')
|
||||
_err "error $error"
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
_namecheap_parse_host() {
|
||||
_host=$1
|
||||
_debug _host "$_host"
|
||||
|
||||
_hostid=$(echo "$_host" | _egrep_o '\sHostId="[^"]*' | cut -d '"' -f 2)
|
||||
_hostname=$(echo "$_host" | _egrep_o '\sName="[^"]*' | cut -d '"' -f 2)
|
||||
_hosttype=$(echo "$_host" | _egrep_o '\sType="[^"]*' | cut -d '"' -f 2)
|
||||
_hostaddress=$(echo "$_host" | _egrep_o '\sAddress="[^"]*' | cut -d '"' -f 2)
|
||||
_hostmxpref=$(echo "$_host" | _egrep_o '\sMXPref="[^"]*' | cut -d '"' -f 2)
|
||||
_hostttl=$(echo "$_host" | _egrep_o '\sTTL="[^"]*' | cut -d '"' -f 2)
|
||||
|
||||
_debug hostid "$_hostid"
|
||||
_debug hostname "$_hostname"
|
||||
_debug hosttype "$_hosttype"
|
||||
_debug hostaddress "$_hostaddress"
|
||||
_debug hostmxpref "$_hostmxpref"
|
||||
_debug hostttl "$_hostttl"
|
||||
}
|
||||
|
||||
_namecheap_check_config() {
|
||||
|
||||
if [ -z "$NAMECHEAP_API_KEY" ]; then
|
||||
_err "No API key specified for Namecheap API."
|
||||
_err "Create your key and export it as NAMECHEAP_API_KEY"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ -z "$NAMECHEAP_USERNAME" ]; then
|
||||
_err "No username key specified for Namecheap API."
|
||||
_err "Create your key and export it as NAMECHEAP_USERNAME"
|
||||
return 1
|
||||
fi
|
||||
|
||||
_saveaccountconf NAMECHEAP_API_KEY "$NAMECHEAP_API_KEY"
|
||||
_saveaccountconf NAMECHEAP_USERNAME "$NAMECHEAP_USERNAME"
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
_set_namecheap_TXT() {
|
||||
subdomain=$2
|
||||
txt=$3
|
||||
tld=$(echo "$1" | cut -d '.' -f 2)
|
||||
sld=$(echo "$1" | cut -d '.' -f 1)
|
||||
request="namecheap.domains.dns.getHosts&SLD=$sld&TLD=$tld"
|
||||
|
||||
if ! _namecheap_post "$request"; then
|
||||
_err "$error"
|
||||
return 1
|
||||
fi
|
||||
|
||||
hosts=$(echo "$response" | _egrep_o '<host[^>]*')
|
||||
_debug hosts "$hosts"
|
||||
|
||||
if [ -z "$hosts" ]; then
|
||||
_error "Hosts not found"
|
||||
return 1
|
||||
fi
|
||||
|
||||
_namecheap_reset_hostList
|
||||
|
||||
while read -r host; do
|
||||
if _contains "$host" "<host"; then
|
||||
_namecheap_parse_host "$host"
|
||||
_namecheap_add_host "$_hostname" "$_hosttype" "$_hostaddress" "$_hostmxpref" "$_hostttl"
|
||||
fi
|
||||
done <<EOT
|
||||
echo "$hosts"
|
||||
EOT
|
||||
|
||||
_namecheap_add_host "$subdomain" "TXT" "$txt" 10 120
|
||||
|
||||
_debug hostrequestfinal "$_hostrequest"
|
||||
|
||||
request="namecheap.domains.dns.setHosts&SLD=${sld}&TLD=${tld}${_hostrequest}"
|
||||
|
||||
if ! _namecheap_post "$request"; then
|
||||
_err "$error"
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
_del_namecheap_TXT() {
|
||||
subdomain=$2
|
||||
txt=$3
|
||||
tld=$(echo "$1" | cut -d '.' -f 2)
|
||||
sld=$(echo "$1" | cut -d '.' -f 1)
|
||||
request="namecheap.domains.dns.getHosts&SLD=$sld&TLD=$tld"
|
||||
|
||||
if ! _namecheap_post "$request"; then
|
||||
_err "$error"
|
||||
return 1
|
||||
fi
|
||||
|
||||
hosts=$(echo "$response" | _egrep_o '<host[^>]*')
|
||||
_debug hosts "$hosts"
|
||||
|
||||
if [ -z "$hosts" ]; then
|
||||
_error "Hosts not found"
|
||||
return 1
|
||||
fi
|
||||
|
||||
_namecheap_reset_hostList
|
||||
|
||||
found=0
|
||||
|
||||
while read -r host; do
|
||||
if _contains "$host" "<host"; then
|
||||
_namecheap_parse_host "$host"
|
||||
if [ "$_hosttype" = "TXT" ] && [ "$_hostname" = "$subdomain" ] && [ "$_hostaddress" = "$txt" ]; then
|
||||
_debug "TXT entry found"
|
||||
found=1
|
||||
else
|
||||
_namecheap_add_host "$_hostname" "$_hosttype" "$_hostaddress" "$_hostmxpref" "$_hostttl"
|
||||
fi
|
||||
fi
|
||||
done <<EOT
|
||||
echo "$hosts"
|
||||
EOT
|
||||
|
||||
if [ $found -eq 0 ]; then
|
||||
_debug "TXT entry not found"
|
||||
return 0
|
||||
fi
|
||||
|
||||
_debug hostrequestfinal "$_hostrequest"
|
||||
|
||||
request="namecheap.domains.dns.setHosts&SLD=${sld}&TLD=${tld}${_hostrequest}"
|
||||
|
||||
if ! _namecheap_post "$request"; then
|
||||
_err "$error"
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
_namecheap_reset_hostList() {
|
||||
_hostindex=0
|
||||
_hostrequest=""
|
||||
}
|
||||
|
||||
#Usage: _namecheap_add_host HostName RecordType Address MxPref TTL
|
||||
_namecheap_add_host() {
|
||||
_hostindex=$(_math "$_hostindex" + 1)
|
||||
_hostrequest=$(printf '%s&HostName%d=%s&RecordType%d=%s&Address%d=%s&MXPref%d=%d&TTL%d=%d' "$_hostrequest" "$_hostindex" "$1" "$_hostindex" "$2" "$_hostindex" "$3" "$_hostindex" "$4" "$_hostindex" "$5")
|
||||
}
|
||||
133
dnsapi/dns_netcup.sh
Normal file
133
dnsapi/dns_netcup.sh
Normal file
@ -0,0 +1,133 @@
|
||||
#!/usr/bin/env sh
|
||||
#developed by linux-insideDE
|
||||
|
||||
NC_Apikey="${NC_Apikey:-$(_readaccountconf_mutable NC_Apikey)}"
|
||||
NC_Apipw="${NC_Apipw:-$(_readaccountconf_mutable NC_Apipw)}"
|
||||
NC_CID="${NC_CID:-$(_readaccountconf_mutable NC_CID)}"
|
||||
end="https://ccp.netcup.net/run/webservice/servers/endpoint.php?JSON"
|
||||
client=""
|
||||
|
||||
dns_netcup_add() {
|
||||
login
|
||||
if [ "$NC_Apikey" = "" ] || [ "$NC_Apipw" = "" ] || [ "$NC_CID" = "" ]; then
|
||||
_err "No Credentials given"
|
||||
return 1
|
||||
fi
|
||||
_saveaccountconf_mutable NC_Apikey "$NC_Apikey"
|
||||
_saveaccountconf_mutable NC_Apipw "$NC_Apipw"
|
||||
_saveaccountconf_mutable NC_CID "$NC_CID"
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
domain=""
|
||||
exit=$(echo "$fulldomain" | tr -dc '.' | wc -c)
|
||||
exit=$(_math "$exit" + 1)
|
||||
i=$exit
|
||||
|
||||
while
|
||||
[ "$exit" -gt 0 ]
|
||||
do
|
||||
tmp=$(echo "$fulldomain" | cut -d'.' -f"$exit")
|
||||
if [ "$(_math "$i" - "$exit")" -eq 0 ]; then
|
||||
domain="$tmp"
|
||||
else
|
||||
domain="$tmp.$domain"
|
||||
fi
|
||||
if [ "$(_math "$i" - "$exit")" -ge 1 ]; then
|
||||
msg=$(_post "{\"action\": \"updateDnsRecords\", \"param\": {\"apikey\": \"$NC_Apikey\", \"apisessionid\": \"$sid\", \"customernumber\": \"$NC_CID\",\"clientrequestid\": \"$client\" , \"domainname\": \"$domain\", \"dnsrecordset\": { \"dnsrecords\": [ {\"id\": \"\", \"hostname\": \"$fulldomain.\", \"type\": \"TXT\", \"priority\": \"\", \"destination\": \"$txtvalue\", \"deleterecord\": \"false\", \"state\": \"yes\"} ]}}}" "$end" "" "POST")
|
||||
_debug "$msg"
|
||||
if [ "$(_getfield "$msg" "5" | sed 's/"statuscode"://g')" != 5028 ]; then
|
||||
if [ "$(_getfield "$msg" "4" | sed s/\"status\":\"//g | sed s/\"//g)" != "success" ]; then
|
||||
_err "$msg"
|
||||
return 1
|
||||
else
|
||||
break
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
exit=$(_math "$exit" - 1)
|
||||
done
|
||||
logout
|
||||
}
|
||||
|
||||
dns_netcup_rm() {
|
||||
login
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
|
||||
domain=""
|
||||
exit=$(echo "$fulldomain" | tr -dc '.' | wc -c)
|
||||
exit=$(_math "$exit" + 1)
|
||||
i=$exit
|
||||
rec=""
|
||||
|
||||
while
|
||||
[ "$exit" -gt 0 ]
|
||||
do
|
||||
tmp=$(echo "$fulldomain" | cut -d'.' -f"$exit")
|
||||
if [ "$(_math "$i" - "$exit")" -eq 0 ]; then
|
||||
domain="$tmp"
|
||||
else
|
||||
domain="$tmp.$domain"
|
||||
fi
|
||||
if [ "$(_math "$i" - "$exit")" -ge 1 ]; then
|
||||
msg=$(_post "{\"action\": \"infoDnsRecords\", \"param\": {\"apikey\": \"$NC_Apikey\", \"apisessionid\": \"$sid\", \"customernumber\": \"$NC_CID\", \"domainname\": \"$domain\"}}" "$end" "" "POST")
|
||||
rec=$(echo "$msg" | sed 's/\[//g' | sed 's/\]//g' | sed 's/{\"serverrequestid\".*\"dnsrecords\"://g' | sed 's/},{/};{/g' | sed 's/{//g' | sed 's/}//g')
|
||||
_debug "$msg"
|
||||
if [ "$(_getfield "$msg" "5" | sed 's/"statuscode"://g')" != 5028 ]; then
|
||||
if [ "$(_getfield "$msg" "4" | sed s/\"status\":\"//g | sed s/\"//g)" != "success" ]; then
|
||||
_err "$msg"
|
||||
return 1
|
||||
else
|
||||
break
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
exit=$(_math "$exit" - 1)
|
||||
done
|
||||
|
||||
ida=0000
|
||||
idv=0001
|
||||
ids=0000000000
|
||||
i=1
|
||||
while
|
||||
[ "$i" -ne 0 ]
|
||||
do
|
||||
specrec=$(_getfield "$rec" "$i" ";")
|
||||
idv="$ida"
|
||||
ida=$(_getfield "$specrec" "1" "," | sed 's/\"id\":\"//g' | sed 's/\"//g')
|
||||
txtv=$(_getfield "$specrec" "5" "," | sed 's/\"destination\":\"//g' | sed 's/\"//g')
|
||||
i=$(_math "$i" + 1)
|
||||
if [ "$txtvalue" = "$txtv" ]; then
|
||||
i=0
|
||||
ids="$ida"
|
||||
fi
|
||||
if [ "$ida" = "$idv" ]; then
|
||||
i=0
|
||||
fi
|
||||
done
|
||||
msg=$(_post "{\"action\": \"updateDnsRecords\", \"param\": {\"apikey\": \"$NC_Apikey\", \"apisessionid\": \"$sid\", \"customernumber\": \"$NC_CID\",\"clientrequestid\": \"$client\" , \"domainname\": \"$domain\", \"dnsrecordset\": { \"dnsrecords\": [ {\"id\": \"$ids\", \"hostname\": \"$fulldomain.\", \"type\": \"TXT\", \"priority\": \"\", \"destination\": \"$txtvalue\", \"deleterecord\": \"TRUE\", \"state\": \"yes\"} ]}}}" "$end" "" "POST")
|
||||
_debug "$msg"
|
||||
if [ "$(_getfield "$msg" "4" | sed s/\"status\":\"//g | sed s/\"//g)" != "success" ]; then
|
||||
_err "$msg"
|
||||
return 1
|
||||
fi
|
||||
logout
|
||||
}
|
||||
|
||||
login() {
|
||||
tmp=$(_post "{\"action\": \"login\", \"param\": {\"apikey\": \"$NC_Apikey\", \"apipassword\": \"$NC_Apipw\", \"customernumber\": \"$NC_CID\"}}" "$end" "" "POST")
|
||||
sid=$(_getfield "$tmp" "8" | sed s/\"responsedata\":\{\"apisessionid\":\"//g | sed 's/\"\}\}//g')
|
||||
_debug "$tmp"
|
||||
if [ "$(_getfield "$msg" "4" | sed s/\"status\":\"//g | sed s/\"//g)" != "success" ]; then
|
||||
_err "$msg"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
logout() {
|
||||
tmp=$(_post "{\"action\": \"logout\", \"param\": {\"apikey\": \"$NC_Apikey\", \"apisessionid\": \"$sid\", \"customernumber\": \"$NC_CID\"}}" "$end" "" "POST")
|
||||
_debug "$tmp"
|
||||
if [ "$(_getfield "$msg" "4" | sed s/\"status\":\"//g | sed s/\"//g)" != "success" ]; then
|
||||
_err "$msg"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
@ -8,12 +8,14 @@ dns_nsupdate_add() {
|
||||
txtvalue=$2
|
||||
_checkKeyFile || return 1
|
||||
[ -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.
|
||||
_saveaccountconf NSUPDATE_SERVER "${NSUPDATE_SERVER}"
|
||||
_saveaccountconf NSUPDATE_SERVER_PORT "${NSUPDATE_SERVER_PORT}"
|
||||
_saveaccountconf NSUPDATE_KEY "${NSUPDATE_KEY}"
|
||||
_info "adding ${fulldomain}. 60 in txt \"${txtvalue}\""
|
||||
nsupdate -k "${NSUPDATE_KEY}" <<EOF
|
||||
server ${NSUPDATE_SERVER}
|
||||
server ${NSUPDATE_SERVER} ${NSUPDATE_SERVER_PORT}
|
||||
update add ${fulldomain}. 60 in txt "${txtvalue}"
|
||||
send
|
||||
EOF
|
||||
@ -30,9 +32,10 @@ dns_nsupdate_rm() {
|
||||
fulldomain=$1
|
||||
_checkKeyFile || return 1
|
||||
[ -n "${NSUPDATE_SERVER}" ] || NSUPDATE_SERVER="localhost"
|
||||
[ -n "${NSUPDATE_SERVER_PORT}" ] || NSUPDATE_SERVER_PORT=53
|
||||
_info "removing ${fulldomain}. txt"
|
||||
nsupdate -k "${NSUPDATE_KEY}" <<EOF
|
||||
server ${NSUPDATE_SERVER}
|
||||
server ${NSUPDATE_SERVER} ${NSUPDATE_SERVER_PORT}
|
||||
update delete ${fulldomain}. txt
|
||||
send
|
||||
EOF
|
||||
|
||||
@ -69,15 +69,21 @@ dns_pdns_add() {
|
||||
#fulldomain
|
||||
dns_pdns_rm() {
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
|
||||
if [ -z "$PDNS_Ttl" ]; then
|
||||
PDNS_Ttl="$DEFAULT_PDNS_TTL"
|
||||
fi
|
||||
|
||||
_debug "Detect root zone"
|
||||
if ! _get_root "$fulldomain"; then
|
||||
_err "invalid domain"
|
||||
return 1
|
||||
fi
|
||||
|
||||
_debug _domain "$_domain"
|
||||
|
||||
if ! rm_record "$_domain" "$fulldomain"; then
|
||||
if ! rm_record "$_domain" "$fulldomain" "$txtvalue"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
@ -88,9 +94,16 @@ set_record() {
|
||||
_info "Adding record"
|
||||
root=$1
|
||||
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."
|
||||
return 1
|
||||
fi
|
||||
@ -106,14 +119,37 @@ rm_record() {
|
||||
_info "Remove record"
|
||||
root=$1
|
||||
full=$2
|
||||
txtvalue=$3
|
||||
|
||||
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
|
||||
#Enumerate existing acme challenges
|
||||
_list_existingchallenges
|
||||
|
||||
if ! notify_slaves "$root"; then
|
||||
return 1
|
||||
if _contains "$_existing_challenges" "$txtvalue"; then
|
||||
#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
|
||||
|
||||
return 0
|
||||
@ -185,3 +221,12 @@ _pdns_rest() {
|
||||
|
||||
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,34 +50,16 @@ dns_unoeuro_add() {
|
||||
_err "Error"
|
||||
return 1
|
||||
fi
|
||||
_info "Adding record"
|
||||
|
||||
if ! _contains "$response" "$_sub_domain" >/dev/null; then
|
||||
_info "Adding record"
|
||||
|
||||
if _uno_rest POST "my/products/$h/dns/records" "{\"name\":\"$fulldomain\",\"type\":\"TXT\",\"data\":\"$txtvalue\",\"ttl\":120}"; then
|
||||
if _contains "$response" "\"status\": 200" >/dev/null; then
|
||||
_info "Added, OK"
|
||||
return 0
|
||||
else
|
||||
_err "Add txt record error."
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
_err "Add txt record error."
|
||||
else
|
||||
_info "Updating record"
|
||||
record_line_number=$(echo "$response" | grep -n "$_sub_domain" | cut -d : -f 1)
|
||||
record_line_number=$(_math "$record_line_number" - 1)
|
||||
record_id=$(echo "$response" | _head_n "$record_line_number" | _tail_n 1 1 | _egrep_o "[0-9]{1,}")
|
||||
_debug "record_id" "$record_id"
|
||||
|
||||
_uno_rest PUT "my/products/$h/dns/records/$record_id" "{\"name\":\"$fulldomain\",\"type\":\"TXT\",\"data\":\"$txtvalue\",\"ttl\":120}"
|
||||
if _uno_rest POST "my/products/$h/dns/records" "{\"name\":\"$fulldomain\",\"type\":\"TXT\",\"data\":\"$txtvalue\",\"ttl\":120}"; then
|
||||
if _contains "$response" "\"status\": 200" >/dev/null; then
|
||||
_info "Updated, OK"
|
||||
_info "Added, OK"
|
||||
return 0
|
||||
else
|
||||
_err "Add txt record error."
|
||||
return 1
|
||||
fi
|
||||
_err "Update error"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
@ -122,23 +104,24 @@ dns_unoeuro_rm() {
|
||||
if ! _contains "$response" "$_sub_domain"; then
|
||||
_info "Don't need to remove."
|
||||
else
|
||||
record_line_number=$(echo "$response" | grep -n "$_sub_domain" | cut -d : -f 1)
|
||||
record_line_number=$(_math "$record_line_number" - 1)
|
||||
record_id=$(echo "$response" | _head_n "$record_line_number" | _tail_n 1 1 | _egrep_o "[0-9]{1,}")
|
||||
_debug "record_id" "$record_id"
|
||||
for record_line_number in $(echo "$response" | grep -n "$_sub_domain" | cut -d : -f 1); do
|
||||
record_line_number=$(_math "$record_line_number" - 1)
|
||||
_debug "record_line_number" "$record_line_number"
|
||||
record_id=$(echo "$response" | _head_n "$record_line_number" | _tail_n 1 1 | _egrep_o "[0-9]{1,}")
|
||||
_debug "record_id" "$record_id"
|
||||
|
||||
if [ -z "$record_id" ]; then
|
||||
_err "Can not get record id to remove."
|
||||
return 1
|
||||
fi
|
||||
if [ -z "$record_id" ]; then
|
||||
_err "Can not get record id to remove."
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! _uno_rest DELETE "my/products/$h/dns/records/$record_id"; then
|
||||
_err "Delete record error."
|
||||
return 1
|
||||
fi
|
||||
_contains "$response" "\"status\": 200"
|
||||
if ! _uno_rest DELETE "my/products/$h/dns/records/$record_id"; then
|
||||
_err "Delete record error."
|
||||
return 1
|
||||
fi
|
||||
_contains "$response" "\"status\": 200"
|
||||
done
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
#################### Private functions below ##################################
|
||||
|
||||
Loading…
Reference in New Issue
Block a user